summaryrefslogtreecommitdiff
path: root/parse/gram.y
diff options
context:
space:
mode:
authorOri Bernstein <ori@eigenstate.org>2016-02-25 15:28:14 -0800
committerOri Bernstein <ori@eigenstate.org>2016-02-25 15:28:57 -0800
commit2a76c9fc491ab08492491ddce7fb26d953879791 (patch)
tree9171cad950e4e55f5445676a9bf6c56700f6532a /parse/gram.y
parent16bbf82067cacf44828b5f5023bdd6ec3b80b570 (diff)
downloadmc-2a76c9fc491ab08492491ddce7fb26d953879791.tar.gz
Fix forward labels in nested blocks.
Fixes #91
Diffstat (limited to 'parse/gram.y')
-rw-r--r--parse/gram.y31
1 files changed, 27 insertions, 4 deletions
diff --git a/parse/gram.y b/parse/gram.y
index 5509e90..fc29391 100644
--- a/parse/gram.y
+++ b/parse/gram.y
@@ -19,6 +19,8 @@
Stab *curscope;
+static Node **lbls;
+static size_t nlbls;
void yyerror(const char *s);
int yylex(void);
@@ -783,10 +785,30 @@ littok : Tstrlit {$$ = mkstr($1->loc, $1->strval);}
}
;
-funclit : Tobrace params Tendln blkbody Tcbrace
- {$$ = mkfunc($1->loc, $2.nl, $2.nn, mktyvar($3->loc), $4);}
- | Tobrace params Tret type Tendln blkbody Tcbrace
- {$$ = mkfunc($1->loc, $2.nl, $2.nn, $4, $6);}
+funclit : Tobrace params Tendln blkbody Tcbrace {
+ size_t i;
+ Node *fn, *lit;
+
+ $$ = mkfunc($1->loc, $2.nl, $2.nn, mktyvar($3->loc), $4);
+ fn = $$->lit.fnval;
+ for (i = 0; i < nlbls; i++) {
+ lit = lbls[i]->expr.args[0];
+ putlbl(fn->func.scope, lit->lit.lblname, lbls[i]);
+ }
+ lfree(&lbls, &nlbls);
+ }
+ | Tobrace params Tret type Tendln blkbody Tcbrace {
+ size_t i;
+ Node *fn, *lit;
+
+ $$ = mkfunc($1->loc, $2.nl, $2.nn, $4, $6);
+ fn = $$->lit.fnval;
+ for (i = 0; i < nlbls; i++) {
+ lit = lbls[i]->expr.args[0];
+ putlbl(fn->func.scope, lbls[i]->lit.lblname, lbls[i]);
+ }
+ lfree(&lbls, &nlbls);
+ }
;
params : fnparam {
@@ -981,6 +1003,7 @@ label : Tcolon Tident {
genlblstr(buf, sizeof buf, $2->id);
$$ = mklbl($2->loc, buf);
$$->expr.args[0]->lit.lblname = strdup($2->id);
+ lappend(&lbls, &nlbls, $$);
}
;