diff --git a/executable_semantics/BUILD b/executable_semantics/BUILD index aa0d504e7bfd..ea2291dde895 100644 --- a/executable_semantics/BUILD +++ b/executable_semantics/BUILD @@ -32,7 +32,7 @@ cc_library( deps = [ "//executable_semantics/ast:declaration", "//executable_semantics/ast:expression", - "//executable_semantics/ast:expression_or_field_list", + "//executable_semantics/ast:field_list", "//executable_semantics/interpreter", ], ) diff --git a/executable_semantics/ast/BUILD b/executable_semantics/ast/BUILD index b981a553a3c1..99e88447dda8 100644 --- a/executable_semantics/ast/BUILD +++ b/executable_semantics/ast/BUILD @@ -24,9 +24,9 @@ cc_library( ) cc_library( - name = "expression_or_field_list", - srcs = ["expression_or_field_list.cpp"], - hdrs = ["expression_or_field_list.h"], + name = "field_list", + srcs = ["field_list.cpp"], + hdrs = ["field_list.h"], deps = [":expression"], ) diff --git a/executable_semantics/ast/expression_or_field_list.cpp b/executable_semantics/ast/expression_or_field_list.cpp deleted file mode 100644 index d3f0f8205b7b..000000000000 --- a/executable_semantics/ast/expression_or_field_list.cpp +++ /dev/null @@ -1,49 +0,0 @@ -// Part of the Carbon Language project, under the Apache License v2.0 with LLVM -// Exceptions. See /LICENSE for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception - -#include "executable_semantics/ast/expression_or_field_list.h" - -namespace Carbon { - -auto MakeExp(Expression* exp) -> ExpOrFieldList* { - auto e = new ExpOrFieldList(); - e->tag = ExpOrFieldListKind::Exp; - e->u.exp = exp; - return e; -} - -auto MakeFieldList(std::list>* fields) - -> ExpOrFieldList* { - auto e = new ExpOrFieldList(); - e->tag = ExpOrFieldListKind::FieldList; - e->u.fields = fields; - return e; -} - -auto MakeConsField(ExpOrFieldList* e1, ExpOrFieldList* e2) -> ExpOrFieldList* { - auto fields = new std::list>(); - switch (e1->tag) { - case ExpOrFieldListKind::Exp: - fields->push_back(std::make_pair("", e1->u.exp)); - break; - case ExpOrFieldListKind::FieldList: - for (auto& field : *e1->u.fields) { - fields->push_back(field); - } - break; - } - switch (e2->tag) { - case ExpOrFieldListKind::Exp: - fields->push_back(std::make_pair("", e2->u.exp)); - break; - case ExpOrFieldListKind::FieldList: - for (auto& field : *e2->u.fields) { - fields->push_back(field); - } - break; - } - return MakeFieldList(fields); -} - -} // namespace Carbon diff --git a/executable_semantics/ast/expression_or_field_list.h b/executable_semantics/ast/expression_or_field_list.h deleted file mode 100644 index b5054c7461ab..000000000000 --- a/executable_semantics/ast/expression_or_field_list.h +++ /dev/null @@ -1,32 +0,0 @@ -// Part of the Carbon Language project, under the Apache License v2.0 with LLVM -// Exceptions. See /LICENSE for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception - -#ifndef EXECUTABLE_SEMANTICS_AST_EXPRESSION_OR_FIELD_LIST_H_ -#define EXECUTABLE_SEMANTICS_AST_EXPRESSION_OR_FIELD_LIST_H_ - -#include - -#include "executable_semantics/ast/expression.h" - -namespace Carbon { - -enum class ExpOrFieldListKind { Exp, FieldList }; - -// This is used in the parsing of tuples and parenthesized expressions. -struct ExpOrFieldList { - ExpOrFieldListKind tag; - union { - Expression* exp; - std::list>* fields; - } u; -}; - -auto MakeExp(Expression* exp) -> ExpOrFieldList*; -auto MakeFieldList(std::list>* fields) - -> ExpOrFieldList*; -auto MakeConsField(ExpOrFieldList* e1, ExpOrFieldList* e2) -> ExpOrFieldList*; - -} // namespace Carbon - -#endif // EXECUTABLE_SEMANTICS_AST_EXPRESSION_OR_FIELD_LIST_H_ diff --git a/executable_semantics/ast/field_list.cpp b/executable_semantics/ast/field_list.cpp new file mode 100644 index 000000000000..96e730a83680 --- /dev/null +++ b/executable_semantics/ast/field_list.cpp @@ -0,0 +1,29 @@ +// Part of the Carbon Language project, under the Apache License v2.0 with LLVM +// Exceptions. See /LICENSE for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +#include "executable_semantics/ast/field_list.h" + +namespace Carbon { + +auto MakeFieldList(std::list>* fields) + -> FieldList* { + auto e = new FieldList(); + e->fields = fields; + return e; +} + +auto MakeConsField(FieldList* e1, FieldList* e2) -> FieldList* { + auto fields = new std::list>(); + for (auto& field : *e1->fields) { + fields->push_back(field); + } + for (auto& field : *e2->fields) { + fields->push_back(field); + } + auto result = MakeFieldList(fields); + result->has_explicit_comma = true; + return result; +} + +} // namespace Carbon diff --git a/executable_semantics/ast/field_list.h b/executable_semantics/ast/field_list.h new file mode 100644 index 000000000000..3d02b7dd7939 --- /dev/null +++ b/executable_semantics/ast/field_list.h @@ -0,0 +1,26 @@ +// Part of the Carbon Language project, under the Apache License v2.0 with LLVM +// Exceptions. See /LICENSE for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +#ifndef EXECUTABLE_SEMANTICS_AST_FIELD_LIST_H_ +#define EXECUTABLE_SEMANTICS_AST_FIELD_LIST_H_ + +#include + +#include "executable_semantics/ast/expression.h" + +namespace Carbon { + +// This is used in the parsing of tuples and parenthesized expressions. +struct FieldList { + std::list>* fields; + bool has_explicit_comma = false; +}; + +auto MakeFieldList(std::list>* fields) + -> FieldList*; +auto MakeConsField(FieldList* e1, FieldList* e2) -> FieldList*; + +} // namespace Carbon + +#endif // EXECUTABLE_SEMANTICS_AST_FIELD_LIST_H_ diff --git a/executable_semantics/syntax.ypp b/executable_semantics/syntax.ypp index 6523a62eb51d..4bb95de2969b 100644 --- a/executable_semantics/syntax.ypp +++ b/executable_semantics/syntax.ypp @@ -15,7 +15,7 @@ %code requires { #include "executable_semantics/ast/declaration.h" -#include "executable_semantics/ast/expression_or_field_list.h" +#include "executable_semantics/ast/field_list.h" #include "executable_semantics/ast/function_definition.h" } @@ -41,7 +41,7 @@ void yyerror(char* error) { std::list* declaration_list; Carbon::Member* member; std::list* member_list; - Carbon::ExpOrFieldList* field_list; + Carbon::FieldList* field_list; std::pair* alternative; std::list>* alternative_list; std::pair* clause; @@ -62,6 +62,7 @@ void yyerror(char* error) { %type expression %type pattern %type return_type +%type paren_expression %type tuple %type member %type member_list @@ -137,7 +138,7 @@ expression: { $$ = Carbon::MakeTypeType(yylineno); } | AUTO { $$ = Carbon::MakeAutoType(yylineno); } -| tuple { $$ = $1; } +| paren_expression { $$ = $1; } | expression EQUAL expression { $$ = Carbon::MakeBinOp(yylineno, Carbon::Operator::Eq, $1, $3); } | expression '+' expression @@ -153,38 +154,39 @@ expression: | '-' expression { $$ = Carbon::MakeUnOp(yylineno, Carbon::Operator::Neg, $2); } | expression tuple - { - if ($2->tag == Carbon::ExpressionKind::Tuple) { - $$ = Carbon::MakeCall(yylineno, $1, $2); - } else { - auto vec = - new std::vector>(); - vec->push_back(std::make_pair("", $2)); - $$ = Carbon::MakeCall(yylineno, $1, Carbon::MakeTuple(yylineno, vec)); - } - } + { $$ = Carbon::MakeCall(yylineno, $1, $2); } | FNTY tuple return_type { $$ = Carbon::MakeFunType(yylineno, $2, $3); } ; designator: '.' identifier { $$ = $2; } ; -tuple: '(' field_list ')' +paren_expression: '(' field_list ')' { - switch ($2->tag) { - case Carbon::ExpOrFieldListKind::Exp: - $$ = $2->u.exp; - break; - case Carbon::ExpOrFieldListKind::FieldList: + if ($2->fields->size() == 1 && + $2->fields->front().first == "" && + !$2->has_explicit_comma) { + $$ = $2->fields->front().second; + } else { auto vec = new std::vector>( - $2->u.fields->begin(), $2->u.fields->end()); + $2->fields->begin(), $2->fields->end()); $$ = Carbon::MakeTuple(yylineno, vec); - break; } } ; +tuple: '(' field_list ')' + { + auto vec = new std::vector>( + $2->fields->begin(), $2->fields->end()); + $$ = Carbon::MakeTuple(yylineno, vec); + } field: pattern - { $$ = Carbon::MakeExp($1); } + { + auto fields = + new std::list>(); + fields->push_back(std::make_pair("", $1)); + $$ = Carbon::MakeFieldList(fields); + } | designator '=' pattern { auto fields =