diff options
| author | Kimplul <kimi.h.kuparinen@gmail.com> | 2023-08-15 21:41:29 +0300 |
|---|---|---|
| committer | Kimplul <kimi.h.kuparinen@gmail.com> | 2023-08-15 21:41:29 +0300 |
| commit | bad9ab7479d66dfdb1c8e2d18c23fbcff9ec394b (patch) | |
| tree | d43dd3a26685c9adc8201dfe1a4035418175c1eb /src/parser.y | |
| parent | 5ffc39352ef0195697953e9318b8a17c79e7ae84 (diff) | |
| download | ek-bad9ab7479d66dfdb1c8e2d18c23fbcff9ec394b.tar.gz ek-bad9ab7479d66dfdb1c8e2d18c23fbcff9ec394b.zip | |
updates to syntax
Diffstat (limited to 'src/parser.y')
| -rw-r--r-- | src/parser.y | 484 |
1 files changed, 272 insertions, 212 deletions
diff --git a/src/parser.y b/src/parser.y index a7a3e4a..22a6bf8 100644 --- a/src/parser.y +++ b/src/parser.y @@ -20,6 +20,7 @@ %define parse.trace %define parse.error verbose %define api.pure full +%define lr.type ielr %lex-param {void *scanner} {struct parser *parser} %parse-param {void *scanner} {struct parser* parser} @@ -35,7 +36,9 @@ %token <dbl> FLOAT %token <str> STRING %token <str> ID +%token <str> APPLY +%token QUESTION "?" %token SQUOTE "'" %token TO "=" %token ELLIPSIS "..." @@ -92,6 +95,7 @@ %token ELSE "else" %token BREAK "break" %token CONTINUE "continue" +%token DEFAULT "default" %token SWITCH "switch" %token CASE "case" %token FOR "for" @@ -135,43 +139,55 @@ %left "::" /* why doesn't bison allow <*> for %nterm? would be so much easier */ -%nterm <node> import binary_op unary_op arg arg_list decl_list call expr -%nterm <node> while do_while statement statement_list body macro_list macro -%nterm <node> expr_list init_expr expr_if if for case case_list switch const -%nterm <node> func_sign variadic_sign type var_decl var -%nterm <node> var_init proc lambda template_elem template_list type_list -%nterm <node> type_alias type_template enum_val enum_list enum top unit id -%nterm <node> embed param_decl union struct struct_list struct_elem +%nterm <node> import binop unop arg args decls expr +%nterm <node> while do_while statement statements body references macro +%nterm <node> exprs if for case cases switch const +%nterm <node> simple_sign func_sign type var_decl var +%nterm <node> var_init proc lambda template_elem template_elems types +%nterm <node> alias template enum_val enums enum top unit id +%nterm <node> embed param_decl union struct members struct_elem %nterm <node> top_if const_if const_for defer goto assign -%nterm <node> struct_construct struct_inits struct_init cond -%nterm <node> generic generic_list +%nterm <node> construct construct_args construct_arg +%nterm <node> generic generics statelet apply -%destructor {} FLOAT INT STRING ID +/* special handling for top level variables */ +%nterm <node> top_var_decl top_var_init top_var + +/* constant operations */ +%nterm <node> const_expr const_unop const_binop + +%destructor {} FLOAT INT STRING ID APPLY %destructor { destroy_ast_tree($$); } <*> %start input; %% -id: ID { +id + : ID { $$ = gen_id(strdup($1)); $$->loc = to_src_loc(&yylloc); } - ; -var: var_decl { $$ = $1; } +apply + : APPLY { + $$ = gen_id(strdup($1)); + $$->loc = to_src_loc(&yylloc); + } + +var + : var_decl { $$ = $1; } | var_init { $$ = $1; } - ; -embed: "embed" "(" STRING ")" { $$ = gen_embed(clone_string($3)); } - ; +embed + : "embed" "(" STRING ")" { $$ = gen_embed(clone_string($3)); } -import: "import" STRING { $$ = gen_import(clone_string($2)); } - ; +import + : "import" STRING { $$ = gen_import(clone_string($2)); } -assign: expr "=" expr { $$ = gen_assign($1, $3); } - | expr "=" struct_construct { $$ = gen_assign($1, $3); } - ; +assign + : expr "=" expr { $$ = gen_assign($1, $3); } -binary_op: expr "+" expr { $$ = gen_binop(AST_ADD, $1, $3); } +binop + : expr "+" expr { $$ = gen_binop(AST_ADD, $1, $3); } | expr "-" expr { $$ = gen_binop(AST_SUB, $1, $3); } | expr "*" expr { $$ = gen_binop(AST_MUL, $1, $3); } | expr "/" expr { $$ = gen_binop(AST_DIV, $1, $3); } @@ -204,45 +220,74 @@ binary_op: expr "+" expr { $$ = gen_binop(AST_ADD, $1, $3); } | expr ">=" expr { $$ = gen_binop(AST_GE, $1, $3); } | expr "!=" expr { $$ = gen_binop(AST_NE, $1, $3); } | expr "==" expr { $$ = gen_binop(AST_EQ, $1, $3); } - ; -unary_op: "-" expr { $$ = gen_unop(AST_NEG, $2); } +unop + : "-" expr { $$ = gen_unop(AST_NEG, $2); } | "!" expr { $$ = gen_unop(AST_LNOT, $2); } | "&" expr { $$ = gen_unop(AST_REF, $2); } | "'" expr { $$ = gen_unop(AST_DEREF, $2); } | "~" expr { $$ = gen_unop(AST_NOT, $2); } - ; -arg: "&" var_decl { $$ = gen_unop(AST_REF, $2); } +arg + : "&" var_decl { $$ = gen_unop(AST_REF, $2); } | var_decl { $$ = $1; } - | init_expr { $$ = $1; } - ; + | expr { $$ = $1; } -arg_list: arg "," arg_list { $$ = $1; $1->next = $3; } +args + : arg "," args { $$ = $1; $1->next = $3; } | arg { $$ = $1; } - ; -param_decl: type { $$ = gen_var(NULL, $1, NULL); } +param_decl + : type { $$ = gen_var(NULL, $1, NULL); } -decl_list: var_decl "," decl_list { $$ = $1; $1->next = $3; } - | param_decl "," decl_list { $$ = $1; $1->next = $3; } +decls + : var_decl "," decls { $$ = $1; $1->next = $3; } + | param_decl "," decls { $$ = $1; $1->next = $3; } | var_decl { $$ = $1; } | param_decl { $$ = $1; } - ; -/* call also works for arrays in this case */ -call: id "(" arg_list ")" { $$ = gen_call($1, $3); } - | id "(" ")" { $$ = gen_call($1, NULL); } - ; +defer + : "defer" expr { $$ = gen_defer($2); } -defer: "defer" "(" expr ")" { $$ = gen_defer($3); } - ; +const_binop + : const_expr "+" const_expr { $$ = gen_binop(AST_ADD, $1, $3); } + | const_expr "-" const_expr { $$ = gen_binop(AST_SUB, $1, $3); } + | const_expr "*" const_expr { $$ = gen_binop(AST_MUL, $1, $3); } + | const_expr "/" const_expr { $$ = gen_binop(AST_DIV, $1, $3); } + | const_expr "%" const_expr { $$ = gen_binop(AST_REM, $1, $3); } + | const_expr "^" const_expr { $$ = gen_binop(AST_XOR, $1, $3); } + | const_expr "^^" const_expr { $$ = gen_binop(AST_POW, $1, $3); } + | const_expr "&" const_expr { $$ = gen_binop(AST_AND, $1, $3); } + | const_expr "&&" const_expr { $$ = gen_binop(AST_LAND, $1, $3); } + | const_expr "|" const_expr { $$ = gen_binop(AST_OR, $1, $3); } + | const_expr "||" const_expr { $$ = gen_binop(AST_LOR, $1, $3); } + | const_expr "<<" const_expr { $$ = gen_binop(AST_LSHIFT, $1, $3); } + | const_expr ">>" const_expr { $$ = gen_binop(AST_RSHIFT, $1, $3); } + | const_expr "<" const_expr { $$ = gen_binop(AST_LT, $1, $3); } + | const_expr ">" const_expr { $$ = gen_binop(AST_GT, $1, $3); } + | const_expr "<=" const_expr { $$ = gen_binop(AST_LE, $1, $3); } + | const_expr ">=" const_expr { $$ = gen_binop(AST_GE, $1, $3); } + | const_expr "!=" const_expr { $$ = gen_binop(AST_NE, $1, $3); } + | const_expr "==" const_expr { $$ = gen_binop(AST_EQ, $1, $3); } -/* TODO: concatenate multiple strings together */ -expr: id { $$ = $1; } +const_unop + : "-" const_expr { $$ = gen_unop(AST_NEG, $2); } + | "!" const_expr { $$ = gen_unop(AST_LNOT, $2); } + | "~" const_expr { $$ = gen_unop(AST_NOT, $2); } + +const_expr + : "(" const_expr ")" { $$ = $2; } + | id { $$ = $1; } + | INT { $$ = gen_int($1); } + | FLOAT { $$ = gen_float($1); } + | const_binop { $$ = $1; } + | const_unop { $$ = $1; } + +/* TODO: concatenate multiple strings together? Or is that the lexer's job? */ +expr + : id { $$ = $1; } | expr "." id { $$ = gen_dot($1, $3); } | "..." id { $$ = $2; } - | "@" { $$ = gen_last(); } | INT { $$ = gen_int($1); $$->loc = to_src_loc(&yylloc); } | FLOAT { $$ = gen_float($1); $$->loc = to_src_loc(&yylloc); } | STRING { @@ -251,10 +296,13 @@ expr: id { $$ = $1; } } | "(" expr ")" { $$ = $2; } | assign { $$ = $1; } - | call { $$ = $1; } - | defer { $$ = $1; } - | binary_op { $$ = $1; } - | unary_op { $$ = $1; } + | expr "(" args ")" { $$ = gen_call($1, $3); } + | expr "(" ")" { $$ = gen_call($1, NULL); } + | expr "[" expr "]" { $$ = gen_call($1, $3); /** @todo add arr access */} + | apply "(" args ")" { $$ = gen_call($1, $3); /* macro call */} + | apply "(" ")" { $$ = gen_call($1, NULL); /* macro call */} + | binop { $$ = $1; } + | unop { $$ = $1; } | "(" var_init ")" { $$ = $2; } | "sizeof" expr { $$ = gen_sizeof($2); } | expr "as" type { $$ = gen_cast($1, $3); } @@ -262,39 +310,42 @@ expr: id { $$ = $1; } | "as" type { $$ = gen_as($2); } | embed { $$ = $1; } | lambda { $$ = $1; } - ; + | if { $$ = $1; } + | switch { $$ = $1; } + | construct { $$ = $1; } + | "(" body ")" { $$ = $2; } -while: "while" expr body { $$ = gen_while($2, $3); } - ; +while + : "while" expr body { $$ = gen_while($2, $3); } -do_while: "do" body "while" expr ";" { +do_while + : "do" body "while" expr ";" { $$ = gen_while($2, $4); ast_set_flags($$, AST_FLAG_DELAYED); } - ; -goto: "goto" id { $$ = gen_goto(gen_label($2)); } +goto + : "goto" id { $$ = gen_goto(gen_label($2)); } -statement: expr ";" { $$ = $1; } - | "return" init_expr ";" { $$ = gen_return($2); } - | "return" ";" { $$ = gen_return(NULL); } - | "break" ";" { $$ = gen_ctrl(AST_CTRL_BREAK, to_src_loc(&yylloc)); } - | "continue" ";" { $$ = gen_ctrl(AST_CTRL_CONTINUE, - to_src_loc(&yylloc)); } - | import ";" { $$ = $1; } - | var ";" { $$ = $1; } - | if { $$ = $1; } - | goto ";"{ $$ = $1; } +statelet + : expr { $$ = $1; } + | "return" expr { $$ = gen_return($2); } + | "return" { $$ = gen_return(NULL); } + | "break" { $$ = gen_ctrl(AST_CTRL_BREAK, to_src_loc(&yylloc)); } + | "continue" { $$ = gen_ctrl(AST_CTRL_CONTINUE, to_src_loc(&yylloc)); } + | import { $$ = $1; } + | var { $$ = $1; } + | goto { $$ = $1; } | id ":" { $$ = gen_label($1); } | for { $$ = $1; } | const { $$ = $1; } | while { $$ = $1; } | do_while { $$ = $1; } - | switch { $$ = $1; } | macro { $$ = $1; } | struct { $$ = $1; } - | type_alias ";" { $$ = $1; } - | type_template { $$ = $1; } + | alias { $$ = $1; } + | template { $$ = $1; } + | defer { $$ = $1; } | enum { $$ = $1; } | body { $$ = $1; } | ";" { $$ = gen_empty(); } @@ -312,25 +363,30 @@ statement: expr ";" { $$ = $1; } yyclearin; yyerrok; } - ; -statement_list: statement statement_list { $$ = $1; $1->next = $2; } +statement + : statelet ";" { $$ = $1; } + +statements + : statement statements { $$ = $1; $1->next = $2; } | statement { $$ = $1; } - ; + | statelet { $$ = $1; } -body: "{" statement_list "}" { $$ = gen_block($2); } +body + : "{" statements "}" { $$ = gen_block($2); } | "{" "}" { $$ = gen_block(gen_empty()); } - ; -macro_list: id "," macro_list { $$ = $1; $$->next = $3; } +references + : id "," references { $$ = $1; $$->next = $3; } | id { $$ = $1; } - ; -macro: "define" id "(" macro_list ")" body { +/* TODO: rethink how macros play into everyting */ +macro + : "define" id "(" references ")" body { $$ = gen_macro($2, $4, $6); ast_set_flags($6, AST_FLAG_UNHYGIENIC); } - | "define" id "(" macro_list "..." id ")" body { + | "define" id "(" references "..." id ")" body { /* TODO: the location data of the variadic ID is way off */ ast_append($4, $6); $$ = gen_macro($2, $4, $8); @@ -341,129 +397,110 @@ macro: "define" id "(" macro_list ")" body { $$ = gen_macro($2, NULL, $5); ast_set_flags($5, AST_FLAG_UNHYGIENIC); } - ; -expr_list: expr "," expr_list { $$ = $1; $1->next = $3; } +exprs + : expr "," exprs { $$ = $1; $1->next = $3; } | expr { $$ = $1; } - ; -struct_init: init_expr { $$ = $1; } - | "." id "=" init_expr { +construct_arg + : expr { $$ = $1; } + | "." id "=" expr { $$ = gen_var($2, NULL, $4); ast_set_flags($$, AST_FLAG_MEMBER); } - ; -struct_inits: struct_init "," struct_inits { $$ = $1; $1->next = $3; } - | struct_init { $$ = $1; } - ; +construct_args + : construct_arg "," construct_args { $$ = $1; $1->next = $3; } + | construct_arg { $$ = $1; } -struct_construct: "{" struct_inits "}" { $$ = gen_init($2); } - ; +construct + : "!" "{" construct_args "}" { $$ = gen_init($3); } -init_expr: expr { $$ = $1; } - | expr_if { $$ = $1; } - | struct_construct { $$ = $1; } - | struct_construct "as" type { $$ = gen_cast($1, $3); } - ; +if + : "if" expr body { $$ = gen_if($2, $3, NULL); } + | "if" expr body "else" body { $$ = gen_if($2, $3, $5); } + | "if" expr body "else" if { $$ = gen_if($2, $3, $5); } -cond: expr { $$ = $1; } - | "(" expr_if ")" { $$ = $2; } - /* note no struct construct */ - ; +/* todo how about leaving out some parts? */ +for + : "for" arg ";" expr ";" expr body { $$ = gen_for($2, $4, $6, $7); } -expr_if: "if" cond body "else" body { $$ = gen_if($2, $3, $5); } - | "if" cond body "else" expr_if { $$ = gen_if($2, $3, $5); } - ; - -if: "if" cond body { $$ = gen_if($2, $3, NULL); } - | "if" cond body "else" body { $$ = gen_if($2, $3, $5); } - | "if" cond body "else" if { $$ = gen_if($2, $3, $5); } - ; - -for: "for" arg ";" expr ";" expr body { $$ = gen_for($2, $4, $6, $7); } - ; - -case: "case" expr ":" statement_list { $$ = gen_case($2, $4); } - ; +case + : "case" const_expr ":" statements { + $$ = gen_case($2, $4); } + | "default" ":" statements { + $$ = gen_case(NULL, $3); + } -case_list: case case_list { $$ = $1; $1->next = $2; } +cases + : case cases { $$ = $1; $1->next = $2; } | case { $$ = $1; } - ; -switch: "switch" expr "{" case_list "}" { $$ = gen_switch($2, $4); } - ; +switch + : "switch" expr "{" cases "}" { $$ = gen_switch($2, $4); } -const_for: "for" id ":" expr_list body { +/* could there be a use case for number based iteration? */ +const_for + : "for" id ":" exprs body { /* TODO: should id be a separate rule? */ $$ = gen_for($2, NULL, $4, $5); ast_set_flags($5, AST_FLAG_UNHYGIENIC); } - ; -const_if: "if" expr body { +const_if + : "if" const_expr body { $$ = gen_if($2, $3, NULL); ast_set_flags($3, AST_FLAG_UNHYGIENIC); } - | "if" expr body "else" body { + | "if" const_expr body "else" body { $$ = gen_if($2, $3, $5); ast_set_flags($3, AST_FLAG_UNHYGIENIC); ast_set_flags($5, AST_FLAG_UNHYGIENIC); } - | "if" expr body "else" const_if { + | "if" const_expr body "else" const_if { $$ = gen_if($2, $3, $5); ast_set_flags($3, AST_FLAG_UNHYGIENIC); } - ; /* maybe I should add a separate gen_iter_for or something and just support * iterator for? */ -const: "const" const_if { $$ = $2; ast_set_flags($$, AST_FLAG_CONST); - } - | "const" const_for { $$ = $2; ast_set_flags($$, AST_FLAG_CONST); - } - ; +const + : "const" const_if { $$ = $2; ast_set_flags($$, AST_FLAG_CONST); } + | "const" const_for { $$ = $2; ast_set_flags($$, AST_FLAG_CONST); } -func_sign: "(" decl_list "=>" type ")" { +simple_sign + : "(" decls "=>" type ")" { $$ = gen_type(AST_TYPE_SIGN, NULL, $2, $4); } - | "(" decl_list ")" { $$ = gen_type(AST_TYPE_SIGN, NULL, $2, NULL); - } - | "(" decl_list "=>" ")" { $$ = gen_type(AST_TYPE_SIGN, NULL, $2, NULL); - } - | "(" "=>" type ")" { $$ = gen_type(AST_TYPE_SIGN, NULL, NULL, $3); - } - | "(" ")" { $$ = gen_type(AST_TYPE_SIGN, NULL, NULL, NULL); - } - ; + | "(" decls ")" { $$ = gen_type(AST_TYPE_SIGN, NULL, $2, NULL); } + | "(" decls "=>" ")" { $$ = gen_type(AST_TYPE_SIGN, NULL, $2, NULL); } + | "(" "=>" type ")" { $$ = gen_type(AST_TYPE_SIGN, NULL, NULL, $3); } + | "(" ")" { $$ = gen_type(AST_TYPE_SIGN, NULL, NULL, NULL); } -variadic_sign: func_sign { $$ = $1; } - | "(" decl_list "..." id "=>" type ")" { +func_sign + : simple_sign { $$ = $1; } + | "(" decls "..." id "=>" type ")" { ast_append($2, $4); $$ = gen_type(AST_TYPE_SIGN, NULL, $2, $6); ast_set_flags($$, AST_FLAG_VARIADIC); } - ; -type: id { $$ = gen_type(AST_TYPE_ID, $1, NULL, NULL); } - | "'" func_sign { +type + : id { $$ = gen_type(AST_TYPE_ID, $1, NULL, NULL); } + | "@" simple_sign { $$ = gen_type(AST_TYPE_POINTER, NULL, NULL, NULL); $$->_type.next = $2; } - | id "(" type_list ")" { + | apply "[" types "]" { $$ = gen_type(AST_TYPE_GENERIC, $1, $3, NULL); } | "'" type { $$ = gen_type(AST_TYPE_POINTER, NULL, NULL, NULL); $$->_type.next = $2; } - | "[" "]" type { - $$ = gen_type(AST_TYPE_ARR, NULL, NULL, NULL); - $$->_type.next = $3; - } - | "[" expr "]" type { - $$ = gen_type(AST_TYPE_ARR, NULL, $2, NULL); - $$->_type.next = $4; + | "'" "[" const_expr "]" type { + $$ = gen_type(AST_TYPE_ARR, NULL, $3, NULL); + $$->_type.next = $5; } | "typeof" expr { $$ = gen_type(AST_TYPE_TYPEOF, NULL, $2, NULL); @@ -471,150 +508,173 @@ type: id { $$ = gen_type(AST_TYPE_ID, $1, NULL, NULL); } | id "::" type { $$ = gen_type(AST_TYPE_MEMBER, $1, $3, NULL); } - ; -var_decl: id "mut" type { +var_decl + : id "mut" type { $$ = gen_var($1, $3, NULL); ast_set_flags($$, AST_FLAG_MUTABLE); } | id "const" type { $$ = gen_var($1, $3, NULL); } | id type { $$ = gen_var($1, $2, NULL); } - ; -var_init: var_decl "=" init_expr { $$ = $1; $1->_var.init = $3; } - | id "mut" "=" init_expr { +var_init + : var_decl "=" expr { $$ = $1; $1->_var.init = $3; } + | id "mut" "=" expr { $$ = gen_var($1, NULL, $4); ast_set_flags($$, AST_FLAG_UNTYPED | AST_FLAG_MUTABLE); } - | id "const" "=" init_expr { + | id "const" "=" expr { $$ = gen_var($1, NULL, $4); ast_set_flags($$, AST_FLAG_UNTYPED); } - ; -proc: id variadic_sign body { +proc + : id func_sign body { $$ = gen_proc($1, $2, $3); ast_set_flags($$, $2->flags); } - | "extern" id func_sign { + | "extern" id simple_sign { $$ = gen_proc($2, $3, NULL); ast_set_flags($$, AST_FLAG_EXTERN); } - ; -lambda: "[" macro_list "]" func_sign body { $$ = gen_lambda($2, $4, $5); } - ; +lambda + : "[" references "]" simple_sign body { $$ = gen_lambda($2, $4, $5); } + | "[" references "]" body { $$ = gen_lambda($2, NULL, $4); } -struct_elem: var_decl { $$ = $1; } - ; +struct_elem + : var_decl { $$ = $1; } -struct_list: struct_elem ";" struct_list { $$ = $1; $1->next = $3; } +members + : struct_elem ";" members { $$ = $1; $1->next = $3; } | struct_elem ";" { $$ = $1; } - ; -union: "union" id "{" struct_list "}" { +union + : "union" id "{" members "}" { $$ = gen_union($2, NULL, $4); } - | "union" id "(" generic_list ")" "{" struct_list "}" { + | "union" id "(" generics ")" "{" members "}" { $$ = gen_union($2, $4, $7); } - ; -generic: id type { $$ = gen_alias($1, $2); } -generic_list: generic "," generic_list { $$ = $1; $$->next = $3; } +generic + : id type { $$ = gen_alias($1, $2); } + +generics + : generic "," generics { $$ = $1; $$->next = $3; } | generic { $$ = $1; } - ; -struct: "struct" id "{" struct_list "}" { +struct + : "struct" id "{" members "}" { $$ = gen_struct($2, NULL, $4); } - | "struct" id "(" generic_list ")" "{" struct_list "}" { + | "struct" id "(" generics ")" "{" members "}" { $$ = gen_struct($2, $4, $7); } - ; /* since traits aren't generic, they don't have to implement anything, meaning * we can keep a pretty clean separation between procs and supertraits */ -template_elem: id ";" { $$ = $1; } - | id func_sign ";" { $$ = gen_proc($1, $2, NULL); } +template_elem + : id ";" { $$ = $1; } + | id simple_sign ";" { $$ = gen_proc($1, $2, NULL); } | var_decl ";" { $$ = $1; } | union { $$ = $1; } - ; -template_list: template_elem template_list { $$ = $1; $1->next = $2; } - | template_elem { $$ = $1; } - ; +template_elems + : template_elem template_elems { $$ = $1; $1->next = $2; } + | template_elem { $$ = $1; } -type_list: type "," type_list { $$ = $1; $1->next = $3; } +types + : type "," types { $$ = $1; $1->next = $3; } | type { $$ = $1; } - ; -type_alias: "typedef" id type { $$ = gen_alias($2, $3); } - ; +alias + : "typedef" id type { $$ = gen_alias($2, $3); } /* we'll parse the arg list later in the AST and check that each node is of some * specific type */ -type_template: "typedef" id "{" template_list "}" { +template + : "typedef" id "{" template_elems "}" { $$ = gen_template($2, $4); } | "typedef" id "{" "}" { /* should match anything, but doesn't implement anything */ $$ = gen_template($2, NULL); } - ; -enum_val: id { $$ = gen_val($1, NULL); } +enum_val + : id { $$ = gen_val($1, NULL); } | id "=" expr { $$ = gen_val($1, $3); } - ; -enum_list: enum_val "," enum_list { $$ = $1; $1->next = $3; } +enums + : enum_val "," enums { $$ = $1; $1->next = $3; } | enum_val "," { $$ = $1; } | enum_val { $$ = $1; } - ; -enum: "enum" id ":" type "{" enum_list "}" { $$ = gen_enum($2, $4, $6); } - | "enum" id "{" enum_list "}" { +enum + : "enum" id ":" type "{" enums "}" { $$ = gen_enum($2, $4, $6); } + | "enum" id "{" enums "}" { $$ = gen_enum($2, NULL, $4); ast_set_flags($$, AST_FLAG_UNTYPED); } - ; -top_if: "if" expr "{" unit "}" { +top_if + : "if" const_expr "{" unit "}" { $$ = gen_if($2, $4, NULL); ast_set_flags($$, AST_FLAG_UNHYGIENIC); } - | "if" expr "{" unit "}" "else" "{" unit "}" { + | "if" const_expr "{" unit "}" "else" "{" unit "}" { $$ = gen_if($2, $4, $8); ast_set_flags($$, AST_FLAG_UNHYGIENIC); } - | "if" expr "{" unit "}" "else" top_if { + | "if" const_expr "{" unit "}" "else" top_if { $$ = gen_if($2, $4, $7); ast_set_flags($$, AST_FLAG_UNHYGIENIC); } - ; + +top_var_decl + : id "mut" type { + $$ = gen_var($1, $3, NULL); + ast_set_flags($$, AST_FLAG_MUTABLE); + } + | id "const" type { $$ = gen_var($1, $3, NULL); } + | id type { $$ = gen_var($1, $2, NULL); } + +top_var_init + : top_var_decl "=" const_expr { $$ = $1; $1->_var.init = $3; } + | id "mut" "=" const_expr { $$ = $1; $1->_var.init = $4; } + | id "const" "=" const_expr { $$ = $1; $1->_var.init = $4; } + +top_var + : top_var_decl { $$ = $1; } + | top_var_init { $$ = $1; } /* slightly silly to allow stray semicolons at a top level, but seems to help * with recovering from certain syntax errors */ -top: ";" { $$ = gen_empty(); } - | enum { $$ = $1; } +top + : enum { $$ = $1; } | proc { $$ = $1; } | struct { $$ = $1; } | union { $$ = $1; } | macro { $$ = $1; } - | "const" top_if { $$ = $2; ast_set_flags($$, AST_FLAG_CONST); } - | import ";" { $$ = $1; } - | type_alias ";" { $$ = $1; } - | type_template { $$ = $1; } + | top_if { $$ = $1; ast_set_flags($$, AST_FLAG_CONST); } + | top_var { $$ = $1; ast_set_flags($$, AST_FLAG_CONST); } + | import { $$ = $1; } + | alias { $$ = $1; } + | template { $$ = $1; } | "pub" enum { $$ = $2; ast_set_flags($2, AST_FLAG_PUBLIC); } | "pub" struct { $$ = $2; ast_set_flags($2, AST_FLAG_PUBLIC); } | "pub" union { $$ = $2; ast_set_flags($2, AST_FLAG_PUBLIC); } | "pub" proc { $$ = $2; ast_set_flags($2, AST_FLAG_PUBLIC); } | "pub" macro { $$ = $2; ast_set_flags($2, AST_FLAG_PUBLIC); } - | "pub" import ";" { $$ = $2; ast_set_flags($2, AST_FLAG_PUBLIC); } - | "pub" type_alias ";" { $$ = $2; ast_set_flags($2, AST_FLAG_PUBLIC); } - | "pub" type_template { $$ = $2; ast_set_flags($2, AST_FLAG_PUBLIC); } - | var ";" { $$ = $1; } - | "pub" var ";" { $$ = $2; ast_set_flags($2, AST_FLAG_PUBLIC); } + | "pub" import { $$ = $2; ast_set_flags($2, AST_FLAG_PUBLIC); } + | "pub" alias { $$ = $2; ast_set_flags($2, AST_FLAG_PUBLIC); } + | "pub" template { $$ = $2; ast_set_flags($2, AST_FLAG_PUBLIC); } + | "pub" top_var { + $$ = $2; ast_set_flags($2, AST_FLAG_PUBLIC); + ast_set_flags($$, AST_FLAG_CONST); + } + | ";" { $$ = gen_empty(); } | error { $$ = gen_empty(); parser->failed = true; @@ -627,14 +687,14 @@ top: ";" { $$ = gen_empty(); } } yyclearin; yyerrok; - } - ; + } -unit: top { $$ = $1; } +unit + : top { $$ = $1; } | top unit { $$ = $1; $1->next = $2; } - ; -input: unit { parser->tree = $1; } +input + : unit { parser->tree = $1; } | /* empty */ - ; + %% |
