Restructure handling of paren expressions (#417)

* Move nontrivial logic out of `parser.ypp` into `FieldList`, rename it to `ParenContents`, make it a class, and add tests
* Use a `FieldInitializer` struct instead of `std::pair<std::string, Expression*>` to represent the fields of a tuple
This commit is contained in:
Geoff Romer
2021-04-05 10:49:25 -07:00
committed by GitHub
parent 98a6477233
commit 80f035874d
9 changed files with 251 additions and 105 deletions
+30 -40
View File
@@ -50,8 +50,8 @@
#include "executable_semantics/ast/abstract_syntax_tree.h"
#include "executable_semantics/ast/declaration.h"
#include "executable_semantics/ast/field_list.h"
#include "executable_semantics/ast/function_definition.h"
#include "executable_semantics/syntax/paren_contents.h"
namespace Carbon {
class ParseAndLexContext;
@@ -89,8 +89,9 @@ void yy::parser::error(
%type <Carbon::Member*> variable_declaration
%type <Carbon::Member*> member
%type <std::list<Carbon::Member*>*> member_list
%type <Carbon::FieldList*> field
%type <Carbon::FieldList*> field_list
%type <Carbon::FieldInitializer> field_initializer
%type <Carbon::ParenContents> paren_contents
%type <std::vector<Carbon::FieldInitializer>> paren_contents_without_trailing_comma
%type <std::pair<std::string, Carbon::Expression*>*> alternative
%type <std::list<std::pair<std::string, Carbon::Expression*>>*> alternative_list
%type <std::pair<Carbon::Expression*, Carbon::Statement*>*> clause
@@ -208,51 +209,40 @@ expression:
;
designator: "." identifier { $$ = $2; }
;
paren_expression: "(" field_list ")"
{
if ($2->fields->size() == 1 &&
$2->fields->front().first == "" &&
!$2->has_explicit_comma) {
$$ = $2->fields->front().second;
} else {
auto vec = new std::vector<std::pair<std::string,Carbon::Expression*>>(
$2->fields->begin(), $2->fields->end());
$$ = Carbon::MakeTuple(yylineno, vec);
}
}
paren_expression: "(" paren_contents ")"
{ $$ = $2.AsExpression(yylineno); }
;
tuple: "(" field_list ")"
{
auto vec = new std::vector<std::pair<std::string,Carbon::Expression*>>(
$2->fields->begin(), $2->fields->end());
$$ = Carbon::MakeTuple(yylineno, vec);
}
field:
tuple: "(" paren_contents ")"
{ $$ = $2.AsTuple(yylineno); }
;
field_initializer:
pattern
{
auto fields =
new std::list<std::pair<std::string, Carbon::Expression*>>();
fields->push_back(std::make_pair("", $1));
$$ = Carbon::MakeFieldList(fields);
}
{ $$ = Carbon::FieldInitializer({"", $1}); }
| designator "=" pattern
{ $$ = Carbon::FieldInitializer({$1, $3}); }
;
paren_contents:
// Empty
{ $$ = Carbon::ParenContents(); }
| paren_contents_without_trailing_comma
{
auto fields =
new std::list<std::pair<std::string, Carbon::Expression*>>();
fields->push_back(std::make_pair($1, $3));
$$ = Carbon::MakeFieldList(fields);
$$ = Carbon::ParenContents($1,
Carbon::ParenContents::HasTrailingComma::No);
}
| paren_contents_without_trailing_comma ","
{
$$ = Carbon::ParenContents($1,
Carbon::ParenContents::HasTrailingComma::Yes);
}
;
field_list:
// Empty
paren_contents_without_trailing_comma:
field_initializer
{ $$ = {$1}; }
| paren_contents_without_trailing_comma "," field_initializer
{
$$ = Carbon::MakeFieldList(
new std::list<std::pair<std::string, Carbon::Expression*>>());
$$ = $1;
$$.push_back($3);
}
| field
{ $$ = $1; }
| field "," field_list
{ $$ = Carbon::MakeConsField($1, $3); }
;
clause:
CASE pattern DBLARROW statement