// 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 %code top { #include #include #include #include #include #include #include "executable_semantics/syntax_helpers.h" } %code requires { #include "executable_semantics/ast/declaration.h" #include "executable_semantics/ast/field_list.h" #include "executable_semantics/ast/function_definition.h" } %code { extern int yylineno; extern int yylex(); void yyerror(char* error) { Carbon::PrintSyntaxError(error, yylineno); } // void yyerror(char* error, ...); } %union { char* str; int num; Carbon::Expression* expression; std::list>* field_types; Carbon::Statement* statement; Carbon::Statement* statement_list; Carbon::FunctionDefinition* function_definition; Carbon::Declaration* declaration; std::list* declaration_list; Carbon::Member* member; std::list* member_list; Carbon::FieldList* field_list; std::pair* alternative; std::list>* alternative_list; std::pair* clause; std::list>* clause_list; Carbon::Expression* fun_type; }; %token integer_literal %token identifier %type designator %type declaration %type function_declaration %type function_definition %type declaration_list %type statement %type optional_else %type statement_list %type expression %type pattern %type return_type %type paren_expression %type tuple %type member %type member_list %type field %type field_list %type alternative %type alternative_list %type clause %type clause_list %token AND %token OR %token NOT %token INT %token BOOL %token TYPE %token FN %token FNTY %token ARROW %token VAR %token EQUAL %token IF %token ELSE %token WHILE %token BREAK %token CONTINUE %token RETURN %token TRUE %token FALSE %token STRUCT %token CHOICE %token MATCH %token CASE %token DBLARROW %token DEFAULT %token AUTO %nonassoc '{' '}' %nonassoc ':' ',' DBLARROW %left OR AND %nonassoc EQUAL NOT %left '+' '-' %left '.' ARROW %nonassoc '(' ')' '[' ']' %start input %locations %% input: declaration_list { Carbon::ExecProgram($1); } ; pattern: expression { $$ = $1; } ; expression: identifier { $$ = Carbon::MakeVar(yylineno, $1); } | expression designator { $$ = Carbon::MakeGetField(yylineno, $1, $2); } | expression '[' expression ']' { $$ = Carbon::MakeIndex(yylineno, $1, $3); } | expression ':' identifier { $$ = Carbon::MakeVarPat(yylineno, $3, $1); } | integer_literal { $$ = Carbon::MakeInt(yylineno, $1); } | TRUE { $$ = Carbon::MakeBool(yylineno, true); } | FALSE { $$ = Carbon::MakeBool(yylineno, false); } | INT { $$ = Carbon::MakeIntType(yylineno); } | BOOL { $$ = Carbon::MakeBoolType(yylineno); } | TYPE { $$ = Carbon::MakeTypeType(yylineno); } | AUTO { $$ = Carbon::MakeAutoType(yylineno); } | paren_expression { $$ = $1; } | expression EQUAL expression { $$ = Carbon::MakeBinOp(yylineno, Carbon::Operator::Eq, $1, $3); } | expression '+' expression { $$ = Carbon::MakeBinOp(yylineno, Carbon::Operator::Add, $1, $3); } | expression '-' expression { $$ = Carbon::MakeBinOp(yylineno, Carbon::Operator::Sub, $1, $3); } | expression AND expression { $$ = Carbon::MakeBinOp(yylineno, Carbon::Operator::And, $1, $3); } | expression OR expression { $$ = Carbon::MakeBinOp(yylineno, Carbon::Operator::Or, $1, $3); } | NOT expression { $$ = Carbon::MakeUnOp(yylineno, Carbon::Operator::Not, $2); } | '-' 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; } ; 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>( $2->fields->begin(), $2->fields->end()); $$ = Carbon::MakeTuple(yylineno, vec); } } ; tuple: '(' field_list ')' { auto vec = new std::vector>( $2->fields->begin(), $2->fields->end()); $$ = Carbon::MakeTuple(yylineno, vec); } field: pattern { auto fields = new std::list>(); fields->push_back(std::make_pair("", $1)); $$ = Carbon::MakeFieldList(fields); } | designator '=' pattern { auto fields = new std::list>(); fields->push_back(std::make_pair($1, $3)); $$ = Carbon::MakeFieldList(fields); } ; field_list: // Empty { $$ = Carbon::MakeFieldList( new std::list>()); } | field { $$ = $1; } | field ',' field_list { $$ = Carbon::MakeConsField($1, $3); } ; clause: CASE pattern DBLARROW statement { $$ = new std::pair($2, $4); } | DEFAULT DBLARROW statement { auto vp = Carbon::MakeVarPat(yylineno, "_", Carbon::MakeAutoType(yylineno)); $$ = new std::pair(vp, $3); } ; clause_list: // Empty { $$ = new std::list>(); } | clause clause_list { $$ = $2; $$->push_front(*$1); } ; statement: expression '=' expression ';' { $$ = Carbon::MakeAssign(yylineno, $1, $3); } | VAR pattern '=' expression ';' { $$ = Carbon::MakeVarDef(yylineno, $2, $4); } | expression ';' { $$ = Carbon::MakeExpStmt(yylineno, $1); } | IF '(' expression ')' statement optional_else { $$ = Carbon::MakeIf(yylineno, $3, $5, $6); } | WHILE '(' expression ')' statement { $$ = Carbon::MakeWhile(yylineno, $3, $5); } | BREAK ';' { $$ = Carbon::MakeBreak(yylineno); } | CONTINUE ';' { $$ = Carbon::MakeContinue(yylineno); } | RETURN expression ';' { $$ = Carbon::MakeReturn(yylineno, $2); } | '{' statement_list '}' { $$ = Carbon::MakeBlock(yylineno, $2); } | MATCH '(' expression ')' '{' clause_list '}' { $$ = Carbon::MakeMatch(yylineno, $3, $6); } ; optional_else: // Empty { $$ = 0; } | ELSE statement { $$ = $2; } ; statement_list: // Empty { $$ = 0; } | statement statement_list { $$ = Carbon::MakeSeq(yylineno, $1, $2); } ; return_type: // Empty { $$ = Carbon::MakeTuple( yylineno, new std::vector>()); } | ARROW expression { $$ = $2; } ; function_definition: FN identifier tuple return_type '{' statement_list '}' { $$ = MakeFunDef(yylineno, $2, $4, $3, $6); } | FN identifier tuple DBLARROW expression ';' { $$ = Carbon::MakeFunDef(yylineno, $2, Carbon::MakeAutoType(yylineno), $3, Carbon::MakeReturn(yylineno, $5)); } ; function_declaration: FN identifier tuple return_type ';' { $$ = MakeFunDef(yylineno, $2, $4, $3, 0); } ; member: VAR expression ':' identifier ';' { $$ = MakeField(yylineno, $4, $2); } ; member_list: // Empty { $$ = new std::list(); } | member member_list { $$ = $2; $$->push_front($1); } ; alternative: identifier tuple { $$ = new std::pair($1, $2); } | identifier { $$ = new std::pair( $1, Carbon::MakeTuple( yylineno, new std::vector>())); } ; alternative_list: // Empty { $$ = new std::list>(); } | alternative { $$ = new std::list>(); $$->push_front(*$1); } | alternative ',' alternative_list { $$ = $3; $$->push_front(*$1); } ; declaration: function_definition { $$ = new Carbon::Declaration(Carbon::FunctionDeclaration{$1}); } | function_declaration { $$ = new Carbon::Declaration(Carbon::FunctionDeclaration{$1}); } | STRUCT identifier '{' member_list '}' { $$ = new Carbon::Declaration( Carbon::StructDeclaration{yylineno, $2, $4}); } | CHOICE identifier '{' alternative_list '}' { $$ = new Carbon::Declaration( Carbon::ChoiceDeclaration{yylineno, $2, std::list(*$4)}); } ; declaration_list: // Empty { $$ = new std::list(); } | declaration declaration_list { $$ = $2; $$->push_front(*$1); } ; %%