Created
February 1, 2019 22:20
-
-
Save antonijn/6626c2b17659cbb69c6c64e32bfdd64f to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| %code requires { | |
| #include "types.h" | |
| #include <stddef.h> | |
| #include <stdio.h> | |
| } | |
| %code { | |
| int yylex(); | |
| void yyerror(ASTFileElement **f, const char *msg); | |
| } | |
| /* dangling else */ | |
| %expect 1 | |
| %define parse.error verbose | |
| %define api.pure full | |
| %parse-param { ASTFileElement **result } | |
| %union { | |
| Token tok; | |
| VarKind varkind; | |
| ASTType *type; | |
| ASTEnumerator *enumerator; | |
| ASTTypeNode *typenode; | |
| ASTVarSpec *varspec; | |
| ASTVarNode *varnode; | |
| ASTVarDecl *vardecl; | |
| ASTDeclarator *declarator; | |
| ASTFileElement *file_elt; | |
| ASTStat *stat; | |
| ASTStatNode *statnode; | |
| ASTSwitchCase *switch_case; | |
| ASTMatchCase *match_case; | |
| ASTExpr *expr; | |
| ASTExprNode *exprnode; | |
| } | |
| %token <tok> TOK_STRING | |
| %token <tok> TOK_ID | |
| %token <tok> TOK_INTEGER | |
| %token <tok> TOK_FLOAT | |
| %token <tok> TOK_BREAK "break" | |
| %token <tok> TOK_CASE "case" | |
| %token <tok> TOK_CHOICE "choice" | |
| %token <tok> TOK_CONST "const" | |
| %token <tok> TOK_CONTINUE "continue" | |
| %token <tok> TOK_DEFAULT "default" | |
| %token <tok> TOK_DO "do" | |
| %token <tok> TOK_ENUM "enum" | |
| %token <tok> TOK_FALSE "false" | |
| %token <tok> TOK_FOR "for" | |
| %token <tok> TOK_FUNC "func" | |
| %token <tok> TOK_IF "if" | |
| %token <tok> TOK_IMPORT "import" | |
| %token <tok> TOK_MATCH "match" | |
| %token <tok> TOK_NULL "null" | |
| %token <tok> TOK_RETURN "return" | |
| %token <tok> TOK_SIZEOF "sizeof" | |
| %token <tok> TOK_STRUCT "struct" | |
| %token <tok> TOK_SWITCH "switch" | |
| %token <tok> TOK_TRUE "true" | |
| %token <tok> TOK_TYPE "type" | |
| %token <tok> TOK_UNION "union" | |
| %token <tok> TOK_VAR "var" | |
| %token <tok> TOK_WHILE "while" | |
| %token <tok> TOK_ELLIPSIS "..." | |
| %token <tok> TOK_SHREQ ">>=" | |
| %token <tok> TOK_SHLEQ "<<=" | |
| %token <tok> TOK_PLUSEQ "+=" | |
| %token <tok> TOK_MINEQ "-=" | |
| %token <tok> TOK_ASTERISKEQ "*=" | |
| %token <tok> TOK_SLASHEQ "/=" | |
| %token <tok> TOK_PERCENTEQ "%=" | |
| %token <tok> TOK_ANDEQ "&=" | |
| %token <tok> TOK_CARETEQ "^=" | |
| %token <tok> TOK_PIPEEQ "|=" | |
| %token <tok> TOK_SHR ">>" | |
| %token <tok> TOK_SHL "<<" | |
| %token <tok> TOK_PLUSPLUS "++" | |
| %token <tok> TOK_MINMIN "--" | |
| %token <tok> TOK_ARROW "->" | |
| %token <tok> TOK_ANDAND "&&" | |
| %token <tok> TOK_PIPEPIPE "||" | |
| %token <tok> TOK_LTE "<=" | |
| %token <tok> TOK_GTE ">=" | |
| %token <tok> TOK_EQEQ "==" | |
| %token <tok> TOK_NOTEQ "!=" | |
| %token <tok> TOK_SEMI ";" | |
| %token <tok> TOK_LBRACK "{" | |
| %token <tok> TOK_RBRACK "}" | |
| %token <tok> TOK_COMMA "," | |
| %token <tok> TOK_COLON ":" | |
| %token <tok> TOK_EQ "=" | |
| %token <tok> TOK_LPAR "(" | |
| %token <tok> TOK_RPAR ")" | |
| %token <tok> TOK_LSQR "[" | |
| %token <tok> TOK_RSQR "]" | |
| %token <tok> TOK_DOT "." | |
| %token <tok> TOK_AND "&" | |
| %token <tok> TOK_NOT "!" | |
| %token <tok> TOK_TILDE "~" | |
| %token <tok> TOK_MIN "-" | |
| %token <tok> TOK_PLUS "+" | |
| %token <tok> TOK_ASTERISK "*" | |
| %token <tok> TOK_SLASH "/" | |
| %token <tok> TOK_PERCENT "%" | |
| %token <tok> TOK_LT "<" | |
| %token <tok> TOK_GT ">" | |
| %token <tok> TOK_CARET "^" | |
| %token <tok> TOK_PIPE "|" | |
| %token <tok> TOK_QUESTION "?" | |
| %type <varkind> varconst | |
| %type <type> type maybe_type | |
| %type <enumerator> enumerator enumerators enumerators_ | |
| %type <vardecl> vardecl | |
| %type <declarator> declarator declarators | |
| %type <typenode> typearg typearglist typearglist_ | |
| %type <varspec> varspec varspecs | |
| %type <varnode> field fields arg arglist arglist_ | |
| %type <file_elt> file file_element function global typedef import | |
| %type <expr> expr maybe_expr assignment ternary_expr scor_expr scand_expr or_expr xor_expr and_expr eq_expr cmp_expr shift_expr add_expr mul_expr basic_expr2 basic_expr terminal_expr | |
| %type <exprnode> exprnode exprlist expr_arglist | |
| %type <stat> stat simple_stat control block for if while dowhile switch match | |
| %type <statnode> stats stat_node | |
| %type <switch_case> switch_case switch_caselist | |
| %type <match_case> match_case match_caselist | |
| %% | |
| file : { *result = $$ = NULL; } | |
| | file_element[F] file[X] { $F->next = $X; *result = $$ = $F; } | |
| ; | |
| file_element : function | |
| | global | |
| | typedef | |
| | import | |
| ; | |
| typedef : "type" TOK_ID[I] type[T] ";" { $$ = ast_typedef($I.str, $T); } | |
| ; | |
| maybe_type : { $$ = NULL; } | |
| | type | |
| ; | |
| type : TOK_ID[I] { $$ = ast_named_type($I.str); } | |
| | "func" "(" typearglist[A] ")" maybe_type[T] { $$ = ast_func_type($A, $T); } | |
| | "*" type[T] { $$ = ast_ptr($T); } | |
| | "struct" "{" fields[F] "}" { $$ = ast_struct($F); } | |
| | "union" "{" fields[F] "}" { $$ = ast_union($F); } | |
| | "choice" "{" fields[F] "}" { $$ = ast_choice($F); } | |
| | "enum" "{" enumerators[E] "}" { $$ = ast_enum($E); } | |
| ; | |
| fields : { $$ = NULL; } | |
| | field[F] fields[X] { $F->next = $X; $$ = $F; } | |
| ; | |
| field : varspecs[V] ";" { $$ = ast_var_node($V); } | |
| ; | |
| declarator : TOK_ID { $$ = ast_declarator($1.str); } | |
| ; | |
| declarators : declarator | |
| | declarator[D] "," declarators[X] { $D->next = $X; $$ = $D; } | |
| ; | |
| varspec : declarator[D] type[T] { $$ = ast_var_spec($D, $T); } | |
| ; | |
| varspecs : declarators[D] type[T] { $$ = ast_var_spec($D, $T); } | |
| ; | |
| enumerators : { $$ = NULL; } | |
| | enumerators_ | |
| | enumerators_ "," | |
| ; | |
| enumerator : TOK_ID[I] { $$ = ast_enumerator($I.str, NULL); } | |
| | TOK_ID[I] "=" expr[E] { $$ = ast_enumerator($I.str, $E); } | |
| ; | |
| enumerators_ : enumerator | |
| | enumerators_[X] "," enumerator[E] { $E->prev = $X; $$ = $E; } | |
| ; | |
| typearglist : { $$ = NULL; } | |
| | typearglist_ | |
| ; | |
| typearg : type[T] { $$ = ast_type_node($T); } | |
| ; | |
| typearglist_ : typearg[T] | |
| | typearg[T] "," typearglist_[X] { $T->next = $X; $$ = $T; } | |
| ; | |
| function : "func" TOK_ID[I] "(" arglist[A] ")" maybe_type[T] block[B] { $$ = ast_function($I.str, $A, $T, $B); } | |
| ; | |
| arglist : { $$ = NULL; } | |
| | arglist_ | |
| ; | |
| arglist_ : arg[A] | |
| | arg[A] "," arglist_[X] { $A->next = $X; } | |
| ; | |
| arg : varspecs[V] { $$ = ast_var_node($V); } | |
| ; | |
| global : vardecl { $$ = ast_global($1); } | |
| ; | |
| import : "import" TOK_STRING[S] ";" { $$ = ast_import($S.str); } | |
| ; | |
| varconst : "var" { $$ = AST_VAR; } | |
| | "const" { $$ = AST_CONST; } | |
| ; | |
| vardecl : varconst[M] varspecs[V] ";" | |
| { $$ = ast_var_decl($M, $V, NULL) ; } | |
| | varconst[M] declarators[D] maybe_type[T] "=" exprlist[E] ";" | |
| { $$ = ast_var_decl($M, ast_var_spec($D, $T), $E); } | |
| ; | |
| stat : simple_stat | |
| | control | |
| | "break" ";" { $$ = ast_break(); } | |
| | "continue" ";" { $$ = ast_continue(); } | |
| | "return" maybe_expr[E] ";" { $$ = ast_return($E); } | |
| | block | |
| ; | |
| simple_stat : expr ";" { $$ = ast_expr_stat($1); } | |
| | ";" { $$ = ast_empty_stat(); } | |
| | vardecl { $$ = ast_local_var($1); } | |
| ; | |
| maybe_expr : { $$ = NULL; } | |
| | expr | |
| ; | |
| control : for | |
| | if | |
| | while | |
| | dowhile | |
| | switch | |
| | match | |
| ; | |
| for : "for" "(" simple_stat[I] maybe_expr[C] ";" maybe_expr[F] ")" stat[S] | |
| { $$ = ast_for($I, $C, $F, $S); } | |
| ; | |
| if : "if" "(" expr[C] ")" stat[S] { $$ = ast_if($C, $S, NULL); } | |
| | "if" "(" expr[C] ")" stat[S] "else" stat[E] { $$ = ast_if($C, $S, $E); } | |
| ; | |
| while : "while" "(" expr[C] ")" stat[S] { $$ = ast_while($C, $S); } | |
| ; | |
| dowhile : "do" stat[S] "while" "(" expr[C] ")" { $$ = ast_dowhile($C, $S); } | |
| ; | |
| switch : "switch" "(" expr[E] ")" "{" switch_caselist[C] "}" { $$ = ast_switch($E, $C); } | |
| ; | |
| switch_caselist : { $$ = NULL; } | |
| | switch_case[C] switch_caselist[X] { $C->next = $X; $$ = $C; } | |
| ; | |
| switch_case : "case" expr[C] ":" stats[S] { $$ = ast_switch_case($C, $S); } | |
| | "default" ":" stats[S] { $$ = ast_switch_case(NULL, $S); } | |
| ; | |
| match : "match" "(" expr[E] ")" "{" match_caselist[C] "}" { $$ = ast_match($E, $C); } | |
| ; | |
| match_caselist : { $$ = NULL; } | |
| | match_case[C] match_caselist[X] { $C->next = $X; $$ = $C; } | |
| ; | |
| match_case : "case" varspec[V] ":" stats[S] { $$ = ast_match_case($V, $S); } | |
| | "default" ":" stats[S] { $$ = ast_match_case(NULL, $S); } | |
| ; | |
| block : "{" stats[S] "}" { $$ = ast_block($S); } | |
| ; | |
| stat_node : stat { $$ = ast_stat_node($1); } | |
| ; | |
| stats : { $$ = NULL; } | |
| | stat_node[S] stats[X] { $S->next = $X; $$ = $S; } | |
| ; | |
| expr : assignment ; | |
| terminal_expr : TOK_ID { $$ = ast_terminal(AST_ID, $1.str); } | |
| | TOK_INTEGER { $$ = ast_terminal(AST_INTEGER, $1.str); } | |
| | TOK_FLOAT { $$ = ast_terminal(AST_FLOAT, $1.str); } | |
| | TOK_STRING { $$ = ast_terminal(AST_STRING, $1.str); } | |
| | "true" { $$ = ast_terminal(AST_TRUE, $1.str); } | |
| | "false" { $$ = ast_terminal(AST_FALSE, $1.str); } | |
| | "null" { $$ = ast_terminal(AST_NULL, $1.str); } | |
| ; | |
| basic_expr : terminal_expr | |
| | "(" expr[E] ")" { $$ = $E; } | |
| | basic_expr[E] "++" { $$ = ast_unop(UNOP_POST_INC, $E); } | |
| | basic_expr[E] "--" { $$ = ast_unop(UNOP_POST_DEC, $E); } | |
| | basic_expr[E] "(" expr_arglist[A] ")" { $$ = ast_fcall($E, $A); } | |
| | basic_expr[E] "[" expr[I] "]" { $$ = ast_index($E, $I); } | |
| | basic_expr[E] "." TOK_ID[I] { $$ = ast_access($E, $I.str, false); } | |
| | basic_expr[E] "->" TOK_ID[I] { $$ = ast_access($E, $I.str, true); } | |
| ; | |
| basic_expr2 : basic_expr | |
| | "++" basic_expr2[E] { $$ = ast_unop(UNOP_PRE_INC, $E); } | |
| | "--" basic_expr2[E] { $$ = ast_unop(UNOP_PRE_DEC, $E); } | |
| | "+" basic_expr2[E] { $$ = ast_unop(UNOP_PROMOTE, $E); } | |
| | "-" basic_expr2[E] { $$ = ast_unop(UNOP_MINUS, $E); } | |
| | "!" basic_expr2[E] { $$ = ast_unop(UNOP_NOT, $E); } | |
| | "~" basic_expr2[E] { $$ = ast_unop(UNOP_INV, $E); } | |
| | "[" type[T] "]" basic_expr2[E] { $$ = ast_cast($T, $E); } | |
| | "*" basic_expr2[E] { $$ = ast_unop(UNOP_DEREF, $E); } | |
| | "&" basic_expr2[E] { $$ = ast_unop(UNOP_REF, $E); } | |
| | "sizeof" "(" expr[E] ")" { $$ = ast_sizeof_expr($E); } | |
| | "sizeof" "[" type[T] "]" { $$ = ast_sizeof_type($T); } | |
| ; | |
| mul_expr : basic_expr2 | |
| | mul_expr[L] "*" basic_expr2[R] { $$ = ast_binop(BINOP_MUL, $L, $R); } | |
| | mul_expr[L] "/" basic_expr2[R] { $$ = ast_binop(BINOP_DIV, $L, $R); } | |
| | mul_expr[L] "%" basic_expr2[R] { $$ = ast_binop(BINOP_MOD, $L, $R); } | |
| ; | |
| add_expr : mul_expr | |
| | add_expr[L] "+" mul_expr[R] { $$ = ast_binop(BINOP_ADD, $L, $R); } | |
| | add_expr[L] "-" mul_expr[R] { $$ = ast_binop(BINOP_SUB, $L, $R); } | |
| ; | |
| shift_expr : add_expr | |
| | shift_expr[L] "<<" add_expr[R] { $$ = ast_binop(BINOP_SHL, $L, $R); } | |
| | shift_expr[L] ">>" add_expr[R] { $$ = ast_binop(BINOP_SHR, $L, $R); } | |
| ; | |
| cmp_expr : shift_expr | |
| | cmp_expr[L] "<" shift_expr[R] { $$ = ast_binop(BINOP_LT, $L, $R); } | |
| | cmp_expr[L] ">" shift_expr[R] { $$ = ast_binop(BINOP_GT, $L, $R); } | |
| | cmp_expr[L] "<=" shift_expr[R] { $$ = ast_binop(BINOP_LTE, $L, $R); } | |
| | cmp_expr[L] ">=" shift_expr[R] { $$ = ast_binop(BINOP_GTE, $L, $R); } | |
| ; | |
| eq_expr : cmp_expr | |
| | eq_expr[L] "==" cmp_expr[R] { $$ = ast_binop(BINOP_EQ, $L, $R); } | |
| | eq_expr[L] "!=" cmp_expr[R] { $$ = ast_binop(BINOP_NEQ, $L, $R); } | |
| ; | |
| and_expr : eq_expr | |
| | and_expr[L] "&" eq_expr[R] { $$ = ast_binop(BINOP_AND, $L, $R); } | |
| ; | |
| xor_expr : and_expr | |
| | xor_expr[L] "^" and_expr[R] { $$ = ast_binop(BINOP_XOR, $L, $R); } | |
| ; | |
| or_expr : xor_expr | |
| | or_expr[L] "|" xor_expr[R] { $$ = ast_binop(BINOP_OR, $L, $R); } | |
| ; | |
| scand_expr : or_expr | |
| | scand_expr[L] "&&" or_expr[R] { $$ = ast_binop(BINOP_SC_AND, $L, $R); } | |
| ; | |
| scor_expr : scand_expr | |
| | scor_expr[L] "||" scand_expr[R] { $$ = ast_binop(BINOP_SC_OR, $L, $R); } | |
| ; | |
| ternary_expr : scor_expr | |
| | ternary_expr[C] "?" scor_expr[L] ":" scor_expr[R] { $$ = ast_conditional($C, $L, $R); } | |
| ; | |
| assignment : ternary_expr | |
| | ternary_expr[L] "=" assignment[R] { $$ = ast_assign(BINOP_NONE, $L, $R); } | |
| | ternary_expr[L] "+=" assignment[R] { $$ = ast_assign(BINOP_ADD, $L, $R); } | |
| | ternary_expr[L] "-=" assignment[R] { $$ = ast_assign(BINOP_SUB, $L, $R); } | |
| | ternary_expr[L] "*=" assignment[R] { $$ = ast_assign(BINOP_MUL, $L, $R); } | |
| | ternary_expr[L] "/=" assignment[R] { $$ = ast_assign(BINOP_DIV, $L, $R); } | |
| | ternary_expr[L] "%=" assignment[R] { $$ = ast_assign(BINOP_MOD, $L, $R); } | |
| | ternary_expr[L] "&=" assignment[R] { $$ = ast_assign(BINOP_AND, $L, $R); } | |
| | ternary_expr[L] "^=" assignment[R] { $$ = ast_assign(BINOP_XOR, $L, $R); } | |
| | ternary_expr[L] "|=" assignment[R] { $$ = ast_assign(BINOP_OR, $L, $R); } | |
| | ternary_expr[L] ">>=" assignment[R] { $$ = ast_assign(BINOP_SHR, $L, $R); } | |
| | ternary_expr[L] "<<=" assignment[R] { $$ = ast_assign(BINOP_SHL, $L, $R); } | |
| ; | |
| expr_arglist : { $$ = NULL; } | |
| | exprlist | |
| ; | |
| exprnode : expr[E] { $$ = ast_expr_node($E); } | |
| ; | |
| exprlist : exprnode[E] | |
| | exprnode[E] "," exprlist[X] { $E->next = $X; $$ = $E; } | |
| ; | |
| %% | |
| void yyerror(ASTFileElement **f, const char *msg) | |
| { | |
| fprintf(stderr, "%s\n", msg); | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment