Implement procedure pointers
This commit is contained in:
18
boot/ast.cc
18
boot/ast.cc
@ -46,7 +46,7 @@ namespace boot
|
||||
|
||||
void empty_visitor::visit(call_expression *expression)
|
||||
{
|
||||
for (auto& argument : expression->arguments())
|
||||
for (struct expression *const argument : expression->arguments)
|
||||
{
|
||||
argument->accept(this);
|
||||
}
|
||||
@ -734,8 +734,8 @@ namespace boot
|
||||
delete m_operand;
|
||||
}
|
||||
|
||||
call_expression::call_expression(const struct position position, const std::string& name)
|
||||
: expression(position), m_name(name)
|
||||
call_expression::call_expression(const struct position position, designator_expression *callable)
|
||||
: expression(position), m_callable(callable)
|
||||
{
|
||||
}
|
||||
|
||||
@ -744,22 +744,18 @@ namespace boot
|
||||
visitor->visit(this);
|
||||
}
|
||||
|
||||
std::string& call_expression::name()
|
||||
designator_expression& call_expression::callable()
|
||||
{
|
||||
return m_name;
|
||||
}
|
||||
|
||||
std::vector<expression *>& call_expression::arguments()
|
||||
{
|
||||
return m_arguments;
|
||||
return *m_callable;
|
||||
}
|
||||
|
||||
call_expression::~call_expression()
|
||||
{
|
||||
for (auto argument : m_arguments)
|
||||
for (expression *const argument : arguments)
|
||||
{
|
||||
delete argument;
|
||||
}
|
||||
delete m_callable;
|
||||
}
|
||||
|
||||
cast_expression::cast_expression(const struct position position,
|
||||
|
191
boot/parser.yy
191
boot/parser.yy
@ -74,25 +74,49 @@ along with GCC; see the file COPYING3. If not see
|
||||
}
|
||||
%start program;
|
||||
|
||||
%token <std::string> IDENTIFIER "identifier"
|
||||
%token <std::int32_t> INTEGER "integer"
|
||||
%token <std::uint32_t> WORD "word"
|
||||
%token <float> FLOAT "float"
|
||||
%token <std::string> CHARACTER "character"
|
||||
%token <std::string> STRING "string"
|
||||
%token <std::string> IDENTIFIER
|
||||
%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 IF WHILE DO THEN ELSE ELSIF RETURN
|
||||
%token CONST VAR PROCEDURE TYPE RECORD UNION
|
||||
%token BEGIN_BLOCK END_BLOCK EXTERN DEFER
|
||||
%token LEFT_PAREN RIGHT_PAREN LEFT_SQUARE RIGHT_SQUARE SEMICOLON DOT COMMA
|
||||
%token NOT CAST EXCLAMATION
|
||||
%token ASSIGNMENT COLON HAT AT NIL ARROW
|
||||
%token LEFT_PAREN "(" RIGHT_PAREN ")" LEFT_SQUARE "[" RIGHT_SQUARE "]"
|
||||
%token ASSIGNMENT ":="
|
||||
ARROW "->" EXCLAMATION "!"
|
||||
AT "@" HAT "^"
|
||||
COLON ":" SEMICOLON ";" DOT "." COMMA ","
|
||||
%token NOT "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"
|
||||
BEGIN_BLOCK "begin"
|
||||
END_BLOCK "end"
|
||||
DEFER "defer"
|
||||
%token OR "or" AND "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 AND XOR
|
||||
%left EQUALS NOT_EQUAL LESS_THAN GREATER_THAN LESS_EQUAL GREATER_EQUAL
|
||||
%left SHIFT_LEFT SHIFT_RIGHT
|
||||
%left PLUS MINUS
|
||||
%left MULTIPLICATION DIVISION REMAINDER
|
||||
%left "or" "and" "xor"
|
||||
%left "=" "<>" "<" ">" "<=" ">="
|
||||
%left "<<" ">>"
|
||||
%left "+" "-"
|
||||
%left "*" "/" "%"
|
||||
|
||||
%type <elna::boot::literal *> literal;
|
||||
%type <elna::boot::constant_definition *> constant_definition;
|
||||
@ -126,7 +150,7 @@ along with GCC; see the file COPYING3. If not see
|
||||
%type <std::vector<std::pair<std::string, bool>>> identifier_definitions;
|
||||
%%
|
||||
program:
|
||||
constant_part type_part variable_part procedure_part BEGIN_BLOCK optional_statements END_BLOCK DOT
|
||||
constant_part type_part variable_part procedure_part "begin" optional_statements "end" "."
|
||||
{
|
||||
auto tree = new elna::boot::program(elna::boot::make_position(@5));
|
||||
|
||||
@ -138,7 +162,7 @@ program:
|
||||
|
||||
driver.tree.reset(tree);
|
||||
}
|
||||
block: constant_part variable_part BEGIN_BLOCK optional_statements END_BLOCK
|
||||
block: constant_part variable_part "begin" optional_statements "end"
|
||||
{
|
||||
$$ = new elna::boot::block(elna::boot::make_position(@3));
|
||||
|
||||
@ -147,7 +171,7 @@ block: constant_part variable_part BEGIN_BLOCK optional_statements END_BLOCK
|
||||
std::swap($$->body, $4);
|
||||
}
|
||||
identifier_definition:
|
||||
IDENTIFIER MULTIPLICATION
|
||||
IDENTIFIER "*"
|
||||
{
|
||||
$$ = std::make_pair($1, true);
|
||||
}
|
||||
@ -156,7 +180,7 @@ identifier_definition:
|
||||
$$ = std::make_pair($1, false);
|
||||
}
|
||||
identifier_definitions:
|
||||
identifier_definition COMMA identifier_definitions
|
||||
identifier_definition "," identifier_definitions
|
||||
{
|
||||
std::swap($$, $3);
|
||||
$$.emplace($$.cbegin(), $1);
|
||||
@ -168,22 +192,22 @@ procedure_heading:
|
||||
$$ = std::make_shared<elna::boot::procedure_type>(elna::boot::make_position(@1));
|
||||
std::swap($1, $$->parameters);
|
||||
}
|
||||
| formal_parameter_list ARROW EXCLAMATION
|
||||
| formal_parameter_list "->" "!"
|
||||
{
|
||||
$$ = std::make_shared<elna::boot::procedure_type>(elna::boot::make_position(@1), elna::boot::no_return);
|
||||
std::swap($1, $$->parameters);
|
||||
}
|
||||
| formal_parameter_list ARROW type_expression
|
||||
| formal_parameter_list "->" type_expression
|
||||
{
|
||||
$$ = std::make_shared<elna::boot::procedure_type>(elna::boot::make_position(@1), $3);
|
||||
std::swap($1, $$->parameters);
|
||||
}
|
||||
procedure_definition:
|
||||
PROCEDURE identifier_definition procedure_heading SEMICOLON block
|
||||
"proc" identifier_definition procedure_heading ";" block
|
||||
{
|
||||
$$ = new elna::boot::procedure_definition(elna::boot::make_position(@1), $2.first, $2.second, $3, $5);
|
||||
}
|
||||
| PROCEDURE identifier_definition procedure_heading SEMICOLON EXTERN
|
||||
| "proc" identifier_definition procedure_heading ";" "extern"
|
||||
{
|
||||
$$ = new elna::boot::procedure_definition(elna::boot::make_position(@1), $2.first, $2.second, $3);
|
||||
}
|
||||
@ -197,21 +221,21 @@ procedure_definitions:
|
||||
procedure_part:
|
||||
/* no procedure definitions */ {}
|
||||
| procedure_definitions { std::swap($$, $1); }
|
||||
assign_statement: designator_expression ASSIGNMENT expression
|
||||
assign_statement: designator_expression ":=" expression
|
||||
{
|
||||
$$ = new elna::boot::assign_statement(elna::boot::make_position(@1), $1, $3);
|
||||
}
|
||||
call_expression: IDENTIFIER actual_parameter_list
|
||||
call_expression: designator_expression actual_parameter_list
|
||||
{
|
||||
$$ = new elna::boot::call_expression(elna::boot::make_position(@1), $1);
|
||||
std::swap($$->arguments(), $2);
|
||||
std::swap($$->arguments, $2);
|
||||
}
|
||||
cast_expression: CAST LEFT_PAREN expression COLON type_expression RIGHT_PAREN
|
||||
cast_expression: "cast" "(" expression ":" type_expression ")"
|
||||
{
|
||||
$$ = new elna::boot::cast_expression(elna::boot::make_position(@1), $5, $3);
|
||||
}
|
||||
elsif_do_statements:
|
||||
ELSIF expression DO optional_statements elsif_do_statements
|
||||
"elsif" expression "do" optional_statements elsif_do_statements
|
||||
{
|
||||
elna::boot::conditional_statements *branch = new elna::boot::conditional_statements($2);
|
||||
std::swap(branch->statements, $4);
|
||||
@ -219,7 +243,7 @@ elsif_do_statements:
|
||||
$$.emplace($$.begin(), branch);
|
||||
}
|
||||
| {}
|
||||
while_statement: WHILE expression DO optional_statements elsif_do_statements END_BLOCK
|
||||
while_statement: "while" expression "do" optional_statements elsif_do_statements "end"
|
||||
{
|
||||
auto body = new elna::boot::conditional_statements($2);
|
||||
std::swap($4, body->statements);
|
||||
@ -227,7 +251,7 @@ while_statement: WHILE expression DO optional_statements elsif_do_statements END
|
||||
std::swap($5, $$->branches);
|
||||
}
|
||||
elsif_then_statements:
|
||||
ELSIF expression THEN optional_statements elsif_then_statements
|
||||
"elsif" expression "then" optional_statements elsif_then_statements
|
||||
{
|
||||
elna::boot::conditional_statements *branch = new elna::boot::conditional_statements($2);
|
||||
std::swap(branch->statements, $4);
|
||||
@ -236,14 +260,14 @@ elsif_then_statements:
|
||||
}
|
||||
| {}
|
||||
if_statement:
|
||||
IF expression THEN optional_statements elsif_then_statements END_BLOCK
|
||||
"if" expression "then" optional_statements elsif_then_statements "end"
|
||||
{
|
||||
auto then = new elna::boot::conditional_statements($2);
|
||||
std::swap($4, then->statements);
|
||||
$$ = new elna::boot::if_statement(elna::boot::make_position(@1), then);
|
||||
std::swap($5, $$->branches);
|
||||
}
|
||||
| IF expression THEN optional_statements elsif_then_statements ELSE optional_statements END_BLOCK
|
||||
| "if" expression "then" optional_statements elsif_then_statements "else" optional_statements "end"
|
||||
{
|
||||
auto then = new elna::boot::conditional_statements($2);
|
||||
std::swap($4, then->statements);
|
||||
@ -251,11 +275,11 @@ if_statement:
|
||||
$$ = new elna::boot::if_statement(elna::boot::make_position(@1), then, _else);
|
||||
std::swap($5, $$->branches);
|
||||
}
|
||||
return_statement: RETURN expression
|
||||
return_statement: "return" expression
|
||||
{
|
||||
$$ = new elna::boot::return_statement(elna::boot::make_position(@1), $2);
|
||||
}
|
||||
defer_statement: DEFER optional_statements END_BLOCK
|
||||
defer_statement: DEFER optional_statements "end"
|
||||
{
|
||||
$$ = new elna::boot::defer_statement(elna::boot::make_position(@1));
|
||||
std::swap($2, $$->statements);
|
||||
@ -281,7 +305,7 @@ literal:
|
||||
{
|
||||
$$ = new elna::boot::number_literal<unsigned char>(elna::boot::make_position(@1), $1.at(0));
|
||||
}
|
||||
| NIL
|
||||
| "nil"
|
||||
{
|
||||
$$ = new elna::boot::number_literal<std::nullptr_t>(elna::boot::make_position(@1), nullptr);
|
||||
}
|
||||
@ -292,129 +316,126 @@ literal:
|
||||
operand:
|
||||
literal { $$ = $1; }
|
||||
| designator_expression { $$ = $1; }
|
||||
| LEFT_PAREN type_expression RIGHT_PAREN
|
||||
{
|
||||
$$ = new elna::boot::type_expression(elna::boot::make_position(@1), $2);
|
||||
}
|
||||
| "(" type_expression ")" { $$ = new elna::boot::type_expression(elna::boot::make_position(@1), $2); }
|
||||
| cast_expression { $$ = $1; }
|
||||
| call_expression { $$ = $1; }
|
||||
| LEFT_PAREN expression RIGHT_PAREN { $$ = $2; }
|
||||
| "(" expression ")" { $$ = $2; }
|
||||
expression:
|
||||
unary { $$ = $1; }
|
||||
| expression MULTIPLICATION expression
|
||||
| expression "*" expression
|
||||
{
|
||||
$$ = new elna::boot::binary_expression(elna::boot::make_position(@2), $1, $3,
|
||||
elna::boot::binary_operator::multiplication);
|
||||
}
|
||||
| expression DIVISION expression
|
||||
| expression "/" expression
|
||||
{
|
||||
$$ = new elna::boot::binary_expression(elna::boot::make_position(@2), $1, $3,
|
||||
elna::boot::binary_operator::division);
|
||||
}
|
||||
| expression REMAINDER expression
|
||||
| expression "%" expression
|
||||
{
|
||||
$$ = new elna::boot::binary_expression(elna::boot::make_position(@2), $1, $3,
|
||||
elna::boot::binary_operator::remainder);
|
||||
}
|
||||
| expression PLUS expression
|
||||
| expression "+" expression
|
||||
{
|
||||
$$ = new elna::boot::binary_expression(elna::boot::make_position(@2), $1, $3,
|
||||
elna::boot::binary_operator::sum);
|
||||
}
|
||||
| expression MINUS expression
|
||||
| expression "-" expression
|
||||
{
|
||||
$$ = new elna::boot::binary_expression(elna::boot::make_position(@2), $1, $3,
|
||||
elna::boot::binary_operator::subtraction);
|
||||
}
|
||||
| expression EQUALS expression
|
||||
| expression "=" expression
|
||||
{
|
||||
$$ = new elna::boot::binary_expression(elna::boot::make_position(@2), $1, $3,
|
||||
elna::boot::binary_operator::equals);
|
||||
}
|
||||
| expression NOT_EQUAL expression
|
||||
| expression "<>" expression
|
||||
{
|
||||
$$ = new elna::boot::binary_expression(elna::boot::make_position(@2), $1, $3,
|
||||
elna::boot::binary_operator::not_equals);
|
||||
}
|
||||
| expression LESS_THAN expression
|
||||
| expression "<" expression
|
||||
{
|
||||
$$ = new elna::boot::binary_expression(elna::boot::make_position(@2), $1, $3,
|
||||
elna::boot::binary_operator::less);
|
||||
}
|
||||
| expression GREATER_THAN expression
|
||||
| expression ">" expression
|
||||
{
|
||||
$$ = new elna::boot::binary_expression(elna::boot::make_position(@2), $1, $3,
|
||||
elna::boot::binary_operator::greater);
|
||||
}
|
||||
| expression LESS_EQUAL expression
|
||||
| expression "<=" expression
|
||||
{
|
||||
$$ = new elna::boot::binary_expression(elna::boot::make_position(@2), $1, $3,
|
||||
elna::boot::binary_operator::less_equal);
|
||||
}
|
||||
| expression GREATER_EQUAL expression
|
||||
| expression ">=" expression
|
||||
{
|
||||
$$ = new elna::boot::binary_expression(elna::boot::make_position(@2), $1, $3,
|
||||
elna::boot::binary_operator::greater_equal);
|
||||
}
|
||||
| expression AND expression
|
||||
| expression "and" expression
|
||||
{
|
||||
$$ = new elna::boot::binary_expression(elna::boot::make_position(@2), $1, $3,
|
||||
elna::boot::binary_operator::conjunction);
|
||||
}
|
||||
| expression OR expression
|
||||
| expression "or" expression
|
||||
{
|
||||
$$ = new elna::boot::binary_expression(elna::boot::make_position(@2), $1, $3,
|
||||
elna::boot::binary_operator::disjunction);
|
||||
}
|
||||
| expression XOR expression
|
||||
| expression "xor" expression
|
||||
{
|
||||
$$ = new elna::boot::binary_expression(elna::boot::make_position(@2), $1, $3,
|
||||
elna::boot::binary_operator::exclusive_disjunction);
|
||||
}
|
||||
| expression SHIFT_LEFT expression
|
||||
| expression "<<" expression
|
||||
{
|
||||
$$ = new elna::boot::binary_expression(elna::boot::make_position(@2), $1, $3,
|
||||
elna::boot::binary_operator::shift_left);
|
||||
}
|
||||
| expression SHIFT_RIGHT expression
|
||||
| expression ">>" expression
|
||||
{
|
||||
$$ = new elna::boot::binary_expression(elna::boot::make_position(@2), $1, $3,
|
||||
elna::boot::binary_operator::shift_right);
|
||||
}
|
||||
unary:
|
||||
AT operand
|
||||
"@" operand
|
||||
{
|
||||
$$ = new elna::boot::unary_expression(elna::boot::make_position(@1), $2,
|
||||
elna::boot::unary_operator::reference);
|
||||
}
|
||||
| NOT operand
|
||||
| "not" operand
|
||||
{
|
||||
$$ = new elna::boot::unary_expression(elna::boot::make_position(@1), $2,
|
||||
elna::boot::unary_operator::negation);
|
||||
}
|
||||
| MINUS operand
|
||||
| "-" operand
|
||||
{
|
||||
$$ = new elna::boot::unary_expression(elna::boot::make_position(@1), $2,
|
||||
elna::boot::unary_operator::minus);
|
||||
}
|
||||
| operand { $$ = $1; }
|
||||
expressions:
|
||||
expression COMMA expressions
|
||||
expression "," expressions
|
||||
{
|
||||
std::swap($$, $3);
|
||||
$$.emplace($$.cbegin(), $1);
|
||||
}
|
||||
| expression { $$.emplace_back(std::move($1)); }
|
||||
designator_expression:
|
||||
operand LEFT_SQUARE expression RIGHT_SQUARE
|
||||
operand "[" expression "]"
|
||||
{
|
||||
$$ = new elna::boot::array_access_expression(elna::boot::make_position(@2), $1, $3);
|
||||
}
|
||||
| operand DOT IDENTIFIER
|
||||
| operand "." IDENTIFIER
|
||||
{
|
||||
$$ = new elna::boot::field_access_expression(elna::boot::make_position(@2), $1, $3);
|
||||
}
|
||||
| operand HAT
|
||||
| operand "^"
|
||||
{
|
||||
$$ = new elna::boot::dereference_expression(elna::boot::make_position(@1), $1);
|
||||
}
|
||||
@ -443,7 +464,7 @@ optional_statements:
|
||||
statements { std::swap($$, $1); }
|
||||
| /* no statements */ {}
|
||||
field_declaration:
|
||||
IDENTIFIER COLON type_expression { $$ = std::make_pair($1, $3); }
|
||||
IDENTIFIER ":" type_expression { $$ = std::make_pair($1, $3); }
|
||||
fields:
|
||||
field_declaration fields
|
||||
{
|
||||
@ -455,23 +476,23 @@ optional_fields:
|
||||
fields { std::swap($$, $1); }
|
||||
| /* no fields */ {}
|
||||
type_expression:
|
||||
LEFT_SQUARE INTEGER RIGHT_SQUARE type_expression
|
||||
"[" INTEGER "]" type_expression
|
||||
{
|
||||
$$ = std::make_shared<elna::boot::array_type>(elna::boot::make_position(@1), $4, $2);
|
||||
}
|
||||
| HAT type_expression
|
||||
| "^" type_expression
|
||||
{
|
||||
$$ = std::make_shared<elna::boot::pointer_type>(elna::boot::make_position(@1), $2);
|
||||
}
|
||||
| RECORD optional_fields END_BLOCK
|
||||
| "record" optional_fields "end"
|
||||
{
|
||||
$$ = std::make_shared<elna::boot::record_type>(elna::boot::make_position(@1), std::move($2));
|
||||
}
|
||||
| UNION fields END_BLOCK
|
||||
| "union" fields "end"
|
||||
{
|
||||
$$ = std::make_shared<elna::boot::union_type>(elna::boot::make_position(@1), std::move($2));
|
||||
}
|
||||
| PROCEDURE procedure_heading
|
||||
| "proc" procedure_heading
|
||||
{
|
||||
$$ = $2;
|
||||
}
|
||||
@ -479,7 +500,7 @@ type_expression:
|
||||
{
|
||||
$$ = std::make_shared<elna::boot::basic_type>(elna::boot::make_position(@1), $1);
|
||||
}
|
||||
variable_declaration: identifier_definitions COLON type_expression
|
||||
variable_declaration: identifier_definitions ":" type_expression
|
||||
{
|
||||
for (const std::pair<std::string, bool>& identifier : $1)
|
||||
{
|
||||
@ -498,8 +519,8 @@ variable_declarations:
|
||||
| variable_declaration { std::swap($$, $1); }
|
||||
variable_part:
|
||||
/* no variable declarations */ {}
|
||||
| VAR variable_declarations { std::swap($$, $2); }
|
||||
constant_definition: identifier_definition EQUALS literal
|
||||
| "var" variable_declarations { std::swap($$, $2); }
|
||||
constant_definition: identifier_definition "=" literal
|
||||
{
|
||||
$$ = new elna::boot::constant_definition(elna::boot::make_position(@1), $1.first, $1.second, $3);
|
||||
}
|
||||
@ -512,9 +533,9 @@ constant_definitions:
|
||||
| constant_definition { $$.emplace_back(std::move($1)); }
|
||||
constant_part:
|
||||
/* no constant definitions */ {}
|
||||
| CONST {}
|
||||
| CONST constant_definitions { std::swap($$, $2); }
|
||||
type_definition: identifier_definition EQUALS type_expression
|
||||
| "const" {}
|
||||
| "const" constant_definitions { std::swap($$, $2); }
|
||||
type_definition: identifier_definition "=" type_expression
|
||||
{
|
||||
$$ = new elna::boot::type_definition(elna::boot::make_position(@1), $1.first, $1.second, $3);
|
||||
}
|
||||
@ -527,25 +548,25 @@ type_definitions:
|
||||
| type_definition { $$.emplace_back(std::move($1)); }
|
||||
type_part:
|
||||
/* no type definitions */ {}
|
||||
| TYPE {}
|
||||
| TYPE type_definitions { std::swap($$, $2); }
|
||||
formal_parameter: IDENTIFIER COLON type_expression
|
||||
| "type" {}
|
||||
| "type" type_definitions { std::swap($$, $2); }
|
||||
formal_parameter: IDENTIFIER ":" type_expression
|
||||
{
|
||||
$$ = new elna::boot::variable_declaration(elna::boot::make_position(@2), $1, $3);
|
||||
}
|
||||
formal_parameters:
|
||||
formal_parameter COMMA formal_parameters
|
||||
formal_parameter "," formal_parameters
|
||||
{
|
||||
std::swap($$, $3);
|
||||
$$.emplace($$.cbegin(), $1);
|
||||
}
|
||||
| formal_parameter { $$.emplace_back(std::move($1)); }
|
||||
formal_parameter_list:
|
||||
LEFT_PAREN RIGHT_PAREN {}
|
||||
| LEFT_PAREN formal_parameters RIGHT_PAREN { std::swap($$, $2); }
|
||||
"(" ")" {}
|
||||
| "(" formal_parameters ")" { std::swap($$, $2); }
|
||||
actual_parameter_list:
|
||||
LEFT_PAREN RIGHT_PAREN {}
|
||||
| LEFT_PAREN expressions RIGHT_PAREN { std::swap($$, $2); }
|
||||
"(" ")" {}
|
||||
| "(" expressions ")" { std::swap($$, $2); }
|
||||
%%
|
||||
|
||||
void yy::parser::error(const location_type& loc, const std::string& message)
|
||||
|
Reference in New Issue
Block a user