mirror of
https://github.com/carbon-language/carbon-lang.git
synced 2026-09-25 11:10:10 +01:00
* Make `field_list` always a list. * Create separate `paren_expression` and `tuple` nonterminals * Rename expression_or_field_list.* to field_list.* Co-authored-by: Jeremy G. Siek <jsiek@indiana.edu>
341 lines
9.1 KiB
Plaintext
341 lines
9.1 KiB
Plaintext
// 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 <algorithm>
|
|
#include <cstdarg>
|
|
#include <cstdio>
|
|
#include <cstdlib>
|
|
#include <iostream>
|
|
#include <list>
|
|
|
|
#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<std::pair<std::string, Carbon::Expression*>>* field_types;
|
|
Carbon::Statement* statement;
|
|
Carbon::Statement* statement_list;
|
|
Carbon::FunctionDefinition* function_definition;
|
|
Carbon::Declaration* declaration;
|
|
std::list<Carbon::Declaration>* declaration_list;
|
|
Carbon::Member* member;
|
|
std::list<Carbon::Member*>* member_list;
|
|
Carbon::FieldList* field_list;
|
|
std::pair<std::string, Carbon::Expression*>* alternative;
|
|
std::list<std::pair<std::string, Carbon::Expression*>>* alternative_list;
|
|
std::pair<Carbon::Expression*, Carbon::Statement*>* clause;
|
|
std::list<std::pair<Carbon::Expression*, Carbon::Statement*>>* clause_list;
|
|
Carbon::Expression* fun_type;
|
|
};
|
|
|
|
%token <num> integer_literal
|
|
%token <str> identifier
|
|
%type <str> designator
|
|
%type <declaration> declaration
|
|
%type <function_definition> function_declaration
|
|
%type <function_definition> function_definition
|
|
%type <declaration_list> declaration_list
|
|
%type <statement> statement
|
|
%type <statement> optional_else
|
|
%type <statement_list> statement_list
|
|
%type <expression> expression
|
|
%type <expression> pattern
|
|
%type <expression> return_type
|
|
%type <expression> paren_expression
|
|
%type <expression> tuple
|
|
%type <member> member
|
|
%type <member_list> member_list
|
|
%type <field_list> field
|
|
%type <field_list> field_list
|
|
%type <alternative> alternative
|
|
%type <alternative_list> alternative_list
|
|
%type <clause> clause
|
|
%type <clause_list> 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<std::pair<std::string,Carbon::Expression*>>(
|
|
$2->fields->begin(), $2->fields->end());
|
|
$$ = Carbon::MakeTuple(yylineno, vec);
|
|
}
|
|
}
|
|
;
|
|
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:
|
|
pattern
|
|
{
|
|
auto fields =
|
|
new std::list<std::pair<std::string, Carbon::Expression*>>();
|
|
fields->push_back(std::make_pair("", $1));
|
|
$$ = Carbon::MakeFieldList(fields);
|
|
}
|
|
| designator '=' pattern
|
|
{
|
|
auto fields =
|
|
new std::list<std::pair<std::string, Carbon::Expression*>>();
|
|
fields->push_back(std::make_pair($1, $3));
|
|
$$ = Carbon::MakeFieldList(fields);
|
|
}
|
|
;
|
|
field_list:
|
|
// Empty
|
|
{
|
|
$$ = Carbon::MakeFieldList(
|
|
new std::list<std::pair<std::string, Carbon::Expression*>>());
|
|
}
|
|
| field
|
|
{ $$ = $1; }
|
|
| field ',' field_list
|
|
{ $$ = Carbon::MakeConsField($1, $3); }
|
|
;
|
|
clause:
|
|
CASE pattern DBLARROW statement
|
|
{ $$ = new std::pair<Carbon::Expression*, Carbon::Statement*>($2, $4); }
|
|
| DEFAULT DBLARROW statement
|
|
{
|
|
auto vp = Carbon::MakeVarPat(yylineno, "_",
|
|
Carbon::MakeAutoType(yylineno));
|
|
$$ = new std::pair<Carbon::Expression*, Carbon::Statement*>(vp, $3);
|
|
}
|
|
;
|
|
clause_list:
|
|
// Empty
|
|
{
|
|
$$ = new std::list<std::pair<Carbon::Expression*, Carbon::Statement*>>();
|
|
}
|
|
| 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<std::pair<std::string, Carbon::Expression*>>());
|
|
}
|
|
| 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<Carbon::Member*>(); }
|
|
| member member_list
|
|
{ $$ = $2; $$->push_front($1); }
|
|
;
|
|
alternative:
|
|
identifier tuple
|
|
{ $$ = new std::pair<std::string, Carbon::Expression*>($1, $2); }
|
|
| identifier
|
|
{
|
|
$$ = new std::pair<std::string, Carbon::Expression*>(
|
|
$1, Carbon::MakeTuple(
|
|
yylineno,
|
|
new std::vector<std::pair<std::string, Carbon::Expression*>>()));
|
|
}
|
|
;
|
|
alternative_list:
|
|
// Empty
|
|
{ $$ = new std::list<std::pair<std::string, Carbon::Expression*>>(); }
|
|
| alternative
|
|
{
|
|
$$ = new std::list<std::pair<std::string, Carbon::Expression*>>();
|
|
$$->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<Carbon::Declaration>(); }
|
|
| declaration declaration_list
|
|
{
|
|
$$ = $2;
|
|
$$->push_front(*$1);
|
|
}
|
|
;
|
|
%%
|