summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRoberto Ierusalimschy <roberto@inf.puc-rio.br>2011-02-09 14:51:28 -0200
committerRoberto Ierusalimschy <roberto@inf.puc-rio.br>2011-02-09 14:51:28 -0200
commite7192dfdbbef6c5ffc8a72d844d7d772ded91c46 (patch)
treee5481916a7c01adc216181771d66bc36e5bed9f0
parent0539f4866115149d2de7a35067b5cbac45dd1c47 (diff)
downloadlua-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.c35
1 files changed, 21 insertions, 14 deletions
diff --git a/lparser.c b/lparser.c
index a479d20f..423e4e20 100644
--- a/lparser.c
+++ b/lparser.c
@@ -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
1051static 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*/
1056static 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, ';');