aboutsummaryrefslogtreecommitdiff
path: root/src/parser.y
diff options
context:
space:
mode:
authorKimplul <kimi.h.kuparinen@gmail.com>2026-05-01 20:35:00 +0300
committerKimplul <kimi.h.kuparinen@gmail.com>2026-05-01 22:16:26 +0300
commit8946c27306abed7065afad3f015df5ee81e72ad2 (patch)
treec53c9a2c0437109e9c1e3f873bf8a54220ee5ded /src/parser.y
parent7790e27b3423901e2080bfd3c600a65a48d42886 (diff)
downloadfwd-8946c27306abed7065afad3f015df5ee81e72ad2.tar.gz
fwd-8946c27306abed7065afad3f015df5ee81e72ad2.zip
add support for coverage
Diffstat (limited to 'src/parser.y')
-rw-r--r--src/parser.y174
1 files changed, 128 insertions, 46 deletions
diff --git a/src/parser.y b/src/parser.y
index 776e1c9..bd5b033 100644
--- a/src/parser.y
+++ b/src/parser.y
@@ -191,12 +191,17 @@ static char match_escape(char c);
*/
static char *strip(const char *s);
+#define Q(x) if (!(x)) { YYABORT; }
+
%}
%start input;
%%
param
- : type ID { $$ = gen_var($2, $1, src_loc(@$)); }
+ : type ID {
+ $$ = gen_var($2, $1, src_loc(@$));
+ Q($$);
+ }
rev_params
: rev_params "," param { $$ = $3; $$->n = $1; }
@@ -214,7 +219,10 @@ opt_params
var
: param
- | ID { $$ = gen_var($1, NULL, src_loc(@$)); }
+ | ID {
+ $$ = gen_var($1, NULL, src_loc(@$));
+ Q($$);
+ }
rev_vars
: rev_vars "," var { $$ = $3; $$->n = $1; }
@@ -231,52 +239,60 @@ opt_vars
proc
: ID "(" opt_params ")" body {
$$ = gen_proc($[ID], $[opt_params], NULL, $[body], src_loc(@$));
+ Q($$);
}
proc_decl
: ID "(" opt_params ")" ";" {
$$ = gen_proc($[ID], $[opt_params], NULL, NULL, src_loc(@$));
+ Q($$);
}
binop
- : expr "+" expr { $$ = gen_binop(AST_ADD, $1, $3, src_loc(@$)); }
- | expr "-" expr { $$ = gen_binop(AST_SUB, $1, $3, src_loc(@$)); }
- | expr "*" expr { $$ = gen_binop(AST_MUL, $1, $3, src_loc(@$)); }
- | expr "/" expr { $$ = gen_binop(AST_DIV, $1, $3, src_loc(@$)); }
- | expr "%" expr { $$ = gen_binop(AST_REM, $1, $3, src_loc(@$)); }
- | expr "<" expr { $$ = gen_comparison(AST_LT, $1, $3, src_loc(@$)); }
- | expr ">" expr { $$ = gen_comparison(AST_GT, $1, $3, src_loc(@$)); }
- | expr "<<" expr { $$ = gen_binop(AST_LSHIFT, $1, $3, src_loc(@$)); }
- | expr ">>" expr { $$ = gen_binop(AST_RSHIFT, $1, $3, src_loc(@$)); }
- | expr "<=" expr { $$ = gen_comparison(AST_LE, $1, $3, src_loc(@$)); }
- | expr ">=" expr { $$ = gen_comparison(AST_GE, $1, $3, src_loc(@$)); }
- | expr "!=" expr { $$ = gen_comparison(AST_NE, $1, $3, src_loc(@$)); }
- | expr "==" expr { $$ = gen_comparison(AST_EQ, $1, $3, src_loc(@$)); }
- | id "~" id { $$ = gen_paste($1, $3, src_loc(@$)); }
+ : expr "+" expr { $$ = gen_binop(AST_ADD, $1, $3, src_loc(@$)); Q($$); }
+ | expr "-" expr { $$ = gen_binop(AST_SUB, $1, $3, src_loc(@$)); Q($$); }
+ | expr "*" expr { $$ = gen_binop(AST_MUL, $1, $3, src_loc(@$)); Q($$); }
+ | expr "/" expr { $$ = gen_binop(AST_DIV, $1, $3, src_loc(@$)); Q($$); }
+ | expr "%" expr { $$ = gen_binop(AST_REM, $1, $3, src_loc(@$)); Q($$); }
+ | expr "<" expr { $$ = gen_comparison(AST_LT, $1, $3, src_loc(@$)); Q($$); }
+ | expr ">" expr { $$ = gen_comparison(AST_GT, $1, $3, src_loc(@$)); Q($$); }
+ | expr "<<" expr { $$ = gen_binop(AST_LSHIFT, $1, $3, src_loc(@$)); Q($$); }
+ | expr ">>" expr { $$ = gen_binop(AST_RSHIFT, $1, $3, src_loc(@$)); Q($$); }
+ | expr "<=" expr { $$ = gen_comparison(AST_LE, $1, $3, src_loc(@$)); Q($$); }
+ | expr ">=" expr { $$ = gen_comparison(AST_GE, $1, $3, src_loc(@$)); Q($$); }
+ | expr "!=" expr { $$ = gen_comparison(AST_NE, $1, $3, src_loc(@$)); Q($$); }
+ | expr "==" expr { $$ = gen_comparison(AST_EQ, $1, $3, src_loc(@$)); Q($$); }
+ | id "~" id { $$ = gen_paste($1, $3, src_loc(@$)); Q($$); }
unop
- : "-" expr { $$ = gen_unop(AST_NEG, $2, src_loc(@$)); }
- | "!" expr { $$ = gen_unop(AST_LNOT, $2, src_loc(@$)); }
- | "~" expr { $$ = gen_unop(AST_BNEG, $2, src_loc(@$)); }
+ : "-" expr { $$ = gen_unop(AST_NEG, $2, src_loc(@$)); Q($$); }
+ | "!" expr { $$ = gen_unop(AST_LNOT, $2, src_loc(@$)); Q($$); }
+ | "~" expr { $$ = gen_unop(AST_BNEG, $2, src_loc(@$)); Q($$); }
type
- : ID { $$ = tgen_id($1, src_loc(@$)); }
- | "(" opt_types ")" { $$ = tgen_closure($2, src_loc(@$)); }
+ : ID {
+ $$ = tgen_id($1, src_loc(@$));
+ Q($$);
+ }
+ | "(" opt_types ")" { $$ = tgen_closure($2, src_loc(@$)); Q($$); }
| "&&" type {
if ($2->k == TYPE_CLOSURE) {
$$ = $2; $$->k = TYPE_PURE_CLOSURE;
} else {
$$ = tgen_ref($2, src_loc(@$));
+ Q($$);
}
/* heh */
$$ = tgen_ref($$, src_loc(@$));
+ Q($$);
}
| "&" type {
if ($2->k == TYPE_CLOSURE) {
$$ = $2; $$->k = TYPE_PURE_CLOSURE;
} else {
$$ = tgen_ref($2, src_loc(@$));
+ Q($$);
}
}
| "*" type {
@@ -284,6 +300,7 @@ type
$$ = $2; $$->k = TYPE_FUNC_PTR;
} else {
$$ = tgen_ptr($2, src_loc(@$));
+ Q($$);
}
}
@@ -302,6 +319,7 @@ opt_types
construction
: expr "=>" ID {
$$ = gen_construction($3, $1, src_loc(@$));
+ Q($$);
}
constructions
@@ -315,6 +333,7 @@ opt_constructions
deconstruction
: ID "=>" var {
$$ = gen_deconstruction($1, $3, src_loc(@$));
+ Q($$);
}
deconstructions
@@ -328,23 +347,33 @@ opt_deconstructions
construct
: "[" opt_constructions "]" ID {
$$ = gen_construct($4, $2, src_loc(@$));
+ Q($$);
}
id
- : ID { $$ = gen_id($1, src_loc(@$)); }
+ : ID {
+ $$ = gen_id($1, src_loc(@$));
+ Q($$);
+ }
expr
- : "sizeof" "(" type ")" { $$ = gen_sizeof($3, src_loc(@$)); }
- | STRING { $$ = gen_const_str(strip($1), src_loc(@$)); }
- | FLOAT { $$ = gen_const_float($1, src_loc(@$)); }
- | BOOL { $$ = gen_const_bool($1, src_loc(@$)); }
- | CHAR { $$ = gen_const_char($1, src_loc(@$)); }
- | INT { $$ = gen_const_int($1, src_loc(@$)); }
- | "*" { $$ = gen_nil(src_loc(@$)); }
+ : "sizeof" "(" type ")" { $$ = gen_sizeof($3, src_loc(@$)); Q($$); }
+ | STRING {
+ char *s = strip($1);
+ Q(s);
+
+ $$ = gen_const_str(s, src_loc(@$));
+ Q($$);
+ }
+ | FLOAT { $$ = gen_const_float($1, src_loc(@$)); Q($$); }
+ | BOOL { $$ = gen_const_bool($1, src_loc(@$)); Q($$); }
+ | CHAR { $$ = gen_const_char($1, src_loc(@$)); Q($$); }
+ | INT { $$ = gen_const_int($1, src_loc(@$)); Q($$); }
+ | "*" { $$ = gen_nil(src_loc(@$)); Q($$); }
| "(" expr ")" { $$ = $2; }
- | expr "&" { $$ = gen_ref($1, src_loc(@$)); }
- | expr "*" { $$ = gen_deref($1, src_loc(@$)); }
- | expr "as" type { $$ = gen_as($1, $3, src_loc(@$)); }
+ | expr "&" { $$ = gen_ref($1, src_loc(@$)); Q($$); }
+ | expr "*" { $$ = gen_deref($1, src_loc(@$)); Q($$); }
+ | expr "as" type { $$ = gen_as($1, $3, src_loc(@$)); Q($$); }
| construct
| id
| binop
@@ -364,9 +393,11 @@ opt_exprs
closure
: "=>" opt_vars body {
$$ = gen_closure($[opt_vars], $[body], src_loc(@$));
+ Q($$);
}
| "&" "=>" opt_vars body {
$$ = gen_closure($[opt_vars], $[body], src_loc(@$));
+ Q($$);
ast_set_flags($$, AST_FLAG_NOMOVES);
}
@@ -375,9 +406,13 @@ rev_closures
| closure
trailing_closure
- : "=>" opt_vars ";" { $$ = gen_closure($[opt_vars], NULL, src_loc(@$));}
+ : "=>" opt_vars ";" {
+ $$ = gen_closure($[opt_vars], NULL, src_loc(@$));
+ Q($$);
+ }
| "&" "=>" opt_vars ";" {
$$ = gen_closure($[opt_vars], NULL, src_loc(@$));
+ Q($$);
ast_set_flags($$, AST_FLAG_NOMOVES);
}
@@ -398,46 +433,66 @@ closures
call
: expr "(" opt_exprs ")" {
$$ = gen_call($1, $[opt_exprs], src_loc(@$));
+ Q($$);
}
| expr "(" opt_exprs ")" "=>" opt_vars ";" {
/* the rest of the function body is our closure, gets fixed up
* later */
struct ast *closure = gen_closure($[opt_vars], NULL, src_loc(@$));
+ Q(closure);
+
ast_append(&$[opt_exprs], closure);
$$ = gen_call($[expr], $[opt_exprs], src_loc(@$));
+ Q($$);
}
| expr "(" opt_exprs ")" closures {
ast_append(&$[opt_exprs], $[closures]);
$$ = gen_call($[expr], $[opt_exprs], src_loc(@$));
+ Q($$);
}
put
- : put "*" { $$ = gen_put($1, src_loc(@$)); }
- | id "*" { $$ = gen_put($1, src_loc(@$)); }
+ : put "*" { $$ = gen_put($1, src_loc(@$)); Q($$); }
+ | id "*" { $$ = gen_put($1, src_loc(@$)); Q($$); }
let
- : expr "=>" var ";" { $$ = gen_let($3, $1, src_loc(@$)); }
- | expr "=>" put ";" { $$ = gen_write($3, $1, src_loc(@$)); }
+ : expr "=>" var ";" {
+ $$ = gen_let($3, $1, src_loc(@$));
+ Q($$);
+ }
+ | expr "=>" put ";" {
+ $$ = gen_write($3, $1, src_loc(@$));
+ Q($$);
+ }
explode
: expr "=>" "[" opt_deconstructions "]" {
$$ = gen_explode($4, $1, src_loc(@$));
+ Q($$);
}
if
- : "if" expr body "else" body { $$ = gen_if($2, $3, $5, src_loc(@$)); }
- | "if" expr body "else" if { $$ = gen_if($2, $3, $5, src_loc(@$)); }
+ : "if" expr body "else" body {
+ $$ = gen_if($2, $3, $5, src_loc(@$));
+ Q($$);
+ }
+ | "if" expr body "else" if {
+ $$ = gen_if($2, $3, $5, src_loc(@$));
+ Q($$);
+ }
nil
: "nil" expr body "=>" var ";" {
/** @todo should nil check define new scope for created
* variable? */
$$ = gen_nil_check($2, $3, $5, src_loc(@$));
+ Q($$);
}
forget
: "nil" ID ";" {
$$ = gen_forget($2, src_loc(@$));
+ Q($$);
}
statement
@@ -448,7 +503,7 @@ statement
| let
| nil
| if
- | ";" { $$ = gen_empty(src_loc(@$)); }
+ | ";" { $$ = gen_empty(src_loc(@$)); Q($$); }
rev_statements
: rev_statements statement { $$ = $2; $2->n = $1; }
@@ -467,6 +522,7 @@ opt_statements
body
: "{" opt_statements "}" {
$$ = gen_block($2, src_loc(@$));
+ Q($$);
}
behaviour
@@ -483,7 +539,10 @@ opt_behaviours
| { $$ = NULL; }
impl
- : ID "!" { $$ = gen_implements($1, src_loc(@$)); }
+ : ID "!" {
+ $$ = gen_implements($1, src_loc(@$));
+ Q($$);
+ }
member
: param
@@ -499,7 +558,10 @@ opt_members
type_param
: ID ID {
struct type *t = tgen_id($1, src_loc(@1));
+ Q(t);
+
$$ = gen_var($2, t, src_loc(@$));
+ Q($$);
}
type_params
@@ -532,38 +594,50 @@ opt_elements
template
: ID "[" opt_type_params "]" "(" opt_vars ")" "{" opt_elements "}" {
$$ = gen_template($1, $3, $6, $9, src_loc(@$));
+ Q($$);
}
supertemplate
: ID "[" opt_type_params "]" "(" opt_vars ")" "="
id "[" opt_types "]" "(" opt_exprs ")" "{" opt_elements "}" {
struct ast *pseudoinst = gen_instance(NULL, $9, $11, $14, src_loc(@$));
+ Q(pseudoinst);
+
$$ = gen_supertemplate($1, $3, $6, pseudoinst, $17, src_loc(@$));
+ Q($$);
}
struct
: ID "{" opt_members "}" {
$$ = gen_struct($1, $3, src_loc(@$));
+ Q($$);
}
struct_cont
: "continue" ID "{" opt_behaviours "}" {
$$ = gen_instance_cont($2, $4, src_loc(@$));
+ Q($$);
}
trait
: ID "=" "{" opt_behaviours "}" {
$$ = gen_trait($1, $4, src_loc(@$));
+ Q($$);
}
instance
: ID "=" id "[" opt_types "]" "(" opt_exprs ")" {
$$ = gen_instance($1, $3, $5, $8, src_loc(@$));
+ Q($$);
}
import
: "import" STRING {
- $$ = gen_import(strip($2), src_loc(@$));
+ char *s = strip($2);
+ Q(s);
+
+ $$ = gen_import(s, src_loc(@$));
+ Q($$);
}
top
@@ -585,6 +659,8 @@ top
| "pub" supertemplate { $$ = $2; ast_set_flags($$, AST_FLAG_PUBLIC); }
| error {
$$ = gen_empty(src_loc(@$));
+ Q($$);
+
parser->failed = true;
/* ignore any content inside a top level thing and just move onto
* the next one */
@@ -679,11 +755,11 @@ static char match_escape(char c)
static char *strip(const char *str)
{
const size_t len = strlen(str) + 1;
- char *buf = malloc(len);
+ char *buf = mallocc(len);
if (!buf) {
/* should probably try to handle the error in some way... */
internal_error("failed allocating buffer for string clone");
- free((void *)str);
+ /* str should be in tracker already, so no need to free it */
return NULL;
}
@@ -693,14 +769,20 @@ static char *strip(const char *str)
buf[j++] = str[i];
buf[j] = 0;
- free((void *)str);
+ track_ptr(buf);
return buf;
}
struct parser *create_parser()
{
- return calloc(1, sizeof(struct parser));
+ struct parser *p = callocc(1, sizeof(struct parser));
+ if (!p) {
+ internal_error("failed allocating parser");
+ return NULL;
+ }
+
+ return p;
}
void destroy_parser(struct parser *p)