From 3065334aec0f357c88eab144628a798db4a3e5ea Mon Sep 17 00:00:00 2001 From: Kimplul Date: Sun, 11 Aug 2024 19:33:23 +0300 Subject: parse struct continuation + Similar in idea to impl in Rust --- include/ek/ast.h | 12 ++++++++- src/ast.c | 1 + src/parser.y | 62 +++++++++++++++++++++++++++++++++++++--------- tests/parse/struct_cont.ek | 3 +++ 4 files changed, 65 insertions(+), 13 deletions(-) create mode 100644 tests/parse/struct_cont.ek diff --git a/include/ek/ast.h b/include/ek/ast.h index 62a0901..59101ba 100644 --- a/include/ek/ast.h +++ b/include/ek/ast.h @@ -79,6 +79,8 @@ enum ast_kind { AST_TRAIT_DEF, /** Structure definition. */ AST_STRUCT_DEF, + /** Structure continuation, kind of like impl in Rust. */ + AST_STRUCT_CONT_DEF, /** If. */ AST_IF, /** Block. E.g. \c {} */ @@ -372,7 +374,8 @@ static inline bool is_primitive(struct type *t) #define gen_type(k, a, type, loc) gen_ast(k, a, NULL, NULL, NULL, type, NULL, \ -1, \ loc) -#define gen_str2(k, s, a, b, loc) gen_ast(k, a, b, NULL, NULL, NULL, s, -1, loc) +#define gen_str3(k, s, a, b, c, loc) gen_ast(k, a, b, c, NULL, NULL, s, -1, loc) +#define gen_str2(k, s, a, b, loc) gen_str3(k, s, a, b, NULL, loc) #define gen_str1(k, s, a, loc) gen_str2(k, s, a, NULL, loc) #define gen_str(k, s, loc) gen_ast(k, NULL, NULL, NULL, NULL, NULL, s, -1, loc) @@ -568,6 +571,13 @@ static inline bool is_primitive(struct type *t) #define gen_struct(id, params, body, loc) \ gen_str2(AST_STRUCT_DEF, id, params, body, loc) +#define struct_cont_id(x) return_s(x, AST_STRUCT_CONT_DEF) +#define struct_cont_params(x) return_a0(x, AST_STRUCT_CONT_DEF) +#define struct_cont_behav(x) return_t1(x, AST_STRUCT_CONT_DEF) +#define struct_cont_body(x) return_a2(x, AST_STRUCT_CONT_DEF) +#define gen_struct_cont(id, params, behav, body, loc) \ + gen_ast(AST_STRUCT_CONT_DEF, params, body, NULL, NULL, behav, id, 0, loc) + #define val_id(x) return_s(x, AST_VAL) #define val_val(x) return_a0(x, AST_VAL) #define gen_val(id, val, loc) \ diff --git a/src/ast.c b/src/ast.c index 6b3b28d..d734252 100644 --- a/src/ast.c +++ b/src/ast.c @@ -244,6 +244,7 @@ void ast_dump(int depth, struct ast *n) DUMP(AST_ALIAS_DEF); DUMP(AST_TRAIT_DEF); DUMP(AST_STRUCT_DEF); + DUMP(AST_STRUCT_CONT_DEF); DUMP(AST_IF); DUMP(AST_BLOCK); DUMP(AST_IMPORT); diff --git a/src/parser.y b/src/parser.y index 6c567a9..06599f2 100644 --- a/src/parser.y +++ b/src/parser.y @@ -140,7 +140,7 @@ %nterm types type opt_type -%nterm tagged_struct expr_if +%nterm struct struct_cont expr_if /* constant operations */ %nterm const_expr const_unop const_binop @@ -155,6 +155,7 @@ /* optional stuff */ %nterm opt_exprs proc_decl member opt_members %nterm opt_types opt_sign_decls sign_decls sign_decl sign_var_decl +%nterm opt_behaviours behaviours behaviour /* reverse lists */ %nterm rev_sign_decls; @@ -250,8 +251,7 @@ id : ID {$$ = gen_id($1, src_loc(@$));} var - : var_decl - | var_init + : var_init embed : "embed" "(" STRING ")" { $$ = gen_embed(strip($3), src_loc(@$)); } @@ -476,7 +476,8 @@ statement | while | do_while | body - | tagged_struct + | struct + | struct_cont | for | defer | if @@ -731,11 +732,14 @@ proc ast_set_flags($$, AST_FLAG_EXTERN | AST_FLAG_NOMANGLE); } -member - : var_decl ";" - | type_expand ";" +behaviour + : type_expand ";" | proc_decl ";" | proc + +member + : var_decl ";" + | behaviour ; members @@ -746,12 +750,23 @@ opt_members : members | {$$ = NULL;} +behaviours + : behaviours behaviour { + $$ = $1; $1->n = $2; + ast_set_flags($$, AST_FLAG_MEMBER); + } + | behaviour { $$ = $1; ast_set_flags($$, AST_FLAG_MEMBER); } + +opt_behaviours + : behaviours + | {$$ = NULL;} + macro_expand : APPLY "(" opt_exprs ")" { $$ = gen_macro_expand($1, $3, src_loc(@$)); } -tagged_struct +struct : "typedef" ID "[" opt_type_params "]" "{" opt_members "}" { $$ = gen_struct($2, $4, $7, src_loc(@$)); } @@ -759,6 +774,25 @@ tagged_struct $$ = gen_struct($2, NULL, $4, src_loc(@$)); } +struct_cont + : "continue" "[" opt_type_params "]" + APPLY "[" opt_types "]" "{" opt_behaviours "}" { + /* full form */ + $$ = gen_struct_cont($5, $3, $7, $10, src_loc(@$)); + } + | "continue" "[" opt_type_params "]" ID "{" opt_behaviours "}" { + /* abbrev 1 */ + $$ = gen_struct_cont($5, $3, NULL, $7, src_loc(@$)); + } + | "continue" APPLY "[" opt_types "]" "{" opt_behaviours "}" { + /* abbrev 2 */ + $$ = gen_struct_cont($2, NULL, $4, $7, src_loc(@$)); + } + | "continue" ID "{" opt_behaviours "}" { + /* abbrev 3 */ + $$ = gen_struct_cont($2, NULL, NULL, $4, src_loc(@$)); + } + alias : "typedef" ID type { $$ = gen_alias($2, $3, src_loc(@$)); @@ -771,7 +805,9 @@ type_param } type_params - : type_param "," type_params { $$ = $1; $1->n = $3; } + : type_param "," type_params { + $$ = $1; $1->n = $3; /** @todo this could be left recursive */ + } | type_param opt_type_params @@ -779,7 +815,7 @@ opt_type_params | { $$ = NULL; } trait - : "define" ID "[" opt_type_params "]" "{" opt_members "}" { + : "define" ID "[" opt_type_params "]" "{" opt_behaviours "}" { $$ = gen_trait($2, $4, $7, src_loc(@$)); } @@ -824,14 +860,16 @@ top_if top : enum | proc - | tagged_struct + | struct + | struct_cont { $$ = $1; } | macro { $$ = $1; } | top_if { $$ = $1; ast_set_flags($$, AST_FLAG_CONST); } | import { $$ = $1; } | alias { $$ = $1; } | trait { $$ = $1; } | "pub" enum { $$ = $2; ast_set_flags($2, AST_FLAG_PUBLIC); } - | "pub" tagged_struct { $$ = $2; ast_set_flags($2, AST_FLAG_PUBLIC); } + | "pub" struct { $$ = $2; ast_set_flags($2, AST_FLAG_PUBLIC); } + | "pub" struct_cont { $$ = $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); } diff --git a/tests/parse/struct_cont.ek b/tests/parse/struct_cont.ek new file mode 100644 index 0000000..f4799aa --- /dev/null +++ b/tests/parse/struct_cont.ek @@ -0,0 +1,3 @@ +typedef i27 {} +continue i27 { +} -- cgit v1.3