summaryrefslogtreecommitdiff
path: root/parse/gram.y
diff options
context:
space:
mode:
authorOri Bernstein <ori@eigenstate.org>2017-03-10 22:11:45 -0800
committerOri Bernstein <ori@eigenstate.org>2017-03-10 22:11:45 -0800
commit1fc981b2ef099974206af6ad0242c38ccdffb02e (patch)
treeb84bcdd4350ad1173a244f660d79ddfacfa92f3a /parse/gram.y
parent46d4b4ea638d8aefc0fb6b4f32413acdc20e2ce7 (diff)
downloadmc-1fc981b2ef099974206af6ad0242c38ccdffb02e.tar.gz
Fix labels in nested functions.
We used to keep a list of labels seen in a function so we could transfer them to the function scope when we finished parsing. This was incorrect because nested functions would collect all the labels from the enclosing scope. We now keep a stack.
Diffstat (limited to 'parse/gram.y')
-rw-r--r--parse/gram.y41
1 files changed, 27 insertions, 14 deletions
diff --git a/parse/gram.y b/parse/gram.y
index 540a4fe..aa6ee2f 100644
--- a/parse/gram.y
+++ b/parse/gram.y
@@ -19,8 +19,11 @@
Stab *curscope;
-static Node **lbls;
-static size_t nlbls;
+#define LBLSTKSZ 64
+static Node **lbls[LBLSTKSZ];
+static size_t nlbls[LBLSTKSZ];
+/* the first time we see a label, we increment to 0 */
+static int lbldepth = -1;
void yyerror(const char *s);
int yylex(void);
@@ -132,7 +135,7 @@ static void setupinit(Node *n);
%type <tylist> typelist typarams optauxtypes
%type <nodelist> typaramlist
-%type <tok> asnop cmpop addop mulop shiftop optident
+%type <tok> asnop cmpop addop mulop shiftop optident obrace
%type <tydef> tydef pkgtydef typeid
%type <trait> traitdef
@@ -806,29 +809,39 @@ strlit : Tstrlit { $$ = mkstr($1->loc, $1->strval); }
}
;
-funclit : Tobrace params Tendln blkbody Tcbrace {
+obrace : Tobrace {
+ assert(lbldepth < LBLSTKSZ);
+ lbldepth++;
+ }
+ ;
+
+funclit : obrace 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]);
+ for (i = 0; i < nlbls[lbldepth]; i++) {
+ lit = lbls[lbldepth][i]->expr.args[0];
+ putlbl(fn->func.scope, lit->lit.lblname, lbls[lbldepth][i]);
}
- lfree(&lbls, &nlbls);
+ lfree(&lbls[lbldepth], &nlbls[lbldepth]);
+ assert(lbldepth >= 0);
+ lbldepth--;
}
- | Tobrace params Tret type Tendln blkbody Tcbrace {
+ | obrace 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, lit->lit.lblname, lbls[i]);
+ for (i = 0; i < nlbls[lbldepth]; i++) {
+ lit = lbls[lbldepth][i]->expr.args[0];
+ putlbl(fn->func.scope, lit->lit.lblname, lbls[lbldepth][i]);
}
- lfree(&lbls, &nlbls);
+ lfree(&lbls[lbldepth], &nlbls[lbldepth]);
+ assert(lbldepth >= 0);
+ lbldepth--;
}
;
@@ -1024,7 +1037,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, $$);
+ lappend(&lbls[lbldepth], &nlbls[lbldepth], $$);
}
;