diff options
| -rw-r--r-- | boot/ast.cc | 15 | ||||
| -rw-r--r-- | boot/parser.yy | 28 | ||||
| -rw-r--r-- | boot/semantic.cc | 8 | ||||
| -rw-r--r-- | doc/appendix.tex | 46 | ||||
| -rw-r--r-- | doc/language.tex | 4 | ||||
| -rw-r--r-- | gcc/gcc/elna-generic.cc | 4 | ||||
| -rw-r--r-- | include/elna/boot/ast.h | 10 | ||||
| -rw-r--r-- | include/elna/boot/semantic.h | 4 | ||||
| -rw-r--r-- | include/elna/gcc/elna-generic.h | 1 | ||||
| -rw-r--r-- | testsuite/compilable/empty_statements_in_a_row.elna | 6 |
10 files changed, 83 insertions, 43 deletions
diff --git a/boot/ast.cc b/boot/ast.cc index e4c46a4..91b46a4 100644 --- a/boot/ast.cc +++ b/boot/ast.cc @@ -114,6 +114,11 @@ namespace elna::boot not_implemented(); } + void empty_visitor::visit(empty_statement *) + { + not_implemented(); + } + void empty_visitor::visit(case_statement *) { not_implemented(); @@ -702,6 +707,16 @@ namespace elna::boot } } + void empty_statement::accept(parser_visitor *visitor) + { + visitor->visit(this); + } + + empty_statement::empty_statement(const struct position position) + : node(position) + { + } + designator_expression::~designator_expression() { } diff --git a/boot/parser.yy b/boot/parser.yy index 1a5364b..4d4f038 100644 --- a/boot/parser.yy +++ b/boot/parser.yy @@ -140,7 +140,7 @@ along with GCC; see the file COPYING3. If not see %type <elna::boot::procedure_call*> call_expression; %type <elna::boot::return_statement *> return_statement; %type <elna::boot::statement *> statement; -%type <std::vector<elna::boot::statement *>> required_statements optional_statements; +%type <std::vector<elna::boot::statement *>> statements; %type <std::unique_ptr<std::vector<elna::boot::statement *>>> statement_part; %type <elna::boot::procedure_declaration *> procedure_declaration; %type <std::pair<std::vector<std::string>, elna::boot::procedure_type_expression *>> procedure_heading; @@ -193,12 +193,12 @@ block: constant_part variable_part statement_part "end" } statement_part: /* no statements */ {} - | "begin" required_statements { $$ = std::make_unique<std::vector<boot::statement *>>(std::move($2));; } + | "begin" statements { $$ = std::make_unique<std::vector<boot::statement *>>(std::move($2));; } | return_statement { $$ = std::make_unique<std::vector<boot::statement *>>(std::vector<boot::statement *>{ $1 }); } - | "begin" required_statements ";" return_statement + | "begin" statements ";" return_statement { $$ = std::make_unique<std::vector<boot::statement *>>(std::move($2)); $$->push_back($4); @@ -253,7 +253,7 @@ call_expression: designator_expression actual_parameter_list cast_expression: "cast" "(" expression ":" type_expression ")" { $$ = new boot::cast_expression(boot::make_position(@1), $5, $3); } elsif_do_statements: - "elsif" expression "do" optional_statements elsif_do_statements + "elsif" expression "do" statements elsif_do_statements { boot::conditional_statements *branch = new boot::conditional_statements($2, std::move($4)); std::swap($5, $$); @@ -261,10 +261,10 @@ elsif_do_statements: } | {} else_statements: - "else" optional_statements { $$ = new std::vector<boot::statement *>(std::move($2)); } + "else" statements { $$ = new std::vector<boot::statement *>(std::move($2)); } | { $$ = nullptr; } elsif_then_statements: - "elsif" expression "then" optional_statements elsif_then_statements + "elsif" expression "then" statements elsif_then_statements { boot::conditional_statements *branch = new boot::conditional_statements($2, std::move($4)); std::swap($5, $$); @@ -406,22 +406,23 @@ designator_expression: statement: designator_expression ":=" expression { $$ = new boot::assign_statement(boot::make_position(@1), $1, $3); } - | "while" expression "do" optional_statements elsif_do_statements "end" + | "while" expression "do" statements elsif_do_statements "end" { boot::conditional_statements *body = new boot::conditional_statements($2, std::move($4)); $$ = new boot::while_statement(boot::make_position(@1), body, std::move($5)); } - | "if" expression "then" optional_statements elsif_then_statements else_statements "end" + | "if" expression "then" statements elsif_then_statements else_statements "end" { boot::conditional_statements *then = new boot::conditional_statements($2, std::move($4)); $$ = new boot::if_statement(boot::make_position(@1), then, std::move($5), $6); } | call_expression { $$ = $1; } - | "defer" optional_statements "end" + | "defer" statements "end" { $$ = new boot::defer_statement(boot::make_position(@1), std::move($2)); } | "case" expression "of" switch_cases else_statements "end" { $$ = new boot::case_statement(boot::make_position(@1), $2, std::move($4), $5); } -switch_case: case_labels ":" optional_statements + | { $$ = new boot::empty_statement(boot::make_position(@$)); } +switch_case: case_labels ":" statements { $$ = { .labels = std::move($1), .statements = std::move($3) }; } switch_cases: switch_case "|" switch_cases @@ -437,16 +438,13 @@ case_labels: $$.emplace($$.cbegin(), $1); } | expression { $$.push_back($1); } -required_statements: - required_statements ";" statement +statements: + statements ";" statement { std::swap($$, $1); $$.insert($$.cend(), $3); } | statement { $$.push_back($1); } -optional_statements: - required_statements { std::swap($$, $1); } - | /* no statements */ {} field_declaration: IDENTIFIER ":" type_expression { $$ = std::make_pair($1, $3); } required_fields: diff --git a/boot/semantic.cc b/boot/semantic.cc index 3ccc81b..300c91d 100644 --- a/boot/semantic.cc +++ b/boot/semantic.cc @@ -139,6 +139,10 @@ namespace elna::boot { } + void type_analysis_visitor::visit(empty_statement *) + { + } + void type_analysis_visitor::visit(case_statement *) { } @@ -463,6 +467,10 @@ namespace elna::boot } } + void name_analysis_visitor::visit(empty_statement *) + { + } + void name_analysis_visitor::visit(case_statement *statement) { statement->condition().accept(this); diff --git a/doc/appendix.tex b/doc/appendix.tex index 09bdbde..d06a49b 100644 --- a/doc/appendix.tex +++ b/doc/appendix.tex @@ -64,7 +64,7 @@ <selector> = `[' <expression> `]' | `.\@' <identifier> | `^'. -<case> = <expressions> `:\@' <optional-statements>. +<case> = <expressions> `:\@' <statements>. <designator> = <reference> <selector> | <identifier>. @@ -95,9 +95,7 @@ <types> = <type> \{`,' <type>\}. -<required-statements> = <statement> \{`;' <statement>\}. - -<optional-statements> = [<required-statements>]. +<statements> = <statement> \{`;' <statement>\}. <return-declaration> = [`->' `!\@' | `->' type]. @@ -122,46 +120,46 @@ <assignment> = <designator> `:=' <expression>. -<if-statement> = `if' <expression> `then' <optional-statements> \\ - \{`elsif' <expression> `then' <optional-statements>\} \\ - {[`else' <optional-statements>]} `end'. +<if-statement> = `if' <expression> `then' <statements> \\ + \{`elsif' <expression> `then' <statements>\} \\ + {[`else' <statements>]} `end'. -<while-statement> = `while' <expression> `do' <optional-statements> \\ - \{`elsif' <expression> `do' <optional-statements>\} `end'. +<while-statement> = `while' <expression> `do' <statements> \\ + \{`elsif' <expression> `do' <statements>\} `end'. -<defer-statement> = `defer' <optional-statements> `end'. +<defer-statement> = `defer' <statements> `end'. <case-statement> = `case' <expression> `of' <case> \{`|' case\} \\ - {[`else' <optional-statements>]} `end'. + {[`else' <statements>]} `end'. <label-declaration> = `.\@' <identifier>. <goto-statement> = `goto' <identifier>. <statement> = <assignment> | <procedure-call> | <defer-statement> - | <label-declaration> | <goto-statement> | - | <while-statement> | <if-statement> | <case-statement>. + | <label-declaration> | <goto-statement> | <while-statement> + | <if-statement> | <case-statement> | $\varepsilon{}$. -<statement-part> = [`begin' <required-statements> +<statement-part> = [`begin' <statements> \alt{} `return' <expression> - \alt{} `begin' <required-statements> `;' `return' <expression>]. + \alt{} `begin' <statements> `;' `return' <expression>]. <constant-declaration> = <identifier-definition> `:=' <expression>. -<constant-part> = [`const' \{<constant-declaration> `;'\}]. +<constant-part> = [`const' \{<constant-declaration>\}]. <variable-declaration> = <identifier-definitions> `:\@' <type> \\ {[`:=' (<expression> | `extern')]}. -<variable-part> = [`var' \{<variable-declaration> `;'\}]. +<variable-part> = [`var' \{<variable-declaration>\}]. <type-declaration> = <identifier-definition> `=' <type>. -<type-part> = [`type' \{<type-declaration> `;'\}]. +<type-part> = [`type' \{<type-declaration>\}]. <import-declaration> = <identifier> \{`.\@' <identifier>\}. -<import-part> = [`import' \{import-declaration `;'\}]. +<import-part> = [`import' \{import-declaration\}]. <procedure-heading> = `proc' <identifier-definition> \\ `(' [<field> \{`,' <field>\}] `)' <return-declaration>. @@ -170,10 +168,8 @@ <procedure-declaration> = <procedure-heading> `;' (block | `extern'). -<declaration-sequence> = <import-part> \\ - <constant-part> <type-part> <variable-part> \\ - \{<procedure-declaration> `;'\}. - -<program> = `program' `;' <declaration-sequence> <statement-part> `end' `.\@' - \alt{} `module' `;' <declaration-sequence> `end' `.\@'. +<program> = <import-part> + <constant-part> <type-part> <variable-part> + \{<procedure-declaration>\} + <statement-part> `end' `.\@'. \end{grammar} diff --git a/doc/language.tex b/doc/language.tex index 36ee877..26d8b48 100644 --- a/doc/language.tex +++ b/doc/language.tex @@ -506,8 +506,8 @@ relations $=$ and $<>$ apply to all types. \begin{grammar} <statement> = <assignment> | <procedure-call> | <defer-statement> - | <label-declaration> | <goto-statement> | - | <while-statement> | <if-statement> | <case-statement>. + | <label-declaration> | <goto-statement> | <while-statement> + | <if-statement> | <case-statement> | $\varepsilon{}$. \end{grammar} Statements denote actions. There are elementary and structured statements. diff --git a/gcc/gcc/elna-generic.cc b/gcc/gcc/elna-generic.cc index 66bd9a2..2c16a37 100644 --- a/gcc/gcc/elna-generic.cc +++ b/gcc/gcc/elna-generic.cc @@ -1190,6 +1190,10 @@ namespace elna::gcc defer(leave_scope()); } + void generic_visitor::visit(boot::empty_statement *) + { + } + void generic_visitor::visit(boot::case_statement *statement) { statement->condition().accept(this); diff --git a/include/elna/boot/ast.h b/include/elna/boot/ast.h index 7d94e84..03d3e27 100644 --- a/include/elna/boot/ast.h +++ b/include/elna/boot/ast.h @@ -87,6 +87,7 @@ namespace elna::boot template<typename T> class literal; class defer_statement; + class empty_statement; /** * Interface for AST visitors. @@ -107,6 +108,7 @@ namespace elna::boot virtual void visit(return_statement *) = 0; virtual void visit(defer_statement *) = 0; virtual void visit(case_statement *) = 0; + virtual void visit(empty_statement *) = 0; virtual void visit(unit *) = 0; virtual void visit(program *) = 0; virtual void visit(binary_expression *) = 0; @@ -158,6 +160,7 @@ namespace elna::boot [[noreturn]] virtual void visit(while_statement *) override; [[noreturn]] virtual void visit(return_statement *) override; [[noreturn]] virtual void visit(defer_statement *) override; + [[noreturn]] virtual void visit(empty_statement *) override; [[noreturn]] virtual void visit(case_statement *) override; [[noreturn]] virtual void visit(procedure_call *) override; [[noreturn]] virtual void visit(unit *) override; @@ -758,6 +761,13 @@ namespace elna::boot virtual ~defer_statement() override; }; + class empty_statement : public statement + { + public: + empty_statement(const struct position); + void accept(parser_visitor *visitor) override; + }; + class binary_expression : public expression { expression *m_lhs; diff --git a/include/elna/boot/semantic.h b/include/elna/boot/semantic.h index 66eb0a7..7094ee9 100644 --- a/include/elna/boot/semantic.h +++ b/include/elna/boot/semantic.h @@ -109,6 +109,7 @@ namespace elna::boot void visit(while_statement *) override; void visit(return_statement *) override; void visit(defer_statement *) override; + void visit(empty_statement *) override; void visit(case_statement *) override; void visit(procedure_call *) override; void visit(unit *unit) override; @@ -151,7 +152,8 @@ namespace elna::boot void visit(import_declaration *) override; void visit(while_statement *statement) override; void visit(return_statement *statement) override; - void visit(defer_statement *statement) override; + void visit(defer_statement *) override; + void visit(empty_statement *statement) override; void visit(case_statement *statement) override; void visit(procedure_call *call) override; void visit(unit *unit) override; diff --git a/include/elna/gcc/elna-generic.h b/include/elna/gcc/elna-generic.h index 7490e92..9e148e6 100644 --- a/include/elna/gcc/elna-generic.h +++ b/include/elna/gcc/elna-generic.h @@ -92,6 +92,7 @@ namespace elna::gcc void visit(boot::while_statement *statement) override; void visit(boot::return_statement *statement) override; void visit(boot::defer_statement *statement) override; + void visit(boot::empty_statement *) override; void visit(boot::case_statement *statement) override; }; } diff --git a/testsuite/compilable/empty_statements_in_a_row.elna b/testsuite/compilable/empty_statements_in_a_row.elna new file mode 100644 index 0000000..3cc283c --- /dev/null +++ b/testsuite/compilable/empty_statements_in_a_row.elna @@ -0,0 +1,6 @@ +proc f() +begin + ; +end + +end. |
