diff options
Diffstat (limited to 'boot/parser.yy')
| -rw-r--r-- | boot/parser.yy | 76 |
1 files changed, 59 insertions, 17 deletions
diff --git a/boot/parser.yy b/boot/parser.yy index 00bdae8..21ff827 100644 --- a/boot/parser.yy +++ b/boot/parser.yy @@ -88,8 +88,7 @@ along with GCC; see the file COPYING3. If not see %token <std::string> STRING %token <bool> BOOLEAN %token LEFT_PAREN "(" RIGHT_PAREN ")" LEFT_SQUARE "[" RIGHT_SQUARE "]" -%token GENERIC_OPEN "#[" -%token LEFT_BRACE "{" RIGHT_BRACE "}" + LEFT_BRACE "{" RIGHT_BRACE "}" GENERIC_OPEN "#[" %token ASSIGNMENT ":=" EXCLAMATION "!" ARROW "->" AT "@" HAT "^" @@ -149,14 +148,16 @@ along with GCC; see the file COPYING3. If not see %type <std::vector<elna::boot::type_declaration *>> type_declarations type_part; %type <std::unique_ptr<elna::boot::procedure_body>> procedure_body; %type <elna::boot::field_declaration> field_declaration; -%type <std::vector<elna::boot::field_declaration>> optional_fields required_fields; +%type <std::vector<elna::boot::field_declaration>> field_declarations; %type <std::unique_ptr<elna::boot::field_initializer>> field_initializer; %type <std::vector<elna::boot::field_initializer>> field_initializers; %type <std::vector<elna::boot::conditional_statements *>> elsif_then_statements elsif_do_statements; %type <std::vector<elna::boot::statement *> *> else_statements; %type <std::unique_ptr<elna::boot::identifier>> identifier with_counter; -%type <std::unique_ptr<elna::boot::identifier_definition>> identifier_definition; +%type <std::unique_ptr<elna::boot::identifier_definition>> identifier_definition attributed_identifier; %type <std::vector<elna::boot::identifier_definition>> identifier_definitions; +%type <std::unique_ptr<elna::boot::attribute>> attribute; +%type <std::vector<elna::boot::attribute>> attributes; %type <std::vector<std::string>> import_declaration; %type <std::vector<elna::boot::identifier>> required_identifiers optional_identifiers generic_parameters; %type <elna::boot::named_expression *> name_reference; @@ -188,18 +189,43 @@ identifier: identifier_definition: IDENTIFIER "*" { $$ = std::make_unique<boot::identifier_definition>($1, boot::make_position(@1), true); } | IDENTIFIER { $$ = std::make_unique<boot::identifier_definition>($1, boot::make_position(@1), false); } +attribute: + TRAIT "(" required_expressions ")" + { + $$ = std::make_unique<boot::attribute>(boot::identifier($1, boot::make_position(@1)), $3); + } +attributes: + %empty {} + | attribute attributes + { + $$ = $2; + $$.emplace($$.cbegin(), std::move(*$1)); + } +attributed_identifier: + attributes identifier_definition + { + $$ = $2; + $$->attributes = $1; + + // An empty rule is located where the previous token ended, which + // would push the declaration's position back over it. + if ($$->attributes.empty()) + { + @$ = @2; + } + } identifier_definitions: - identifier_definition "," identifier_definitions + attributed_identifier "," identifier_definitions { $$ = $3; $$.emplace($$.cbegin(), std::move(*$1)); } - | identifier_definition { $$.emplace_back(std::move(*$1)); } + | attributed_identifier { $$.emplace_back(std::move(*$1)); } return_declaration: %empty {} | "->" "!" { $$ = boot::procedure_type_expression::return_t(std::monostate{}); } | "->" type_expression { $$ = boot::procedure_type_expression::return_t($2); } -procedure_heading: "(" optional_fields ")" return_declaration +procedure_heading: "(" field_declarations ")" return_declaration { $$ = std::make_unique<boot::procedure_type_expression>(boot::make_position(@$), $2, $4); } procedure_declaration: "proc" identifier_definition generic_parameters procedure_heading procedure_body @@ -555,16 +581,15 @@ statements: } | statement { $$.push_back($1); } field_declaration: - required_identifiers ":" type_expression { $$ = std::make_pair($1, std::shared_ptr<boot::type_expression>($3)); } -required_fields: - field_declaration ";" required_fields + identifier_definitions ":" type_expression + { $$ = std::make_pair($1, std::shared_ptr<boot::type_expression>($3)); } +field_declarations: + field_declaration ";" field_declarations { $$ = $3; $$.emplace($$.cbegin(), $1); } | field_declaration { $$.emplace_back($1); } -optional_fields: - required_fields { $$ = $1; } | %empty {} field_initializer: identifier ":" expression { $$ = std::make_unique<boot::field_initializer>(std::move(*$1), $3); } @@ -591,18 +616,35 @@ type_expression: { $$ = new boot::pointer_type_expression(boot::make_position(@$), $2); } - | "record" optional_fields "end" + | attributes "record" field_declarations "end" { - $$ = new boot::record_type_expression(boot::make_position(@$), $2); + std::vector<boot::attribute> written = $1; + + if (written.empty()) + { + @$ = @2 + @4; + } + auto *record = new boot::record_type_expression(boot::make_position(@$), $3); + + record->attributes = std::move(written); + $$ = record; } - | "record" "(" name_reference ")" optional_fields "end" + | attributes "record" "(" name_reference ")" field_declarations "end" { - boot::named_expression *reference = $3; + std::vector<boot::attribute> written = $1; - $$ = new boot::record_type_expression(boot::make_position(@$), $5, + if (written.empty()) + { + @$ = @2 + @7; + } + boot::named_expression *reference = $4; + auto *record = new boot::record_type_expression(boot::make_position(@$), $6, boot::identifier(reference->name, reference->position()), std::move(reference->arguments)); + + record->attributes = std::move(written); delete reference; + $$ = record; } | "proc" procedure_heading { |
