diff options
author | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2011-02-14 12:59:28 -0200 |
---|---|---|
committer | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2011-02-14 12:59:28 -0200 |
commit | 0009ac1f3addb79e3cb4f1f1d12929a975f1f241 (patch) | |
tree | 6726033f4ba57035f22975b772a363402d327e3c /lparser.c | |
parent | 7b968bb51404d73cd0b4d75ad092f3cab299fac9 (diff) | |
download | lua-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.c | 165 |
1 files changed, 84 insertions, 81 deletions
@@ -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 | */ |
56 | static void statlist (LexState *ls); | 56 | static void statement (LexState *ls); |
57 | static void expr (LexState *ls, expdesc *v); | 57 | static 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 | ||
586 | Proto *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 | */ | ||
597 | static 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 | |||
608 | static 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 | |||
615 | static void fieldsel (LexState *ls, expdesc *v) { | 620 | static 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 | ||
808 | static int explist1 (LexState *ls, expdesc *v) { | 813 | static 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 | */ | ||
1087 | static 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 | |||
1098 | static void block (LexState *ls) { | 1087 | static 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 | ||
1315 | static void forlist (LexState *ls, TString *indexname) { | 1304 | static 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 | ||
1401 | static void localstat (LexState *ls) { | 1390 | static 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 | ||
1461 | static void retstat (LexState *ls) { | 1450 | static 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 | ||
1493 | static int statement (LexState *ls) { | 1483 | static 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 | ||
1563 | static void statlist (LexState *ls) { | 1559 | |
1564 | /* statlist -> { stat [`;'] } */ | 1560 | Proto *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 | /* }====================================================================== */ | ||