Merge GCC frontend into the branch
This commit is contained in:
594
frontend/parser.yy
Normal file
594
frontend/parser.yy
Normal file
@@ -0,0 +1,594 @@
|
||||
/* Syntax analyzer.
|
||||
Copyright (C) 2025 Free Software Foundation, Inc.
|
||||
|
||||
GCC is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 3, or (at your option)
|
||||
any later version.
|
||||
|
||||
GCC is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with GCC; see the file COPYING3. If not see
|
||||
<http://www.gnu.org/licenses/>. */
|
||||
|
||||
%require "3.4"
|
||||
%language "c++"
|
||||
|
||||
%code {
|
||||
using namespace elna;
|
||||
}
|
||||
|
||||
%code requires {
|
||||
#include <cstdint>
|
||||
#include <iostream>
|
||||
#include "elna/frontend/driver.h"
|
||||
|
||||
#if !defined(yyFlexLexerOnce)
|
||||
#include <FlexLexer.h>
|
||||
#endif
|
||||
|
||||
namespace elna::frontend
|
||||
{
|
||||
class lexer;
|
||||
}
|
||||
}
|
||||
|
||||
%code provides {
|
||||
namespace elna::frontend
|
||||
{
|
||||
|
||||
class lexer: public yyFlexLexer
|
||||
{
|
||||
public:
|
||||
yy::location location;
|
||||
|
||||
lexer(std::istream& arg_yyin)
|
||||
: yyFlexLexer(&arg_yyin)
|
||||
{
|
||||
}
|
||||
|
||||
yy::parser::symbol_type lex(driver& driver);
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
%define api.token.raw
|
||||
%define api.token.constructor
|
||||
%define api.value.type variant
|
||||
|
||||
%parse-param {elna::frontend::lexer& lexer}
|
||||
%param {elna::frontend::driver& driver}
|
||||
%locations
|
||||
|
||||
%header
|
||||
|
||||
%code {
|
||||
#define yylex lexer.lex
|
||||
}
|
||||
%start program;
|
||||
|
||||
%token <std::string> IDENTIFIER
|
||||
%token <std::string> TRAIT
|
||||
%token <std::int32_t> INTEGER
|
||||
%token <std::uint32_t> WORD
|
||||
%token <float> FLOAT
|
||||
%token <std::string> CHARACTER
|
||||
%token <std::string> STRING
|
||||
%token <bool> BOOLEAN
|
||||
%token LEFT_PAREN "(" RIGHT_PAREN ")" LEFT_SQUARE "[" RIGHT_SQUARE "]"
|
||||
%token ASSIGNMENT ":="
|
||||
ARROW "->" EXCLAMATION "!"
|
||||
AT "@" HAT "^"
|
||||
COLON ":" SEMICOLON ";" DOT "." COMMA ","
|
||||
%token NOT "~"
|
||||
CAST "cast"
|
||||
NIL "nil"
|
||||
CONST "const"
|
||||
VAR "var"
|
||||
PROCEDURE "proc"
|
||||
TYPE "type"
|
||||
RECORD "record"
|
||||
UNION "union"
|
||||
EXTERN "extern"
|
||||
IF "if"
|
||||
WHILE "while"
|
||||
DO "do"
|
||||
THEN "then"
|
||||
ELSE "else"
|
||||
ELSIF "elsif"
|
||||
RETURN "return"
|
||||
PROGRAM "program"
|
||||
MODULE "module"
|
||||
IMPORT "import"
|
||||
BEGIN_BLOCK "begin"
|
||||
END_BLOCK "end"
|
||||
DEFER "defer"
|
||||
CASE "case"
|
||||
OF "of"
|
||||
PIPE "|"
|
||||
%token OR "or" AND "&" XOR "xor"
|
||||
EQUALS "=" NOT_EQUAL "<>" LESS_THAN "<" GREATER_THAN ">" LESS_EQUAL "<=" GREATER_EQUAL ">="
|
||||
SHIFT_LEFT "<<" SHIFT_RIGHT ">>"
|
||||
PLUS "+" MINUS "-"
|
||||
MULTIPLICATION "*" DIVISION "/" REMAINDER "%"
|
||||
|
||||
%left "or" "&" "xor"
|
||||
%left "=" "<>" "<" ">" "<=" ">="
|
||||
%left "<<" ">>"
|
||||
%left "+" "-"
|
||||
%left "*" "/" "%"
|
||||
|
||||
%type <elna::frontend::literal_expression *> literal;
|
||||
%type <std::vector<elna::frontend::expression *>> case_labels;
|
||||
%type <elna::frontend::switch_case> switch_case;
|
||||
%type <std::vector<elna::frontend::switch_case>> switch_cases;
|
||||
%type <elna::frontend::constant_declaration *> constant_declaration;
|
||||
%type <std::vector<elna::frontend::constant_declaration *>> constant_part constant_declarations;
|
||||
%type <elna::frontend::variable_declaration *> variable_declaration;
|
||||
%type <std::vector<elna::frontend::variable_declaration *>> variable_declarations variable_part;
|
||||
%type <elna::frontend::type_expression *> type_expression;
|
||||
%type <std::vector<elna::frontend::type_expression *>> type_expressions;
|
||||
%type <elna::frontend::traits_expression *> traits_expression;
|
||||
%type <elna::frontend::expression *> expression operand simple_expression;
|
||||
%type <elna::frontend::unary_expression *> unary_expression;
|
||||
%type <elna::frontend::binary_expression *> binary_expression;
|
||||
%type <std::vector<elna::frontend::expression *>> expressions actual_parameter_list;
|
||||
%type <elna::frontend::designator_expression *> designator_expression;
|
||||
%type <elna::frontend::procedure_call*> call_expression;
|
||||
%type <elna::frontend::return_statement *> return_statement;
|
||||
%type <elna::frontend::statement *> statement;
|
||||
%type <std::vector<elna::frontend::statement *>> required_statements optional_statements statement_part;
|
||||
%type <elna::frontend::procedure_declaration *> procedure_declaration;
|
||||
%type <std::pair<std::vector<std::string>, elna::frontend::procedure_type_expression *>> procedure_heading;
|
||||
%type <elna::frontend::procedure_type_expression::return_t> return_declaration;
|
||||
%type <std::vector<elna::frontend::procedure_declaration *>> procedure_declarations procedure_part;
|
||||
%type <elna::frontend::type_declaration *> type_declaration;
|
||||
%type <std::vector<elna::frontend::type_declaration *>> type_declarations type_part;
|
||||
%type <std::unique_ptr<elna::frontend::block>> block;
|
||||
%type <elna::frontend::field_declaration> field_declaration formal_parameter;
|
||||
%type <std::vector<std::pair<std::string, elna::frontend::type_expression *>>>
|
||||
optional_fields required_fields formal_parameters formal_parameter_list;
|
||||
%type <std::vector<elna::frontend::conditional_statements *>> elsif_then_statements elsif_do_statements;
|
||||
%type <std::vector<elna::frontend::statement *> *> else_statements;
|
||||
%type <elna::frontend::cast_expression *> cast_expression;
|
||||
%type <elna::frontend::identifier_definition> identifier_definition;
|
||||
%type <std::vector<elna::frontend::identifier_definition>> identifier_definitions;
|
||||
%type <std::vector<std::string>> identifiers import_declaration;
|
||||
%type <std::vector<elna::frontend::import_declaration *>> import_declarations import_part;
|
||||
%%
|
||||
program:
|
||||
"program" ";" import_part constant_part type_part variable_part procedure_part statement_part "end" "."
|
||||
{
|
||||
auto tree = new frontend::program(frontend::make_position(@1));
|
||||
|
||||
std::swap(tree->imports, $3);
|
||||
std::swap(tree->constants, $4);
|
||||
std::swap(tree->types , $5);
|
||||
std::swap(tree->variables, $6);
|
||||
std::swap(tree->procedures, $7);
|
||||
std::swap(tree->body, $8);
|
||||
|
||||
driver.tree.reset(tree);
|
||||
}
|
||||
| "module" ";" import_part constant_part type_part variable_part procedure_part "end" "."
|
||||
{
|
||||
auto tree = new frontend::unit(frontend::make_position(@1));
|
||||
|
||||
std::swap(tree->imports, $3);
|
||||
std::swap(tree->constants, $4);
|
||||
std::swap(tree->types , $5);
|
||||
std::swap(tree->variables, $6);
|
||||
std::swap(tree->procedures, $7);
|
||||
|
||||
driver.tree.reset(tree);
|
||||
}
|
||||
block: constant_part variable_part statement_part "end"
|
||||
{
|
||||
$$ = std::make_unique<frontend::block>(std::move($1), std::move($2), std::move($3));
|
||||
}
|
||||
statement_part:
|
||||
/* no statements */ {}
|
||||
| "begin" required_statements { std::swap($$, $2); }
|
||||
| return_statement { $$.push_back($1); }
|
||||
| "begin" required_statements ";" return_statement
|
||||
{
|
||||
std::swap($$, $2);
|
||||
$$.push_back($4);
|
||||
}
|
||||
identifier_definition:
|
||||
IDENTIFIER "*" { $$ = frontend::identifier_definition{ $1, true }; }
|
||||
| IDENTIFIER { $$ = frontend::identifier_definition{ $1, false }; }
|
||||
identifier_definitions:
|
||||
identifier_definition "," identifier_definitions
|
||||
{
|
||||
std::swap($$, $3);
|
||||
$$.emplace($$.cbegin(), $1);
|
||||
}
|
||||
| identifier_definition { $$.emplace_back(std::move($1)); }
|
||||
return_declaration:
|
||||
/* proper procedure */ {}
|
||||
| "->" "!" { $$ = frontend::procedure_type_expression::return_t(std::monostate{}); }
|
||||
| "->" type_expression { $$ = frontend::procedure_type_expression::return_t($2); }
|
||||
procedure_heading: formal_parameter_list return_declaration
|
||||
{
|
||||
$$.second = new frontend::procedure_type_expression(frontend::make_position(@1), std::move($2));
|
||||
for (auto& [name, type] : $1)
|
||||
{
|
||||
$$.first.emplace_back(std::move(name));
|
||||
$$.second->parameters.push_back(type);
|
||||
}
|
||||
}
|
||||
procedure_declaration:
|
||||
"proc" identifier_definition procedure_heading ";" block ";"
|
||||
{
|
||||
$$ = new frontend::procedure_declaration(frontend::make_position(@1), std::move($2), $3.second, std::move(*$5));
|
||||
std::swap($3.first, $$->parameter_names);
|
||||
}
|
||||
| "proc" identifier_definition procedure_heading ";" "extern" ";"
|
||||
{
|
||||
$$ = new frontend::procedure_declaration(frontend::make_position(@1), std::move($2), $3.second);
|
||||
std::swap($3.first, $$->parameter_names);
|
||||
}
|
||||
procedure_declarations:
|
||||
procedure_declaration procedure_declarations
|
||||
{
|
||||
std::swap($$, $2);
|
||||
$$.emplace($$.cbegin(), std::move($1));
|
||||
}
|
||||
| procedure_declaration { $$.emplace_back(std::move($1)); }
|
||||
procedure_part:
|
||||
/* no procedure definitions */ {}
|
||||
| procedure_declarations { std::swap($$, $1); }
|
||||
call_expression: designator_expression actual_parameter_list
|
||||
{
|
||||
$$ = new frontend::procedure_call(frontend::make_position(@1), $1);
|
||||
std::swap($$->arguments, $2);
|
||||
}
|
||||
cast_expression: "cast" "(" expression ":" type_expression ")"
|
||||
{ $$ = new frontend::cast_expression(frontend::make_position(@1), $5, $3); }
|
||||
elsif_do_statements:
|
||||
"elsif" expression "do" optional_statements elsif_do_statements
|
||||
{
|
||||
frontend::conditional_statements *branch = new frontend::conditional_statements($2, std::move($4));
|
||||
std::swap($5, $$);
|
||||
$$.emplace($$.begin(), branch);
|
||||
}
|
||||
| {}
|
||||
else_statements:
|
||||
"else" optional_statements { $$ = new std::vector<frontend::statement *>(std::move($2)); }
|
||||
| { $$ = nullptr; }
|
||||
elsif_then_statements:
|
||||
"elsif" expression "then" optional_statements elsif_then_statements
|
||||
{
|
||||
frontend::conditional_statements *branch = new frontend::conditional_statements($2, std::move($4));
|
||||
std::swap($5, $$);
|
||||
$$.emplace($$.begin(), branch);
|
||||
}
|
||||
| {}
|
||||
return_statement: "return" expression
|
||||
{ $$ = new frontend::return_statement(frontend::make_position(@1), $2); }
|
||||
literal:
|
||||
INTEGER { $$ = new frontend::literal<std::int32_t>(frontend::make_position(@1), $1); }
|
||||
| WORD { $$ = new frontend::literal<std::uint32_t>(frontend::make_position(@1), $1); }
|
||||
| FLOAT { $$ = new frontend::literal<double>(frontend::make_position(@1), $1); }
|
||||
| BOOLEAN { $$ = new frontend::literal<bool>(frontend::make_position(@1), $1); }
|
||||
| CHARACTER { $$ = new frontend::literal<unsigned char>(frontend::make_position(@1), $1.at(0)); }
|
||||
| "nil" { $$ = new frontend::literal<std::nullptr_t>(frontend::make_position(@1), nullptr); }
|
||||
| STRING { $$ = new frontend::literal<std::string>(frontend::make_position(@1), $1); }
|
||||
traits_expression:
|
||||
TRAIT "(" type_expressions ")"
|
||||
{
|
||||
$$ = new frontend::traits_expression(frontend::make_position(@1), $1);
|
||||
std::swap($3, $$->parameters);
|
||||
}
|
||||
simple_expression:
|
||||
literal { $$ = $1; }
|
||||
| designator_expression { $$ = $1; }
|
||||
| traits_expression { $$ = $1; }
|
||||
| cast_expression { $$ = $1; }
|
||||
| call_expression { $$ = $1; }
|
||||
| "(" expression ")" { $$ = $2; }
|
||||
operand:
|
||||
unary_expression { $$ = $1; }
|
||||
| simple_expression { $$ = $1; }
|
||||
expression:
|
||||
binary_expression { $$ = $1; }
|
||||
| operand { $$ = $1; }
|
||||
binary_expression:
|
||||
expression "*" expression
|
||||
{
|
||||
$$ = new frontend::binary_expression(frontend::make_position(@2), $1, $3, frontend::binary_operator::multiplication);
|
||||
}
|
||||
| expression "/" expression
|
||||
{
|
||||
$$ = new frontend::binary_expression(frontend::make_position(@2), $1, $3, frontend::binary_operator::division);
|
||||
}
|
||||
| expression "%" expression
|
||||
{
|
||||
$$ = new frontend::binary_expression(frontend::make_position(@2), $1, $3, frontend::binary_operator::remainder);
|
||||
}
|
||||
| expression "+" expression
|
||||
{
|
||||
$$ = new frontend::binary_expression(frontend::make_position(@2), $1, $3, frontend::binary_operator::sum);
|
||||
}
|
||||
| expression "-" expression
|
||||
{
|
||||
$$ = new frontend::binary_expression(frontend::make_position(@2), $1, $3, frontend::binary_operator::subtraction);
|
||||
}
|
||||
| expression "=" expression
|
||||
{
|
||||
$$ = new frontend::binary_expression(frontend::make_position(@2), $1, $3, frontend::binary_operator::equals);
|
||||
}
|
||||
| expression "<>" expression
|
||||
{
|
||||
$$ = new frontend::binary_expression(frontend::make_position(@2), $1, $3, frontend::binary_operator::not_equals);
|
||||
}
|
||||
| expression "<" expression
|
||||
{
|
||||
$$ = new frontend::binary_expression(frontend::make_position(@2), $1, $3, frontend::binary_operator::less);
|
||||
}
|
||||
| expression ">" expression
|
||||
{
|
||||
$$ = new frontend::binary_expression(frontend::make_position(@2), $1, $3, frontend::binary_operator::greater);
|
||||
}
|
||||
| expression "<=" expression
|
||||
{
|
||||
$$ = new frontend::binary_expression(frontend::make_position(@2), $1, $3,
|
||||
frontend::binary_operator::less_equal);
|
||||
}
|
||||
| expression ">=" expression
|
||||
{
|
||||
$$ = new frontend::binary_expression(frontend::make_position(@2), $1, $3, frontend::binary_operator::greater_equal);
|
||||
}
|
||||
| expression "&" expression
|
||||
{
|
||||
$$ = new frontend::binary_expression(frontend::make_position(@2), $1, $3, frontend::binary_operator::conjunction);
|
||||
}
|
||||
| expression "or" expression
|
||||
{
|
||||
$$ = new frontend::binary_expression(frontend::make_position(@2), $1, $3, frontend::binary_operator::disjunction);
|
||||
}
|
||||
| expression "xor" expression
|
||||
{
|
||||
$$ = new frontend::binary_expression(frontend::make_position(@2), $1, $3,
|
||||
frontend::binary_operator::exclusive_disjunction);
|
||||
}
|
||||
| expression "<<" expression
|
||||
{
|
||||
$$ = new frontend::binary_expression(frontend::make_position(@2), $1, $3, frontend::binary_operator::shift_left);
|
||||
}
|
||||
| expression ">>" expression
|
||||
{
|
||||
$$ = new frontend::binary_expression(frontend::make_position(@2), $1, $3, frontend::binary_operator::shift_right);
|
||||
}
|
||||
unary_expression:
|
||||
"@" operand
|
||||
{
|
||||
$$ = new frontend::unary_expression(frontend::make_position(@1), $2, frontend::unary_operator::reference);
|
||||
}
|
||||
| "~" operand
|
||||
{
|
||||
$$ = new frontend::unary_expression(frontend::make_position(@1), $2, frontend::unary_operator::negation);
|
||||
}
|
||||
| "-" operand
|
||||
{
|
||||
$$ = new frontend::unary_expression(frontend::make_position(@1), $2, frontend::unary_operator::minus);
|
||||
}
|
||||
expressions:
|
||||
expression "," expressions
|
||||
{
|
||||
std::swap($$, $3);
|
||||
$$.emplace($$.cbegin(), $1);
|
||||
}
|
||||
| expression { $$.push_back($1); }
|
||||
type_expressions:
|
||||
type_expression "," type_expressions
|
||||
{
|
||||
std::swap($$, $3);
|
||||
$$.emplace($$.cbegin(), $1);
|
||||
}
|
||||
| type_expression { $$.push_back($1); }
|
||||
designator_expression:
|
||||
simple_expression "[" expression "]"
|
||||
{ $$ = new frontend::array_access_expression(frontend::make_position(@2), $1, $3); }
|
||||
| simple_expression "." IDENTIFIER
|
||||
{ $$ = new frontend::field_access_expression(frontend::make_position(@2), $1, $3); }
|
||||
| simple_expression "^"
|
||||
{ $$ = new frontend::dereference_expression(frontend::make_position(@1), $1); }
|
||||
| IDENTIFIER
|
||||
{ $$ = new frontend::variable_expression(frontend::make_position(@1), $1); }
|
||||
statement:
|
||||
designator_expression ":=" expression
|
||||
{ $$ = new frontend::assign_statement(frontend::make_position(@1), $1, $3); }
|
||||
| "while" expression "do" optional_statements elsif_do_statements "end"
|
||||
{
|
||||
frontend::conditional_statements *body = new frontend::conditional_statements($2, std::move($4));
|
||||
$$ = new frontend::while_statement(frontend::make_position(@1), body, std::move($5));
|
||||
}
|
||||
| "if" expression "then" optional_statements elsif_then_statements else_statements "end"
|
||||
{
|
||||
frontend::conditional_statements *then = new frontend::conditional_statements($2, std::move($4));
|
||||
$$ = new frontend::if_statement(frontend::make_position(@1), then, std::move($5), $6);
|
||||
}
|
||||
| call_expression { $$ = $1; }
|
||||
| "defer" optional_statements "end"
|
||||
{ $$ = new frontend::defer_statement(frontend::make_position(@1), std::move($2)); }
|
||||
| "case" expression "of" switch_cases else_statements "end"
|
||||
{ $$ = new frontend::case_statement(frontend::make_position(@1), $2, std::move($4), $5); }
|
||||
switch_case: case_labels ":" optional_statements
|
||||
{ $$ = { .labels = std::move($1), .statements = std::move($3) }; }
|
||||
switch_cases:
|
||||
switch_case "|" switch_cases
|
||||
{
|
||||
std::swap($$, $3);
|
||||
$$.emplace($$.cbegin(), $1);
|
||||
}
|
||||
| switch_case { $$.push_back($1); }
|
||||
case_labels:
|
||||
expression "," case_labels
|
||||
{
|
||||
std::swap($$, $3);
|
||||
$$.emplace($$.cbegin(), $1);
|
||||
}
|
||||
| expression { $$.push_back($1); }
|
||||
required_statements:
|
||||
required_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:
|
||||
field_declaration ";" required_fields
|
||||
{
|
||||
std::swap($$, $3);
|
||||
$$.emplace($$.cbegin(), $1);
|
||||
}
|
||||
| field_declaration { $$.emplace_back($1); }
|
||||
optional_fields:
|
||||
required_fields { std::swap($$, $1); }
|
||||
| /* no fields */ {}
|
||||
type_expression:
|
||||
"[" INTEGER "]" type_expression
|
||||
{
|
||||
$$ = new frontend::array_type_expression(frontend::make_position(@1), $4, $2);
|
||||
}
|
||||
| "^" type_expression
|
||||
{
|
||||
$$ = new frontend::pointer_type_expression(frontend::make_position(@1), $2);
|
||||
}
|
||||
| "record" optional_fields "end"
|
||||
{
|
||||
$$ = new frontend::record_type_expression(frontend::make_position(@1), std::move($2));
|
||||
}
|
||||
| "union" required_fields "end"
|
||||
{
|
||||
$$ = new frontend::union_type_expression(frontend::make_position(@1), std::move($2));
|
||||
}
|
||||
| "proc" "(" type_expressions ")" return_declaration
|
||||
{
|
||||
auto result = new frontend::procedure_type_expression(frontend::make_position(@1), std::move($5));
|
||||
std::swap(result->parameters, $3);
|
||||
$$ = result;
|
||||
}
|
||||
| "(" identifiers ")"
|
||||
{
|
||||
$$ = new frontend::enumeration_type_expression(frontend::make_position(@1), std::move($2));
|
||||
}
|
||||
| IDENTIFIER
|
||||
{
|
||||
$$ = new frontend::named_type_expression(frontend::make_position(@1), $1);
|
||||
}
|
||||
identifiers:
|
||||
IDENTIFIER "," identifiers
|
||||
{
|
||||
std::swap($$, $3);
|
||||
$$.emplace($$.cbegin(), std::move($1));
|
||||
}
|
||||
| IDENTIFIER { $$.emplace_back(std::move($1)); }
|
||||
variable_declaration:
|
||||
identifier_definitions ":" type_expression ";"
|
||||
{
|
||||
std::shared_ptr<frontend::type_expression> shared_type{ $3 };
|
||||
$$ = new frontend::variable_declaration( frontend::make_position(@2), std::move($1), shared_type);
|
||||
}
|
||||
| identifier_definitions ":" type_expression ":=" "extern" ";"
|
||||
{
|
||||
std::shared_ptr<frontend::type_expression> shared_type{ $3 };
|
||||
$$ = new frontend::variable_declaration( frontend::make_position(@2), std::move($1), shared_type,
|
||||
std::monostate{});
|
||||
}
|
||||
| identifier_definitions ":" type_expression ":=" expression ";"
|
||||
{
|
||||
std::shared_ptr<frontend::type_expression> shared_type{ $3 };
|
||||
$$ = new frontend::variable_declaration( frontend::make_position(@2), std::move($1), shared_type, $5);
|
||||
}
|
||||
variable_declarations:
|
||||
/* no variable declarations */ {}
|
||||
| variable_declaration variable_declarations
|
||||
{
|
||||
std::swap($$, $2);
|
||||
$$.insert(std::cbegin($$), $1);
|
||||
}
|
||||
variable_part:
|
||||
/* no variable declarations */ {}
|
||||
| "var" variable_declarations { std::swap($$, $2); }
|
||||
constant_declaration: identifier_definition ":=" expression ";"
|
||||
{
|
||||
$$ = new frontend::constant_declaration(frontend::make_position(@1), std::move($1), $3);
|
||||
}
|
||||
constant_declarations:
|
||||
constant_declaration constant_declarations
|
||||
{
|
||||
std::swap($$, $2);
|
||||
$$.insert(std::cbegin($$), $1);
|
||||
}
|
||||
| /* no constant definitions */ {}
|
||||
constant_part:
|
||||
/* no constant definitions */ {}
|
||||
| "const" constant_declarations { std::swap($$, $2); }
|
||||
import_declaration:
|
||||
IDENTIFIER "." import_declaration
|
||||
{
|
||||
std::swap($$, $3);
|
||||
$$.emplace($$.cbegin(), std::move($1));
|
||||
}
|
||||
| IDENTIFIER { $$.emplace_back(std::move($1)); }
|
||||
import_declarations:
|
||||
import_declaration "," import_declarations
|
||||
{
|
||||
std::swap($$, $3);
|
||||
$$.emplace($$.cbegin(), new frontend::import_declaration(frontend::make_position(@1), std::move($1)));
|
||||
}
|
||||
| import_declaration
|
||||
{
|
||||
$$.emplace_back(new frontend::import_declaration(frontend::make_position(@1), std::move($1)));
|
||||
}
|
||||
import_part:
|
||||
/* no import declarations */ {}
|
||||
| "import" import_declarations ";" { std::swap($$, $2); }
|
||||
type_declaration: identifier_definition "=" type_expression ";"
|
||||
{
|
||||
$$ = new frontend::type_declaration(frontend::make_position(@1), std::move($1), $3);
|
||||
}
|
||||
type_declarations:
|
||||
type_declaration type_declarations
|
||||
{
|
||||
std::swap($$, $2);
|
||||
$$.insert($$.cbegin(), $1);
|
||||
}
|
||||
| /* no type definitions */ {}
|
||||
type_part:
|
||||
/* no type definitions */ {}
|
||||
| "type" type_declarations { std::swap($$, $2); }
|
||||
formal_parameter:
|
||||
IDENTIFIER ":" type_expression { $$ = std::make_pair($1, $3); }
|
||||
formal_parameter_list:
|
||||
"(" ")" {}
|
||||
| "(" formal_parameters ")" { std::swap($$, $2); }
|
||||
formal_parameters:
|
||||
formal_parameter "," formal_parameters
|
||||
{
|
||||
std::swap($$, $3);
|
||||
$$.emplace($$.cbegin(), std::move($1));
|
||||
}
|
||||
| formal_parameter { $$.emplace_back(std::move($1)); }
|
||||
actual_parameter_list:
|
||||
"(" ")" {}
|
||||
| "(" expressions ")" { std::swap($$, $2); }
|
||||
%%
|
||||
|
||||
void yy::parser::error(const location_type& loc, const std::string& message)
|
||||
{
|
||||
driver.add_error<frontend::syntax_error>(message, driver.input_file, loc);
|
||||
}
|
||||
Reference in New Issue
Block a user