From 2be60b930f723e907b6a21acb49ce50236adf299 Mon Sep 17 00:00:00 2001 From: MatthewGodsmark Date: Thu, 21 Mar 2024 02:08:11 +0000 Subject: [PATCH] Added loops --- include/ast.hpp | 3 ++ include/ast_for_statement.hpp | 53 +++++++++++++++++++++++++++ include/ast_switch_statement.hpp | 59 ++++++++++++++++++++++++++++++ include/ast_while_statement.hpp | 42 +++++++++++++++++++++ src/ast_add_statement.cpp | 2 +- src/ast_for_statement.cpp | 63 ++++++++++++++++++++++++++++++++ src/ast_if_statement.cpp | 10 ++--- src/ast_switch_statement.cpp | 55 ++++++++++++++++++++++++++++ src/ast_while_statement.cpp | 51 ++++++++++++++++++++++++++ src/parser.y | 14 +++---- 10 files changed, 339 insertions(+), 13 deletions(-) create mode 100644 include/ast_for_statement.hpp create mode 100644 include/ast_switch_statement.hpp create mode 100644 include/ast_while_statement.hpp create mode 100644 src/ast_for_statement.cpp create mode 100644 src/ast_switch_statement.cpp create mode 100644 src/ast_while_statement.cpp diff --git a/include/ast.hpp b/include/ast.hpp index c0adbf2..3a05824 100644 --- a/include/ast.hpp +++ b/include/ast.hpp @@ -19,6 +19,9 @@ #include "ast_variable_ref.hpp" #include "ast_if_statement.hpp" +#include "ast_switch_statement.hpp" +#include "ast_while_statement.hpp" +#include "ast_for_statement.hpp" #include "ast_add_statement.hpp" // #include "ast_assign_operator.hpp" diff --git a/include/ast_for_statement.hpp b/include/ast_for_statement.hpp new file mode 100644 index 0000000..75207d1 --- /dev/null +++ b/include/ast_for_statement.hpp @@ -0,0 +1,53 @@ +#ifndef AST_FOR_STATEMENT_HPP +#define AST_FOR_STATEMENT_HPP + +#include "ast_node.hpp" + +class ForStatement : public Node +{ +private: + Node *expression_statement_initialize_; + Node *expression_statement_loop_; + Node *statement_; + +public: + ForStatement(Node *expression_statement_initialize, Node *expression_statement_loop, Node *statement) : expression_statement_initialize_(expression_statement_initialize), + expression_statement_loop_(expression_statement_loop), + statement_(statement){}; + ~ForStatement() + { + delete expression_statement_initialize_; + delete expression_statement_loop_; + delete statement_; + }; + + void EmitRISC(std::ostream &stream, Context &context) const override; + void Print(std::ostream &stream) const override; +}; + +class ExprForStatement : public Node +{ +private: + Node *expression_statement_initialize_; + Node *expression_statement_loop_; + Node *expression_; + Node *statement_; + +public: + ExprForStatement(Node *expression_statement_initialize, Node *expression_statement_loop, Node *expression, Node *statement) : expression_statement_initialize_(expression_statement_initialize), + expression_statement_loop_(expression_statement_loop), + expression_(expression), + statement_(statement){}; + ~ExprForStatement() + { + delete expression_statement_initialize_; + delete expression_statement_loop_; + delete expression_; + delete statement_; + }; + + void EmitRISC(std::ostream &stream, Context &context) const override; + void Print(std::ostream &stream) const override; +}; + +#endif diff --git a/include/ast_switch_statement.hpp b/include/ast_switch_statement.hpp new file mode 100644 index 0000000..2e3dc3e --- /dev/null +++ b/include/ast_switch_statement.hpp @@ -0,0 +1,59 @@ +#ifndef AST_SWITCH_STATEMENT_HPP +#define AST_SWITCH_STATEMENT_HPP + +#include "ast_node.hpp" + +class SwitchStatement : public Node +{ +private: + Node *expression_; + Node *statement_; + +public: + SwitchStatement(Node *expression, Node *statement) : expression_(expression), statement_(statement){}; + ~SwitchStatement() + { + delete expression_; + delete statement_; + }; + + void EmitRISC(std::ostream &stream, Context &context) const override; + void Print(std::ostream &stream) const override; +}; + +class CaseStatement : public Node +{ +private: + Node *constant_expression_; + Node *statement_; + +public: + CaseStatement(Node *constant_expression, Node *statement) : constant_expression_(constant_expression), statement_(statement){}; + ~CaseStatement() + { + delete constant_expression_; + delete statement_; + }; + + void EmitRISC(std::ostream &stream, Context &context) const override; + void Print(std::ostream &stream) const override; +}; + +class DefaultStatement : public Node +{ +private: + Node *statement_; + +public: + DefaultStatement(Node *statement) : statement_(statement){}; + ~DefaultStatement() + { + delete statement_; + }; + + void EmitRISC(std::ostream &stream, Context &context) const override; + void Print(std::ostream &stream) const override; +}; + +#endif + diff --git a/include/ast_while_statement.hpp b/include/ast_while_statement.hpp new file mode 100644 index 0000000..6eac9d0 --- /dev/null +++ b/include/ast_while_statement.hpp @@ -0,0 +1,42 @@ +#ifndef AST_WHILE_STATEMENT_HPP +#define AST_WHILE_STATEMENT_HPP + +#include "ast_node.hpp" + +class WhileStatement : public Node +{ +private: + Node *expression_; + Node *statement_; + +public: + WhileStatement(Node *expression, Node *statement) : expression_(expression), statement_(statement){}; + ~WhileStatement() + { + delete expression_; + delete statement_; + }; + + void EmitRISC(std::ostream &stream, Context &context) const override; + void Print(std::ostream &stream) const override; +}; + +class DoWhileStatement : public Node +{ +private: + Node *statement_; + Node *expression_; + +public: + DoWhileStatement(Node *statement, Node *expression) : statement_(statement), expression_(expression){}; + ~DoWhileStatement() + { + delete statement_; + delete expression_; + }; + + void EmitRISC(std::ostream &stream, Context &context) const override; + void Print(std::ostream &stream) const override; +}; + +#endif diff --git a/src/ast_add_statement.cpp b/src/ast_add_statement.cpp index cd542fc..c2990cf 100644 --- a/src/ast_add_statement.cpp +++ b/src/ast_add_statement.cpp @@ -5,7 +5,7 @@ void AddStatement::EmitRISC(std::ostream &stream, Context &context) const additive_expression_->EmitRISC(stream, context); - stream << "mv t0, a0" << std::endl; // find register that expression_->EmitRISC(stream, context); is saved into + stream << "mv t0, a0" << std::endl; multiplicative_expression_->EmitRISC(stream, context); diff --git a/src/ast_for_statement.cpp b/src/ast_for_statement.cpp new file mode 100644 index 0000000..d9d0cd2 --- /dev/null +++ b/src/ast_for_statement.cpp @@ -0,0 +1,63 @@ +#include "ast_for_statement.hpp" + +void ForStatement::EmitRISC(std::ostream &stream, Context &context) const +{ + + expression_statement_initialize_->EmitRISC(stream, context); + + stream << "start:" << std::endl; + + expression_statement_loop_->EmitRISC(stream, context); + + stream << "beqz a0, end" << std::endl; + + statement_->EmitRISC(stream, context); + + stream << "beqz zero, start" << std::endl; + + stream << "end:" << std::endl; +} + +void ForStatement::Print(std::ostream &stream) const +{ + stream << "for("; + expression_statement_initialize_->Print(stream); + stream << "; "; + expression_statement_loop_->Print(stream); + stream << "){" << std::endl; + statement_->Print(stream); + stream << "}" << std::endl; +} + +void ExprForStatement::EmitRISC(std::ostream &stream, Context &context) const +{ + + expression_statement_initialize_->EmitRISC(stream, context); + + stream << "start:" << std::endl; + + expression_statement_loop_->EmitRISC(stream, context); + + stream << "beqz a0, end" << std::endl; + + statement_->EmitRISC(stream, context); + + expression_->EmitRISC(stream, context); + + stream << "beqz zero, start" << std::endl; + + stream << "end:" << std::endl; +} + +void ExprForStatement::Print(std::ostream &stream) const +{ + stream << "for("; + expression_statement_initialize_->Print(stream); + stream << "; "; + expression_statement_loop_->Print(stream); + stream << "; "; + expression_->Print(stream); + stream << "){" << std::endl; + statement_->Print(stream); + stream << "}" << std::endl; +} diff --git a/src/ast_if_statement.cpp b/src/ast_if_statement.cpp index 8d14d6b..80ed681 100644 --- a/src/ast_if_statement.cpp +++ b/src/ast_if_statement.cpp @@ -14,9 +14,9 @@ void IfStatement::EmitRISC(std::ostream &stream, Context &context) const void IfStatement::Print(std::ostream &stream) const { - stream << "if ( "; + stream << "if("; expression_->Print(stream); - stream << " ) { " << std::endl; + stream << " ){" << std::endl; statement_->Print(stream); stream << "}" << std::endl; } @@ -41,12 +41,12 @@ void IfElseStatement::EmitRISC(std::ostream &stream, Context &context) const void IfElseStatement::Print(std::ostream &stream) const { - stream << "if ( "; + stream << "if("; expression_->Print(stream); - stream << " ) { " << std::endl; + stream << "){" << std::endl; statement_->Print(stream); stream << "}" << std::endl; - stream << "else {"; + stream << "else{"; elsestatement_->Print(stream); stream << "}" << std::endl; diff --git a/src/ast_switch_statement.cpp b/src/ast_switch_statement.cpp new file mode 100644 index 0000000..e484cee --- /dev/null +++ b/src/ast_switch_statement.cpp @@ -0,0 +1,55 @@ +#include "ast_switch_statement.hpp" + +void SwitchStatement::EmitRISC(std::ostream &stream, Context &context) const +{ + + expression_->EmitRISC(stream, context); + + stream << "mv t0, a0" << std::endl; + + statement_->EmitRISC(stream, context); + +} + +void SwitchStatement::Print(std::ostream &stream) const +{ + stream << "switch("; + expression_->Print(stream); + stream << "){" << std::endl; + statement_->Print(stream); + stream << "}" << std::endl; +} + +void CaseStatement::EmitRISC(std::ostream &stream, Context &context) const +{ + + constant_expression_->EmitRISC(stream, context); + + stream << "BNE t0, a0, NotEqual" << std::endl; // Give branches different names + + statement_->EmitRISC(stream, context); + + stream << "NotEqual:" << std::endl; + +} + +void CaseStatement::Print(std::ostream &stream) const +{ + stream << "case "; + constant_expression_->Print(stream); + stream << ":" << std::endl; + statement_->Print(stream); +} + +void DefaultStatement::EmitRISC(std::ostream &stream, Context &context) const +{ + + statement_->EmitRISC(stream, context); + +} + +void DefaultStatement::Print(std::ostream &stream) const +{ + stream << "default: "; + statement_->Print(stream); +} diff --git a/src/ast_while_statement.cpp b/src/ast_while_statement.cpp new file mode 100644 index 0000000..e8a0ebd --- /dev/null +++ b/src/ast_while_statement.cpp @@ -0,0 +1,51 @@ +#include "ast_while_statement.hpp" + +void WhileStatement::EmitRISC(std::ostream &stream, Context &context) const +{ + + stream << "start:" << std::endl; + + expression_->EmitRISC(stream, context); + + stream << "beqz a0, end" << std::endl; + + statement_->EmitRISC(stream, context); + + stream << "beqz zero, start" << std::endl; + + stream << "end:" << std::endl; +} + +void WhileStatement::Print(std::ostream &stream) const +{ + stream << "while("; + expression_->Print(stream); + stream << "){" << std::endl; + statement_->Print(stream); + stream << "}" << std::endl; +} + +void DoWhileStatement::EmitRISC(std::ostream &stream, Context &context) const +{ + + stream << "start:" << std::endl; + + statement_->EmitRISC(stream, context); + + expression_->EmitRISC(stream, context); + + stream << "beqz a0, end" << std::endl; + + stream << "beqz zero, start" << std::endl; + + stream << "end:" << std::endl; +} + +void DoWhileStatement::Print(std::ostream &stream) const +{ + stream << "do{"; + statement_->Print(stream); + stream << "}while("; + expression_->Print(stream); + stream << ");" << std::endl; +} diff --git a/src/parser.y b/src/parser.y index 95a5c24..b0dbc29 100644 --- a/src/parser.y +++ b/src/parser.y @@ -480,10 +480,10 @@ labeled_statement assert(!"Unimplemented"); } | CASE constant_expression ':' statement { - assert(!"Unimplemented"); + $$ = new CaseStatement($2, $4); } | DEFAULT ':' statement { - assert(!"Unimplemented"); + $$ = new DefaultStatement($3); } ; @@ -525,22 +525,22 @@ selection_statement $$ = new IfElseStatement($3, $5, $7); } | SWITCH '(' expression ')' statement { - assert(!"Unimplemented"); + $$ = new SwitchStatement($3, $5); } ; iteration_statement : WHILE '(' expression ')' statement { - assert(!"Unimplemented"); + $$ = new WhileStatement($3, $5); } | DO statement WHILE '(' expression ')' ';' { - assert(!"Unimplemented"); + $$ = new DoWhileStatement($2, $5); } | FOR '(' expression_statement expression_statement ')' statement { - assert(!"Unimplemented"); + $$ = new ForStatement($3, $4, $6); } | FOR '(' expression_statement expression_statement expression ')' statement { - assert(!"Unimplemented"); + $$ = new ExprForStatement($3, $4, $5, $7); } ;