aboutsummaryrefslogtreecommitdiff
path: root/lparser.c
diff options
context:
space:
mode:
authorRoberto Ierusalimschy <roberto@inf.puc-rio.br>2011-02-14 12:59:28 -0200
committerRoberto Ierusalimschy <roberto@inf.puc-rio.br>2011-02-14 12:59:28 -0200
commit0009ac1f3addb79e3cb4f1f1d12929a975f1f241 (patch)
tree6726033f4ba57035f22975b772a363402d327e3c /lparser.c
parent7b968bb51404d73cd0b4d75ad092f3cab299fac9 (diff)
downloadlua-0009ac1f3addb79e3cb4f1f1d12929a975f1f241.tar.gz
lua-0009ac1f3addb79e3cb4f1f1d12929a975f1f241.tar.bz2
lua-0009ac1f3addb79e3cb4f1f1d12929a975f1f241.zip
'break' does not need to be last statement in a block +
'explist1' -> 'explist' + moving a few functions around
Diffstat (limited to 'lparser.c')
-rw-r--r--lparser.c165
1 files changed, 84 insertions, 81 deletions
diff --git a/lparser.c b/lparser.c
index 9da2e2c1..6933499e 100644
--- a/lparser.c
+++ b/lparser.c
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: lparser.c,v 2.103 2011/02/09 17:03:18 roberto Exp $ 2** $Id: lparser.c,v 2.104 2011/02/10 14:50:41 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*/
@@ -53,7 +53,7 @@ typedef struct BlockCnt {
53/* 53/*
54** prototypes for recursive non-terminal functions 54** prototypes for recursive non-terminal functions
55*/ 55*/
56static void statlist (LexState *ls); 56static void statement (LexState *ls);
57static void expr (LexState *ls, expdesc *v); 57static void expr (LexState *ls, expdesc *v);
58 58
59 59
@@ -583,35 +583,40 @@ static void open_mainfunc (LexState *ls, FuncState *fs, BlockCnt *bl) {
583} 583}
584 584
585 585
586Proto *luaY_parser (lua_State *L, ZIO *z, Mbuffer *buff,
587 Dyndata *dyd, const char *name) {
588 LexState lexstate;
589 FuncState funcstate;
590 BlockCnt bl;
591 TString *tname = luaS_new(L, name);
592 setsvalue2s(L, L->top, tname); /* push name to protect it */
593 incr_top(L);
594 lexstate.buff = buff;
595 lexstate.dyd = dyd;
596 dyd->actvar.n = dyd->gt.n = dyd->label.n = 0;
597 luaX_setinput(L, &lexstate, z, tname);
598 open_mainfunc(&lexstate, &funcstate, &bl);
599 luaX_next(&lexstate); /* read first token */
600 statlist(&lexstate); /* main body */
601 check(&lexstate, TK_EOS);
602 close_func(&lexstate);
603 L->top--; /* pop name */
604 lua_assert(!funcstate.prev && funcstate.nups == 1 && !lexstate.fs);
605 return funcstate.f;
606}
607
608
609 586
610/*============================================================*/ 587/*============================================================*/
611/* GRAMMAR RULES */ 588/* GRAMMAR RULES */
612/*============================================================*/ 589/*============================================================*/
613 590
614 591
592/*
593** check whether current token is in the follow set of a block.
594** 'until' closes syntactical blocks, but do not close scope,
595** so it handled in separate.
596*/
597static int block_follow (LexState *ls, int withuntil) {
598 switch (ls->t.token) {
599 case TK_ELSE: case TK_ELSEIF:
600 case TK_END: case TK_EOS:
601 return 1;
602 case TK_UNTIL: return withuntil;
603 default: return 0;
604 }
605}
606
607
608static void statlist (LexState *ls) {
609 /* statlist -> { stat [`;'] } */
610 while (!block_follow(ls, 1)) {
611 if (ls->t.token == TK_RETURN) {
612 statement(ls);
613 return; /* 'return' must be last statement */
614 }
615 statement(ls);
616 }
617}
618
619
615static void fieldsel (LexState *ls, expdesc *v) { 620static void fieldsel (LexState *ls, expdesc *v) {
616 /* fieldsel -> ['.' | ':'] NAME */ 621 /* fieldsel -> ['.' | ':'] NAME */
617 FuncState *fs = ls->fs; 622 FuncState *fs = ls->fs;
@@ -805,8 +810,8 @@ static void body (LexState *ls, expdesc *e, int ismethod, int line) {
805} 810}
806 811
807 812
808static int explist1 (LexState *ls, expdesc *v) { 813static int explist (LexState *ls, expdesc *v) {
809 /* explist1 -> expr { `,' expr } */ 814 /* explist -> expr { `,' expr } */
810 int n = 1; /* at least one expression */ 815 int n = 1; /* at least one expression */
811 expr(ls, v); 816 expr(ls, v);
812 while (testnext(ls, ',')) { 817 while (testnext(ls, ',')) {
@@ -823,12 +828,12 @@ static void funcargs (LexState *ls, expdesc *f, int line) {
823 expdesc args; 828 expdesc args;
824 int base, nparams; 829 int base, nparams;
825 switch (ls->t.token) { 830 switch (ls->t.token) {
826 case '(': { /* funcargs -> `(' [ explist1 ] `)' */ 831 case '(': { /* funcargs -> `(' [ explist ] `)' */
827 luaX_next(ls); 832 luaX_next(ls);
828 if (ls->t.token == ')') /* arg list is empty? */ 833 if (ls->t.token == ')') /* arg list is empty? */
829 args.k = VVOID; 834 args.k = VVOID;
830 else { 835 else {
831 explist1(ls, &args); 836 explist(ls, &args);
832 luaK_setmultret(fs, &args); 837 luaK_setmultret(fs, &args);
833 } 838 }
834 check_match(ls, ')', '(', line); 839 check_match(ls, ')', '(', line);
@@ -1079,22 +1084,6 @@ static void expr (LexState *ls, expdesc *v) {
1079*/ 1084*/
1080 1085
1081 1086
1082/*
1083** check whether current token is in the follow set of a block.
1084** 'until' closes syntactical blocks, but do not close scope,
1085** so it handled in separate.
1086*/
1087static int block_follow (LexState *ls, int withuntil) {
1088 switch (ls->t.token) {
1089 case TK_ELSE: case TK_ELSEIF:
1090 case TK_END: case TK_EOS:
1091 return 1;
1092 case TK_UNTIL: return withuntil;
1093 default: return 0;
1094 }
1095}
1096
1097
1098static void block (LexState *ls) { 1087static void block (LexState *ls) {
1099 /* block -> statlist */ 1088 /* block -> statlist */
1100 FuncState *fs = ls->fs; 1089 FuncState *fs = ls->fs;
@@ -1159,10 +1148,10 @@ static void assignment (LexState *ls, struct LHS_assign *lh, int nvars) {
1159 "variable names"); 1148 "variable names");
1160 assignment(ls, &nv, nvars+1); 1149 assignment(ls, &nv, nvars+1);
1161 } 1150 }
1162 else { /* assignment -> `=' explist1 */ 1151 else { /* assignment -> `=' explist */
1163 int nexps; 1152 int nexps;
1164 checknext(ls, '='); 1153 checknext(ls, '=');
1165 nexps = explist1(ls, &e); 1154 nexps = explist(ls, &e);
1166 if (nexps != nvars) { 1155 if (nexps != nvars) {
1167 adjust_assign(ls, nvars, nexps, &e); 1156 adjust_assign(ls, nvars, nexps, &e);
1168 if (nexps > nvars) 1157 if (nexps > nvars)
@@ -1313,7 +1302,7 @@ static void fornum (LexState *ls, TString *varname, int line) {
1313 1302
1314 1303
1315static void forlist (LexState *ls, TString *indexname) { 1304static void forlist (LexState *ls, TString *indexname) {
1316 /* forlist -> NAME {,NAME} IN explist1 forbody */ 1305 /* forlist -> NAME {,NAME} IN explist forbody */
1317 FuncState *fs = ls->fs; 1306 FuncState *fs = ls->fs;
1318 expdesc e; 1307 expdesc e;
1319 int nvars = 4; /* gen, state, control, plus at least one declared var */ 1308 int nvars = 4; /* gen, state, control, plus at least one declared var */
@@ -1331,7 +1320,7 @@ static void forlist (LexState *ls, TString *indexname) {
1331 } 1320 }
1332 checknext(ls, TK_IN); 1321 checknext(ls, TK_IN);
1333 line = ls->linenumber; 1322 line = ls->linenumber;
1334 adjust_assign(ls, 3, explist1(ls, &e), &e); 1323 adjust_assign(ls, 3, explist(ls, &e), &e);
1335 luaK_checkstack(fs, 3); /* extra space to call generator */ 1324 luaK_checkstack(fs, 3); /* extra space to call generator */
1336 forbody(ls, base, line, nvars - 3, 0); 1325 forbody(ls, base, line, nvars - 3, 0);
1337} 1326}
@@ -1399,7 +1388,7 @@ static void localfunc (LexState *ls) {
1399 1388
1400 1389
1401static void localstat (LexState *ls) { 1390static void localstat (LexState *ls) {
1402 /* stat -> LOCAL NAME {`,' NAME} [`=' explist1] */ 1391 /* stat -> LOCAL NAME {`,' NAME} [`=' explist] */
1403 int nvars = 0; 1392 int nvars = 0;
1404 int nexps; 1393 int nexps;
1405 expdesc e; 1394 expdesc e;
@@ -1408,7 +1397,7 @@ static void localstat (LexState *ls) {
1408 nvars++; 1397 nvars++;
1409 } while (testnext(ls, ',')); 1398 } while (testnext(ls, ','));
1410 if (testnext(ls, '=')) 1399 if (testnext(ls, '='))
1411 nexps = explist1(ls, &e); 1400 nexps = explist(ls, &e);
1412 else { 1401 else {
1413 e.k = VVOID; 1402 e.k = VVOID;
1414 nexps = 0; 1403 nexps = 0;
@@ -1459,14 +1448,14 @@ static void exprstat (LexState *ls) {
1459 1448
1460 1449
1461static void retstat (LexState *ls) { 1450static void retstat (LexState *ls) {
1462 /* stat -> RETURN explist */ 1451 /* stat -> RETURN [explist] [';'] */
1463 FuncState *fs = ls->fs; 1452 FuncState *fs = ls->fs;
1464 expdesc e; 1453 expdesc e;
1465 int first, nret; /* registers with returned values */ 1454 int first, nret; /* registers with returned values */
1466 if (block_follow(ls, 1) || ls->t.token == ';') 1455 if (block_follow(ls, 1) || ls->t.token == ';')
1467 first = nret = 0; /* return no values */ 1456 first = nret = 0; /* return no values */
1468 else { 1457 else {
1469 nret = explist1(ls, &e); /* optional return values */ 1458 nret = explist(ls, &e); /* optional return values */
1470 if (hasmultret(e.k)) { 1459 if (hasmultret(e.k)) {
1471 luaK_setmultret(fs, &e); 1460 luaK_setmultret(fs, &e);
1472 if (e.k == VCALL && nret == 1) { /* tail call? */ 1461 if (e.k == VCALL && nret == 1) { /* tail call? */
@@ -1487,41 +1476,43 @@ static void retstat (LexState *ls) {
1487 } 1476 }
1488 } 1477 }
1489 luaK_ret(fs, first, nret); 1478 luaK_ret(fs, first, nret);
1479 testnext(ls, ';'); /* skip optional semicollon */
1490} 1480}
1491 1481
1492 1482
1493static int statement (LexState *ls) { 1483static void statement (LexState *ls) {
1494 int line = ls->linenumber; /* may be needed for error messages */ 1484 int line = ls->linenumber; /* may be needed for error messages */
1485 enterlevel(ls);
1495 switch (ls->t.token) { 1486 switch (ls->t.token) {
1496 case ';': { /* stat -> ';' (empty statement) */ 1487 case ';': { /* stat -> ';' (empty statement) */
1497 luaX_next(ls); /* skip ';' */ 1488 luaX_next(ls); /* skip ';' */
1498 return 0; 1489 break;
1499 } 1490 }
1500 case TK_IF: { /* stat -> ifstat */ 1491 case TK_IF: { /* stat -> ifstat */
1501 ifstat(ls, line); 1492 ifstat(ls, line);
1502 return 0; 1493 break;
1503 } 1494 }
1504 case TK_WHILE: { /* stat -> whilestat */ 1495 case TK_WHILE: { /* stat -> whilestat */
1505 whilestat(ls, line); 1496 whilestat(ls, line);
1506 return 0; 1497 break;
1507 } 1498 }
1508 case TK_DO: { /* stat -> DO block END */ 1499 case TK_DO: { /* stat -> DO block END */
1509 luaX_next(ls); /* skip DO */ 1500 luaX_next(ls); /* skip DO */
1510 block(ls); 1501 block(ls);
1511 check_match(ls, TK_END, TK_DO, line); 1502 check_match(ls, TK_END, TK_DO, line);
1512 return 0; 1503 break;
1513 } 1504 }
1514 case TK_FOR: { /* stat -> forstat */ 1505 case TK_FOR: { /* stat -> forstat */
1515 forstat(ls, line); 1506 forstat(ls, line);
1516 return 0; 1507 break;
1517 } 1508 }
1518 case TK_REPEAT: { /* stat -> repeatstat */ 1509 case TK_REPEAT: { /* stat -> repeatstat */
1519 repeatstat(ls, line); 1510 repeatstat(ls, line);
1520 return 0; 1511 break;
1521 } 1512 }
1522 case TK_FUNCTION: { /* stat -> funcstat */ 1513 case TK_FUNCTION: { /* stat -> funcstat */
1523 funcstat(ls, line); 1514 funcstat(ls, line);
1524 return 0; 1515 break;
1525 } 1516 }
1526 case TK_LOCAL: { /* stat -> localstat */ 1517 case TK_LOCAL: { /* stat -> localstat */
1527 luaX_next(ls); /* skip LOCAL */ 1518 luaX_next(ls); /* skip LOCAL */
@@ -1529,50 +1520,62 @@ static int statement (LexState *ls) {
1529 localfunc(ls); 1520 localfunc(ls);
1530 else 1521 else
1531 localstat(ls); 1522 localstat(ls);
1532 return 0; 1523 break;
1533 } 1524 }
1534 case '@': { /* stat -> label */ 1525 case '@': { /* stat -> label */
1535 luaX_next(ls); /* skip '@' */ 1526 luaX_next(ls); /* skip '@' */
1536 labelstat(ls, str_checkname(ls)); 1527 labelstat(ls, str_checkname(ls));
1537 return 0; 1528 break;
1538 } 1529 }
1539 case TK_RETURN: { /* stat -> retstat */ 1530 case TK_RETURN: { /* stat -> retstat */
1540 luaX_next(ls); /* skip RETURN */ 1531 luaX_next(ls); /* skip RETURN */
1541 retstat(ls); 1532 retstat(ls);
1542 return 1; /* must be last statement */ 1533 break;
1543 } 1534 }
1544 case TK_BREAK: { /* stat -> breakstat */ 1535 case TK_BREAK: { /* stat -> breakstat */
1545 luaX_next(ls); /* skip BREAK */ 1536 luaX_next(ls); /* skip BREAK */
1546 /* code it as "goto 'break'" */ 1537 /* code it as "goto 'break'" */
1547 gotostat(ls, luaS_new(ls->L, "break"), line); 1538 gotostat(ls, luaS_new(ls->L, "break"), line);
1548 return 1; /* must be last statement */ 1539 break;
1549 } 1540 }
1550 case TK_GOTO: { /* stat -> 'goto' NAME */ 1541 case TK_GOTO: { /* stat -> 'goto' NAME */
1551 luaX_next(ls); /* skip GOTO */ 1542 luaX_next(ls); /* skip GOTO */
1552 gotostat(ls, str_checkname(ls), line); 1543 gotostat(ls, str_checkname(ls), line);
1553 return 0; 1544 break;
1554 } 1545 }
1555 default: { /* stat -> func | assignment */ 1546 default: { /* stat -> func | assignment */
1556 exprstat(ls); 1547 exprstat(ls);
1557 return 0; 1548 break;
1558 } 1549 }
1559 } 1550 }
1551 lua_assert(ls->fs->f->maxstacksize >= ls->fs->freereg &&
1552 ls->fs->freereg >= ls->fs->nactvar);
1553 ls->fs->freereg = ls->fs->nactvar; /* free registers */
1554 leavelevel(ls);
1560} 1555}
1561 1556
1557/* }====================================================================== */
1562 1558
1563static void statlist (LexState *ls) { 1559
1564 /* statlist -> { stat [`;'] } */ 1560Proto *luaY_parser (lua_State *L, ZIO *z, Mbuffer *buff,
1565 int islast = 0; 1561 Dyndata *dyd, const char *name) {
1566 enterlevel(ls); 1562 LexState lexstate;
1567 while (!islast && !block_follow(ls, 1)) { 1563 FuncState funcstate;
1568 islast = statement(ls); 1564 BlockCnt bl;
1569 if (islast) 1565 TString *tname = luaS_new(L, name);
1570 testnext(ls, ';'); 1566 setsvalue2s(L, L->top, tname); /* push name to protect it */
1571 lua_assert(ls->fs->f->maxstacksize >= ls->fs->freereg && 1567 incr_top(L);
1572 ls->fs->freereg >= ls->fs->nactvar); 1568 lexstate.buff = buff;
1573 ls->fs->freereg = ls->fs->nactvar; /* free registers */ 1569 lexstate.dyd = dyd;
1574 } 1570 dyd->actvar.n = dyd->gt.n = dyd->label.n = 0;
1575 leavelevel(ls); 1571 luaX_setinput(L, &lexstate, z, tname);
1572 open_mainfunc(&lexstate, &funcstate, &bl);
1573 luaX_next(&lexstate); /* read first token */
1574 statlist(&lexstate); /* main body */
1575 check(&lexstate, TK_EOS);
1576 close_func(&lexstate);
1577 L->top--; /* pop name */
1578 lua_assert(!funcstate.prev && funcstate.nups == 1 && !lexstate.fs);
1579 return funcstate.f;
1576} 1580}
1577 1581
1578/* }====================================================================== */