diff --git a/ast/ast_dumper.cpp b/ast/ast_dumper.cpp index 0aaba4a..89293c6 100644 --- a/ast/ast_dumper.cpp +++ b/ast/ast_dumper.cpp @@ -2,367 +2,434 @@ #include -bool ast_dumper::visit_expr(expr* node) { - std::cout << "expr\n"; - std::cout << " -> " << node->get_location().file << ":" - << node->get_location().begin_line << ":" - << node->get_location().begin_column << "\n"; - node->accept(this); - return true; -} - bool ast_dumper::visit_null_expr(null_expr* node) { - std::cout << "null\n"; - std::cout << " -> " << node->get_location().file << ":" - << node->get_location().begin_line << ":" - << node->get_location().begin_column << "\n"; + dump_indent(); + std::cout << "null" << format_location(node->get_location()); return true; } bool ast_dumper::visit_nil_expr(nil_expr* node) { - std::cout << "nil\n"; - std::cout << " -> " << node->get_location().file << ":" - << node->get_location().begin_line << ":" - << node->get_location().begin_column << "\n"; + dump_indent(); + std::cout << "nil" << format_location(node->get_location()); return true; } bool ast_dumper::visit_number_literal(number_literal* node) { - std::cout << "number " << node->get_number() << "\n"; - std::cout << " -> " << node->get_location().file << ":" - << node->get_location().begin_line << ":" - << node->get_location().begin_column << "\n"; + dump_indent(); + std::cout << "number " << node->get_number(); + std::cout << format_location(node->get_location()); return true; } bool ast_dumper::visit_string_literal(string_literal* node) { - std::cout << "string " << node->get_content() << "\n"; - std::cout << " -> " << node->get_location().file << ":" - << node->get_location().begin_line << ":" - << node->get_location().begin_column << "\n"; + dump_indent(); + std::cout << "string \"" << rawstr(node->get_content()) << "\""; + std::cout << format_location(node->get_location()); return true; } bool ast_dumper::visit_identifier(identifier* node) { - std::cout << "identifier " << node->get_name() << "\n"; - std::cout << " -> " << node->get_location().file << ":" - << node->get_location().begin_line << ":" - << node->get_location().begin_column << "\n"; + dump_indent(); + std::cout << "identifier " << node->get_name(); + std::cout << format_location(node->get_location()); return true; } bool ast_dumper::visit_bool_literal(bool_literal* node) { - std::cout << "bool " << node->get_flag() << "\n"; - std::cout << " -> " << node->get_location().file << ":" - << node->get_location().begin_line << ":" - << node->get_location().begin_column << "\n"; + dump_indent(); + std::cout << "bool " << node->get_flag(); + std::cout << format_location(node->get_location()); return true; } bool ast_dumper::visit_vector_expr(vector_expr* node) { - std::cout << "vector\n"; - std::cout << " -> " << node->get_location().file << ":" - << node->get_location().begin_line << ":" - << node->get_location().begin_column << "\n"; + dump_indent(); + std::cout << "vector"; + std::cout << format_location(node->get_location()); + push_indent(); for(auto i : node->get_elements()) { + if (i==node->get_elements().back()) { + set_last(); + } i->accept(this); } + pop_indent(); return true; } bool ast_dumper::visit_hash_expr(hash_expr* node) { - std::cout << "hash\n"; - std::cout << " -> " << node->get_location().file << ":" - << node->get_location().begin_line << ":" - << node->get_location().begin_column << "\n"; + dump_indent(); + std::cout << "hash"; + std::cout << format_location(node->get_location()); + push_indent(); for(auto i : node->get_members()) { + if (i==node->get_members().back()) { + set_last(); + } i->accept(this); } + pop_indent(); return true; } bool ast_dumper::visit_hash_pair(hash_pair* node) { - std::cout << "pair\n"; - std::cout << " -> " << node->get_location().file << ":" - << node->get_location().begin_line << ":" - << node->get_location().begin_column << "\n"; + dump_indent(); + std::cout << "pair " << node->get_name(); + std::cout << format_location(node->get_location()); if (node->get_value()) { + push_indent(); + set_last(); node->get_value()->accept(this); + pop_indent(); } return true; } bool ast_dumper::visit_function(function* node) { - std::cout << "function\n"; - std::cout << " -> " << node->get_location().file << ":" - << node->get_location().begin_line << ":" - << node->get_location().begin_column << "\n"; + dump_indent(); + std::cout << "function"; + std::cout << format_location(node->get_location()); + push_indent(); for(auto i : node->get_parameter_list()) { i->accept(this); } + set_last(); node->get_code_block()->accept(this); + pop_indent(); return true; } bool ast_dumper::visit_code_block(code_block* node) { - std::cout << "block\n"; - std::cout << " -> " << node->get_location().file << ":" - << node->get_location().begin_line << ":" - << node->get_location().begin_column << "\n"; + dump_indent(); + std::cout << "block"; + std::cout << format_location(node->get_location()); + push_indent(); for(auto i : node->get_expressions()) { + if (i==node->get_expressions().back()) { + set_last(); + } i->accept(this); } + pop_indent(); return true; } bool ast_dumper::visit_parameter(parameter* node) { - std::cout << "parameter\n"; - std::cout << " -> " << node->get_location().file << ":" - << node->get_location().begin_line << ":" - << node->get_location().begin_column << "\n"; + dump_indent(); + std::cout << "parameter"; + std::cout << format_location(node->get_location()); + push_indent(); + if (!node->get_default_value()) { + set_last(); + } node->get_parameter_name()->accept(this); if (node->get_default_value()) { + set_last(); node->get_default_value()->accept(this); } + pop_indent(); return true; } bool ast_dumper::visit_ternary_operator(ternary_operator* node) { - std::cout << "ternary\n"; - std::cout << " -> " << node->get_location().file << ":" - << node->get_location().begin_line << ":" - << node->get_location().begin_column << "\n"; + dump_indent(); + std::cout << "ternary"; + std::cout << format_location(node->get_location()); + push_indent(); node->get_condition()->accept(this); node->get_left()->accept(this); + set_last(); node->get_right()->accept(this); + pop_indent(); return true; } bool ast_dumper::visit_binary_operator(binary_operator* node) { - std::cout << "binary\n"; - std::cout << " -> " << node->get_location().file << ":" - << node->get_location().begin_line << ":" - << node->get_location().begin_column << "\n"; + dump_indent(); + std::cout << "binary"; + std::cout << format_location(node->get_location()); + push_indent(); node->get_left()->accept(this); + set_last(); node->get_right()->accept(this); + pop_indent(); return true; } bool ast_dumper::visit_unary_operator(unary_operator* node) { - std::cout << "unary\n"; - std::cout << " -> " << node->get_location().file << ":" - << node->get_location().begin_line << ":" - << node->get_location().begin_column << "\n"; + dump_indent(); + std::cout << "unary"; + std::cout << format_location(node->get_location()); + push_indent(); + set_last(); node->get_value()->accept(this); + pop_indent(); return true; } bool ast_dumper::visit_call_expr(call_expr* node) { - std::cout << "call_expr\n"; - std::cout << " -> " << node->get_location().file << ":" - << node->get_location().begin_line << ":" - << node->get_location().begin_column << "\n"; + dump_indent(); + std::cout << "call_expr"; + std::cout << format_location(node->get_location()); + push_indent(); + if (!node->get_calls().size()) { + set_last(); + } node->get_first()->accept(this); for(auto i : node->get_calls()) { + if (i==node->get_calls().back()) { + set_last(); + } i->accept(this); } + pop_indent(); return true; } bool ast_dumper::visit_call_hash(call_hash* node) { - std::cout << "call_hash\n"; - std::cout << " -> " << node->get_location().file << ":" - << node->get_location().begin_line << ":" - << node->get_location().begin_column << "\n"; + dump_indent(); + std::cout << "call_hash" << node->get_field(); + std::cout << format_location(node->get_location()); return true; } bool ast_dumper::visit_call_vector(call_vector* node) { - std::cout << "call_vector\n"; - std::cout << " -> " << node->get_location().file << ":" - << node->get_location().begin_line << ":" - << node->get_location().begin_column << "\n"; + dump_indent(); + std::cout << "call_vector"; + std::cout << format_location(node->get_location()); + push_indent(); for(auto i : node->get_slices()) { + if (i==node->get_slices().back()) { + set_last(); + } i->accept(this); } + pop_indent(); return true; } bool ast_dumper::visit_call_function(call_function* node) { - std::cout << "call_function\n"; - std::cout << " -> " << node->get_location().file << ":" - << node->get_location().begin_line << ":" - << node->get_location().begin_column << "\n"; + dump_indent(); + std::cout << "call_function"; + std::cout << format_location(node->get_location()); + push_indent(); for(auto i : node->get_argument()) { + if (i==node->get_argument().back()) { + set_last(); + } i->accept(this); } + pop_indent(); return true; } bool ast_dumper::visit_slice_vector(slice_vector* node) { - std::cout << "slice\n"; - std::cout << " -> " << node->get_location().file << ":" - << node->get_location().begin_line << ":" - << node->get_location().begin_column << "\n"; + dump_indent(); + std::cout << "slice"; + std::cout << format_location(node->get_location()); + push_indent(); + if (!node->get_end()) { + set_last(); + } node->get_begin()->accept(this); if (node->get_end()) { + set_last(); node->get_end()->accept(this); } + pop_indent(); return true; } bool ast_dumper::visit_definition_expr(definition_expr* node) { - std::cout << "definition\n"; - std::cout << " -> " << node->get_location().file << ":" - << node->get_location().begin_line << ":" - << node->get_location().begin_column << "\n"; + dump_indent(); + std::cout << "definition"; + std::cout << format_location(node->get_location()); + push_indent(); if (node->get_variable_name()) { node->get_variable_name()->accept(this); } else { node->get_variables()->accept(this); } + set_last(); node->get_value()->accept(this); + pop_indent(); return true; } bool ast_dumper::visit_assignment_expr(assignment_expr* node) { - std::cout << "assignment\n"; - std::cout << " -> " << node->get_location().file << ":" - << node->get_location().begin_line << ":" - << node->get_location().begin_column << "\n"; + dump_indent(); + std::cout << "assignment"; + std::cout << format_location(node->get_location()); + push_indent(); node->get_left()->accept(this); + set_last(); node->get_right()->accept(this); + pop_indent(); return true; } bool ast_dumper::visit_multi_identifier(multi_identifier* node) { - std::cout << "multi_define\n"; - std::cout << " -> " << node->get_location().file << ":" - << node->get_location().begin_line << ":" - << node->get_location().begin_column << "\n"; + dump_indent(); + std::cout << "multi_define"; + std::cout << format_location(node->get_location()); + push_indent(); for(auto i : node->get_variables()) { + if (i==node->get_variables().back()) { + set_last(); + } i->accept(this); } + pop_indent(); return true; } bool ast_dumper::visit_tuple_expr(tuple_expr* node) { - std::cout << "tuple\n"; - std::cout << " -> " << node->get_location().file << ":" - << node->get_location().begin_line << ":" - << node->get_location().begin_column << "\n"; + dump_indent(); + std::cout << "tuple"; + std::cout << format_location(node->get_location()); + push_indent(); for(auto i : node->get_elements()) { + if (i==node->get_elements().back()) { + set_last(); + } i->accept(this); } + pop_indent(); return true; } bool ast_dumper::visit_multi_assign(multi_assign* node) { - std::cout << "multi_assign\n"; - std::cout << " -> " << node->get_location().file << ":" - << node->get_location().begin_line << ":" - << node->get_location().begin_column << "\n"; + dump_indent(); + std::cout << "multi_assign"; + std::cout << format_location(node->get_location()); + push_indent(); node->get_tuple()->accept(this); + set_last(); node->get_value()->accept(this); + pop_indent(); return true; } bool ast_dumper::visit_while_expr(while_expr* node) { - std::cout << "while\n"; - std::cout << " -> " << node->get_location().file << ":" - << node->get_location().begin_line << ":" - << node->get_location().begin_column << "\n"; + dump_indent(); + std::cout << "while"; + std::cout << format_location(node->get_location()); + push_indent(); node->get_condition()->accept(this); + set_last(); node->get_code_block()->accept(this); + pop_indent(); return true; } bool ast_dumper::visit_for_expr(for_expr* node) { - std::cout << "for\n"; - std::cout << " -> " << node->get_location().file << ":" - << node->get_location().begin_line << ":" - << node->get_location().begin_column << "\n"; + dump_indent(); + std::cout << "for"; + std::cout << format_location(node->get_location()); + push_indent(); node->get_initial()->accept(this); node->get_condition()->accept(this); node->get_step()->accept(this); + set_last(); node->get_code_block()->accept(this); + pop_indent(); return true; } bool ast_dumper::visit_iter_expr(iter_expr* node) { - std::cout << "iter\n"; - std::cout << " -> " << node->get_location().file << ":" - << node->get_location().begin_line << ":" - << node->get_location().begin_column << "\n"; + dump_indent(); + std::cout << "iter"; + std::cout << format_location(node->get_location()); + push_indent(); + set_last(); if (node->get_name()) { node->get_name()->accept(this); } else { node->get_call()->accept(this); } + pop_indent(); return true; } bool ast_dumper::visit_forei_expr(forei_expr* node) { - std::cout << "forei\n"; - std::cout << " -> " << node->get_location().file << ":" - << node->get_location().begin_line << ":" - << node->get_location().begin_column << "\n"; + dump_indent(); + if (node->get_type()==forei_expr::forei_loop_type::foreach) { + std::cout << "foreach"; + } else { + std::cout << "forindex"; + } + std::cout << format_location(node->get_location()); + push_indent(); node->get_iterator()->accept(this); node->get_value()->accept(this); + set_last(); node->get_code_block()->accept(this); + pop_indent(); return true; } bool ast_dumper::visit_condition_expr(condition_expr* node) { - std::cout << "condition\n"; - std::cout << " -> " << node->get_location().file << ":" - << node->get_location().begin_line << ":" - << node->get_location().begin_column << "\n"; + dump_indent(); + std::cout << "condition"; + std::cout << format_location(node->get_location()); + push_indent(); + if (!node->get_elsif_stataments().size() && + !node->get_else_statement()) { + set_last(); + } node->get_if_statement()->accept(this); for(auto i : node->get_elsif_stataments()) { + if (i==node->get_elsif_stataments().back() && + !node->get_else_statement()) { + set_last(); + } i->accept(this); } if (node->get_else_statement()) { + set_last(); node->get_else_statement()->accept(this); } + pop_indent(); return true; } bool ast_dumper::visit_if_expr(if_expr* node) { - std::cout << "if\n"; - std::cout << " -> " << node->get_location().file << ":" - << node->get_location().begin_line << ":" - << node->get_location().begin_column << "\n"; + dump_indent(); + std::cout << "if"; + std::cout << format_location(node->get_location()); + push_indent(); if (node->get_condition()) { node->get_condition()->accept(this); } + set_last(); node->get_code_block()->accept(this); + pop_indent(); return true; } bool ast_dumper::visit_continue_expr(continue_expr* node) { - std::cout << "continue\n"; - std::cout << " -> " << node->get_location().file << ":" - << node->get_location().begin_line << ":" - << node->get_location().begin_column << "\n"; + dump_indent(); + std::cout << "continue"; + std::cout << format_location(node->get_location()); return true; } bool ast_dumper::visit_break_expr(break_expr* node) { - std::cout << "break\n"; - std::cout << " -> " << node->get_location().file << ":" - << node->get_location().begin_line << ":" - << node->get_location().begin_column << "\n"; + dump_indent(); + std::cout << "break"; + std::cout << format_location(node->get_location()); return true; } bool ast_dumper::visit_return_expr(return_expr* node) { - std::cout << "return\n"; - std::cout << " -> " << node->get_location().file << ":" - << node->get_location().begin_line << ":" - << node->get_location().begin_column << "\n"; + dump_indent(); + std::cout << "return"; + std::cout << format_location(node->get_location()); if (node->get_value()) { + push_indent(); + set_last(); node->get_value()->accept(this); + pop_indent(); } return true; } \ No newline at end of file diff --git a/ast/ast_dumper.h b/ast/ast_dumper.h index 4599537..e6fbb51 100644 --- a/ast/ast_dumper.h +++ b/ast/ast_dumper.h @@ -2,9 +2,44 @@ #include "ast_visitor.h" +#include +#include +#include + class ast_dumper:public ast_visitor { +private: + std::vector indent; + void push_indent() { + if (indent.size()) { + if (indent.back()=="|--") { + indent.back() = "| "; + } else if (indent.back()=="+--") { + indent.back() = " "; + } + // indent.back() = (indent.back()=="|--")? "| ":" "; + } + indent.push_back("|--"); + } + void pop_indent() {indent.pop_back();} + void set_last() {indent.back() = "+--";} + void dump_indent() { + if (indent.size() && indent.back()=="| ") { + indent.back() = "|--"; + } + for(const auto& i : indent) { + std::cout << i; + } + } + std::string format_location(const span& location) { + std::stringstream ss; + ss << " -> "; + ss << location.file << ":"; + ss << location.begin_line << ":" << location.begin_column; + ss << "\n"; + return ss.str(); + } + public: - bool visit_expr(expr*) override; bool visit_null_expr(null_expr*) override; bool visit_nil_expr(nil_expr*) override; bool visit_number_literal(number_literal*) override; diff --git a/ast/nasal_new_main.cpp b/ast/nasal_new_main.cpp index 3f473b8..6ba6175 100644 --- a/ast/nasal_new_main.cpp +++ b/ast/nasal_new_main.cpp @@ -51,7 +51,7 @@ std::ostream& logo(std::ostream& out) { <<" \\_\\ \\/ \\__,_|___/\\__,_|_|\n" <<"ver : "<<__nasver<<" ("<<__DATE__<<" "<<__TIME__<<")\n" <<"std : c++ "<<__cplusplus<<"\n" - <<"core : "<visit_expr(parse.tree()); + dumper->visit_code_block(parse.tree()); } // linker gets parser's ast and load import files to this ast diff --git a/ast/nasal_new_parse.cpp b/ast/nasal_new_parse.cpp index 00e3727..e175910 100644 --- a/ast/nasal_new_parse.cpp +++ b/ast/nasal_new_parse.cpp @@ -610,7 +610,7 @@ expr* parse::scalar() { } else if (lookahead(tok::lbrace)) { node = hash(); } else if (lookahead(tok::lcurve)) { - const auto& loc=toks[ptr].loc; + const auto& loc = toks[ptr].loc; match(tok::lcurve); node = calc(); node->set_begin(loc.begin_line, loc.begin_column); @@ -625,7 +625,7 @@ expr* parse::scalar() { node = def_node; } else { die(thisspan, "expected scalar"); - return node; + return null(); } // check call and avoid ambiguous syntax if (is_call(toks[ptr].type) && !(lookahead(tok::lcurve) && toks[ptr+1].type==tok::var)) { @@ -839,7 +839,10 @@ expr* parse::loop() { case tok::rfor: node = for_loop(); break; case tok::forindex: case tok::foreach: node = forei_loop(); break; - default: break; + default: + die(thisspan, "unreachable"); + node = null(); + break; } --in_loop; return node; diff --git a/main.cpp b/main.cpp index aef7268..084e28d 100644 --- a/main.cpp +++ b/main.cpp @@ -11,6 +11,7 @@ #include "nasal_vm.h" #include "nasal_dbg.h" +#include #include const u32 VM_AST =0x01; @@ -55,6 +56,7 @@ std::ostream& logo(std::ostream& out) { <<" \\_\\ \\/ \\__,_|___/\\__,_|_|\n" <<"ver : "<<__nasver<<" ("<<__DATE__<<" "<<__TIME__<<")\n" <<"std : c++ "<<__cplusplus<<"\n" + <<"core : "<