[executable semantics] Use type-safe variant in C++ parser (#364)

We're now one step away from eliminating bare pointers in semantic actions.

There are plenty of other cleanups and modernizations that can be made in the
parser, but the elimination of bare pointers is the one that has the highest
impact for the codebase.
This commit is contained in:
Dave Abrahams
2021-03-09 21:17:06 -08:00
committed by GitHub
parent 436a9dda79
commit 120e0145ce
3 changed files with 190 additions and 105 deletions
+62 -38
View File
@@ -9,9 +9,16 @@
%require "3.2"
%language "c++"
// We don't need a separate header for Bison locations yet.
// We don't need a separate header for Bison locations.
%define api.location.file none
// Use a type-safe C++ variant for semantic values
%define api.value.type variant
// Have Bison generate the functions ‘make_TEXT’ and ‘make_NUMBER’, but also
// ‘make_YYEOF’, for the end of input.
%define api.token.constructor
//
// Parameters to the parser and lexer
//
@@ -64,8 +71,6 @@ void yy::parser::error(
}
%define api.value.type union
%token <int> integer_literal
%token <char*> identifier
%type <char*> designator
@@ -89,6 +94,7 @@ void yy::parser::error(
%type <std::list<std::pair<std::string, Carbon::Expression*>>*> alternative_list
%type <std::pair<Carbon::Expression*, Carbon::Statement*>*> clause
%type <std::list<std::pair<Carbon::Expression*, Carbon::Statement*>>*> clause_list
%token END_OF_FILE 0
%token AND
%token OR
%token NOT
@@ -99,7 +105,7 @@ void yy::parser::error(
%token FNTY
%token ARROW
%token VAR
%token EQUAL
%token EQUAL_EQUAL
%token IF
%token ELSE
%token WHILE
@@ -115,13 +121,31 @@ void yy::parser::error(
%token DBLARROW
%token DEFAULT
%token AUTO
%nonassoc '{' '}'
%nonassoc ':' ',' DBLARROW
%token
EQUAL "="
MINUS "-"
PLUS "+"
STAR "*"
SLASH "/"
LEFT_PARENTHESIS "("
RIGHT_PARENTHESIS ")"
LEFT_CURLY_BRACE "{"
RIGHT_CURLY_BRACE "}"
LEFT_SQUARE_BRACKET "["
RIGHT_SQUARE_BRACKET "]"
PERIOD "."
COMMA ","
SEMICOLON ";"
COLON ":"
;
%nonassoc "{" "}"
%nonassoc ":" "," DBLARROW
%left OR AND
%nonassoc EQUAL NOT
%left '+' '-'
%left '.' ARROW
%nonassoc '(' ')' '[' ']'
%nonassoc EQUAL_EQUAL NOT
%left "+" "-"
%left "." ARROW
%nonassoc "(" ")" "[" "]"
%start input
%locations
%%
@@ -137,9 +161,9 @@ expression:
{ $$ = Carbon::MakeVar(yylineno, $1); }
| expression designator
{ $$ = Carbon::MakeGetField(yylineno, $1, $2); }
| expression '[' expression ']'
| expression "[" expression "]"
{ $$ = Carbon::MakeIndex(yylineno, $1, $3); }
| expression ':' identifier
| expression ":" identifier
{ $$ = Carbon::MakeVarPat(yylineno, $3, $1); }
| integer_literal
{ $$ = Carbon::MakeInt(yylineno, $1); }
@@ -156,11 +180,11 @@ expression:
| AUTO
{ $$ = Carbon::MakeAutoType(yylineno); }
| paren_expression { $$ = $1; }
| expression EQUAL expression
| expression EQUAL_EQUAL expression
{ $$ = Carbon::MakeBinOp(yylineno, Carbon::Operator::Eq, $1, $3); }
| expression '+' expression
| expression "+" expression
{ $$ = Carbon::MakeBinOp(yylineno, Carbon::Operator::Add, $1, $3); }
| expression '-' expression
| expression "-" expression
{ $$ = Carbon::MakeBinOp(yylineno, Carbon::Operator::Sub, $1, $3); }
| expression AND expression
{ $$ = Carbon::MakeBinOp(yylineno, Carbon::Operator::And, $1, $3); }
@@ -168,16 +192,16 @@ expression:
{ $$ = Carbon::MakeBinOp(yylineno, Carbon::Operator::Or, $1, $3); }
| NOT expression
{ $$ = Carbon::MakeUnOp(yylineno, Carbon::Operator::Not, $2); }
| '-' expression
| "-" expression
{ $$ = Carbon::MakeUnOp(yylineno, Carbon::Operator::Neg, $2); }
| expression tuple
{ $$ = Carbon::MakeCall(yylineno, $1, $2); }
| FNTY tuple return_type
{ $$ = Carbon::MakeFunType(yylineno, $2, $3); }
;
designator: '.' identifier { $$ = $2; }
designator: "." identifier { $$ = $2; }
;
paren_expression: '(' field_list ')'
paren_expression: "(" field_list ")"
{
if ($2->fields->size() == 1 &&
$2->fields->front().first == "" &&
@@ -190,7 +214,7 @@ paren_expression: '(' field_list ')'
}
}
;
tuple: '(' field_list ')'
tuple: "(" field_list ")"
{
auto vec = new std::vector<std::pair<std::string,Carbon::Expression*>>(
$2->fields->begin(), $2->fields->end());
@@ -204,7 +228,7 @@ field:
fields->push_back(std::make_pair("", $1));
$$ = Carbon::MakeFieldList(fields);
}
| designator '=' pattern
| designator "=" pattern
{
auto fields =
new std::list<std::pair<std::string, Carbon::Expression*>>();
@@ -220,7 +244,7 @@ field_list:
}
| field
{ $$ = $1; }
| field ',' field_list
| field "," field_list
{ $$ = Carbon::MakeConsField($1, $3); }
;
clause:
@@ -242,25 +266,25 @@ clause_list:
{ $$ = $2; $$->push_front(*$1); }
;
statement:
expression '=' expression ';'
expression "=" expression ";"
{ $$ = Carbon::MakeAssign(yylineno, $1, $3); }
| VAR pattern '=' expression ';'
| VAR pattern "=" expression ";"
{ $$ = Carbon::MakeVarDef(yylineno, $2, $4); }
| expression ';'
| expression ";"
{ $$ = Carbon::MakeExpStmt(yylineno, $1); }
| IF '(' expression ')' statement optional_else
| IF "(" expression ")" statement optional_else
{ $$ = Carbon::MakeIf(yylineno, $3, $5, $6); }
| WHILE '(' expression ')' statement
| WHILE "(" expression ")" statement
{ $$ = Carbon::MakeWhile(yylineno, $3, $5); }
| BREAK ';'
| BREAK ";"
{ $$ = Carbon::MakeBreak(yylineno); }
| CONTINUE ';'
| CONTINUE ";"
{ $$ = Carbon::MakeContinue(yylineno); }
| RETURN expression ';'
| RETURN expression ";"
{ $$ = Carbon::MakeReturn(yylineno, $2); }
| '{' statement_list '}'
| "{" statement_list "}"
{ $$ = Carbon::MakeBlock(yylineno, $2); }
| MATCH '(' expression ')' '{' clause_list '}'
| MATCH "(" expression ")" "{" clause_list "}"
{ $$ = Carbon::MakeMatch(yylineno, $3, $6); }
;
optional_else:
@@ -285,20 +309,20 @@ return_type:
{ $$ = $2; }
;
function_definition:
FN identifier tuple return_type '{' statement_list '}'
FN identifier tuple return_type "{" statement_list "}"
{ $$ = MakeFunDef(yylineno, $2, $4, $3, $6); }
| FN identifier tuple DBLARROW expression ';'
| FN identifier tuple DBLARROW expression ";"
{
$$ = Carbon::MakeFunDef(yylineno, $2, Carbon::MakeAutoType(yylineno), $3,
Carbon::MakeReturn(yylineno, $5));
}
;
function_declaration:
FN identifier tuple return_type ';'
FN identifier tuple return_type ";"
{ $$ = MakeFunDef(yylineno, $2, $4, $3, 0); }
;
member:
VAR expression ':' identifier ';'
VAR expression ":" identifier ";"
{ $$ = MakeField(yylineno, $4, $2); }
;
member_list:
@@ -326,7 +350,7 @@ alternative_list:
$$ = new std::list<std::pair<std::string, Carbon::Expression*>>();
$$->push_front(*$1);
}
| alternative ',' alternative_list
| alternative "," alternative_list
{ $$ = $3; $$->push_front(*$1); }
;
declaration:
@@ -334,12 +358,12 @@ declaration:
{ $$ = new Carbon::Declaration(Carbon::FunctionDeclaration{$1}); }
| function_declaration
{ $$ = new Carbon::Declaration(Carbon::FunctionDeclaration{$1}); }
| STRUCT identifier '{' member_list '}'
| STRUCT identifier "{" member_list "}"
{
$$ = new Carbon::Declaration(
Carbon::StructDeclaration{yylineno, $2, $4});
}
| CHOICE identifier '{' alternative_list '}'
| CHOICE identifier "{" alternative_list "}"
{
$$ = new Carbon::Declaration(
Carbon::ChoiceDeclaration{yylineno, $2, std::list(*$4)});