diff --git a/README.md b/README.md index 6903e26..40ae135 100644 --- a/README.md +++ b/README.md @@ -34,7 +34,7 @@ program = [ "type" type_definitions ";" ] [ constant_part ] { procedure_definition } [ variable_part ] - compound_statement "."; + "begin" [ statement_list ] "end" "."; procedure_definition = "proc" ident formal_parameter_list ";" ( block | "extern" ) ";"; @@ -45,14 +45,18 @@ block = [ constant_part ] constant_part = "const" ident "=" integer { "," ident "=" integer } ";"; variable_part = "var" variable_declarations ";"; -statement = compound_statement - | ident ":=" expression +statement = ident ":=" expression | ident actual_parameter_list - | "while" condition "do" statement - | "if" expression "then" statement [ else statement ]; + | while_do + | if_then_else; + + +while_do = "while" condition "do" [ statement_list ] "end"; +if_then_else = "if" expression + "then" [ statement_list ] + [ else statement_list ] "end"; statement_list = statement {";" statement }; -compound_statement = "begin" [ statement_list ] "end"; condition = "odd" expression | expression ("="|"#"|"<"|"<="|">"|">=") expression; @@ -86,7 +90,7 @@ variable_declarations = variable_declaration { ";" variable_declaration }; variable_declaration = ident ":" type_expression; type_expression = "array" integer "of" type_expression - | "^" type_expression + | "pointer" "to" type_expression | "record" field_list "end" | ident; diff --git a/include/elna/source/ast.h b/include/elna/source/ast.h index dd99e53..95e9a74 100644 --- a/include/elna/source/ast.h +++ b/include/elna/source/ast.h @@ -443,13 +443,11 @@ namespace source class compound_statement : public statement { - std::vector m_statements; - public: - explicit compound_statement(const struct position position); - virtual void accept(parser_visitor *visitor) override; + std::vector statements; - std::vector& statements(); + compound_statement(const struct position position, std::vector&& statements); + virtual void accept(parser_visitor *visitor) override; virtual ~compound_statement() override; }; @@ -556,8 +554,8 @@ namespace source class if_statement : public statement { expression *m_prerequisite; - statement *m_body; - statement *m_alternative; + compound_statement *m_body; + compound_statement *m_alternative; public: /** @@ -567,12 +565,12 @@ namespace source * \param alternative Statement executed if the condition is not met. */ if_statement(const struct position position, expression *prerequisite, - statement *body, statement *alternative = nullptr); + compound_statement *body, compound_statement *alternative = nullptr); virtual void accept(parser_visitor *visitor) override; expression& prerequisite(); - statement& body(); - statement *alternative(); + compound_statement& body(); + compound_statement *alternative(); virtual ~if_statement() override; }; @@ -583,7 +581,7 @@ namespace source class while_statement : public statement { expression *m_prerequisite; - statement *m_body; + compound_statement *m_body; public: /** @@ -592,11 +590,11 @@ namespace source * \param body Statement executed while the condition is met. */ while_statement(const struct position position, expression *prerequisite, - statement *body); + compound_statement *body); virtual void accept(parser_visitor *visitor) override; expression& prerequisite(); - statement& body(); + compound_statement& body(); virtual ~while_statement() override; }; diff --git a/source/ast.cc b/source/ast.cc index fdbe984..5f8b90c 100644 --- a/source/ast.cc +++ b/source/ast.cc @@ -43,7 +43,7 @@ namespace source void empty_visitor::visit(compound_statement *statement) { - for (auto& nested_statement : statement->statements()) + for (const auto nested_statement : statement->statements) { nested_statement->accept(this); } @@ -766,8 +766,8 @@ namespace source } } - compound_statement::compound_statement(const struct position position) - : statement(position) + compound_statement::compound_statement(const struct position position, std::vector&& statements) + : statement(position), statements(std::move(statements)) { } @@ -776,14 +776,9 @@ namespace source visitor->visit(this); } - std::vector& compound_statement::statements() - { - return m_statements; - } - compound_statement::~compound_statement() { - for (auto statement : m_statements) + for (auto statement : statements) { delete statement; } @@ -836,7 +831,7 @@ namespace source } if_statement::if_statement(const struct position position, expression *prerequisite, - statement *body, statement *alternative) + compound_statement *body, compound_statement *alternative) : statement(position), m_prerequisite(prerequisite), m_body(body), m_alternative(alternative) { @@ -852,12 +847,12 @@ namespace source return *m_prerequisite; } - statement& if_statement::body() + compound_statement& if_statement::body() { return *m_body; } - statement *if_statement::alternative() + compound_statement *if_statement::alternative() { return m_alternative; } @@ -874,7 +869,7 @@ namespace source } while_statement::while_statement(const struct position position, expression *prerequisite, - statement *body) + compound_statement *body) : statement(position), m_prerequisite(prerequisite), m_body(body) { } @@ -889,7 +884,7 @@ namespace source return *m_prerequisite; } - statement& while_statement::body() + compound_statement& while_statement::body() { return *m_body; } diff --git a/source/lexer.ll b/source/lexer.ll index 6f5c397..4ab1d35 100644 --- a/source/lexer.ll +++ b/source/lexer.ll @@ -76,6 +76,12 @@ type { record { return yy::parser::make_RECORD(this->location); } +pointer { + return yy::parser::make_POINTER(this->location); + } +to { + return yy::parser::make_TO(this->location); + } true { return yy::parser::make_BOOLEAN(true, this->location); } diff --git a/source/parser.yy b/source/parser.yy index 57aaf5a..3529352 100644 --- a/source/parser.yy +++ b/source/parser.yy @@ -62,8 +62,8 @@ %token CHARACTER "character" %token STRING "string" %token BOOLEAN -%token IF WHILE DO -%token CONST VAR PROCEDURE ARRAY OF TYPE RECORD +%token IF WHILE DO THEN ELSE +%token CONST VAR PROCEDURE ARRAY OF TYPE RECORD POINTER TO %token BEGIN_BLOCK END_BLOCK EXTERN %token LEFT_PAREN RIGHT_PAREN LEFT_SQUARE RIGHT_SQUARE SEMICOLON DOT COMMA %token AND OR NOT @@ -71,9 +71,6 @@ %token PLUS MINUS MULTIPLICATION DIVISION %token ASSIGNMENT COLON HAT AT -%precedence THEN -%precedence ELSE - %type literal; %type constant_definition; %type > constant_part constant_definitions; @@ -84,7 +81,6 @@ %type expression pointer summand factor comparand logical_operand; %type > expressions actual_parameter_list; %type designator_expression; -%type compound_statement; %type assign_statement; %type call_statement; %type while_statement; @@ -167,11 +163,6 @@ procedure_definitions: procedure_part: /* no procedure definitions */ {} | procedure_definitions { std::swap($$, $1); } -compound_statement: BEGIN_BLOCK optional_statements END_BLOCK - { - $$ = new elna::source::compound_statement(elna::source::make_position(@1)); - std::swap($$->statements(), $2); - } assign_statement: designator_expression ASSIGNMENT expression { $$ = new elna::source::assign_statement(elna::source::make_position(@1), $1, $3); @@ -181,21 +172,22 @@ call_statement: IDENTIFIER actual_parameter_list $$ = new elna::source::call_statement(elna::source::make_position(@1), $1); std::swap($$->arguments(), $2); } -while_statement: WHILE expression DO statement +while_statement: WHILE expression DO optional_statements END_BLOCK { - $$ = new elna::source::while_statement(elna::source::make_position(@1), - $2, $4); + auto body = new elna::source::compound_statement(elna::source::make_position(@3), std::move($4)); + $$ = new elna::source::while_statement(elna::source::make_position(@1), $2, body); } if_statement: - IF expression THEN statement + IF expression THEN optional_statements END_BLOCK { - $$ = new elna::source::if_statement(elna::source::make_position(@1), - $2, $4); + auto then = new elna::source::compound_statement(elna::source::make_position(@3), std::move($4)); + $$ = new elna::source::if_statement(elna::source::make_position(@1), $2, then); } - | IF expression THEN statement ELSE statement + | IF expression THEN optional_statements ELSE optional_statements END_BLOCK { - $$ = new elna::source::if_statement(elna::source::make_position(@1), - $2, $4, $6); + auto then = new elna::source::compound_statement(elna::source::make_position(@3), std::move($4)); + auto _else = new elna::source::compound_statement(elna::source::make_position(@5), std::move($6)); + $$ = new elna::source::if_statement(elna::source::make_position(@1), $2, then, _else); } literal: INTEGER @@ -315,8 +307,7 @@ designator_expression: $$ = new elna::source::variable_expression(elna::source::make_position(@1), $1); } statement: - compound_statement { $$ = $1; } - | assign_statement { $$ = $1; } + assign_statement { $$ = $1; } | call_statement { $$ = $1; } | while_statement { $$ = $1; } | if_statement { $$ = $1; } @@ -344,9 +335,9 @@ type_expression: { $$ = new elna::source::array_type_expression(elna::source::make_position(@1), $4, $2); } - | HAT type_expression + | POINTER TO type_expression { - $$ = new elna::source::pointer_type_expression(elna::source::make_position(@1), $2); + $$ = new elna::source::pointer_type_expression(elna::source::make_position(@1), $3); } | RECORD field_list END_BLOCK {