aboutsummaryrefslogtreecommitdiff
path: root/src/parser.y
diff options
context:
space:
mode:
authorKimplul <kimi.h.kuparinen@gmail.com>2023-08-15 21:41:29 +0300
committerKimplul <kimi.h.kuparinen@gmail.com>2023-08-15 21:41:29 +0300
commitbad9ab7479d66dfdb1c8e2d18c23fbcff9ec394b (patch)
treed43dd3a26685c9adc8201dfe1a4035418175c1eb /src/parser.y
parent5ffc39352ef0195697953e9318b8a17c79e7ae84 (diff)
downloadek-bad9ab7479d66dfdb1c8e2d18c23fbcff9ec394b.tar.gz
ek-bad9ab7479d66dfdb1c8e2d18c23fbcff9ec394b.zip
updates to syntax
Diffstat (limited to 'src/parser.y')
-rw-r--r--src/parser.y484
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 */
- ;
+
%%