aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lparser.c55
1 files changed, 37 insertions, 18 deletions
diff --git a/lparser.c b/lparser.c
index 899d2fe6..56faf1e9 100644
--- a/lparser.c
+++ b/lparser.c
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: lparser.c,v 2.116 2011/08/23 17:24:34 roberto Exp roberto $ 2** $Id: lparser.c,v 2.117 2011/08/25 13:45:24 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*/
@@ -383,7 +383,8 @@ static int findlabel (LexState *ls, int g) {
383static int newlabelentry (LexState *ls, Labellist *l, TString *name, 383static int newlabelentry (LexState *ls, Labellist *l, TString *name,
384 int line, int pc) { 384 int line, int pc) {
385 int n = l->n; 385 int n = l->n;
386 luaM_growvector(ls->L, l->arr, n, l->size, Labeldesc, SHRT_MAX, "labels"); 386 luaM_growvector(ls->L, l->arr, n, l->size,
387 Labeldesc, SHRT_MAX, "labels/gotos");
387 l->arr[n].name = name; 388 l->arr[n].name = name;
388 l->arr[n].line = line; 389 l->arr[n].line = line;
389 l->arr[n].nactvar = ls->fs->nactvar; 390 l->arr[n].nactvar = ls->fs->nactvar;
@@ -1178,10 +1179,18 @@ static int cond (LexState *ls) {
1178} 1179}
1179 1180
1180 1181
1181static void gotostat (LexState *ls, TString *label, int line) { 1182static void gotostat (LexState *ls, int pc) {
1182 /* create new entry for this goto */ 1183 int line = ls->linenumber;
1183 int g = newlabelentry(ls, &ls->dyd->gt, label, line, luaK_jump(ls->fs)); 1184 TString *label;
1184 findlabel(ls, g); 1185 int g;
1186 if (testnext(ls, TK_GOTO))
1187 label = str_checkname(ls);
1188 else {
1189 luaX_next(ls); /* skip break */
1190 label = luaS_new(ls->L, "break");
1191 }
1192 g = newlabelentry(ls, &ls->dyd->gt, label, line, pc);
1193 findlabel(ls, g); /* close it if label already defined */
1185} 1194}
1186 1195
1187 1196
@@ -1362,16 +1371,32 @@ static void forstat (LexState *ls, int line) {
1362 1371
1363static void test_then_block (LexState *ls, int *escapelist) { 1372static void test_then_block (LexState *ls, int *escapelist) {
1364 /* test_then_block -> [IF | ELSEIF] cond THEN block */ 1373 /* test_then_block -> [IF | ELSEIF] cond THEN block */
1374 BlockCnt bl;
1365 FuncState *fs = ls->fs; 1375 FuncState *fs = ls->fs;
1366 int condexit; 1376 expdesc v;
1377 int jf; /* instruction to skip 'then' code (if condition is false) */
1367 luaX_next(ls); /* skip IF or ELSEIF */ 1378 luaX_next(ls); /* skip IF or ELSEIF */
1368 condexit = cond(ls); /* 'if' condition */ 1379 enterblock(fs, &bl, 0);
1380 expr(ls, &v); /* read condition */
1369 checknext(ls, TK_THEN); 1381 checknext(ls, TK_THEN);
1370 block(ls); /* `then' part */ 1382 if (ls->t.token == TK_GOTO || ls->t.token == TK_BREAK) {
1383 luaK_goiffalse(ls->fs, &v); /* will jump to label if condition is true */
1384 gotostat(ls, v.t); /* handle goto/break */
1385 if (block_follow(ls, 0)) /* no more code after 'goto'? */
1386 goto leave; /* that is it */
1387 else /* must skip over 'then' part if condition is false */
1388 jf = luaK_jump(fs);
1389 }
1390 else { /* regular case (not goto/break) */
1391 luaK_goiftrue(ls->fs, &v); /* skip over block if condition is false */
1392 jf = v.f;
1393 }
1394 statlist(ls); /* `then' part */
1371 if (ls->t.token == TK_ELSE || 1395 if (ls->t.token == TK_ELSE ||
1372 ls->t.token == TK_ELSEIF) /* followed by 'else'/'elseif'? */ 1396 ls->t.token == TK_ELSEIF) /* followed by 'else'/'elseif'? */
1373 luaK_concat(fs, escapelist, luaK_jump(fs)); /* must jump over it */ 1397 luaK_concat(fs, escapelist, luaK_jump(fs)); /* must jump over it */
1374 luaK_patchtohere(fs, condexit); /* 'if' condition jumps to here */ 1398 luaK_patchtohere(fs, jf);
1399 leave: leaveblock(fs);
1375} 1400}
1376 1401
1377 1402
@@ -1545,15 +1570,9 @@ static void statement (LexState *ls) {
1545 retstat(ls); 1570 retstat(ls);
1546 break; 1571 break;
1547 } 1572 }
1548 case TK_BREAK: { /* stat -> breakstat */ 1573 case TK_BREAK: /* stat -> breakstat */
1549 luaX_next(ls); /* skip BREAK */
1550 /* code it as "goto 'break'" */
1551 gotostat(ls, luaS_new(ls->L, "break"), line);
1552 break;
1553 }
1554 case TK_GOTO: { /* stat -> 'goto' NAME */ 1574 case TK_GOTO: { /* stat -> 'goto' NAME */
1555 luaX_next(ls); /* skip GOTO */ 1575 gotostat(ls, luaK_jump(ls->fs));
1556 gotostat(ls, str_checkname(ls), line);
1557 break; 1576 break;
1558 } 1577 }
1559 default: { /* stat -> func | assignment */ 1578 default: { /* stat -> func | assignment */