From e56ce20da1b6d8e50728cf54da0f3335f46cde70 Mon Sep 17 00:00:00 2001 From: Sh0g0-1758 Date: Tue, 18 Feb 2025 00:10:01 +0530 Subject: [PATCH 1/8] the parser battle begins --- CMakeLists.txt | 2 +- ast/ast.hh | 16 ++++++- codegen/codegen.cc | 14 ++---- driver/driver.cc | 27 ++++------- parser/parser.cc | 111 +++++++++++++++++++++++++++++++++++++-------- parser/parser.hh | 37 +++++++++++++-- 6 files changed, 152 insertions(+), 55 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index a019ad8..d0e3dfe 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -79,7 +79,7 @@ target_compile_options(scarlet PRIVATE -O3) add_custom_target(test-scarlet DEPENDS scarlet COMMAND echo "Running lexer test" - COMMAND ${CMAKE_SOURCE_DIR}/test_compiler ./scarlet --chapter 7 --stage lex + COMMAND ${CMAKE_SOURCE_DIR}/test_compiler ./scarlet --chapter 8 --stage lex COMMAND echo "Running parser test" COMMAND ${CMAKE_SOURCE_DIR}/test_compiler ./scarlet --chapter 7 --stage parse COMMAND echo "Running semantic analysis test" diff --git a/ast/ast.hh b/ast/ast.hh index f695bb2..7884723 100644 --- a/ast/ast.hh +++ b/ast/ast.hh @@ -18,7 +18,8 @@ Grammar: ::= | ::= "{" { } "}" ::= "int" [ "=" ] ";" - ::= "return" ";" | ";" | ";" | "if" "(" ")" [ "else" ] | "goto" ";" | ":" | + ::= | [ ] + ::= "return" ";" | ";" | ";" | "if" "(" ")" [ "else" ] | "goto" ";" | ":" | | "break" ";" | "continue" ";" | "while" "(" ")" | "for" "(" ";" [ ] ";" [ ] ")" | "do" "while" "(" ")" ";" ::= | | "?" ":" ::= | | | "(" ")" ::= "~" | "-" | "!" | "--" | "++" @@ -192,7 +193,12 @@ enum class statementType { _IFELSE_END, GOTO, LABEL, - BLOCK + BLOCK, + BREAK, + CONTINUE, + WHILE, + FOR, + DO_WHILE }; class AST_Statement_Node { @@ -200,6 +206,7 @@ private: std::shared_ptr exps; statementType type; std::shared_ptr block; + std::shared_ptr label; public: std::string get_AST_name() { return "Statement"; } @@ -215,6 +222,11 @@ public: void set_block(std::shared_ptr block) { this->block = std::move(block); } + + std::shared_ptr get_label() { return label; } + void set_label(std::shared_ptr label) { + this->label = std::move(label); + } }; enum class DeclarationType { INT }; diff --git a/codegen/codegen.cc b/codegen/codegen.cc index fd5f365..e2b039e 100644 --- a/codegen/codegen.cc +++ b/codegen/codegen.cc @@ -556,11 +556,8 @@ void Codegen::gen_scar_block( scar_instruction->set_type(scar::instruction_type::JUMP); MAKE_SHARED(scar::scar_Val_Node, scar_val_src); scar_val_src->set_type(scar::val_type::UNKNOWN); - scar_val_src->set_value(inst->get_statement() - ->get_exps() - ->get_factor_node() - ->get_identifier_node() - ->get_value()); + scar_val_src->set_value( + inst->get_statement()->get_label()->get_value()); scar_instruction->set_src1(std::move(scar_val_src)); scar_function->add_instruction(scar_instruction); } else if (inst->get_statement()->get_type() == @@ -569,11 +566,8 @@ void Codegen::gen_scar_block( scar_instruction->set_type(scar::instruction_type::LABEL); MAKE_SHARED(scar::scar_Val_Node, scar_val_src); scar_val_src->set_type(scar::val_type::UNKNOWN); - scar_val_src->set_value(inst->get_statement() - ->get_exps() - ->get_factor_node() - ->get_identifier_node() - ->get_value()); + scar_val_src->set_value( + inst->get_statement()->get_label()->get_value()); scar_instruction->set_src1(std::move(scar_val_src)); scar_function->add_instruction(scar_instruction); } else if (inst->get_statement()->get_type() == diff --git a/driver/driver.cc b/driver/driver.cc index 89980c8..3088534 100644 --- a/driver/driver.cc +++ b/driver/driver.cc @@ -61,16 +61,18 @@ int main(int argc, char *argv[]) { scarlet::lexer::lexer lex; lex.set_file_path(std::format("{}.scp", file_name)); lex.tokenize(); + + // delete the intermediate preprocessed file + result = system(std::format("rm {}.scp", file_name).c_str()); + + if (result != 0) { + std::cerr << "[ERROR]: Unable to delete the intermediate preprocessed file" + << std::endl; + return 1; + } + if (!lex.is_success()) { lex.print_error_recovery(); - result = system(std::format("rm {}.scp", file_name).c_str()); - - if (result != 0) { - std::cerr - << "[ERROR]: Unable to delete the intermediate preprocessed file" - << std::endl; - return 1; - } return 1; } @@ -80,15 +82,6 @@ int main(int argc, char *argv[]) { return 0; } - // delete the intermediate preprocessed file - result = system(std::format("rm {}.scp", file_name).c_str()); - - if (result != 0) { - std::cerr << "[ERROR]: Unable to delete the intermediate preprocessed file" - << std::endl; - return 1; - } - // PARSER scarlet::parser::parser gnu; gnu.parse_program(lex.get_tokens()); diff --git a/parser/parser.cc b/parser/parser.cc index 18dd50b..93c8db5 100644 --- a/parser/parser.cc +++ b/parser/parser.cc @@ -215,11 +215,7 @@ void parser::parse_statement(std::vector &tokens, tokens.erase(tokens.begin()); statement->set_type(ast::statementType::GOTO); EXPECT_IDENTIFIER(); - MAKE_SHARED(ast::AST_exp_Node, exp); - MAKE_SHARED(ast::AST_factor_Node, factor); - factor->set_identifier_node(std::move(identifier)); - exp->set_factor_node(std::move(factor)); - statement->set_exp(std::move(exp)); + statement->set_label(std::move(identifier)); EXPECT(token::TOKEN::SEMICOLON); block_item->set_statement(std::move(statement)); block->add_blockItem(std::move(block_item)); @@ -228,11 +224,7 @@ void parser::parse_statement(std::vector &tokens, tokens[1].get_token() == token::TOKEN::COLON) { statement->set_type(ast::statementType::LABEL); EXPECT_IDENTIFIER(); - MAKE_SHARED(ast::AST_exp_Node, exp); - MAKE_SHARED(ast::AST_factor_Node, factor); - factor->set_identifier_node(std::move(identifier)); - exp->set_factor_node(std::move(factor)); - statement->set_exp(std::move(exp)); + statement->set_label(std::move(identifier)); EXPECT(token::TOKEN::COLON); block_item->set_statement(std::move(statement)); block->add_blockItem(std::move(block_item)); @@ -243,6 +235,81 @@ void parser::parse_statement(std::vector &tokens, statement->set_block(std::move(block_node)); block_item->set_statement(std::move(statement)); block->add_blockItem(std::move(block_item)); + } else if (tokens[0].get_token() == token::TOKEN::WHILE) { + statement->set_type(ast::statementType::WHILE); + MAKE_SHARED(ast::AST_identifier_Node, start_label); + MAKE_SHARED(ast::AST_identifier_Node, end_label); + start_label->set_identifier(get_loop_start_label()); + end_label->set_identifier(get_loop_end_label()); + statement->set_label(std::move(start_label)); + tokens.erase(tokens.begin()); + EXPECT(token::TOKEN::OPEN_PARANTHESES); + MAKE_SHARED(ast::AST_exp_Node, exp); + parse_exp(tokens, exp); + statement->set_exp(std::move(exp)); + EXPECT(token::TOKEN::CLOSE_PARANTHESES); + block_item->set_statement(std::move(statement)); + block->add_blockItem(std::move(block_item)); + parse_statement(tokens, block); + + // add the end label + MAKE_SHARED(ast::AST_Block_Item_Node, block_item2); + block_item2->set_type(ast::BlockItemType::STATEMENT); + MAKE_SHARED(ast::AST_Statement_Node, statement2); + statement2->set_type(ast::statementType::LABEL); + statement2->set_label(std::move(end_label)); + block_item2->set_statement(std::move(statement2)); + block->add_blockItem(std::move(block_item2)); + + remove_loop_start_label(); + remove_loop_end_label(); + } else if (tokens[0].get_token() == token::TOKEN::CONTINUE) { + statement->set_type(ast::statementType::CONTINUE); + MAKE_SHARED(ast::AST_identifier_Node, label); + label->set_identifier(get_prev_loop_start_label()); + statement->set_label(std::move(label)); + tokens.erase(tokens.begin()); + EXPECT(token::TOKEN::SEMICOLON); + block_item->set_statement(std::move(statement)); + block->add_blockItem(std::move(block_item)); + } else if (tokens[0].get_token() == token::TOKEN::BREAK) { + // set label + statement->set_type(ast::statementType::BREAK); + MAKE_SHARED(ast::AST_identifier_Node, label); + label->set_identifier(get_prev_loop_end_label()); + statement->set_label(std::move(label)); + tokens.erase(tokens.begin()); + EXPECT(token::TOKEN::SEMICOLON); + block_item->set_statement(std::move(statement)); + block->add_blockItem(std::move(block_item)); + } else if (tokens[0].get_token() == token::TOKEN::DO) { + tokens.erase(tokens.begin()); + statement->set_type(ast::statementType::DO_WHILE); + MAKE_SHARED(ast::AST_identifier_Node, start_label); + MAKE_SHARED(ast::AST_identifier_Node, end_label); + start_label->set_identifier(get_loop_start_label()); + end_label->set_identifier(get_loop_end_label()); + statement->set_label(std::move(start_label)); + EXPECT(token::TOKEN::OPEN_BRACE); + parse_statement(tokens, block); + EXPECT(token::TOKEN::CLOSE_BRACE); + EXPECT(token::TOKEN::WHILE); + EXPECT(token::TOKEN::OPEN_PARANTHESES); + MAKE_SHARED(ast::AST_exp_Node, exp); + parse_exp(tokens, exp); + statement->set_exp(std::move(exp)); + EXPECT(token::TOKEN::CLOSE_PARANTHESES); + EXPECT(token::TOKEN::SEMICOLON); + block_item->set_statement(std::move(statement)); + block->add_blockItem(std::move(block_item)); + } else if (tokens[0].get_token() == token::TOKEN::FOR) { + tokens.erase(tokens.begin()); + statement->set_type(ast::statementType::FOR); + MAKE_SHARED(ast::AST_identifier_Node, start_label); + MAKE_SHARED(ast::AST_identifier_Node, end_label); + start_label->set_identifier(get_loop_start_label()); + end_label->set_identifier(get_loop_end_label()); + statement->set_label(std::move(start_label)); } else { statement->set_type(ast::statementType::EXP); MAKE_SHARED(ast::AST_exp_Node, exp); @@ -653,11 +720,8 @@ void parser::analyze_block( // actually declared and we also need to make sure that there are no // duplicate labels if (blockItem->get_statement()->get_type() == ast::statementType::GOTO) { - std::string label = blockItem->get_statement() - ->get_exps() - ->get_factor_node() - ->get_identifier_node() - ->get_value(); + std::string label = + blockItem->get_statement()->get_label()->get_value(); if (goto_labels.find(label) == goto_labels.end()) { goto_labels[label] = false; } @@ -665,11 +729,8 @@ void parser::analyze_block( } if (blockItem->get_statement()->get_type() == ast::statementType::LABEL) { - std::string label = blockItem->get_statement() - ->get_exps() - ->get_factor_node() - ->get_identifier_node() - ->get_value(); + std::string label = + blockItem->get_statement()->get_label()->get_value(); if (goto_labels.find(label) != goto_labels.end()) { if (goto_labels[label] == false) { goto_labels[label] = true; @@ -755,6 +816,16 @@ std::string to_string(ast::statementType type) { return "Label"; case ast::statementType::BLOCK: return "Block"; + case ast::statementType::CONTINUE: + return "Continue"; + case ast::statementType::BREAK: + return "Break"; + case ast::statementType::WHILE: + return "While"; + case ast::statementType::DO_WHILE: + return "DoWhile"; + case ast::statementType::FOR: + return "For"; case ast::statementType::UNKNOWN: UNREACHABLE() } diff --git a/parser/parser.hh b/parser/parser.hh index 57c1bf6..ab0205f 100644 --- a/parser/parser.hh +++ b/parser/parser.hh @@ -4,6 +4,7 @@ #include #include #include +#include #include #include #include @@ -17,6 +18,10 @@ private: int symbol_counter = 0; std::map goto_labels; ast::AST_Program_Node program; + int loop_start_counter = 0; + int loop_end_counter = 0; + std::stack loop_start_labels; + std::stack loop_end_labels; std::shared_ptr parse_function(std::vector &tokens); void parse_block(std::vector &tokens, @@ -44,11 +49,6 @@ private: void pretty_print_exp(std::shared_ptr exp); void pretty_print_factor(std::shared_ptr factor); void pretty_print_block(std::shared_ptr block); - std::string get_temp_name(std::string &name) { - std::string tmp = name + "." + std::to_string(symbol_counter); - symbol_counter++; - return tmp; - } void analyze_exp(std::shared_ptr exp, std::map, std::string> &symbol_table, @@ -58,6 +58,33 @@ private: std::map, std::string> &symbol_table, int indx); + std::string get_temp_name(std::string &name) { + std::string tmp = name + "." + std::to_string(symbol_counter); + symbol_counter++; + return tmp; + } + + std::string get_loop_start_label() { + std::string label = "loopStart." + std::to_string(loop_start_counter); + loop_start_counter++; + loop_start_labels.push(label); + return label; + } + + std::string get_loop_end_label() { + std::string label = "loopEnd." + std::to_string(loop_end_counter); + loop_end_counter++; + loop_end_labels.push(label); + return label; + } + + std::string get_prev_loop_start_label() { return loop_start_labels.top(); } + + std::string get_prev_loop_end_label() { return loop_end_labels.top(); } + + void remove_loop_start_label() { loop_start_labels.pop(); } + void remove_loop_end_label() { loop_end_labels.pop(); } + public: void parse_program(std::vector tokens); void semantic_analysis(); From d02b64301510b1bbea15db615daadf8740bbe663 Mon Sep 17 00:00:00 2001 From: Sh0g0-1758 Date: Wed, 19 Feb 2025 00:25:24 +0530 Subject: [PATCH 2/8] parser battle has some sunshine --- ast/ast.hh | 52 ++++++++++++++++++-- codegen/codegen.cc | 4 +- parser/parser.cc | 117 ++++++++++++++++++++++++++++++++++++++------- parser/parser.hh | 2 + 4 files changed, 152 insertions(+), 23 deletions(-) diff --git a/ast/ast.hh b/ast/ast.hh index 7884723..f1c59ba 100644 --- a/ast/ast.hh +++ b/ast/ast.hh @@ -206,7 +206,9 @@ private: std::shared_ptr exps; statementType type; std::shared_ptr block; - std::shared_ptr label; + std::pair, + std::shared_ptr> + labels; public: std::string get_AST_name() { return "Statement"; } @@ -223,9 +225,15 @@ public: this->block = std::move(block); } - std::shared_ptr get_label() { return label; } - void set_label(std::shared_ptr label) { - this->label = std::move(label); + std::pair, + std::shared_ptr> + get_labels() { + return labels; + } + void set_labels(std::pair, + std::shared_ptr> + labels) { + this->labels = std::move(labels); } }; @@ -256,6 +264,42 @@ public: } }; +class AST_For_Init_Node { +private: + std::shared_ptr declaration; + std::shared_ptr exp; + +public: + std::string get_AST_name() { return "ForInit"; } + std::shared_ptr get_declaration() { + return declaration; + } + void set_declaration(std::shared_ptr declaration) { + this->declaration = std::move(declaration); + } + std::shared_ptr get_exp() { return exp; } + void set_exp(std::shared_ptr exp) { + this->exp = std::move(exp); + } +}; + +class AST_For_Statement_Node : public AST_Statement_Node { +private: + std::shared_ptr for_init; + std::shared_ptr exp2; + +public: + std::string get_AST_name() { return "ForStatement"; } + std::shared_ptr get_for_init() { return for_init; } + void set_for_init(std::shared_ptr for_init) { + this->for_init = std::move(for_init); + } + std::shared_ptr get_exp2() { return exp2; } + void set_exp2(std::shared_ptr exp2) { + this->exp2 = std::move(exp2); + } +}; + enum class BlockItemType { UNKNOWN, STATEMENT, DECLARATION }; // Right now, we determine whether a block item is a statement or a declaration diff --git a/codegen/codegen.cc b/codegen/codegen.cc index e2b039e..af327a8 100644 --- a/codegen/codegen.cc +++ b/codegen/codegen.cc @@ -557,7 +557,7 @@ void Codegen::gen_scar_block( MAKE_SHARED(scar::scar_Val_Node, scar_val_src); scar_val_src->set_type(scar::val_type::UNKNOWN); scar_val_src->set_value( - inst->get_statement()->get_label()->get_value()); + inst->get_statement()->get_labels().first->get_value()); scar_instruction->set_src1(std::move(scar_val_src)); scar_function->add_instruction(scar_instruction); } else if (inst->get_statement()->get_type() == @@ -567,7 +567,7 @@ void Codegen::gen_scar_block( MAKE_SHARED(scar::scar_Val_Node, scar_val_src); scar_val_src->set_type(scar::val_type::UNKNOWN); scar_val_src->set_value( - inst->get_statement()->get_label()->get_value()); + inst->get_statement()->get_labels().first->get_value()); scar_instruction->set_src1(std::move(scar_val_src)); scar_function->add_instruction(scar_instruction); } else if (inst->get_statement()->get_type() == diff --git a/parser/parser.cc b/parser/parser.cc index e304b17..bf30af6 100644 --- a/parser/parser.cc +++ b/parser/parser.cc @@ -215,7 +215,7 @@ void parser::parse_statement(std::vector &tokens, tokens.erase(tokens.begin()); statement->set_type(ast::statementType::GOTO); EXPECT_IDENTIFIER(); - statement->set_label(std::move(identifier)); + statement->set_labels({std::move(identifier), nullptr}); EXPECT(token::TOKEN::SEMICOLON); block_item->set_statement(std::move(statement)); block->add_blockItem(std::move(block_item)); @@ -224,7 +224,7 @@ void parser::parse_statement(std::vector &tokens, tokens[1].get_token() == token::TOKEN::COLON) { statement->set_type(ast::statementType::LABEL); EXPECT_IDENTIFIER(); - statement->set_label(std::move(identifier)); + statement->set_labels({std::move(identifier), nullptr}); EXPECT(token::TOKEN::COLON); block_item->set_statement(std::move(statement)); block->add_blockItem(std::move(block_item)); @@ -241,7 +241,7 @@ void parser::parse_statement(std::vector &tokens, MAKE_SHARED(ast::AST_identifier_Node, end_label); start_label->set_identifier(get_loop_start_label()); end_label->set_identifier(get_loop_end_label()); - statement->set_label(std::move(start_label)); + statement->set_labels({std::move(start_label), end_label}); tokens.erase(tokens.begin()); EXPECT(token::TOKEN::OPEN_PARANTHESES); MAKE_SHARED(ast::AST_exp_Node, exp); @@ -252,12 +252,12 @@ void parser::parse_statement(std::vector &tokens, block->add_blockItem(std::move(block_item)); parse_statement(tokens, block); - // add the end label + // make the end label MAKE_SHARED(ast::AST_Block_Item_Node, block_item2); block_item2->set_type(ast::BlockItemType::STATEMENT); MAKE_SHARED(ast::AST_Statement_Node, statement2); statement2->set_type(ast::statementType::LABEL); - statement2->set_label(std::move(end_label)); + statement2->set_labels({std::move(end_label), nullptr}); block_item2->set_statement(std::move(statement2)); block->add_blockItem(std::move(block_item2)); @@ -267,49 +267,103 @@ void parser::parse_statement(std::vector &tokens, statement->set_type(ast::statementType::CONTINUE); MAKE_SHARED(ast::AST_identifier_Node, label); label->set_identifier(get_prev_loop_start_label()); - statement->set_label(std::move(label)); + statement->set_labels({std::move(label), nullptr}); tokens.erase(tokens.begin()); EXPECT(token::TOKEN::SEMICOLON); block_item->set_statement(std::move(statement)); block->add_blockItem(std::move(block_item)); } else if (tokens[0].get_token() == token::TOKEN::BREAK) { - // set label statement->set_type(ast::statementType::BREAK); MAKE_SHARED(ast::AST_identifier_Node, label); label->set_identifier(get_prev_loop_end_label()); - statement->set_label(std::move(label)); + statement->set_labels({std::move(label), nullptr}); tokens.erase(tokens.begin()); EXPECT(token::TOKEN::SEMICOLON); block_item->set_statement(std::move(statement)); block->add_blockItem(std::move(block_item)); } else if (tokens[0].get_token() == token::TOKEN::DO) { tokens.erase(tokens.begin()); - statement->set_type(ast::statementType::DO_WHILE); MAKE_SHARED(ast::AST_identifier_Node, start_label); MAKE_SHARED(ast::AST_identifier_Node, end_label); start_label->set_identifier(get_loop_start_label()); end_label->set_identifier(get_loop_end_label()); - statement->set_label(std::move(start_label)); - EXPECT(token::TOKEN::OPEN_BRACE); + + // make the start label + MAKE_SHARED(ast::AST_Block_Item_Node, block_item2); + block_item2->set_type(ast::BlockItemType::STATEMENT); + MAKE_SHARED(ast::AST_Statement_Node, statement2); + statement2->set_type(ast::statementType::LABEL); + statement2->set_labels({start_label, nullptr}); + block_item2->set_statement(std::move(statement2)); + block->add_blockItem(std::move(block_item2)); + + statement->set_labels({std::move(start_label), std::move(end_label)}); + parse_statement(tokens, block); - EXPECT(token::TOKEN::CLOSE_BRACE); + EXPECT(token::TOKEN::WHILE); EXPECT(token::TOKEN::OPEN_PARANTHESES); MAKE_SHARED(ast::AST_exp_Node, exp); parse_exp(tokens, exp); - statement->set_exp(std::move(exp)); EXPECT(token::TOKEN::CLOSE_PARANTHESES); EXPECT(token::TOKEN::SEMICOLON); + statement->set_exp(std::move(exp)); + statement->set_type(ast::statementType::DO_WHILE); block_item->set_statement(std::move(statement)); block->add_blockItem(std::move(block_item)); + + remove_loop_start_label(); + remove_loop_end_label(); } else if (tokens[0].get_token() == token::TOKEN::FOR) { + // For statement has additional constructs, so we use a + // child class AST_For_Statement_Node to represent it. + // We will use the power of down and upcasting to handle this. + // for ( ; ; ) tokens.erase(tokens.begin()); - statement->set_type(ast::statementType::FOR); + EXPECT(token::TOKEN::OPEN_PARANTHESES); + + MAKE_SHARED(ast::AST_For_Statement_Node, for_statement); + parse_for_init(tokens, for_statement); + + EXPECT(token::TOKEN::SEMICOLON); + + MAKE_SHARED(ast::AST_exp_Node, exp); + parse_exp(tokens, exp); + for_statement->set_exp(std::move(exp)); + + EXPECT(token::TOKEN::SEMICOLON); + + MAKE_SHARED(ast::AST_exp_Node, exp2); + parse_exp(tokens, exp2); + for_statement->set_exp2(std::move(exp2)); + + EXPECT(token::TOKEN::CLOSE_PARANTHESES); + MAKE_SHARED(ast::AST_identifier_Node, start_label); MAKE_SHARED(ast::AST_identifier_Node, end_label); start_label->set_identifier(get_loop_start_label()); end_label->set_identifier(get_loop_end_label()); - statement->set_label(std::move(start_label)); + + for_statement->set_labels({std::move(start_label), end_label}); + + statement = + std::dynamic_pointer_cast(for_statement); + block_item->set_statement(std::move(statement)); + block->add_blockItem(std::move(block_item)); + + parse_statement(tokens, block); + + // make the end label + MAKE_SHARED(ast::AST_Block_Item_Node, block_item2); + block_item2->set_type(ast::BlockItemType::STATEMENT); + MAKE_SHARED(ast::AST_Statement_Node, statement2); + statement2->set_type(ast::statementType::LABEL); + statement2->set_labels({std::move(end_label), nullptr}); + block_item2->set_statement(std::move(statement2)); + block->add_blockItem(std::move(block_item2)); + + remove_loop_start_label(); + remove_loop_end_label(); } else { statement->set_type(ast::statementType::EXP); MAKE_SHARED(ast::AST_exp_Node, exp); @@ -321,6 +375,35 @@ void parser::parse_statement(std::vector &tokens, } } +void parser::parse_for_init( + std::vector &tokens, + std::shared_ptr forstmt) { + MAKE_SHARED(ast::AST_For_Init_Node, for_init); + if (tokens[0].get_token() == token::TOKEN::INT) { + tokens.erase(tokens.begin()); + EXPECT_IDENTIFIER(); + MAKE_SHARED(ast::AST_Declaration_Node, declaration); + declaration->set_identifier(std::move(identifier)); + if (tokens[0].get_token() == token::TOKEN::SEMICOLON) { + // the variable just have a declaration + tokens.erase(tokens.begin()); + } else { + // the variable has a definition as well + EXPECT(token::TOKEN::ASSIGNMENT); + MAKE_SHARED(ast::AST_exp_Node, exp); + parse_exp(tokens, exp); + declaration->set_exp(std::move(exp)); + EXPECT(token::TOKEN::SEMICOLON); + } + for_init->set_declaration(std::move(declaration)); + } else { + MAKE_SHARED(ast::AST_exp_Node, exp); + parse_exp(tokens, exp); + for_init->set_exp(std::move(exp)); + } + forstmt->set_for_init(std::move(for_init)); +} + std::pair parser::is_single_identifier_parentheses(std::vector &tokens) { int i = 0; @@ -776,7 +859,7 @@ void parser::analyze_block( // duplicate labels if (blockItem->get_statement()->get_type() == ast::statementType::GOTO) { std::string label = - blockItem->get_statement()->get_label()->get_value(); + blockItem->get_statement()->get_labels().first->get_value(); if (goto_labels.find(label) == goto_labels.end()) { goto_labels[label] = false; } @@ -785,7 +868,7 @@ void parser::analyze_block( if (blockItem->get_statement()->get_type() == ast::statementType::LABEL) { std::string label = - blockItem->get_statement()->get_label()->get_value(); + blockItem->get_statement()->get_labels().first->get_value(); if (goto_labels.find(label) != goto_labels.end()) { if (goto_labels[label] == false) { goto_labels[label] = true; diff --git a/parser/parser.hh b/parser/parser.hh index f2d5fc9..0532fee 100644 --- a/parser/parser.hh +++ b/parser/parser.hh @@ -32,6 +32,8 @@ private: std::shared_ptr function); void parse_statement(std::vector &tokens, std::shared_ptr function); + void parse_for_init(std::vector &tokens, + std::shared_ptr forstmt); void parse_factor(std::vector &tokens, std::shared_ptr factor); void parse_exp(std::vector &tokens, From 4ba945606bb93983f770d13ffa0ab83af0693c09 Mon Sep 17 00:00:00 2001 From: Sh0g0-1758 Date: Wed, 19 Feb 2025 02:24:13 +0530 Subject: [PATCH 3/8] done with parser --- CMakeLists.txt | 2 +- parser/parser.cc | 152 +++++++++++++++--- parser/parser.hh | 14 +- .../break_not_in_loop.c | 0 .../continue_not_in_loop.c | 0 5 files changed, 141 insertions(+), 27 deletions(-) rename tests/chapter_8/{invalid_semantics => invalid_parse}/break_not_in_loop.c (100%) rename tests/chapter_8/{invalid_semantics => invalid_parse}/continue_not_in_loop.c (100%) diff --git a/CMakeLists.txt b/CMakeLists.txt index d0e3dfe..7fb255a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -81,7 +81,7 @@ add_custom_target(test-scarlet COMMAND echo "Running lexer test" COMMAND ${CMAKE_SOURCE_DIR}/test_compiler ./scarlet --chapter 8 --stage lex COMMAND echo "Running parser test" - COMMAND ${CMAKE_SOURCE_DIR}/test_compiler ./scarlet --chapter 7 --stage parse + COMMAND ${CMAKE_SOURCE_DIR}/test_compiler ./scarlet --chapter 8 --stage parse COMMAND echo "Running semantic analysis test" COMMAND ${CMAKE_SOURCE_DIR}/test_compiler ./scarlet --chapter 7 --stage validate COMMAND echo "Running scar test" diff --git a/parser/parser.cc b/parser/parser.cc index bf30af6..f7166e9 100644 --- a/parser/parser.cc +++ b/parser/parser.cc @@ -266,21 +266,37 @@ void parser::parse_statement(std::vector &tokens, } else if (tokens[0].get_token() == token::TOKEN::CONTINUE) { statement->set_type(ast::statementType::CONTINUE); MAKE_SHARED(ast::AST_identifier_Node, label); - label->set_identifier(get_prev_loop_start_label()); - statement->set_labels({std::move(label), nullptr}); - tokens.erase(tokens.begin()); - EXPECT(token::TOKEN::SEMICOLON); - block_item->set_statement(std::move(statement)); - block->add_blockItem(std::move(block_item)); + auto [lbl, res] = get_prev_loop_start_label(); + if (!res) { + tokens.erase(tokens.begin()); + error_messages.emplace_back( + "Continue statement found outside of a loop construct"); + success = false; + } else { + label->set_identifier(lbl); + statement->set_labels({std::move(label), nullptr}); + tokens.erase(tokens.begin()); + EXPECT(token::TOKEN::SEMICOLON); + block_item->set_statement(std::move(statement)); + block->add_blockItem(std::move(block_item)); + } } else if (tokens[0].get_token() == token::TOKEN::BREAK) { statement->set_type(ast::statementType::BREAK); MAKE_SHARED(ast::AST_identifier_Node, label); - label->set_identifier(get_prev_loop_end_label()); - statement->set_labels({std::move(label), nullptr}); - tokens.erase(tokens.begin()); - EXPECT(token::TOKEN::SEMICOLON); - block_item->set_statement(std::move(statement)); - block->add_blockItem(std::move(block_item)); + auto [lbl, res] = get_prev_loop_end_label(); + if (!res) { + tokens.erase(tokens.begin()); + error_messages.emplace_back( + "Break statement found outside of a loop construct"); + success = false; + } else { + label->set_identifier(lbl); + statement->set_labels({std::move(label), nullptr}); + tokens.erase(tokens.begin()); + EXPECT(token::TOKEN::SEMICOLON); + block_item->set_statement(std::move(statement)); + block->add_blockItem(std::move(block_item)); + } } else if (tokens[0].get_token() == token::TOKEN::DO) { tokens.erase(tokens.begin()); MAKE_SHARED(ast::AST_identifier_Node, start_label); @@ -323,19 +339,29 @@ void parser::parse_statement(std::vector &tokens, EXPECT(token::TOKEN::OPEN_PARANTHESES); MAKE_SHARED(ast::AST_For_Statement_Node, for_statement); - parse_for_init(tokens, for_statement); + for_statement->set_type(ast::statementType::FOR); + if (tokens[0].get_token() != token::TOKEN::SEMICOLON) + parse_for_init(tokens, for_statement); EXPECT(token::TOKEN::SEMICOLON); - MAKE_SHARED(ast::AST_exp_Node, exp); - parse_exp(tokens, exp); - for_statement->set_exp(std::move(exp)); + if (tokens[0].get_token() != token::TOKEN::SEMICOLON) { + MAKE_SHARED(ast::AST_exp_Node, exp); + parse_exp(tokens, exp); + for_statement->set_exp(std::move(exp)); + } else { + for_statement->set_exp(nullptr); + } EXPECT(token::TOKEN::SEMICOLON); - MAKE_SHARED(ast::AST_exp_Node, exp2); - parse_exp(tokens, exp2); - for_statement->set_exp2(std::move(exp2)); + if (tokens[0].get_token() != token::TOKEN::CLOSE_PARANTHESES) { + MAKE_SHARED(ast::AST_exp_Node, exp2); + parse_exp(tokens, exp2); + for_statement->set_exp2(std::move(exp2)); + } else { + for_statement->set_exp2(nullptr); + } EXPECT(token::TOKEN::CLOSE_PARANTHESES); @@ -347,7 +373,7 @@ void parser::parse_statement(std::vector &tokens, for_statement->set_labels({std::move(start_label), end_label}); statement = - std::dynamic_pointer_cast(for_statement); + std::static_pointer_cast(for_statement); block_item->set_statement(std::move(statement)); block->add_blockItem(std::move(block_item)); @@ -393,7 +419,6 @@ void parser::parse_for_init( MAKE_SHARED(ast::AST_exp_Node, exp); parse_exp(tokens, exp); declaration->set_exp(std::move(exp)); - EXPECT(token::TOKEN::SEMICOLON); } for_init->set_declaration(std::move(declaration)); } else { @@ -881,6 +906,24 @@ void parser::analyze_block( } continue; } + // downcast for loop statement + if (blockItem->get_statement()->get_type() == ast::statementType::FOR) { + auto forstmt = std::static_pointer_cast( + blockItem->get_statement()); + std::map, std::string> proxy_symbol_table( + symbol_table); + if (forstmt->get_for_init()->get_declaration() != nullptr) { + analyze_exp(forstmt->get_for_init()->get_declaration()->get_exp(), + proxy_symbol_table, indx); + } + if (forstmt->get_exps() != nullptr) { + analyze_exp(forstmt->get_exps(), proxy_symbol_table, indx); + } + if (forstmt->get_exp2() != nullptr) { + analyze_exp(forstmt->get_exp2(), proxy_symbol_table, indx); + } + continue; + } if (blockItem->get_statement()->get_exps() != nullptr) { analyze_exp(blockItem->get_statement()->get_exps(), symbol_table, indx); } @@ -1040,12 +1083,73 @@ void parser::pretty_print_block(std::shared_ptr block) { std::cout << "\t\t\t\t\ttype=" << to_string(blockItem->get_statement()->get_type()) << "," << std::endl; + if (blockItem->get_statement()->get_type() == ast::statementType::FOR) { + std::shared_ptr forstmt = + std::static_pointer_cast( + blockItem->get_statement()); + std::cout << "\t\t\t\t\tlabels=(" + << forstmt->get_labels().first->get_value() << "," + << forstmt->get_labels().second->get_value() << ")," + << std::endl; + std::cout << "\t\t\t\t\tfor_init=(" << std::endl; + if (forstmt->get_for_init() != nullptr) { + if (forstmt->get_for_init()->get_declaration() != nullptr) { + std::cout << "\t\t\t\t\t\tDeclaration=(" << std::endl; + std::cout << "\t\t\t\t\t\t\tidentifier=\"" + << forstmt->get_for_init() + ->get_declaration() + ->get_identifier() + ->get_value() + << "\"," << std::endl; + if (forstmt->get_for_init()->get_declaration()->get_exp() != + nullptr) { + std::cout << "\t\t\t\t\t\t\texp=(" << std::endl; + pretty_print_exp( + forstmt->get_for_init()->get_declaration()->get_exp()); + std::cout << "\t\t\t\t\t\t\t)," << std::endl; + } + std::cout << "\t\t\t\t\t\t)," << std::endl; + } else { + std::cout << "\t\t\t\t\t\texp=(" << std::endl; + pretty_print_exp(forstmt->get_for_init()->get_exp()); + std::cout << "\t\t\t\t\t\t)," << std::endl; + } + } + std::cout << "\t\t\t\t\t)," << std::endl; + + std::cout << "\t\t\t\t\tcondition=(" << std::endl; + if (forstmt->get_exps() != nullptr) + pretty_print_exp(forstmt->get_exps()); + std::cout << "\t\t\t\t\t)," << std::endl; + + std::cout << "\t\t\t\t\tpost=(" << std::endl; + if (forstmt->get_exp2() != nullptr) + pretty_print_exp(forstmt->get_exp2()); + std::cout << "\t\t\t\t\t)," << std::endl; + + continue; + } if (blockItem->get_statement()->get_block() != nullptr) pretty_print_block(blockItem->get_statement()->get_block()); else { - std::cout << "\t\t\t\t\texp=(" << std::endl; - pretty_print_exp(blockItem->get_statement()->get_exps()); - std::cout << "\t\t\t\t\t)," << std::endl; + if (blockItem->get_statement()->get_exps() != nullptr) { + std::cout << "\t\t\t\t\texp=(" << std::endl; + pretty_print_exp(blockItem->get_statement()->get_exps()); + std::cout << "\t\t\t\t\t)," << std::endl; + } + if (blockItem->get_statement()->get_labels().first != nullptr) { + std::cout + << "\t\t\t\t\tlabels=(" + << blockItem->get_statement()->get_labels().first->get_value(); + if (blockItem->get_statement()->get_labels().second != nullptr) { + std::cout << ","; + std::cout + << blockItem->get_statement()->get_labels().second->get_value() + << ")" << std::endl; + } else { + std::cout << ")" << std::endl; + } + } } } std::cout << "\t\t\t\t)," << std::endl; diff --git a/parser/parser.hh b/parser/parser.hh index 0532fee..c0cf312 100644 --- a/parser/parser.hh +++ b/parser/parser.hh @@ -82,9 +82,19 @@ private: return label; } - std::string get_prev_loop_start_label() { return loop_start_labels.top(); } + std::pair get_prev_loop_start_label() { + if (loop_start_labels.empty()) { + return {"", false}; + } + return {loop_start_labels.top(), true}; + } - std::string get_prev_loop_end_label() { return loop_end_labels.top(); } + std::pair get_prev_loop_end_label() { + if (loop_end_labels.empty()) { + return {"", false}; + } + return {loop_end_labels.top(), true}; + } void remove_loop_start_label() { loop_start_labels.pop(); } void remove_loop_end_label() { loop_end_labels.pop(); } diff --git a/tests/chapter_8/invalid_semantics/break_not_in_loop.c b/tests/chapter_8/invalid_parse/break_not_in_loop.c similarity index 100% rename from tests/chapter_8/invalid_semantics/break_not_in_loop.c rename to tests/chapter_8/invalid_parse/break_not_in_loop.c diff --git a/tests/chapter_8/invalid_semantics/continue_not_in_loop.c b/tests/chapter_8/invalid_parse/continue_not_in_loop.c similarity index 100% rename from tests/chapter_8/invalid_semantics/continue_not_in_loop.c rename to tests/chapter_8/invalid_parse/continue_not_in_loop.c From f8162fc27c15633a3509c145d89f23f0ddda8fbb Mon Sep 17 00:00:00 2001 From: Sh0g0-1758 Date: Thu, 20 Feb 2025 02:59:53 +0530 Subject: [PATCH 4/8] for loop battle showdown --- CMakeLists.txt | 2 +- ast/ast.hh | 64 ++++- codegen/codegen.cc | 473 ++++++++++++++++++++++++--------- codegen/codegen.hh | 12 + parser/parser.cc | 638 ++++++++++++++++++++++++--------------------- parser/parser.hh | 76 ++++-- 6 files changed, 822 insertions(+), 443 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 7fb255a..1da33a1 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -83,7 +83,7 @@ add_custom_target(test-scarlet COMMAND echo "Running parser test" COMMAND ${CMAKE_SOURCE_DIR}/test_compiler ./scarlet --chapter 8 --stage parse COMMAND echo "Running semantic analysis test" - COMMAND ${CMAKE_SOURCE_DIR}/test_compiler ./scarlet --chapter 7 --stage validate + COMMAND ${CMAKE_SOURCE_DIR}/test_compiler ./scarlet --chapter 8 --stage validate COMMAND echo "Running scar test" COMMAND ${CMAKE_SOURCE_DIR}/test_compiler ./scarlet --chapter 7 --stage tacky COMMAND echo "Running Codegen test" diff --git a/ast/ast.hh b/ast/ast.hh index f1c59ba..7caa9ab 100644 --- a/ast/ast.hh +++ b/ast/ast.hh @@ -185,12 +185,11 @@ class AST_Block_Node; // since each if statement can either exist on its own or have an else statement enum class statementType { UNKNOWN, + NULLSTMT, RETURN, EXP, IF, IFELSE, - _IF_END, - _IFELSE_END, GOTO, LABEL, BLOCK, @@ -205,7 +204,6 @@ class AST_Statement_Node { private: std::shared_ptr exps; statementType type; - std::shared_ptr block; std::pair, std::shared_ptr> labels; @@ -220,11 +218,6 @@ public: this->exps = std::move(exp); } - std::shared_ptr get_block() { return block; } - void set_block(std::shared_ptr block) { - this->block = std::move(block); - } - std::pair, std::shared_ptr> get_labels() { @@ -237,6 +230,53 @@ public: } }; +class AST_block_statement_node : public AST_Statement_Node { +private: + std::shared_ptr block; + +public: + std::string get_AST_name() { return "BlockStatement"; } + std::shared_ptr get_block() { return block; } + void set_block(std::shared_ptr block) { + this->block = std::move(block); + } +}; + +class AST_if_else_statement_Node : public AST_Statement_Node { +private: + std::shared_ptr stmt1; + std::shared_ptr stmt2; + +public: + std::string get_AST_name() { + if (this->get_type() == statementType::IF) { + return "IfStatement"; + } else { + return "IfElseStatement"; + } + } + std::shared_ptr get_stmt1() { return stmt1; } + void set_stmt1(std::shared_ptr stmt1) { + this->stmt1 = std::move(stmt1); + } + std::shared_ptr get_stmt2() { return stmt2; } + void set_stmt2(std::shared_ptr stmt2) { + this->stmt2 = std::move(stmt2); + } +}; + +class AST_while_statement_Node : public AST_Statement_Node { +private: + std::shared_ptr stmt; + +public: + std::string get_AST_name() { return "WhileStatement"; } + std::shared_ptr get_stmt() { return stmt; } + void set_stmt(std::shared_ptr stmt) { + this->stmt = std::move(stmt); + } +}; + enum class DeclarationType { INT }; class AST_Declaration_Node { @@ -287,6 +327,7 @@ class AST_For_Statement_Node : public AST_Statement_Node { private: std::shared_ptr for_init; std::shared_ptr exp2; + std::shared_ptr stmt; public: std::string get_AST_name() { return "ForStatement"; } @@ -298,6 +339,11 @@ public: void set_exp2(std::shared_ptr exp2) { this->exp2 = std::move(exp2); } + + std::shared_ptr get_stmt() { return stmt; } + void set_stmt(std::shared_ptr stmt) { + this->stmt = std::move(stmt); + } }; enum class BlockItemType { UNKNOWN, STATEMENT, DECLARATION }; @@ -333,7 +379,7 @@ private: public: std::string get_AST_name() { return "Block"; } - std::vector> get_blockItems() { + std::vector> &get_blockItems() { return blockItems; } void add_blockItem(std::shared_ptr statement) { diff --git a/codegen/codegen.cc b/codegen/codegen.cc index af327a8..ad998f1 100644 --- a/codegen/codegen.cc +++ b/codegen/codegen.cc @@ -4,6 +4,11 @@ namespace scarlet { namespace codegen { +#define UNREACHABLE() \ + std::cout << "Unreachable code reached in " << __FILE__ << " at line " \ + << __LINE__ << std::endl; \ + __builtin_unreachable(); + void Codegen::gen_scar_factor( std::shared_ptr factor, std::shared_ptr scar_function) { @@ -464,132 +469,356 @@ void Codegen::gen_scar_exp( } } +void Codegen::gen_scar_statement( + std::shared_ptr statement, + std::shared_ptr scar_function) { + switch (statement->get_type()) { + case ast::statementType::NULLSTMT: + break; + case ast::statementType::RETURN: { + gen_scar_exp(statement->get_exps(), scar_function); + MAKE_SHARED(scar::scar_Instruction_Node, scar_instruction); + scar_instruction->set_type(scar::instruction_type::RETURN); + MAKE_SHARED(scar::scar_Val_Node, scar_val_src); + SETVARCONSTANTREG(scar_val_src); + scar_instruction->set_src1(scar_val_src); + scar_function->add_instruction(scar_instruction); + } break; + case ast::statementType::EXP: { + gen_scar_exp(statement->get_exps(), scar_function); + } break; + case ast::statementType::IF: { + // (stored in exps) + // c = + // JumpIfZero(c, end) + // (handled in the next iteration) + // Label(end) (Added during the end of if statement) + auto if_statement = + std::static_pointer_cast(statement); + gen_scar_exp(if_statement->get_exps(), scar_function); + MAKE_SHARED(scar::scar_Instruction_Node, scar_instruction); + scar_instruction->set_type(scar::instruction_type::JUMP_IF_ZERO); + MAKE_SHARED(scar::scar_Val_Node, scar_val_src); + SETVARCONSTANTREG(scar_val_src); + scar_instruction->set_src1(std::move(scar_val_src)); + MAKE_SHARED(scar::scar_Val_Node, scar_val_dst); + scar_val_dst->set_type(scar::val_type::UNKNOWN); + scar_val_dst->set_value(if_statement->get_labels().first->get_value()); + scar_instruction->set_dst(std::move(scar_val_dst)); + scar_function->add_instruction(std::move(scar_instruction)); + + // generate scar for the statement + gen_scar_statement(if_statement->get_stmt1(), scar_function); + + // generate the end label + MAKE_SHARED(scar::scar_Instruction_Node, scar_instruction2); + scar_instruction2->set_type(scar::instruction_type::LABEL); + MAKE_SHARED(scar::scar_Val_Node, scar_val_src2); + scar_val_src2->set_type(scar::val_type::UNKNOWN); + scar_val_src2->set_value(if_statement->get_labels().first->get_value()); + scar_instruction2->set_src1(std::move(scar_val_src2)); + scar_function->add_instruction(std::move(scar_instruction2)); + } break; + case ast::statementType::IFELSE: { + // + // c = + // JumpIfZero(c, else_label) + // + // Jump(end) + // Label(else_label) + // + // Label(end) + + auto if_else_statement = + std::static_pointer_cast(statement); + gen_scar_exp(if_else_statement->get_exps(), scar_function); + + // Jump if zero to else statement + MAKE_SHARED(scar::scar_Instruction_Node, scar_instruction); + scar_instruction->set_type(scar::instruction_type::JUMP_IF_ZERO); + MAKE_SHARED(scar::scar_Val_Node, scar_val_src); + SETVARCONSTANTREG(scar_val_src); + scar_instruction->set_src1(std::move(scar_val_src)); + MAKE_SHARED(scar::scar_Val_Node, scar_val_dst); + scar_val_dst->set_type(scar::val_type::UNKNOWN); + scar_val_dst->set_value(if_else_statement->get_labels().first->get_value()); + scar_instruction->set_dst(std::move(scar_val_dst)); + scar_function->add_instruction(std::move(scar_instruction)); + + // generate scar for the if statement + gen_scar_statement(if_else_statement->get_stmt1(), scar_function); + + // jump to the end + MAKE_SHARED(scar::scar_Instruction_Node, scar_instruction2); + scar_instruction2->set_type(scar::instruction_type::JUMP); + MAKE_SHARED(scar::scar_Val_Node, scar_val_src2); + scar_val_src2->set_type(scar::val_type::UNKNOWN); + scar_val_src2->set_value( + if_else_statement->get_labels().second->get_value()); + scar_instruction2->set_src1(std::move(scar_val_src2)); + scar_function->add_instruction(std::move(scar_instruction2)); + + // generate the else label + MAKE_SHARED(scar::scar_Instruction_Node, scar_instruction3); + scar_instruction3->set_type(scar::instruction_type::LABEL); + MAKE_SHARED(scar::scar_Val_Node, scar_val_src3); + scar_val_src3->set_type(scar::val_type::UNKNOWN); + scar_val_src3->set_value( + if_else_statement->get_labels().first->get_value()); + scar_instruction3->set_src1(std::move(scar_val_src3)); + scar_function->add_instruction(std::move(scar_instruction3)); + + // generate scar for the else statement + gen_scar_statement(if_else_statement->get_stmt2(), scar_function); + + // generate the end label + MAKE_SHARED(scar::scar_Instruction_Node, scar_instruction4); + scar_instruction4->set_type(scar::instruction_type::LABEL); + MAKE_SHARED(scar::scar_Val_Node, scar_val_src4); + scar_val_src4->set_type(scar::val_type::UNKNOWN); + scar_val_src4->set_value( + if_else_statement->get_labels().second->get_value()); + scar_instruction4->set_src1(std::move(scar_val_src4)); + scar_function->add_instruction(std::move(scar_instruction4)); + } break; + + case ast::statementType::GOTO: + case ast::statementType::BREAK: + case ast::statementType::CONTINUE: { + MAKE_SHARED(scar::scar_Instruction_Node, scar_instruction); + scar_instruction->set_type(scar::instruction_type::JUMP); + MAKE_SHARED(scar::scar_Val_Node, scar_val_src); + scar_val_src->set_type(scar::val_type::UNKNOWN); + scar_val_src->set_value(statement->get_labels().first->get_value()); + scar_instruction->set_src1(std::move(scar_val_src)); + scar_function->add_instruction(scar_instruction); + } break; + + case ast::statementType::LABEL: { + MAKE_SHARED(scar::scar_Instruction_Node, scar_instruction); + scar_instruction->set_type(scar::instruction_type::LABEL); + MAKE_SHARED(scar::scar_Val_Node, scar_val_src); + scar_val_src->set_type(scar::val_type::UNKNOWN); + scar_val_src->set_value(statement->get_labels().first->get_value()); + scar_instruction->set_src1(std::move(scar_val_src)); + scar_function->add_instruction(scar_instruction); + } break; + + case ast::statementType::BLOCK: { + auto block_statement = + std::static_pointer_cast(statement); + gen_scar_block(block_statement->get_block(), scar_function); + } break; + + case ast::statementType::WHILE: { + auto while_statement = + std::static_pointer_cast(statement); + + // Label(start) + // + // c = + // JumpIfZero(c, end) + // + // Jump(start) + // Label(end) + + MAKE_SHARED(scar::scar_Instruction_Node, scar_instruction); + scar_instruction->set_type(scar::instruction_type::LABEL); + MAKE_SHARED(scar::scar_Val_Node, scar_val_src); + scar_val_src->set_type(scar::val_type::UNKNOWN); + scar_val_src->set_value(while_statement->get_labels().first->get_value()); + scar_instruction->set_src1(std::move(scar_val_src)); + scar_function->add_instruction(scar_instruction); + + gen_scar_exp(while_statement->get_exps(), scar_function); + + MAKE_SHARED(scar::scar_Instruction_Node, scar_instruction2); + scar_instruction2->set_type(scar::instruction_type::JUMP_IF_ZERO); + MAKE_SHARED(scar::scar_Val_Node, scar_val_src2); + SETVARCONSTANTREG(scar_val_src2); + scar_instruction2->set_src1(std::move(scar_val_src2)); + MAKE_SHARED(scar::scar_Val_Node, scar_val_dst2); + scar_val_dst2->set_type(scar::val_type::UNKNOWN); + scar_val_dst2->set_value(while_statement->get_labels().second->get_value()); + scar_instruction2->set_dst(std::move(scar_val_dst2)); + scar_function->add_instruction(scar_instruction2); + + gen_scar_statement(while_statement->get_stmt(), scar_function); + + MAKE_SHARED(scar::scar_Instruction_Node, scar_instruction3); + scar_instruction3->set_type(scar::instruction_type::JUMP); + MAKE_SHARED(scar::scar_Val_Node, scar_val_src3); + scar_val_src3->set_type(scar::val_type::UNKNOWN); + scar_val_src3->set_value(while_statement->get_labels().first->get_value()); + scar_instruction3->set_src1(std::move(scar_val_src3)); + scar_function->add_instruction(scar_instruction3); + + MAKE_SHARED(scar::scar_Instruction_Node, scar_instruction4); + scar_instruction4->set_type(scar::instruction_type::LABEL); + MAKE_SHARED(scar::scar_Val_Node, scar_val_src4); + scar_val_src4->set_type(scar::val_type::UNKNOWN); + scar_val_src4->set_value(while_statement->get_labels().second->get_value()); + scar_instruction4->set_src1(std::move(scar_val_src4)); + scar_function->add_instruction(scar_instruction4); + } break; + + case ast::statementType::DO_WHILE: { + auto do_while_statement = + std::static_pointer_cast(statement); + + // Label(start) + // + // + // c = + // JumpIfNotZero(c, start) + // Label(end) + + MAKE_SHARED(scar::scar_Instruction_Node, scar_instruction); + scar_instruction->set_type(scar::instruction_type::LABEL); + MAKE_SHARED(scar::scar_Val_Node, scar_val_src); + scar_val_src->set_type(scar::val_type::UNKNOWN); + scar_val_src->set_value( + do_while_statement->get_labels().first->get_value()); + scar_instruction->set_src1(std::move(scar_val_src)); + scar_function->add_instruction(scar_instruction); + + gen_scar_statement(do_while_statement->get_stmt(), scar_function); + + gen_scar_exp(do_while_statement->get_exps(), scar_function); + + MAKE_SHARED(scar::scar_Instruction_Node, scar_instruction2); + scar_instruction2->set_type(scar::instruction_type::JUMP_IF_NOT_ZERO); + MAKE_SHARED(scar::scar_Val_Node, scar_val_src2); + SETVARCONSTANTREG(scar_val_src2); + scar_instruction2->set_src1(std::move(scar_val_src2)); + MAKE_SHARED(scar::scar_Val_Node, scar_val_dst2); + scar_val_dst2->set_type(scar::val_type::UNKNOWN); + scar_val_dst2->set_value( + do_while_statement->get_labels().first->get_value()); + scar_instruction2->set_dst(std::move(scar_val_dst2)); + scar_function->add_instruction(scar_instruction2); + + MAKE_SHARED(scar::scar_Instruction_Node, scar_instruction3); + scar_instruction3->set_type(scar::instruction_type::LABEL); + MAKE_SHARED(scar::scar_Val_Node, scar_val_src3); + scar_val_src3->set_type(scar::val_type::UNKNOWN); + scar_val_src3->set_value( + do_while_statement->get_labels().second->get_value()); + scar_instruction3->set_src1(std::move(scar_val_src3)); + scar_function->add_instruction(scar_instruction3); + } break; + + case ast::statementType::FOR: { + auto for_statement = + std::static_pointer_cast(statement); + + // + // Label(Forstart) + // + // c = + // JumpIfZero(c, end) + // + // Label(continue) + // + // Jump(Forstart) + // Label(end) + + if (for_statement->get_for_init() != nullptr) { + if (for_statement->get_for_init()->get_declaration() != nullptr) { + gen_scar_declaration(for_statement->get_for_init()->get_declaration(), + scar_function); + } else { + gen_scar_exp(for_statement->get_for_init()->get_exp(), scar_function); + } + } + + std::string FOR_START = get_for_label_name(); + + MAKE_SHARED(scar::scar_Instruction_Node, scar_instruction); + scar_instruction->set_type(scar::instruction_type::LABEL); + MAKE_SHARED(scar::scar_Val_Node, scar_val_src); + scar_val_src->set_type(scar::val_type::UNKNOWN); + scar_val_src->set_value(FOR_START); + scar_instruction->set_src1(std::move(scar_val_src)); + scar_function->add_instruction(scar_instruction); + + gen_scar_exp(for_statement->get_exps(), scar_function); + + MAKE_SHARED(scar::scar_Instruction_Node, scar_instruction2); + scar_instruction2->set_type(scar::instruction_type::JUMP_IF_ZERO); + MAKE_SHARED(scar::scar_Val_Node, scar_val_src2); + SETVARCONSTANTREG(scar_val_src2); + scar_instruction2->set_src1(std::move(scar_val_src2)); + MAKE_SHARED(scar::scar_Val_Node, scar_val_dst2); + scar_val_dst2->set_type(scar::val_type::UNKNOWN); + scar_val_dst2->set_value(for_statement->get_labels().second->get_value()); + scar_instruction2->set_dst(std::move(scar_val_dst2)); + scar_function->add_instruction(scar_instruction2); + + gen_scar_statement(for_statement->get_stmt(), scar_function); + + MAKE_SHARED(scar::scar_Instruction_Node, scar_instruction3); + scar_instruction3->set_type(scar::instruction_type::LABEL); + MAKE_SHARED(scar::scar_Val_Node, scar_val_src3); + scar_val_src3->set_type(scar::val_type::UNKNOWN); + scar_val_src3->set_value(for_statement->get_labels().first->get_value()); + scar_instruction3->set_src1(std::move(scar_val_src3)); + scar_function->add_instruction(scar_instruction3); + + gen_scar_exp(for_statement->get_exp2(), scar_function); + + MAKE_SHARED(scar::scar_Instruction_Node, scar_instruction4); + scar_instruction4->set_type(scar::instruction_type::JUMP); + MAKE_SHARED(scar::scar_Val_Node, scar_val_src4); + scar_val_src4->set_type(scar::val_type::UNKNOWN); + scar_val_src4->set_value(FOR_START); + scar_instruction4->set_src1(std::move(scar_val_src4)); + scar_function->add_instruction(scar_instruction4); + + MAKE_SHARED(scar::scar_Instruction_Node, scar_instruction5); + scar_instruction5->set_type(scar::instruction_type::LABEL); + MAKE_SHARED(scar::scar_Val_Node, scar_val_src5); + scar_val_src5->set_type(scar::val_type::UNKNOWN); + scar_val_src5->set_value(for_statement->get_labels().second->get_value()); + scar_instruction5->set_src1(std::move(scar_val_src5)); + scar_function->add_instruction(scar_instruction5); + } break; + case ast::statementType::UNKNOWN: + UNREACHABLE() + } +} +void Codegen::gen_scar_declaration( + std::shared_ptr declaration, + std::shared_ptr scar_function) { + // if there is no definition, we ignore it + if (declaration->get_exp() != nullptr) { + gen_scar_exp(declaration->get_exp(), scar_function); + MAKE_SHARED(scar::scar_Instruction_Node, scar_instruction); + scar_instruction->set_type(scar::instruction_type::COPY); + MAKE_SHARED(scar::scar_Val_Node, scar_val_src); + SETVARCONSTANTREG(scar_val_src); + scar_instruction->set_src1(scar_val_src); + MAKE_SHARED(scar::scar_Val_Node, scar_val_dst); + scar_val_dst->set_type(scar::val_type::VAR); + scar_val_dst->set_reg_name(declaration->get_identifier()->get_value()); + scar_instruction->set_dst(scar_val_dst); + scar_function->add_instruction(scar_instruction); + } +} + void Codegen::gen_scar_block( std::shared_ptr block, std::shared_ptr scar_function) { - // The trick is that since each else will bind to the nearest if only - // It is okay to maintain a count of the number of if-else blocks - // and use the path of the if-else if this counter is greater than 0 - int if_else_count = 0; for (auto inst : block->get_blockItems()) { - if (inst->get_type() == ast::BlockItemType::STATEMENT) { - if (inst->get_statement()->get_type() == ast::statementType::RETURN) { - gen_scar_exp(inst->get_statement()->get_exps(), scar_function); - MAKE_SHARED(scar::scar_Instruction_Node, scar_instruction); - scar_instruction->set_type(scar::instruction_type::RETURN); - MAKE_SHARED(scar::scar_Val_Node, scar_val_src); - SETVARCONSTANTREG(scar_val_src); - scar_instruction->set_src1(scar_val_src); - scar_function->add_instruction(scar_instruction); - } else if (inst->get_statement()->get_type() == ast::statementType::EXP) { - gen_scar_exp(inst->get_statement()->get_exps(), scar_function); - } else if (inst->get_statement()->get_type() == ast::statementType::IF) { - // (stored in exps) - // c = - // JumpIfZero(c, end) - // (handled in the next iteration) - // Label(end) (Added during the end of if statement) - gen_scar_exp(inst->get_statement()->get_exps(), scar_function); - MAKE_SHARED(scar::scar_Instruction_Node, scar_instruction); - scar_instruction->set_type(scar::instruction_type::JUMP_IF_ZERO); - MAKE_SHARED(scar::scar_Val_Node, scar_val_src); - SETVARCONSTANTREG(scar_val_src); - scar_instruction->set_src1(std::move(scar_val_src)); - MAKE_SHARED(scar::scar_Val_Node, scar_val_dst); - scar_val_dst->set_type(scar::val_type::UNKNOWN); - scar_val_dst->set_value(get_fr_label_name()); - scar_instruction->set_dst(std::move(scar_val_dst)); - scar_function->add_instruction(std::move(scar_instruction)); - } else if (inst->get_statement()->get_type() == - ast::statementType::_IF_END) { - MAKE_SHARED(scar::scar_Instruction_Node, scar_instruction); - scar_instruction->set_type(scar::instruction_type::LABEL); - MAKE_SHARED(scar::scar_Val_Node, scar_val_src); - scar_val_src->set_type(scar::val_type::UNKNOWN); - scar_val_src->set_value(get_last_fr_label_name(true)); - scar_instruction->set_src1(std::move(scar_val_src)); - if (if_else_count > 0) { - MAKE_SHARED(scar::scar_Instruction_Node, scar_instruction2); - scar_instruction2->set_type(scar::instruction_type::JUMP); - MAKE_SHARED(scar::scar_Val_Node, scar_val_src2); - scar_val_src2->set_type(scar::val_type::UNKNOWN); - scar_val_src2->set_value(get_fr_label_name()); - scar_instruction2->set_src1(std::move(scar_val_src2)); - scar_function->add_instruction(std::move(scar_instruction2)); - if_else_count--; - } - scar_function->add_instruction(std::move(scar_instruction)); - } else if (inst->get_statement()->get_type() == - ast::statementType::IFELSE) { - // - // c = - // JumpIfZero(c, else_label) - // - // Jump(end) - // Label(else_label) - // - // Label(end) - if_else_count++; - gen_scar_exp(inst->get_statement()->get_exps(), scar_function); - MAKE_SHARED(scar::scar_Instruction_Node, scar_instruction); - scar_instruction->set_type(scar::instruction_type::JUMP_IF_ZERO); - MAKE_SHARED(scar::scar_Val_Node, scar_val_src); - SETVARCONSTANTREG(scar_val_src); - scar_instruction->set_src1(std::move(scar_val_src)); - MAKE_SHARED(scar::scar_Val_Node, scar_val_dst); - scar_val_dst->set_type(scar::val_type::UNKNOWN); - scar_val_dst->set_value(get_fr_label_name()); - scar_instruction->set_dst(std::move(scar_val_dst)); - scar_function->add_instruction(std::move(scar_instruction)); - } else if (inst->get_statement()->get_type() == - ast::statementType::_IFELSE_END) { - MAKE_SHARED(scar::scar_Instruction_Node, scar_instruction); - scar_instruction->set_type(scar::instruction_type::LABEL); - MAKE_SHARED(scar::scar_Val_Node, scar_val_src); - scar_val_src->set_type(scar::val_type::UNKNOWN); - scar_val_src->set_value(get_last_fr_label_name(true)); - scar_instruction->set_src1(std::move(scar_val_src)); - scar_function->add_instruction(std::move(scar_instruction)); - } else if (inst->get_statement()->get_type() == - ast::statementType::GOTO) { - MAKE_SHARED(scar::scar_Instruction_Node, scar_instruction); - scar_instruction->set_type(scar::instruction_type::JUMP); - MAKE_SHARED(scar::scar_Val_Node, scar_val_src); - scar_val_src->set_type(scar::val_type::UNKNOWN); - scar_val_src->set_value( - inst->get_statement()->get_labels().first->get_value()); - scar_instruction->set_src1(std::move(scar_val_src)); - scar_function->add_instruction(scar_instruction); - } else if (inst->get_statement()->get_type() == - ast::statementType::LABEL) { - MAKE_SHARED(scar::scar_Instruction_Node, scar_instruction); - scar_instruction->set_type(scar::instruction_type::LABEL); - MAKE_SHARED(scar::scar_Val_Node, scar_val_src); - scar_val_src->set_type(scar::val_type::UNKNOWN); - scar_val_src->set_value( - inst->get_statement()->get_labels().first->get_value()); - scar_instruction->set_src1(std::move(scar_val_src)); - scar_function->add_instruction(scar_instruction); - } else if (inst->get_statement()->get_type() == - ast::statementType::BLOCK) { - gen_scar_block(inst->get_statement()->get_block(), scar_function); - } - } else if (inst->get_type() == ast::BlockItemType::DECLARATION) { - // if there is no definition, we ignore it - if (inst->get_declaration()->get_exp() != nullptr) { - gen_scar_exp(inst->get_declaration()->get_exp(), scar_function); - MAKE_SHARED(scar::scar_Instruction_Node, scar_instruction); - scar_instruction->set_type(scar::instruction_type::COPY); - MAKE_SHARED(scar::scar_Val_Node, scar_val_src); - SETVARCONSTANTREG(scar_val_src); - scar_instruction->set_src1(scar_val_src); - MAKE_SHARED(scar::scar_Val_Node, scar_val_dst); - scar_val_dst->set_type(scar::val_type::VAR); - scar_val_dst->set_reg_name( - inst->get_declaration()->get_identifier()->get_value()); - scar_instruction->set_dst(scar_val_dst); - scar_function->add_instruction(scar_instruction); - } + switch (inst->get_type()) { + case ast::BlockItemType::STATEMENT: + gen_scar_statement(inst->get_statement(), scar_function); + break; + case ast::BlockItemType::DECLARATION: + gen_scar_declaration(inst->get_declaration(), scar_function); + break; + case ast::BlockItemType::UNKNOWN: + UNREACHABLE() } } } diff --git a/codegen/codegen.hh b/codegen/codegen.hh index 545836c..098c487 100644 --- a/codegen/codegen.hh +++ b/codegen/codegen.hh @@ -56,8 +56,15 @@ private: std::shared_ptr scar_function); void gen_scar_factor(std::shared_ptr factor, std::shared_ptr scar_function); + void + gen_scar_statement(std::shared_ptr statement, + std::shared_ptr scar_function); + void + gen_scar_declaration(std::shared_ptr declaration, + std::shared_ptr scar_function); void gen_scar_block(std::shared_ptr block, std::shared_ptr scar_function); + int for_label_counter = 1; int fr_label_counter = 1; int res_label_counter = 1; std::stack fr_label_stack; @@ -112,6 +119,11 @@ public: res_label_stack.pop(); return tmp; } + std::string get_for_label_name() { + std::string label_name = "labelFor." + std::to_string(for_label_counter); + for_label_counter++; + return label_name; + } std::map compound_to_base = { {binop::BINOP::COMPOUND_DIFFERENCE, binop::BINOP::SUB}, {binop::BINOP::COMPOUND_DIVISION, binop::BINOP::DIV}, diff --git a/parser/parser.cc b/parser/parser.cc index f7166e9..99e7c7f 100644 --- a/parser/parser.cc +++ b/parser/parser.cc @@ -2,7 +2,6 @@ namespace scarlet { namespace parser { -#define MAKE_SHARED(a, b) std::shared_ptr b = std::make_shared() #define UNREACHABLE() \ std::cout << "Unreachable code reached in " << __FILE__ << " at line " \ << __LINE__ << std::endl; \ @@ -109,7 +108,10 @@ void parser::parse_block_item(std::vector &tokens, } else { // we have a return statement, an expression, an if-else block or a null // statement - parse_statement(tokens, block); + MAKE_SHARED(ast::AST_Block_Item_Node, block_item); + block_item->set_type(ast::BlockItemType::STATEMENT); + MAKE_SHARED(ast::AST_Statement_Node, statement); + parse_statement(tokens, statement); } } @@ -136,8 +138,9 @@ void parser::parse_declaration(std::vector &tokens, block->add_blockItem(std::move(block_item)); } -void parser::parse_statement(std::vector &tokens, - std::shared_ptr block) { +void parser::parse_statement( + std::vector &tokens, + std::shared_ptr statement) { // NOTE THESE CHECKS ARE NECESSARY BECAUSE THE FUNCTION CAN BE CALLED // RECURSIVELY if (!success) @@ -147,9 +150,6 @@ void parser::parse_statement(std::vector &tokens, return; } // =============================== - MAKE_SHARED(ast::AST_Block_Item_Node, block_item); - block_item->set_type(ast::BlockItemType::STATEMENT); - MAKE_SHARED(ast::AST_Statement_Node, statement); if (tokens[0].get_token() == token::TOKEN::RETURN) { tokens.erase(tokens.begin()); @@ -160,11 +160,9 @@ void parser::parse_statement(std::vector &tokens, statement->set_exp(std::move(exp)); EXPECT(token::TOKEN::SEMICOLON); - - block_item->set_statement(std::move(statement)); - block->add_blockItem(std::move(block_item)); } else if (tokens[0].get_token() == token::TOKEN::IF) { // We first check for the if (exp) statement + MAKE_SHARED(ast::AST_if_else_statement_Node, if_else_statement); tokens.erase(tokens.begin()); EXPECT(token::TOKEN::OPEN_PARANTHESES); @@ -172,53 +170,41 @@ void parser::parse_statement(std::vector &tokens, // exp MAKE_SHARED(ast::AST_exp_Node, exp); parse_exp(tokens, exp); - statement->set_type(ast::statementType::IF); - statement->set_exp(std::move(exp)); + if_else_statement->set_exp(std::move(exp)); EXPECT(token::TOKEN::CLOSE_PARANTHESES); - // Don't move it as we modify it later in case it has an else statement - block_item->set_statement(statement); - block->add_blockItem(std::move(block_item)); - // statement - parse_statement(tokens, block); + MAKE_SHARED(ast::AST_Statement_Node, stmt); + parse_statement(tokens, stmt); + if_else_statement->set_stmt1(std::move(stmt)); - // mark the end of this if statement - MAKE_SHARED(ast::AST_Block_Item_Node, block_item2); - block_item2->set_type(ast::BlockItemType::STATEMENT); - MAKE_SHARED(ast::AST_Statement_Node, statement2); - statement2->set_type(ast::statementType::_IF_END); - block_item2->set_statement(std::move(statement2)); - block->add_blockItem(std::move(block_item2)); + if_else_statement->set_labels(get_ifelse_labels()); // Then we optionally check for the else statement if (tokens[0].get_token() == token::TOKEN::ELSE) { tokens.erase(tokens.begin()); - statement->set_type(ast::statementType::IFELSE); - // the statement following else is being treated as another block item - parse_statement(tokens, block); - - // mark the end of this else statement - MAKE_SHARED(ast::AST_Block_Item_Node, block_item3); - block_item3->set_type(ast::BlockItemType::STATEMENT); - MAKE_SHARED(ast::AST_Statement_Node, statement3); - statement3->set_type(ast::statementType::_IFELSE_END); - block_item3->set_statement(std::move(statement3)); - block->add_blockItem(std::move(block_item3)); + if_else_statement->set_type(ast::statementType::IFELSE); + + MAKE_SHARED(ast::AST_Statement_Node, stmt2); + parse_statement(tokens, stmt2); + + if_else_statement->set_stmt2(std::move(stmt2)); + } else { + if_else_statement->set_type(ast::statementType::IF); } + statement = + std::static_pointer_cast(if_else_statement); } else if (tokens[0].get_token() == token::TOKEN::SEMICOLON) { // ignore the empty statement tokens.erase(tokens.begin()); - return; + statement->set_type(ast::statementType::NULLSTMT); } else if (tokens[0].get_token() == token::TOKEN::GOTO) { tokens.erase(tokens.begin()); statement->set_type(ast::statementType::GOTO); EXPECT_IDENTIFIER(); statement->set_labels({std::move(identifier), nullptr}); EXPECT(token::TOKEN::SEMICOLON); - block_item->set_statement(std::move(statement)); - block->add_blockItem(std::move(block_item)); } else if (tokens.size() >= 2 && tokens[0].get_token() == token::TOKEN::IDENTIFIER && tokens[1].get_token() == token::TOKEN::COLON) { @@ -226,110 +212,79 @@ void parser::parse_statement(std::vector &tokens, EXPECT_IDENTIFIER(); statement->set_labels({std::move(identifier), nullptr}); EXPECT(token::TOKEN::COLON); - block_item->set_statement(std::move(statement)); - block->add_blockItem(std::move(block_item)); } else if (tokens[0].get_token() == token::TOKEN::OPEN_BRACE) { + MAKE_SHARED(ast::AST_block_statement_node, block_stmt); MAKE_SHARED(ast::AST_Block_Node, block_node); parse_block(tokens, block_node); - statement->set_type(ast::statementType::BLOCK); - statement->set_block(std::move(block_node)); - block_item->set_statement(std::move(statement)); - block->add_blockItem(std::move(block_item)); + block_stmt->set_type(ast::statementType::BLOCK); + block_stmt->set_block(std::move(block_node)); + statement = std::static_pointer_cast(block_stmt); } else if (tokens[0].get_token() == token::TOKEN::WHILE) { - statement->set_type(ast::statementType::WHILE); - MAKE_SHARED(ast::AST_identifier_Node, start_label); - MAKE_SHARED(ast::AST_identifier_Node, end_label); - start_label->set_identifier(get_loop_start_label()); - end_label->set_identifier(get_loop_end_label()); - statement->set_labels({std::move(start_label), end_label}); + MAKE_SHARED(ast::AST_while_statement_Node, while_statement); + while_statement->set_type(ast::statementType::WHILE); tokens.erase(tokens.begin()); + while_statement->set_labels(get_loop_labels()); + EXPECT(token::TOKEN::OPEN_PARANTHESES); MAKE_SHARED(ast::AST_exp_Node, exp); parse_exp(tokens, exp); - statement->set_exp(std::move(exp)); + while_statement->set_exp(std::move(exp)); + EXPECT(token::TOKEN::CLOSE_PARANTHESES); - block_item->set_statement(std::move(statement)); - block->add_blockItem(std::move(block_item)); - parse_statement(tokens, block); - - // make the end label - MAKE_SHARED(ast::AST_Block_Item_Node, block_item2); - block_item2->set_type(ast::BlockItemType::STATEMENT); - MAKE_SHARED(ast::AST_Statement_Node, statement2); - statement2->set_type(ast::statementType::LABEL); - statement2->set_labels({std::move(end_label), nullptr}); - block_item2->set_statement(std::move(statement2)); - block->add_blockItem(std::move(block_item2)); - - remove_loop_start_label(); - remove_loop_end_label(); + + MAKE_SHARED(ast::AST_Statement_Node, stmt); + parse_statement(tokens, stmt); + while_statement->set_stmt(std::move(stmt)); + + remove_loop_labels(); + statement = + std::static_pointer_cast(while_statement); } else if (tokens[0].get_token() == token::TOKEN::CONTINUE) { + tokens.erase(tokens.begin()); statement->set_type(ast::statementType::CONTINUE); - MAKE_SHARED(ast::AST_identifier_Node, label); - auto [lbl, res] = get_prev_loop_start_label(); - if (!res) { - tokens.erase(tokens.begin()); + auto lbl = get_prev_loop_start_label(); + if (lbl == nullptr) { error_messages.emplace_back( "Continue statement found outside of a loop construct"); success = false; } else { - label->set_identifier(lbl); - statement->set_labels({std::move(label), nullptr}); - tokens.erase(tokens.begin()); + statement->set_labels({std::move(lbl), nullptr}); EXPECT(token::TOKEN::SEMICOLON); - block_item->set_statement(std::move(statement)); - block->add_blockItem(std::move(block_item)); } } else if (tokens[0].get_token() == token::TOKEN::BREAK) { + tokens.erase(tokens.begin()); statement->set_type(ast::statementType::BREAK); - MAKE_SHARED(ast::AST_identifier_Node, label); - auto [lbl, res] = get_prev_loop_end_label(); - if (!res) { - tokens.erase(tokens.begin()); + auto lbl = get_prev_loop_end_label(); + if (lbl == nullptr) { error_messages.emplace_back( "Break statement found outside of a loop construct"); success = false; } else { - label->set_identifier(lbl); - statement->set_labels({std::move(label), nullptr}); + statement->set_labels({std::move(lbl), nullptr}); tokens.erase(tokens.begin()); EXPECT(token::TOKEN::SEMICOLON); - block_item->set_statement(std::move(statement)); - block->add_blockItem(std::move(block_item)); } } else if (tokens[0].get_token() == token::TOKEN::DO) { tokens.erase(tokens.begin()); - MAKE_SHARED(ast::AST_identifier_Node, start_label); - MAKE_SHARED(ast::AST_identifier_Node, end_label); - start_label->set_identifier(get_loop_start_label()); - end_label->set_identifier(get_loop_end_label()); - - // make the start label - MAKE_SHARED(ast::AST_Block_Item_Node, block_item2); - block_item2->set_type(ast::BlockItemType::STATEMENT); - MAKE_SHARED(ast::AST_Statement_Node, statement2); - statement2->set_type(ast::statementType::LABEL); - statement2->set_labels({start_label, nullptr}); - block_item2->set_statement(std::move(statement2)); - block->add_blockItem(std::move(block_item2)); - - statement->set_labels({std::move(start_label), std::move(end_label)}); + MAKE_SHARED(ast::AST_while_statement_Node, while_statement); + while_statement->set_type(ast::statementType::DO_WHILE); + while_statement->set_labels(get_loop_labels()); - parse_statement(tokens, block); + MAKE_SHARED(ast::AST_Statement_Node, stmt); + parse_statement(tokens, stmt); + while_statement->set_stmt(std::move(stmt)); EXPECT(token::TOKEN::WHILE); EXPECT(token::TOKEN::OPEN_PARANTHESES); MAKE_SHARED(ast::AST_exp_Node, exp); parse_exp(tokens, exp); + while_statement->set_exp(std::move(exp)); EXPECT(token::TOKEN::CLOSE_PARANTHESES); EXPECT(token::TOKEN::SEMICOLON); - statement->set_exp(std::move(exp)); - statement->set_type(ast::statementType::DO_WHILE); - block_item->set_statement(std::move(statement)); - block->add_blockItem(std::move(block_item)); - remove_loop_start_label(); - remove_loop_end_label(); + remove_loop_labels(); + statement = + std::static_pointer_cast(while_statement); } else if (tokens[0].get_token() == token::TOKEN::FOR) { // For statement has additional constructs, so we use a // child class AST_For_Statement_Node to represent it. @@ -356,48 +311,30 @@ void parser::parse_statement(std::vector &tokens, EXPECT(token::TOKEN::SEMICOLON); if (tokens[0].get_token() != token::TOKEN::CLOSE_PARANTHESES) { - MAKE_SHARED(ast::AST_exp_Node, exp2); - parse_exp(tokens, exp2); - for_statement->set_exp2(std::move(exp2)); + MAKE_SHARED(ast::AST_exp_Node, exp); + parse_exp(tokens, exp); + for_statement->set_exp2(std::move(exp)); } else { for_statement->set_exp2(nullptr); } EXPECT(token::TOKEN::CLOSE_PARANTHESES); - MAKE_SHARED(ast::AST_identifier_Node, start_label); - MAKE_SHARED(ast::AST_identifier_Node, end_label); - start_label->set_identifier(get_loop_start_label()); - end_label->set_identifier(get_loop_end_label()); + for_statement->set_labels(get_loop_labels()); - for_statement->set_labels({std::move(start_label), end_label}); + MAKE_SHARED(ast::AST_Statement_Node, stmt); + parse_statement(tokens, stmt); + for_statement->set_stmt(std::move(stmt)); + remove_loop_labels(); statement = std::static_pointer_cast(for_statement); - block_item->set_statement(std::move(statement)); - block->add_blockItem(std::move(block_item)); - - parse_statement(tokens, block); - - // make the end label - MAKE_SHARED(ast::AST_Block_Item_Node, block_item2); - block_item2->set_type(ast::BlockItemType::STATEMENT); - MAKE_SHARED(ast::AST_Statement_Node, statement2); - statement2->set_type(ast::statementType::LABEL); - statement2->set_labels({std::move(end_label), nullptr}); - block_item2->set_statement(std::move(statement2)); - block->add_blockItem(std::move(block_item2)); - - remove_loop_start_label(); - remove_loop_end_label(); } else { statement->set_type(ast::statementType::EXP); MAKE_SHARED(ast::AST_exp_Node, exp); parse_exp(tokens, exp); statement->set_exp(std::move(exp)); EXPECT(token::TOKEN::SEMICOLON); - block_item->set_statement(std::move(statement)); - block->add_blockItem(std::move(block_item)); } } @@ -850,6 +787,149 @@ void parser::analyze_exp( analyze_exp(exp->get_middle(), symbol_table, indx); } +void parser::analyze_declaration( + std::shared_ptr declaration, + std::map, std::string> &symbol_table, + int indx) { + std::string var_name = declaration->get_identifier()->get_value(); + if (symbol_table.find({var_name, indx}) != symbol_table.end()) { + // the symbol has been declared twice which is illegal + success = false; + error_messages.emplace_back("Variable " + var_name + " already declared"); + } else { + symbol_table[{var_name, indx}] = get_temp_name(var_name); + declaration->get_identifier()->set_identifier( + symbol_table[{var_name, indx}]); + if (declaration->get_exp() != nullptr) + analyze_exp(declaration->get_exp(), symbol_table, indx); + } +} + +void parser::analyze_statement( + std::shared_ptr statement, + std::map, std::string> &symbol_table, + int indx) { + + // every variable that is used in any of the statement should already + // have been declared. + + // We need to check that the labels used in goto statements are + // actually declared and we also need to make sure that there are no + // duplicate labels + + switch (statement->get_type()) { + case ast::statementType::RETURN: + analyze_exp(statement->get_exps(), symbol_table, indx); + break; + case ast::statementType::IF: { + auto if_statement = + std::static_pointer_cast(statement); + analyze_exp(if_statement->get_exps(), symbol_table, indx); + analyze_statement(if_statement->get_stmt1(), symbol_table, indx); + } break; + case ast::statementType::IFELSE: { + auto if_else_statement = + std::static_pointer_cast(statement); + analyze_exp(if_else_statement->get_exps(), symbol_table, indx); + analyze_statement(if_else_statement->get_stmt1(), symbol_table, indx); + analyze_statement(if_else_statement->get_stmt2(), symbol_table, indx); + } break; + case ast::statementType::WHILE: + case ast::statementType::DO_WHILE: { + auto while_statement = + std::static_pointer_cast(statement); + analyze_exp(while_statement->get_exps(), symbol_table, indx); + analyze_statement(while_statement->get_stmt(), symbol_table, indx); + } break; + case ast::statementType::FOR: + analyze_for_statement( + std::static_pointer_cast(statement), + symbol_table, indx); + break; + case ast::statementType::BLOCK: { + auto block_statement = + std::static_pointer_cast(statement); + std::map, std::string> proxy_symbol_table( + symbol_table); + analyze_block(block_statement->get_block(), proxy_symbol_table, indx); + } break; + case ast::statementType::GOTO: { + std::string label = statement->get_labels().first->get_value(); + if (goto_labels.find(label) == goto_labels.end()) { + goto_labels[label] = false; + } + } break; + case ast::statementType::LABEL: { + std::string label = statement->get_labels().first->get_value(); + if (goto_labels.find(label) != goto_labels.end()) { + if (goto_labels[label] == false) { + goto_labels[label] = true; + } else { + success = false; + error_messages.emplace_back("Label " + label + " already declared"); + } + } else { + goto_labels[label] = true; + } + } break; + case ast::statementType::EXP: + analyze_exp(statement->get_exps(), symbol_table, indx); + break; + case ast::statementType::NULLSTMT: + case ast::statementType::CONTINUE: + case ast::statementType::BREAK: + break; + case ast::statementType::UNKNOWN: + UNREACHABLE() + } +} + +void parser::analyze_for_statement( + std::shared_ptr for_statement, + std::map, std::string> &symbol_table, + int indx) { + // When init is null or init is a simple expression, then + // we don't need to add another level to the symbol table + if (for_statement->get_for_init() == nullptr) { + analyze_exp(for_statement->get_exps(), symbol_table, indx); + analyze_exp(for_statement->get_exp2(), symbol_table, indx); + if (for_statement->get_stmt()->get_type() == ast::statementType::FOR) { + auto forstmt = std::static_pointer_cast( + for_statement->get_stmt()); + analyze_for_statement(forstmt, symbol_table, indx); + } else { + analyze_statement(for_statement->get_stmt(), symbol_table, indx); + } + } else if (for_statement->get_for_init()->get_declaration() == nullptr) { + analyze_exp(for_statement->get_for_init()->get_exp(), symbol_table, indx); + analyze_exp(for_statement->get_exps(), symbol_table, indx); + analyze_exp(for_statement->get_exp2(), symbol_table, indx); + if (for_statement->get_stmt()->get_type() == ast::statementType::FOR) { + auto forstmt = std::static_pointer_cast( + for_statement->get_stmt()); + analyze_for_statement(forstmt, symbol_table, indx); + } else { + analyze_statement(for_statement->get_stmt(), symbol_table, indx); + } + } else { + // Add another level to the symbol table + std::map, std::string> proxy_symbol_table( + symbol_table); + analyze_declaration(for_statement->get_for_init()->get_declaration(), + proxy_symbol_table, indx + 1); + analyze_exp(for_statement->get_exps(), proxy_symbol_table, indx + 1); + analyze_exp(for_statement->get_exp2(), proxy_symbol_table, indx + 1); + if (for_statement->get_stmt()->get_type() == ast::statementType::FOR) { + auto forstmt = std::static_pointer_cast( + for_statement->get_stmt()); + analyze_for_statement(forstmt, proxy_symbol_table, indx + 1); + } else { + analyze_statement(for_statement->get_stmt(), proxy_symbol_table, + indx + 1); + } + } +} + // NOTE: symbol table here is a map from {variable_name, block_indx} -> // temporary_variable_name(used as scar registers later) void parser::analyze_block( @@ -858,82 +938,15 @@ void parser::analyze_block( int indx) { if (block == nullptr) return; - for (auto blockItem : block->get_blockItems()) { - if (blockItem->get_type() == ast::BlockItemType::DECLARATION) { - std::string var_name = - blockItem->get_declaration()->get_identifier()->get_value(); - if (symbol_table.find({var_name, indx}) != symbol_table.end()) { - // the symbol has been declared twice which is illegal - success = false; - error_messages.emplace_back("Variable " + var_name + - " already declared"); - } else { - symbol_table[{var_name, indx}] = get_temp_name(var_name); - blockItem->get_declaration()->get_identifier()->set_identifier( - symbol_table[{var_name, indx}]); - if (blockItem->get_declaration()->get_exp() != nullptr) - analyze_exp(blockItem->get_declaration()->get_exp(), symbol_table, - indx); - } - } else if (blockItem->get_type() == ast::BlockItemType::STATEMENT) { - // every variable that is used in any of the statement should already - // have been declared. - - // We need to check that the labels used in goto statements are - // actually declared and we also need to make sure that there are no - // duplicate labels - if (blockItem->get_statement()->get_type() == ast::statementType::GOTO) { - std::string label = - blockItem->get_statement()->get_labels().first->get_value(); - if (goto_labels.find(label) == goto_labels.end()) { - goto_labels[label] = false; - } - continue; - } - - if (blockItem->get_statement()->get_type() == ast::statementType::LABEL) { - std::string label = - blockItem->get_statement()->get_labels().first->get_value(); - if (goto_labels.find(label) != goto_labels.end()) { - if (goto_labels[label] == false) { - goto_labels[label] = true; - } else { - success = false; - error_messages.emplace_back("Label " + label + " already declared"); - } - } else { - goto_labels[label] = true; - } - continue; - } - // downcast for loop statement - if (blockItem->get_statement()->get_type() == ast::statementType::FOR) { - auto forstmt = std::static_pointer_cast( - blockItem->get_statement()); - std::map, std::string> proxy_symbol_table( - symbol_table); - if (forstmt->get_for_init()->get_declaration() != nullptr) { - analyze_exp(forstmt->get_for_init()->get_declaration()->get_exp(), - proxy_symbol_table, indx); - } - if (forstmt->get_exps() != nullptr) { - analyze_exp(forstmt->get_exps(), proxy_symbol_table, indx); - } - if (forstmt->get_exp2() != nullptr) { - analyze_exp(forstmt->get_exp2(), proxy_symbol_table, indx); - } - continue; - } - if (blockItem->get_statement()->get_exps() != nullptr) { - analyze_exp(blockItem->get_statement()->get_exps(), symbol_table, indx); - } - if (blockItem->get_statement()->get_block() != nullptr) { - std::map, std::string> proxy_symbol_table( - symbol_table); - analyze_block(blockItem->get_statement()->get_block(), - proxy_symbol_table, indx + 1); - } + auto block_item = block->get_blockItems().begin(); + auto block_end = block->get_blockItems().end(); + while (block_item != block_end) { + if (((*block_item)->get_type()) == ast::BlockItemType::DECLARATION) { + analyze_declaration((*block_item)->get_declaration(), symbol_table, indx); + } else if ((*block_item)->get_type() == ast::BlockItemType::STATEMENT) { + analyze_statement((*block_item)->get_statement(), symbol_table, indx); } + block_item++; } } @@ -979,6 +992,8 @@ std::string to_string(ast::BlockItemType type) { std::string to_string(ast::statementType type) { switch (type) { + case ast::statementType::NULLSTMT: + return "NullStmt"; case ast::statementType::RETURN: return "Return"; case ast::statementType::EXP: @@ -987,10 +1002,6 @@ std::string to_string(ast::statementType type) { return "If"; case ast::statementType::IFELSE: return "IfElse"; - case ast::statementType::_IF_END: - return "_If_End"; - case ast::statementType::_IFELSE_END: - return "_IfElse_End"; case ast::statementType::GOTO: return "Goto"; case ast::statementType::LABEL: @@ -1010,7 +1021,7 @@ std::string to_string(ast::statementType type) { case ast::statementType::UNKNOWN: UNREACHABLE() } - UNREACHABLE() + return ""; } void parser::pretty_print_factor(std::shared_ptr factor) { @@ -1063,96 +1074,137 @@ void parser::pretty_print_exp(std::shared_ptr exp) { } } +void parser::pretty_print_declaration( + std::shared_ptr declaration) { + if (declaration == nullptr) + return; + std::cout << "\t\t\tDeclaration=(" << std::endl; + std::cout << "\t\t\t\tidentifier=\"" + << declaration->get_identifier()->get_value() << "\"," << std::endl; + if (declaration->get_exp() != nullptr) { + std::cout << "\t\t\t\texp=(" << std::endl; + pretty_print_exp(declaration->get_exp()); + std::cout << "\t\t\t\t)," << std::endl; + } + std::cout << "\t\t\t)" << std::endl; +} + +void parser::pretty_print_statement( + std::shared_ptr statement) { + if (statement == nullptr) + return; + std::cout << "\t\t\tStatement=(" << std::endl; + std::cout << "\t\t\t\ttype=" << to_string(statement->get_type()) << "," + << std::endl; + switch (statement->get_type()) { + case ast::statementType::RETURN: + pretty_print_exp(statement->get_exps()); + break; + case ast::statementType::IF: { + auto if_statement = + std::static_pointer_cast(statement); + std::cout << "\t\t\t\tlabels=(" + << if_statement->get_labels().first->get_value() << "," + << if_statement->get_labels().second->get_value() << ")," + << std::endl; + std::cout << "\t\t\t\texps=(" << std::endl; + pretty_print_exp(if_statement->get_exps()); + std::cout << "\t\t\t\t)," << std::endl; + std::cout << "\t\t\t\tstmt1=(" << std::endl; + pretty_print_statement(if_statement->get_stmt1()); + std::cout << "\t\t\t\t)" << std::endl; + } break; + case ast::statementType::IFELSE: { + auto if_else_statement = + std::static_pointer_cast(statement); + std::cout << "\t\t\t\tlabels=(" + << if_else_statement->get_labels().first->get_value() << "," + << if_else_statement->get_labels().second->get_value() << ")," + << std::endl; + std::cout << "\t\t\t\texps=(" << std::endl; + pretty_print_exp(if_else_statement->get_exps()); + std::cout << "\t\t\t\t)," << std::endl; + std::cout << "\t\t\t\tstmt1=(" << std::endl; + pretty_print_statement(if_else_statement->get_stmt1()); + std::cout << "\t\t\t\t)," << std::endl; + std::cout << "\t\t\t\tstmt2=(" << std::endl; + pretty_print_statement(if_else_statement->get_stmt2()); + std::cout << "\t\t\t\t)" << std::endl; + } break; + case ast::statementType::WHILE: + case ast::statementType::DO_WHILE: { + auto while_statement = + std::static_pointer_cast(statement); + std::cout << "\t\t\t\tlabels=(" + << while_statement->get_labels().first->get_value() << "," + << while_statement->get_labels().second->get_value() << ")," + << std::endl; + std::cout << "\t\t\t\texps=(" << std::endl; + pretty_print_exp(while_statement->get_exps()); + std::cout << "\t\t\t\t)," << std::endl; + std::cout << "\t\t\t\tstmt=(" << std::endl; + pretty_print_statement(while_statement->get_stmt()); + std::cout << "\t\t\t\t)" << std::endl; + } break; + case ast::statementType::FOR: { + auto for_statement = + std::static_pointer_cast(statement); + std::cout << "\t\t\t\tlabels=(" + << for_statement->get_labels().first->get_value() << "," + << for_statement->get_labels().second->get_value() << ")," + << std::endl; + if (for_statement->get_for_init() != nullptr) { + std::cout << "\t\t\t\tfor_init=(" << std::endl; + if (for_statement->get_for_init()->get_declaration() != nullptr) { + pretty_print_declaration( + for_statement->get_for_init()->get_declaration()); + } else { + pretty_print_exp(for_statement->get_for_init()->get_exp()); + } + std::cout << "\t\t\t\t)," << std::endl; + } + std::cout << "\t\t\t\tcondition=(" << std::endl; + pretty_print_exp(for_statement->get_exps()); + std::cout << "\t\t\t\t)," << std::endl; + std::cout << "\t\t\t\tpost=(" << std::endl; + pretty_print_exp(for_statement->get_exp2()); + std::cout << "\t\t\t\t)," << std::endl; + std::cout << "\t\t\t\tstmt=(" << std::endl; + pretty_print_statement(for_statement->get_stmt()); + std::cout << "\t\t\t\t)" << std::endl; + } break; + case ast::statementType::BLOCK: { + auto block_statement = + std::static_pointer_cast(statement); + pretty_print_block(block_statement->get_block()); + } break; + case ast::statementType::GOTO: + case ast::statementType::LABEL: + case ast::statementType::CONTINUE: + case ast::statementType::BREAK: + std::cout << "\t\t\t\tlabel=(" << statement->get_labels().first->get_value() + << ")" << std::endl; + break; + case ast::statementType::EXP: + pretty_print_exp(statement->get_exps()); + break; + case ast::statementType::NULLSTMT: + break; + case ast::statementType::UNKNOWN: + UNREACHABLE() + } +} + void parser::pretty_print_block(std::shared_ptr block) { if (block == nullptr) return; std::cout << "\t\t\t" << "Block=(" << std::endl; for (auto blockItem : block->get_blockItems()) { - std::cout << "\t\t\t\t" << to_string(blockItem->get_type()) << "(" - << std::endl; if (blockItem->get_type() == ast::BlockItemType::DECLARATION) { - std::cout << "\t\t\t\t\tidentifier=\"" - << blockItem->get_declaration()->get_identifier()->get_value() - << "\"," << std::endl; - if (blockItem->get_declaration()->get_exp() != nullptr) { - std::cout << "\t\t\t\t\texp=(" << std::endl; - pretty_print_exp(blockItem->get_declaration()->get_exp()); - std::cout << "\t\t\t\t\t)," << std::endl; - } + pretty_print_declaration(blockItem->get_declaration()); } else { - std::cout << "\t\t\t\t\ttype=" - << to_string(blockItem->get_statement()->get_type()) << "," - << std::endl; - if (blockItem->get_statement()->get_type() == ast::statementType::FOR) { - std::shared_ptr forstmt = - std::static_pointer_cast( - blockItem->get_statement()); - std::cout << "\t\t\t\t\tlabels=(" - << forstmt->get_labels().first->get_value() << "," - << forstmt->get_labels().second->get_value() << ")," - << std::endl; - std::cout << "\t\t\t\t\tfor_init=(" << std::endl; - if (forstmt->get_for_init() != nullptr) { - if (forstmt->get_for_init()->get_declaration() != nullptr) { - std::cout << "\t\t\t\t\t\tDeclaration=(" << std::endl; - std::cout << "\t\t\t\t\t\t\tidentifier=\"" - << forstmt->get_for_init() - ->get_declaration() - ->get_identifier() - ->get_value() - << "\"," << std::endl; - if (forstmt->get_for_init()->get_declaration()->get_exp() != - nullptr) { - std::cout << "\t\t\t\t\t\t\texp=(" << std::endl; - pretty_print_exp( - forstmt->get_for_init()->get_declaration()->get_exp()); - std::cout << "\t\t\t\t\t\t\t)," << std::endl; - } - std::cout << "\t\t\t\t\t\t)," << std::endl; - } else { - std::cout << "\t\t\t\t\t\texp=(" << std::endl; - pretty_print_exp(forstmt->get_for_init()->get_exp()); - std::cout << "\t\t\t\t\t\t)," << std::endl; - } - } - std::cout << "\t\t\t\t\t)," << std::endl; - - std::cout << "\t\t\t\t\tcondition=(" << std::endl; - if (forstmt->get_exps() != nullptr) - pretty_print_exp(forstmt->get_exps()); - std::cout << "\t\t\t\t\t)," << std::endl; - - std::cout << "\t\t\t\t\tpost=(" << std::endl; - if (forstmt->get_exp2() != nullptr) - pretty_print_exp(forstmt->get_exp2()); - std::cout << "\t\t\t\t\t)," << std::endl; - - continue; - } - if (blockItem->get_statement()->get_block() != nullptr) - pretty_print_block(blockItem->get_statement()->get_block()); - else { - if (blockItem->get_statement()->get_exps() != nullptr) { - std::cout << "\t\t\t\t\texp=(" << std::endl; - pretty_print_exp(blockItem->get_statement()->get_exps()); - std::cout << "\t\t\t\t\t)," << std::endl; - } - if (blockItem->get_statement()->get_labels().first != nullptr) { - std::cout - << "\t\t\t\t\tlabels=(" - << blockItem->get_statement()->get_labels().first->get_value(); - if (blockItem->get_statement()->get_labels().second != nullptr) { - std::cout << ","; - std::cout - << blockItem->get_statement()->get_labels().second->get_value() - << ")" << std::endl; - } else { - std::cout << ")" << std::endl; - } - } - } + pretty_print_statement(blockItem->get_statement()); } - std::cout << "\t\t\t\t)," << std::endl; } std::cout << "\t\t\t)" << std::endl; } diff --git a/parser/parser.hh b/parser/parser.hh index c0cf312..4f37aad 100644 --- a/parser/parser.hh +++ b/parser/parser.hh @@ -9,6 +9,9 @@ #include #include #include + +#define MAKE_SHARED(a, b) std::shared_ptr b = std::make_shared() + namespace scarlet { namespace parser { class parser { @@ -20,6 +23,7 @@ private: ast::AST_Program_Node program; int loop_start_counter = 0; int loop_end_counter = 0; + int ifelse_counter = 0; std::stack loop_start_labels; std::stack loop_end_labels; std::shared_ptr @@ -31,7 +35,7 @@ private: void parse_declaration(std::vector &tokens, std::shared_ptr function); void parse_statement(std::vector &tokens, - std::shared_ptr function); + std::shared_ptr stmt); void parse_for_init(std::vector &tokens, std::shared_ptr forstmt); void parse_factor(std::vector &tokens, @@ -53,6 +57,10 @@ private: void pretty_print_exp(std::shared_ptr exp); void pretty_print_factor(std::shared_ptr factor); void pretty_print_block(std::shared_ptr block); + void pretty_print_declaration( + std::shared_ptr declaration); + void + pretty_print_statement(std::shared_ptr statement); void analyze_exp(std::shared_ptr exp, std::map, std::string> &symbol_table, @@ -61,6 +69,18 @@ private: std::shared_ptr block, std::map, std::string> &symbol_table, int indx); + void analyze_declaration( + std::shared_ptr declaration, + std::map, std::string> &symbol_table, + int indx); + void analyze_statement( + std::shared_ptr statement, + std::map, std::string> &symbol_table, + int indx); + void analyze_for_statement( + std::shared_ptr for_statement, + std::map, std::string> &symbol_table, + int indx); std::string get_temp_name(std::string &name) { std::string tmp = name + "." + std::to_string(symbol_counter); @@ -68,36 +88,56 @@ private: return tmp; } - std::string get_loop_start_label() { - std::string label = "loopStart." + std::to_string(loop_start_counter); - loop_start_counter++; - loop_start_labels.push(label); - return label; + std::pair, + std::shared_ptr> + get_ifelse_labels() { + std::string if_label = "if_end." + std::to_string(ifelse_counter); + std::string else_label = "else_end." + std::to_string(ifelse_counter); + ifelse_counter++; + MAKE_SHARED(ast::AST_identifier_Node, if_label_node); + MAKE_SHARED(ast::AST_identifier_Node, else_label_node); + if_label_node->set_identifier(if_label); + else_label_node->set_identifier(else_label); + return {if_label_node, else_label_node}; } - std::string get_loop_end_label() { - std::string label = "loopEnd." + std::to_string(loop_end_counter); + std::pair, + std::shared_ptr> + get_loop_labels() { + std::string start_label = + "loop_start." + std::to_string(loop_start_counter); + std::string end_label = "loop_end." + std::to_string(loop_end_counter); + loop_start_counter++; loop_end_counter++; - loop_end_labels.push(label); - return label; + MAKE_SHARED(ast::AST_identifier_Node, start_label_node); + MAKE_SHARED(ast::AST_identifier_Node, end_label_node); + start_label_node->set_identifier(start_label); + end_label_node->set_identifier(end_label); + return {start_label_node, end_label_node}; } - std::pair get_prev_loop_start_label() { + std::shared_ptr get_prev_loop_start_label() { if (loop_start_labels.empty()) { - return {"", false}; + return nullptr; } - return {loop_start_labels.top(), true}; + MAKE_SHARED(ast::AST_identifier_Node, label); + label->set_identifier(loop_start_labels.top()); + return label; } - std::pair get_prev_loop_end_label() { + std::shared_ptr get_prev_loop_end_label() { if (loop_end_labels.empty()) { - return {"", false}; + return nullptr; } - return {loop_end_labels.top(), true}; + MAKE_SHARED(ast::AST_identifier_Node, label); + label->set_identifier(loop_end_labels.top()); + return label; } - void remove_loop_start_label() { loop_start_labels.pop(); } - void remove_loop_end_label() { loop_end_labels.pop(); } + void remove_loop_labels() { + loop_start_labels.pop(); + loop_end_labels.pop(); + } public: void parse_program(std::vector tokens); From 2a749fbc25ca58c6b51bea0672faf40405379d03 Mon Sep 17 00:00:00 2001 From: Sh0g0-1758 Date: Thu, 20 Feb 2025 03:51:18 +0530 Subject: [PATCH 5/8] a taste of victory --- CMakeLists.txt | 18 ++++++++++++++-- parser/parser.cc | 55 +++++++++++++++++++----------------------------- parser/parser.hh | 21 +++++++++--------- 3 files changed, 49 insertions(+), 45 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 1da33a1..be3b5ec 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,6 +1,18 @@ cmake_minimum_required(VERSION 3.14) project(Scarlet LANGUAGES CXX) +if(NOT CMAKE_BUILD_TYPE) + set(CMAKE_BUILD_TYPE Release CACHE STRING "Choose build type: Debug Release" FORCE) +endif() + +if(CMAKE_BUILD_TYPE STREQUAL "Debug") + message(STATUS "Building in debug mode") +elseif(CMAKE_BUILD_TYPE STREQUAL "Release") + message(STATUS "Building in release mode") +else() + message(FATAL_ERROR "Invalid build type: ${CMAKE_BUILD_TYPE}\nValid build types are: Debug, Release") +endif() + set(CMAKE_CXX_STANDARD 20) set(CMAKE_CXX_STANDARD_REQUIRED ON) @@ -26,7 +38,8 @@ function(set_basic_compile_options target) -fno-strict-aliasing -fwrapv -fpie - -O3 + $<$:-g -O0 -DDEBUG> + $<$:-O3> ) endfunction() @@ -51,10 +64,11 @@ endif() add_executable(scarlet ${SOURCES}) target_compile_options(scarlet PRIVATE - -O3 -Wall -Wextra -Werror + $<$:-g -O0 -DDEBUG> + $<$:-O3> ) add_dependencies( diff --git a/parser/parser.cc b/parser/parser.cc index 99e7c7f..c1fa149 100644 --- a/parser/parser.cc +++ b/parser/parser.cc @@ -101,25 +101,25 @@ void parser::parse_block(std::vector &tokens, } void parser::parse_block_item(std::vector &tokens, - std::shared_ptr block) { - // We have a variable declaration / defintion + std::shared_ptr &block) { + MAKE_SHARED(ast::AST_Block_Item_Node, block_item); if (tokens[0].get_token() == token::TOKEN::INT) { - parse_declaration(tokens, block); + block_item->set_type(ast::BlockItemType::DECLARATION); + MAKE_SHARED(ast::AST_Declaration_Node, declaration); + parse_declaration(tokens, declaration); + block_item->set_declaration(std::move(declaration)); } else { - // we have a return statement, an expression, an if-else block or a null - // statement - MAKE_SHARED(ast::AST_Block_Item_Node, block_item); block_item->set_type(ast::BlockItemType::STATEMENT); MAKE_SHARED(ast::AST_Statement_Node, statement); parse_statement(tokens, statement); + block_item->set_statement(std::move(statement)); } + block->add_blockItem(std::move(block_item)); } -void parser::parse_declaration(std::vector &tokens, - std::shared_ptr block) { - MAKE_SHARED(ast::AST_Block_Item_Node, block_item); - block_item->set_type(ast::BlockItemType::DECLARATION); - MAKE_SHARED(ast::AST_Declaration_Node, declaration); +void parser::parse_declaration( + std::vector &tokens, + std::shared_ptr &declaration) { EXPECT(token::TOKEN::INT); EXPECT_IDENTIFIER(); declaration->set_identifier(std::move(identifier)); @@ -134,13 +134,11 @@ void parser::parse_declaration(std::vector &tokens, declaration->set_exp(std::move(exp)); EXPECT(token::TOKEN::SEMICOLON); } - block_item->set_declaration(std::move(declaration)); - block->add_blockItem(std::move(block_item)); } void parser::parse_statement( std::vector &tokens, - std::shared_ptr statement) { + std::shared_ptr &statement) { // NOTE THESE CHECKS ARE NECESSARY BECAUSE THE FUNCTION CAN BE CALLED // RECURSIVELY if (!success) @@ -161,6 +159,7 @@ void parser::parse_statement( EXPECT(token::TOKEN::SEMICOLON); } else if (tokens[0].get_token() == token::TOKEN::IF) { + std::cout << "Parsing if statement" << std::endl; // We first check for the if (exp) statement MAKE_SHARED(ast::AST_if_else_statement_Node, if_else_statement); tokens.erase(tokens.begin()); @@ -183,6 +182,7 @@ void parser::parse_statement( // Then we optionally check for the else statement if (tokens[0].get_token() == token::TOKEN::ELSE) { + std::cout << "Parsing else statement" << std::endl; tokens.erase(tokens.begin()); if_else_statement->set_type(ast::statementType::IFELSE); @@ -290,6 +290,7 @@ void parser::parse_statement( // child class AST_For_Statement_Node to represent it. // We will use the power of down and upcasting to handle this. // for ( ; ; ) + std::cout << "Parsing for statement" << std::endl; tokens.erase(tokens.begin()); EXPECT(token::TOKEN::OPEN_PARANTHESES); @@ -340,23 +341,11 @@ void parser::parse_statement( void parser::parse_for_init( std::vector &tokens, - std::shared_ptr forstmt) { + std::shared_ptr &forstmt) { MAKE_SHARED(ast::AST_For_Init_Node, for_init); if (tokens[0].get_token() == token::TOKEN::INT) { - tokens.erase(tokens.begin()); - EXPECT_IDENTIFIER(); MAKE_SHARED(ast::AST_Declaration_Node, declaration); - declaration->set_identifier(std::move(identifier)); - if (tokens[0].get_token() == token::TOKEN::SEMICOLON) { - // the variable just have a declaration - tokens.erase(tokens.begin()); - } else { - // the variable has a definition as well - EXPECT(token::TOKEN::ASSIGNMENT); - MAKE_SHARED(ast::AST_exp_Node, exp); - parse_exp(tokens, exp); - declaration->set_exp(std::move(exp)); - } + parse_declaration(tokens, declaration); for_init->set_declaration(std::move(declaration)); } else { MAKE_SHARED(ast::AST_exp_Node, exp); @@ -397,7 +386,7 @@ parser::is_single_identifier_parentheses(std::vector &tokens) { } void parser::parse_factor(std::vector &tokens, - std::shared_ptr factor) { + std::shared_ptr &factor) { if (tokens[0].get_token() == token::TOKEN::CONSTANT) { parse_int(tokens, factor); } else if (tokens[0].get_token() == token::TOKEN::IDENTIFIER) { @@ -494,7 +483,7 @@ void parser::parse_exp(std::vector &tokens, } void parser::parse_binop(std::vector &tokens, - std::shared_ptr binop) { + std::shared_ptr &binop) { switch (tokens[0].get_token()) { case token::TOKEN::PLUS: binop->set_op(binop::BINOP::ADD); @@ -596,7 +585,7 @@ void parser::parse_binop(std::vector &tokens, } void parser::parse_unary_op(std::vector &tokens, - std::shared_ptr factor) { + std::shared_ptr &factor) { MAKE_SHARED(ast::AST_unop_Node, unop); switch (tokens[0].get_token()) { case token::TOKEN::TILDE: @@ -623,13 +612,13 @@ void parser::parse_unary_op(std::vector &tokens, void parser::parse_identifier( std::vector &tokens, - std::shared_ptr function) { + std::shared_ptr &function) { EXPECT_IDENTIFIER(); function->set_identifier(std::move(identifier)); } void parser::parse_int(std::vector &tokens, - std::shared_ptr factor) { + std::shared_ptr &factor) { EXPECT_INT(token::TOKEN::CONSTANT); } diff --git a/parser/parser.hh b/parser/parser.hh index 4f37aad..ef1093d 100644 --- a/parser/parser.hh +++ b/parser/parser.hh @@ -31,25 +31,26 @@ private: void parse_block(std::vector &tokens, std::shared_ptr block); void parse_block_item(std::vector &tokens, - std::shared_ptr function); - void parse_declaration(std::vector &tokens, - std::shared_ptr function); + std::shared_ptr &block); + void + parse_declaration(std::vector &tokens, + std::shared_ptr &declaration); void parse_statement(std::vector &tokens, - std::shared_ptr stmt); + std::shared_ptr &stmt); void parse_for_init(std::vector &tokens, - std::shared_ptr forstmt); + std::shared_ptr &forstmt); void parse_factor(std::vector &tokens, - std::shared_ptr factor); + std::shared_ptr &factor); void parse_exp(std::vector &tokens, std::shared_ptr &exp, int prec = 0); void parse_unary_op(std::vector &tokens, - std::shared_ptr factor); + std::shared_ptr &factor); void parse_identifier(std::vector &tokens, - std::shared_ptr function); + std::shared_ptr &function); void parse_int(std::vector &tokens, - std::shared_ptr factor); + std::shared_ptr &factor); void parse_binop(std::vector &tokens, - std::shared_ptr binop); + std::shared_ptr &binop); void expect(token::TOKEN actual_token, token::TOKEN expected_token); std::pair is_single_identifier_parentheses(std::vector &tokens); From 93ccf25e0d85630155a8736fea064f14df3f8532 Mon Sep 17 00:00:00 2001 From: Sh0g0-1758 Date: Thu, 20 Feb 2025 04:51:32 +0530 Subject: [PATCH 6/8] the battle is over --- CMakeLists.txt | 6 +++--- codegen/codegen.cc | 20 +++++++++++++++----- codegen/codegen.hh | 5 +++-- parser/parser.cc | 22 ++++++++-------------- parser/parser.hh | 2 ++ 5 files changed, 31 insertions(+), 24 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index be3b5ec..e74da83 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -99,11 +99,11 @@ add_custom_target(test-scarlet COMMAND echo "Running semantic analysis test" COMMAND ${CMAKE_SOURCE_DIR}/test_compiler ./scarlet --chapter 8 --stage validate COMMAND echo "Running scar test" - COMMAND ${CMAKE_SOURCE_DIR}/test_compiler ./scarlet --chapter 7 --stage tacky + COMMAND ${CMAKE_SOURCE_DIR}/test_compiler ./scarlet --chapter 8 --stage tacky COMMAND echo "Running Codegen test" - COMMAND ${CMAKE_SOURCE_DIR}/test_compiler ./scarlet --chapter 7 --stage codegen + COMMAND ${CMAKE_SOURCE_DIR}/test_compiler ./scarlet --chapter 8 --stage codegen COMMAND echo "Running bitwise, compound, increment/decrement and goto test" COMMAND ${CMAKE_SOURCE_DIR}/test_compiler ./scarlet --chapter 7 --extra-credit COMMAND echo "Running test asm" - COMMAND ${CMAKE_SOURCE_DIR}/test_compiler ./scarlet --chapter 7 + COMMAND ${CMAKE_SOURCE_DIR}/test_compiler ./scarlet --chapter 8 ) diff --git a/codegen/codegen.cc b/codegen/codegen.cc index ad998f1..ab6fb09 100644 --- a/codegen/codegen.cc +++ b/codegen/codegen.cc @@ -668,22 +668,33 @@ void Codegen::gen_scar_statement( // Label(start) // + // Label(continue) // // c = // JumpIfNotZero(c, start) // Label(end) + std::string DO_START = get_loop_start_label_name(); + MAKE_SHARED(scar::scar_Instruction_Node, scar_instruction); scar_instruction->set_type(scar::instruction_type::LABEL); MAKE_SHARED(scar::scar_Val_Node, scar_val_src); scar_val_src->set_type(scar::val_type::UNKNOWN); - scar_val_src->set_value( - do_while_statement->get_labels().first->get_value()); + scar_val_src->set_value(DO_START); scar_instruction->set_src1(std::move(scar_val_src)); scar_function->add_instruction(scar_instruction); gen_scar_statement(do_while_statement->get_stmt(), scar_function); + MAKE_SHARED(scar::scar_Instruction_Node, scar_instruction1); + scar_instruction1->set_type(scar::instruction_type::LABEL); + MAKE_SHARED(scar::scar_Val_Node, scar_val_src1); + scar_val_src1->set_type(scar::val_type::UNKNOWN); + scar_val_src1->set_value( + do_while_statement->get_labels().first->get_value()); + scar_instruction1->set_src1(std::move(scar_val_src1)); + scar_function->add_instruction(scar_instruction1); + gen_scar_exp(do_while_statement->get_exps(), scar_function); MAKE_SHARED(scar::scar_Instruction_Node, scar_instruction2); @@ -693,8 +704,7 @@ void Codegen::gen_scar_statement( scar_instruction2->set_src1(std::move(scar_val_src2)); MAKE_SHARED(scar::scar_Val_Node, scar_val_dst2); scar_val_dst2->set_type(scar::val_type::UNKNOWN); - scar_val_dst2->set_value( - do_while_statement->get_labels().first->get_value()); + scar_val_dst2->set_value(DO_START); scar_instruction2->set_dst(std::move(scar_val_dst2)); scar_function->add_instruction(scar_instruction2); @@ -732,7 +742,7 @@ void Codegen::gen_scar_statement( } } - std::string FOR_START = get_for_label_name(); + std::string FOR_START = get_loop_start_label_name(); MAKE_SHARED(scar::scar_Instruction_Node, scar_instruction); scar_instruction->set_type(scar::instruction_type::LABEL); diff --git a/codegen/codegen.hh b/codegen/codegen.hh index 098c487..7794b0b 100644 --- a/codegen/codegen.hh +++ b/codegen/codegen.hh @@ -119,8 +119,9 @@ public: res_label_stack.pop(); return tmp; } - std::string get_for_label_name() { - std::string label_name = "labelFor." + std::to_string(for_label_counter); + std::string get_loop_start_label_name() { + std::string label_name = + "labelLoopStart." + std::to_string(for_label_counter); for_label_counter++; return label_name; } diff --git a/parser/parser.cc b/parser/parser.cc index c1fa149..bb6ab87 100644 --- a/parser/parser.cc +++ b/parser/parser.cc @@ -159,7 +159,6 @@ void parser::parse_statement( EXPECT(token::TOKEN::SEMICOLON); } else if (tokens[0].get_token() == token::TOKEN::IF) { - std::cout << "Parsing if statement" << std::endl; // We first check for the if (exp) statement MAKE_SHARED(ast::AST_if_else_statement_Node, if_else_statement); tokens.erase(tokens.begin()); @@ -182,7 +181,6 @@ void parser::parse_statement( // Then we optionally check for the else statement if (tokens[0].get_token() == token::TOKEN::ELSE) { - std::cout << "Parsing else statement" << std::endl; tokens.erase(tokens.begin()); if_else_statement->set_type(ast::statementType::IFELSE); @@ -249,8 +247,8 @@ void parser::parse_statement( success = false; } else { statement->set_labels({std::move(lbl), nullptr}); - EXPECT(token::TOKEN::SEMICOLON); } + EXPECT(token::TOKEN::SEMICOLON); } else if (tokens[0].get_token() == token::TOKEN::BREAK) { tokens.erase(tokens.begin()); statement->set_type(ast::statementType::BREAK); @@ -261,9 +259,8 @@ void parser::parse_statement( success = false; } else { statement->set_labels({std::move(lbl), nullptr}); - tokens.erase(tokens.begin()); - EXPECT(token::TOKEN::SEMICOLON); } + EXPECT(token::TOKEN::SEMICOLON); } else if (tokens[0].get_token() == token::TOKEN::DO) { tokens.erase(tokens.begin()); MAKE_SHARED(ast::AST_while_statement_Node, while_statement); @@ -290,23 +287,21 @@ void parser::parse_statement( // child class AST_For_Statement_Node to represent it. // We will use the power of down and upcasting to handle this. // for ( ; ; ) - std::cout << "Parsing for statement" << std::endl; tokens.erase(tokens.begin()); EXPECT(token::TOKEN::OPEN_PARANTHESES); MAKE_SHARED(ast::AST_For_Statement_Node, for_statement); for_statement->set_type(ast::statementType::FOR); - if (tokens[0].get_token() != token::TOKEN::SEMICOLON) + if (tokens[0].get_token() != token::TOKEN::SEMICOLON) { parse_for_init(tokens, for_statement); - - EXPECT(token::TOKEN::SEMICOLON); + } else { + EXPECT(token::TOKEN::SEMICOLON); + } if (tokens[0].get_token() != token::TOKEN::SEMICOLON) { MAKE_SHARED(ast::AST_exp_Node, exp); parse_exp(tokens, exp); for_statement->set_exp(std::move(exp)); - } else { - for_statement->set_exp(nullptr); } EXPECT(token::TOKEN::SEMICOLON); @@ -315,8 +310,6 @@ void parser::parse_statement( MAKE_SHARED(ast::AST_exp_Node, exp); parse_exp(tokens, exp); for_statement->set_exp2(std::move(exp)); - } else { - for_statement->set_exp2(nullptr); } EXPECT(token::TOKEN::CLOSE_PARANTHESES); @@ -351,6 +344,7 @@ void parser::parse_for_init( MAKE_SHARED(ast::AST_exp_Node, exp); parse_exp(tokens, exp); for_init->set_exp(std::move(exp)); + EXPECT(token::TOKEN::SEMICOLON); } forstmt->set_for_init(std::move(for_init)); } @@ -840,7 +834,7 @@ void parser::analyze_statement( std::static_pointer_cast(statement); std::map, std::string> proxy_symbol_table( symbol_table); - analyze_block(block_statement->get_block(), proxy_symbol_table, indx); + analyze_block(block_statement->get_block(), proxy_symbol_table, indx + 1); } break; case ast::statementType::GOTO: { std::string label = statement->get_labels().first->get_value(); diff --git a/parser/parser.hh b/parser/parser.hh index ef1093d..9d52255 100644 --- a/parser/parser.hh +++ b/parser/parser.hh @@ -110,6 +110,8 @@ private: std::string end_label = "loop_end." + std::to_string(loop_end_counter); loop_start_counter++; loop_end_counter++; + loop_start_labels.push(start_label); + loop_end_labels.push(end_label); MAKE_SHARED(ast::AST_identifier_Node, start_label_node); MAKE_SHARED(ast::AST_identifier_Node, end_label_node); start_label_node->set_identifier(start_label); From 4abd7ab13d8655f5fa40259e7eb4081390431eff Mon Sep 17 00:00:00 2001 From: Sh0g0-1758 Date: Thu, 20 Feb 2025 05:02:38 +0530 Subject: [PATCH 7/8] final clean up --- ast/ast.hh | 12 ++++++++++++ codegen/codegen.cc | 12 ++++-------- codegen/codegen.hh | 7 ------- parser/parser.cc | 2 ++ parser/parser.hh | 11 +++++++++-- 5 files changed, 27 insertions(+), 17 deletions(-) diff --git a/ast/ast.hh b/ast/ast.hh index 7caa9ab..9cfdab9 100644 --- a/ast/ast.hh +++ b/ast/ast.hh @@ -204,6 +204,7 @@ class AST_Statement_Node { private: std::shared_ptr exps; statementType type; + // Labels serve different purpose for different statements std::pair, std::shared_ptr> labels; @@ -268,6 +269,7 @@ public: class AST_while_statement_Node : public AST_Statement_Node { private: std::shared_ptr stmt; + std::string start_label; public: std::string get_AST_name() { return "WhileStatement"; } @@ -275,6 +277,10 @@ public: void set_stmt(std::shared_ptr stmt) { this->stmt = std::move(stmt); } + std::string get_start_label() { return start_label; } + void set_start_label(std::string &&start_label) { + this->start_label = std::move(start_label); + } }; enum class DeclarationType { INT }; @@ -328,6 +334,7 @@ private: std::shared_ptr for_init; std::shared_ptr exp2; std::shared_ptr stmt; + std::string start_label; public: std::string get_AST_name() { return "ForStatement"; } @@ -344,6 +351,11 @@ public: void set_stmt(std::shared_ptr stmt) { this->stmt = std::move(stmt); } + + std::string get_start_label() { return start_label; } + void set_start_label(std::string &&start_label) { + this->start_label = std::move(start_label); + } }; enum class BlockItemType { UNKNOWN, STATEMENT, DECLARATION }; diff --git a/codegen/codegen.cc b/codegen/codegen.cc index ab6fb09..6fbe234 100644 --- a/codegen/codegen.cc +++ b/codegen/codegen.cc @@ -674,13 +674,11 @@ void Codegen::gen_scar_statement( // JumpIfNotZero(c, start) // Label(end) - std::string DO_START = get_loop_start_label_name(); - MAKE_SHARED(scar::scar_Instruction_Node, scar_instruction); scar_instruction->set_type(scar::instruction_type::LABEL); MAKE_SHARED(scar::scar_Val_Node, scar_val_src); scar_val_src->set_type(scar::val_type::UNKNOWN); - scar_val_src->set_value(DO_START); + scar_val_src->set_value(do_while_statement->get_start_label()); scar_instruction->set_src1(std::move(scar_val_src)); scar_function->add_instruction(scar_instruction); @@ -704,7 +702,7 @@ void Codegen::gen_scar_statement( scar_instruction2->set_src1(std::move(scar_val_src2)); MAKE_SHARED(scar::scar_Val_Node, scar_val_dst2); scar_val_dst2->set_type(scar::val_type::UNKNOWN); - scar_val_dst2->set_value(DO_START); + scar_val_dst2->set_value(do_while_statement->get_start_label()); scar_instruction2->set_dst(std::move(scar_val_dst2)); scar_function->add_instruction(scar_instruction2); @@ -742,13 +740,11 @@ void Codegen::gen_scar_statement( } } - std::string FOR_START = get_loop_start_label_name(); - MAKE_SHARED(scar::scar_Instruction_Node, scar_instruction); scar_instruction->set_type(scar::instruction_type::LABEL); MAKE_SHARED(scar::scar_Val_Node, scar_val_src); scar_val_src->set_type(scar::val_type::UNKNOWN); - scar_val_src->set_value(FOR_START); + scar_val_src->set_value(for_statement->get_start_label()); scar_instruction->set_src1(std::move(scar_val_src)); scar_function->add_instruction(scar_instruction); @@ -781,7 +777,7 @@ void Codegen::gen_scar_statement( scar_instruction4->set_type(scar::instruction_type::JUMP); MAKE_SHARED(scar::scar_Val_Node, scar_val_src4); scar_val_src4->set_type(scar::val_type::UNKNOWN); - scar_val_src4->set_value(FOR_START); + scar_val_src4->set_value(for_statement->get_start_label()); scar_instruction4->set_src1(std::move(scar_val_src4)); scar_function->add_instruction(scar_instruction4); diff --git a/codegen/codegen.hh b/codegen/codegen.hh index 7794b0b..9444c4a 100644 --- a/codegen/codegen.hh +++ b/codegen/codegen.hh @@ -64,7 +64,6 @@ private: std::shared_ptr scar_function); void gen_scar_block(std::shared_ptr block, std::shared_ptr scar_function); - int for_label_counter = 1; int fr_label_counter = 1; int res_label_counter = 1; std::stack fr_label_stack; @@ -119,12 +118,6 @@ public: res_label_stack.pop(); return tmp; } - std::string get_loop_start_label_name() { - std::string label_name = - "labelLoopStart." + std::to_string(for_label_counter); - for_label_counter++; - return label_name; - } std::map compound_to_base = { {binop::BINOP::COMPOUND_DIFFERENCE, binop::BINOP::SUB}, {binop::BINOP::COMPOUND_DIVISION, binop::BINOP::DIV}, diff --git a/parser/parser.cc b/parser/parser.cc index bb6ab87..165fa93 100644 --- a/parser/parser.cc +++ b/parser/parser.cc @@ -266,6 +266,7 @@ void parser::parse_statement( MAKE_SHARED(ast::AST_while_statement_Node, while_statement); while_statement->set_type(ast::statementType::DO_WHILE); while_statement->set_labels(get_loop_labels()); + while_statement->set_start_label(get_loop_start_label()); MAKE_SHARED(ast::AST_Statement_Node, stmt); parse_statement(tokens, stmt); @@ -315,6 +316,7 @@ void parser::parse_statement( EXPECT(token::TOKEN::CLOSE_PARANTHESES); for_statement->set_labels(get_loop_labels()); + for_statement->set_start_label(get_loop_start_label()); MAKE_SHARED(ast::AST_Statement_Node, stmt); parse_statement(tokens, stmt); diff --git a/parser/parser.hh b/parser/parser.hh index 9d52255..68eea14 100644 --- a/parser/parser.hh +++ b/parser/parser.hh @@ -22,6 +22,7 @@ private: std::map goto_labels; ast::AST_Program_Node program; int loop_start_counter = 0; + int loop_continue_counter = 0; int loop_end_counter = 0; int ifelse_counter = 0; std::stack loop_start_labels; @@ -106,9 +107,9 @@ private: std::shared_ptr> get_loop_labels() { std::string start_label = - "loop_start." + std::to_string(loop_start_counter); + "loop_continue." + std::to_string(loop_continue_counter); std::string end_label = "loop_end." + std::to_string(loop_end_counter); - loop_start_counter++; + loop_continue_counter++; loop_end_counter++; loop_start_labels.push(start_label); loop_end_labels.push(end_label); @@ -119,6 +120,12 @@ private: return {start_label_node, end_label_node}; } + std::string get_loop_start_label() { + std::string label = "loop_start." + std::to_string(loop_start_counter); + loop_start_counter++; + return label; + } + std::shared_ptr get_prev_loop_start_label() { if (loop_start_labels.empty()) { return nullptr; From 25d4cd87c60d61a2184b2471865667d623f8caa7 Mon Sep 17 00:00:00 2001 From: Sh0g0-1758 Date: Thu, 20 Feb 2025 05:04:08 +0530 Subject: [PATCH 8/8] update docs --- README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index a84dba9..ae37344 100644 --- a/README.md +++ b/README.md @@ -63,7 +63,8 @@ Scarlet currently supports the following architectures: - [x] Add support for compound operators (+=,-=,*=,/=,<<=,>>=,%=) - [x] Add support for goto statement - [x] Add support for compound statements -- [ ] Add support for Loops +- [x] Add support for Loops (for, while, do-while) +- [ ] Add support for switch-case - [ ] Add support for Functions - [ ] Add support for static keyword and global scope - [ ] Add support for Long Integers