diff options
author | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2011-02-09 14:51:28 -0200 |
---|---|---|
committer | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2011-02-09 14:51:28 -0200 |
commit | e7192dfdbbef6c5ffc8a72d844d7d772ded91c46 (patch) | |
tree | e5481916a7c01adc216181771d66bc36e5bed9f0 | |
parent | 0539f4866115149d2de7a35067b5cbac45dd1c47 (diff) | |
download | lua-e7192dfdbbef6c5ffc8a72d844d7d772ded91c46.tar.gz lua-e7192dfdbbef6c5ffc8a72d844d7d772ded91c46.tar.bz2 lua-e7192dfdbbef6c5ffc8a72d844d7d772ded91c46.zip |
corrected 'follow' for checking whether label is last statement
in a block
-rw-r--r-- | lparser.c | 35 |
1 files changed, 21 insertions, 14 deletions
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lparser.c,v 2.100 2011/02/07 19:00:30 roberto Exp roberto $ | 2 | ** $Id: lparser.c,v 2.101 2011/02/09 14:45:19 roberto Exp roberto $ |
3 | ** Lua Parser | 3 | ** Lua Parser |
4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
5 | */ | 5 | */ |
@@ -342,7 +342,7 @@ static void closegoto (LexState *ls, int g, Labeldesc *label) { | |||
342 | FuncState *fs = ls->fs; | 342 | FuncState *fs = ls->fs; |
343 | Dyndata *dyd = ls->dyd; | 343 | Dyndata *dyd = ls->dyd; |
344 | Labeldesc *gt = &dyd->gt.arr[g]; | 344 | Labeldesc *gt = &dyd->gt.arr[g]; |
345 | lua_assert(gt->name == label->name); | 345 | lua_assert(eqstr(gt->name, label->name)); |
346 | if (gt->nactvar < label->nactvar) { | 346 | if (gt->nactvar < label->nactvar) { |
347 | const char *msg = luaO_pushfstring(ls->L, | 347 | const char *msg = luaO_pushfstring(ls->L, |
348 | "<goto %s> at line %d jumps into the scope of local " LUA_QS, | 348 | "<goto %s> at line %d jumps into the scope of local " LUA_QS, |
@@ -368,7 +368,7 @@ static int findlabel (LexState *ls, int g) { | |||
368 | /* check labels in current block for a match */ | 368 | /* check labels in current block for a match */ |
369 | for (i = bl->firstlabel; i < dyd->label.n; i++) { | 369 | for (i = bl->firstlabel; i < dyd->label.n; i++) { |
370 | Labeldesc *lb = &dyd->label.arr[i]; | 370 | Labeldesc *lb = &dyd->label.arr[i]; |
371 | if (lb->name == gt->name) { /* correct label? */ | 371 | if (eqstr(lb->name, gt->name)) { /* correct label? */ |
372 | if (gt->nactvar > lb->nactvar && | 372 | if (gt->nactvar > lb->nactvar && |
373 | (bl->upval || dyd->label.n > bl->firstlabel)) | 373 | (bl->upval || dyd->label.n > bl->firstlabel)) |
374 | luaK_patchclose(ls->fs, gt->pc, lb->nactvar); | 374 | luaK_patchclose(ls->fs, gt->pc, lb->nactvar); |
@@ -388,7 +388,7 @@ static void findgotos (LexState *ls, Labeldesc *lb) { | |||
388 | int i; | 388 | int i; |
389 | Dyndata *dyd = ls->dyd; | 389 | Dyndata *dyd = ls->dyd; |
390 | for (i = ls->fs->bl->firstgoto; i < dyd->gt.n; i++) { | 390 | for (i = ls->fs->bl->firstgoto; i < dyd->gt.n; i++) { |
391 | if (dyd->gt.arr[i].name == lb->name) | 391 | if (eqstr(dyd->gt.arr[i].name, lb->name)) |
392 | closegoto(ls, i, lb); | 392 | closegoto(ls, i, lb); |
393 | } | 393 | } |
394 | } | 394 | } |
@@ -439,7 +439,7 @@ static void leaveblock (FuncState *fs) { | |||
439 | ls->dyd->label.n = bl->firstlabel; /* remove local labels */ | 439 | ls->dyd->label.n = bl->firstlabel; /* remove local labels */ |
440 | if (bl->previous) /* inner block? */ | 440 | if (bl->previous) /* inner block? */ |
441 | movegotosout(fs, bl); /* update pending gotos to outer block */ | 441 | movegotosout(fs, bl); /* update pending gotos to outer block */ |
442 | else if (bl->firstgoto < ls->dyd->gt.n) { /* check pending gotos */ | 442 | else if (bl->firstgoto < ls->dyd->gt.n) { /* pending gotos in outer block? */ |
443 | Labeldesc *gt = &ls->dyd->gt.arr[bl->firstgoto]; | 443 | Labeldesc *gt = &ls->dyd->gt.arr[bl->firstgoto]; |
444 | const char *msg = luaO_pushfstring(ls->L, | 444 | const char *msg = luaO_pushfstring(ls->L, |
445 | "label " LUA_QS " (<goto> at line %d) undefined", | 445 | "label " LUA_QS " (<goto> at line %d) undefined", |
@@ -1048,11 +1048,17 @@ static void expr (LexState *ls, expdesc *v) { | |||
1048 | */ | 1048 | */ |
1049 | 1049 | ||
1050 | 1050 | ||
1051 | static int block_follow (int token) { | 1051 | /* |
1052 | switch (token) { | 1052 | ** check whether current token is in the follow set of a block. |
1053 | case TK_ELSE: case TK_ELSEIF: case TK_END: | 1053 | ** 'until' closes syntactical blocks, but do not close scope, |
1054 | case TK_UNTIL: case TK_EOS: | 1054 | ** so it handled in separate. |
1055 | */ | ||
1056 | static int block_follow (LexState *ls, int withuntil) { | ||
1057 | switch (ls->t.token) { | ||
1058 | case TK_ELSE: case TK_ELSEIF: | ||
1059 | case TK_END: case TK_EOS: | ||
1055 | return 1; | 1060 | return 1; |
1061 | case TK_UNTIL: return withuntil; | ||
1056 | default: return 0; | 1062 | default: return 0; |
1057 | } | 1063 | } |
1058 | } | 1064 | } |
@@ -1207,10 +1213,11 @@ static void labelstat (LexState *ls, TString *label) { | |||
1207 | /* create new entry for this label */ | 1213 | /* create new entry for this label */ |
1208 | l = newlabelentry(ls, &ls->dyd->label, label, 0, fs->pc); | 1214 | l = newlabelentry(ls, &ls->dyd->label, label, 0, fs->pc); |
1209 | lb = &ls->dyd->label.arr[l]; | 1215 | lb = &ls->dyd->label.arr[l]; |
1210 | /* if label is last statement in the block, | 1216 | while (testnext(ls, ';')) ; /* skip trailing semicolons */ |
1211 | assume that local variables are already out of scope */ | 1217 | if (block_follow(ls, 0)) { /* label is last statement in the block? */ |
1212 | if (ls->t.token == TK_END) | 1218 | /* assume that locals are already out of scope */ |
1213 | lb->nactvar = fs->bl->nactvar; | 1219 | lb->nactvar = fs->bl->nactvar; |
1220 | } | ||
1214 | findgotos(ls, lb); | 1221 | findgotos(ls, lb); |
1215 | } | 1222 | } |
1216 | 1223 | ||
@@ -1470,7 +1477,7 @@ static void retstat (LexState *ls) { | |||
1470 | FuncState *fs = ls->fs; | 1477 | FuncState *fs = ls->fs; |
1471 | expdesc e; | 1478 | expdesc e; |
1472 | int first, nret; /* registers with returned values */ | 1479 | int first, nret; /* registers with returned values */ |
1473 | if (block_follow(ls->t.token) || ls->t.token == ';') | 1480 | if (block_follow(ls, 1) || ls->t.token == ';') |
1474 | first = nret = 0; /* return no values */ | 1481 | first = nret = 0; /* return no values */ |
1475 | else { | 1482 | else { |
1476 | nret = explist1(ls, &e); /* optional return values */ | 1483 | nret = explist1(ls, &e); /* optional return values */ |
@@ -1570,7 +1577,7 @@ static void statlist (LexState *ls) { | |||
1570 | /* statlist -> { stat [`;'] } */ | 1577 | /* statlist -> { stat [`;'] } */ |
1571 | int islast = 0; | 1578 | int islast = 0; |
1572 | enterlevel(ls); | 1579 | enterlevel(ls); |
1573 | while (!islast && !block_follow(ls->t.token)) { | 1580 | while (!islast && !block_follow(ls, 1)) { |
1574 | islast = statement(ls); | 1581 | islast = statement(ls); |
1575 | if (islast) | 1582 | if (islast) |
1576 | testnext(ls, ';'); | 1583 | testnext(ls, ';'); |