diff options
| author | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2001-02-14 15:19:28 -0200 |
|---|---|---|
| committer | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2001-02-14 15:19:28 -0200 |
| commit | 40f4e931f317f56725cba0b61ed82c0688a821f6 (patch) | |
| tree | a5cb02942b7471b1628bcc1d3ad3bee84484cc29 | |
| parent | 29371ecfe87d546b9ffab480808640bd2ef226a1 (diff) | |
| download | lua-40f4e931f317f56725cba0b61ed82c0688a821f6.tar.gz lua-40f4e931f317f56725cba0b61ed82c0688a821f6.tar.bz2 lua-40f4e931f317f56725cba0b61ed82c0688a821f6.zip | |
more liberal syntax for expressions
Diffstat (limited to '')
| -rw-r--r-- | lparser.c | 151 |
1 files changed, 70 insertions, 81 deletions
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | ** $Id: lparser.c,v 1.131 2001/02/09 18:37:33 roberto Exp roberto $ | 2 | ** $Id: lparser.c,v 1.132 2001/02/09 20:22:29 roberto Exp roberto $ |
| 3 | ** LL(1) Parser and code generator for Lua | 3 | ** LL(1) Parser and code generator for Lua |
| 4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
| 5 | */ | 5 | */ |
| @@ -352,7 +352,7 @@ static void close_func (LexState *ls) { | |||
| 352 | luaM_reallocvector(L, f->lineinfo, f->sizelineinfo, fs->nlineinfo+1, int); | 352 | luaM_reallocvector(L, f->lineinfo, f->sizelineinfo, fs->nlineinfo+1, int); |
| 353 | f->lineinfo[fs->nlineinfo++] = MAX_INT; /* end flag */ | 353 | f->lineinfo[fs->nlineinfo++] = MAX_INT; /* end flag */ |
| 354 | f->sizelineinfo = fs->nlineinfo; | 354 | f->sizelineinfo = fs->nlineinfo; |
| 355 | lua_assert(luaG_checkcode(f)); | 355 | lua_assert(luaG_checkcode(L, f)); |
| 356 | ls->fs = fs->prev; | 356 | ls->fs = fs->prev; |
| 357 | lua_assert(fs->bl == NULL); | 357 | lua_assert(fs->bl == NULL); |
| 358 | } | 358 | } |
| @@ -433,60 +433,6 @@ static void funcargs (LexState *ls, int slf) { | |||
| 433 | } | 433 | } |
| 434 | 434 | ||
| 435 | 435 | ||
| 436 | static void var_or_func_tail (LexState *ls, expdesc *v) { | ||
| 437 | for (;;) { | ||
| 438 | switch (ls->t.token) { | ||
| 439 | case '.': { /* var_or_func_tail -> '.' NAME */ | ||
| 440 | next(ls); | ||
| 441 | luaK_tostack(ls, v, 1); /* `v' must be on stack */ | ||
| 442 | luaK_kstr(ls, checkname(ls)); | ||
| 443 | v->k = VINDEXED; | ||
| 444 | break; | ||
| 445 | } | ||
| 446 | case '[': { /* var_or_func_tail -> '[' exp1 ']' */ | ||
| 447 | next(ls); | ||
| 448 | luaK_tostack(ls, v, 1); /* `v' must be on stack */ | ||
| 449 | v->k = VINDEXED; | ||
| 450 | exp1(ls); | ||
| 451 | check(ls, ']'); | ||
| 452 | break; | ||
| 453 | } | ||
| 454 | case ':': { /* var_or_func_tail -> ':' NAME funcargs */ | ||
| 455 | next(ls); | ||
| 456 | luaK_tostack(ls, v, 1); /* `v' must be on stack */ | ||
| 457 | luaK_code1(ls->fs, OP_PUSHSELF, checkname(ls)); | ||
| 458 | funcargs(ls, 1); | ||
| 459 | v->k = VEXP; | ||
| 460 | v->u.l.t = v->u.l.f = NO_JUMP; | ||
| 461 | break; | ||
| 462 | } | ||
| 463 | case '(': case TK_STRING: case '{': { /* var_or_func_tail -> funcargs */ | ||
| 464 | luaK_tostack(ls, v, 1); /* `v' must be on stack */ | ||
| 465 | funcargs(ls, 0); | ||
| 466 | v->k = VEXP; | ||
| 467 | v->u.l.t = v->u.l.f = NO_JUMP; | ||
| 468 | break; | ||
| 469 | } | ||
| 470 | default: return; /* should be follow... */ | ||
| 471 | } | ||
| 472 | } | ||
| 473 | } | ||
| 474 | |||
| 475 | |||
| 476 | static void var_or_func (LexState *ls, expdesc *v) { | ||
| 477 | /* var_or_func -> ['%'] NAME var_or_func_tail */ | ||
| 478 | if (optional(ls, '%')) { /* upvalue? */ | ||
| 479 | pushupvalue(ls, str_checkname(ls)); | ||
| 480 | v->k = VEXP; | ||
| 481 | v->u.l.t = v->u.l.f = NO_JUMP; | ||
| 482 | } | ||
| 483 | else /* variable name */ | ||
| 484 | singlevar(ls, str_checkname(ls), v); | ||
| 485 | var_or_func_tail(ls, v); | ||
| 486 | } | ||
| 487 | |||
| 488 | |||
| 489 | |||
| 490 | /* | 436 | /* |
| 491 | ** {====================================================================== | 437 | ** {====================================================================== |
| 492 | ** Rules for Constructors | 438 | ** Rules for Constructors |
| @@ -615,47 +561,51 @@ static void constructor (LexState *ls) { | |||
| 615 | ** ======================================================================= | 561 | ** ======================================================================= |
| 616 | */ | 562 | */ |
| 617 | 563 | ||
| 618 | 564 | static void primaryexp (LexState *ls, expdesc *v) { | |
| 619 | static void simpleexp (LexState *ls, expdesc *v) { | ||
| 620 | FuncState *fs = ls->fs; | 565 | FuncState *fs = ls->fs; |
| 621 | switch (ls->t.token) { | 566 | switch (ls->t.token) { |
| 622 | case TK_NUMBER: { /* simpleexp -> NUMBER */ | 567 | case TK_NUMBER: { |
| 623 | lua_Number r = ls->t.seminfo.r; | 568 | lua_Number r = ls->t.seminfo.r; |
| 624 | next(ls); | 569 | next(ls); |
| 625 | luaK_number(fs, r); | 570 | luaK_number(fs, r); |
| 626 | break; | 571 | break; |
| 627 | } | 572 | } |
| 628 | case TK_STRING: { /* simpleexp -> STRING */ | 573 | case TK_STRING: { |
| 629 | code_string(ls, ls->t.seminfo.ts); /* must use `seminfo' before `next' */ | 574 | code_string(ls, ls->t.seminfo.ts); /* must use `seminfo' before `next' */ |
| 630 | next(ls); | 575 | next(ls); |
| 631 | break; | 576 | break; |
| 632 | } | 577 | } |
| 633 | case TK_NIL: { /* simpleexp -> NIL */ | 578 | case TK_NIL: { |
| 634 | luaK_adjuststack(fs, -1); | 579 | luaK_adjuststack(fs, -1); |
| 635 | next(ls); | 580 | next(ls); |
| 636 | break; | 581 | break; |
| 637 | } | 582 | } |
| 638 | case '{': { /* simpleexp -> constructor */ | 583 | case '{': { /* constructor */ |
| 639 | constructor(ls); | 584 | constructor(ls); |
| 640 | break; | 585 | break; |
| 641 | } | 586 | } |
| 642 | case TK_FUNCTION: { /* simpleexp -> FUNCTION body */ | 587 | case TK_FUNCTION: { |
| 643 | next(ls); | 588 | next(ls); |
| 644 | body(ls, 0, ls->linenumber); | 589 | body(ls, 0, ls->linenumber); |
| 645 | break; | 590 | break; |
| 646 | } | 591 | } |
| 647 | case '(': { /* simpleexp -> '(' expr ')' */ | 592 | case '(': { |
| 648 | next(ls); | 593 | next(ls); |
| 649 | expr(ls, v); | 594 | expr(ls, v); |
| 650 | check(ls, ')'); | 595 | check(ls, ')'); |
| 651 | return; | 596 | return; |
| 652 | } | 597 | } |
| 653 | case TK_NAME: case '%': { | 598 | case TK_NAME: { |
| 654 | var_or_func(ls, v); | 599 | singlevar(ls, str_checkname(ls), v); |
| 655 | return; | 600 | return; |
| 656 | } | 601 | } |
| 602 | case '%': { | ||
| 603 | next(ls); /* skip `%' */ | ||
| 604 | pushupvalue(ls, str_checkname(ls)); | ||
| 605 | break; | ||
| 606 | } | ||
| 657 | default: { | 607 | default: { |
| 658 | luaK_error(ls, "<expression> expected"); | 608 | luaK_error(ls, "unexpected symbol"); |
| 659 | return; | 609 | return; |
| 660 | } | 610 | } |
| 661 | } | 611 | } |
| @@ -664,10 +614,46 @@ static void simpleexp (LexState *ls, expdesc *v) { | |||
| 664 | } | 614 | } |
| 665 | 615 | ||
| 666 | 616 | ||
| 667 | static void exp1 (LexState *ls) { | 617 | static void simpleexp (LexState *ls, expdesc *v) { |
| 668 | expdesc v; | 618 | /* simpleexp -> |
| 669 | expr(ls, &v); | 619 | primaryexp { '.' NAME | '[' exp ']' | ':' NAME funcargs | funcargs } */ |
| 670 | luaK_tostack(ls, &v, 1); | 620 | primaryexp(ls, v); |
| 621 | for (;;) { | ||
| 622 | switch (ls->t.token) { | ||
| 623 | case '.': { /* '.' NAME */ | ||
| 624 | next(ls); | ||
| 625 | luaK_tostack(ls, v, 1); /* `v' must be on stack */ | ||
| 626 | luaK_kstr(ls, checkname(ls)); | ||
| 627 | v->k = VINDEXED; | ||
| 628 | break; | ||
| 629 | } | ||
| 630 | case '[': { /* '[' exp1 ']' */ | ||
| 631 | next(ls); | ||
| 632 | luaK_tostack(ls, v, 1); /* `v' must be on stack */ | ||
| 633 | v->k = VINDEXED; | ||
| 634 | exp1(ls); | ||
| 635 | check(ls, ']'); | ||
| 636 | break; | ||
| 637 | } | ||
| 638 | case ':': { /* ':' NAME funcargs */ | ||
| 639 | next(ls); | ||
| 640 | luaK_tostack(ls, v, 1); /* `v' must be on stack */ | ||
| 641 | luaK_code1(ls->fs, OP_PUSHSELF, checkname(ls)); | ||
| 642 | funcargs(ls, 1); | ||
| 643 | v->k = VEXP; | ||
| 644 | v->u.l.t = v->u.l.f = NO_JUMP; | ||
| 645 | break; | ||
| 646 | } | ||
| 647 | case '(': case TK_STRING: case '{': { /* funcargs */ | ||
| 648 | luaK_tostack(ls, v, 1); /* `v' must be on stack */ | ||
| 649 | funcargs(ls, 0); | ||
| 650 | v->k = VEXP; | ||
| 651 | v->u.l.t = v->u.l.f = NO_JUMP; | ||
| 652 | break; | ||
| 653 | } | ||
| 654 | default: return; /* should be follow... */ | ||
| 655 | } | ||
| 656 | } | ||
| 671 | } | 657 | } |
| 672 | 658 | ||
| 673 | 659 | ||
| @@ -748,6 +734,13 @@ static void expr (LexState *ls, expdesc *v) { | |||
| 748 | subexpr(ls, v, -1); | 734 | subexpr(ls, v, -1); |
| 749 | } | 735 | } |
| 750 | 736 | ||
| 737 | |||
| 738 | static void exp1 (LexState *ls) { | ||
| 739 | expdesc v; | ||
| 740 | expr(ls, &v); | ||
| 741 | luaK_tostack(ls, &v, 1); | ||
| 742 | } | ||
| 743 | |||
| 751 | /* }==================================================================== */ | 744 | /* }==================================================================== */ |
| 752 | 745 | ||
| 753 | 746 | ||
| @@ -781,10 +774,10 @@ static void block (LexState *ls) { | |||
| 781 | static int assignment (LexState *ls, expdesc *v, int nvars) { | 774 | static int assignment (LexState *ls, expdesc *v, int nvars) { |
| 782 | int left = 0; /* number of values left in the stack after assignment */ | 775 | int left = 0; /* number of values left in the stack after assignment */ |
| 783 | luaX_checklimit(ls, nvars, MAXVARSLH, "variables in a multiple assignment"); | 776 | luaX_checklimit(ls, nvars, MAXVARSLH, "variables in a multiple assignment"); |
| 784 | if (ls->t.token == ',') { /* assignment -> ',' NAME assignment */ | 777 | if (ls->t.token == ',') { /* assignment -> ',' simpleexp assignment */ |
| 785 | expdesc nv; | 778 | expdesc nv; |
| 786 | next(ls); | 779 | next(ls); |
| 787 | var_or_func(ls, &nv); | 780 | simpleexp(ls, &nv); |
| 788 | check_condition(ls, (nv.k != VEXP), "syntax error"); | 781 | check_condition(ls, (nv.k != VEXP), "syntax error"); |
| 789 | left = assignment(ls, &nv, nvars+1); | 782 | left = assignment(ls, &nv, nvars+1); |
| 790 | } | 783 | } |
| @@ -998,15 +991,15 @@ static void funcstat (LexState *ls, int line) { | |||
| 998 | 991 | ||
| 999 | 992 | ||
| 1000 | static void namestat (LexState *ls) { | 993 | static void namestat (LexState *ls) { |
| 1001 | /* stat -> func | ['%'] NAME assignment */ | 994 | /* stat -> func | assignment */ |
| 1002 | FuncState *fs = ls->fs; | 995 | FuncState *fs = ls->fs; |
| 1003 | expdesc v; | 996 | expdesc v; |
| 1004 | var_or_func(ls, &v); | 997 | simpleexp(ls, &v); |
| 1005 | if (v.k == VEXP) { /* stat -> func */ | 998 | if (v.k == VEXP) { /* stat -> func */ |
| 1006 | check_condition(ls, luaK_lastisopen(fs), "syntax error"); /* an upvalue? */ | 999 | check_condition(ls, luaK_lastisopen(fs), "syntax error"); /* an upvalue? */ |
| 1007 | luaK_setcallreturns(fs, 0); /* call statement uses no results */ | 1000 | luaK_setcallreturns(fs, 0); /* call statement uses no results */ |
| 1008 | } | 1001 | } |
| 1009 | else { /* stat -> ['%'] NAME assignment */ | 1002 | else { /* stat -> assignment */ |
| 1010 | int left = assignment(ls, &v, 1); | 1003 | int left = assignment(ls, &v, 1); |
| 1011 | luaK_adjuststack(fs, left); /* remove eventual garbage left on stack */ | 1004 | luaK_adjuststack(fs, left); /* remove eventual garbage left on stack */ |
| 1012 | } | 1005 | } |
| @@ -1072,10 +1065,6 @@ static int stat (LexState *ls) { | |||
| 1072 | localstat(ls); | 1065 | localstat(ls); |
| 1073 | return 0; | 1066 | return 0; |
| 1074 | } | 1067 | } |
| 1075 | case TK_NAME: case '%': { /* stat -> namestat */ | ||
| 1076 | namestat(ls); | ||
| 1077 | return 0; | ||
| 1078 | } | ||
| 1079 | case TK_RETURN: { /* stat -> retstat */ | 1068 | case TK_RETURN: { /* stat -> retstat */ |
| 1080 | retstat(ls); | 1069 | retstat(ls); |
| 1081 | return 1; /* must be last statement */ | 1070 | return 1; /* must be last statement */ |
| @@ -1085,7 +1074,7 @@ static int stat (LexState *ls) { | |||
| 1085 | return 1; /* must be last statement */ | 1074 | return 1; /* must be last statement */ |
| 1086 | } | 1075 | } |
| 1087 | default: { | 1076 | default: { |
| 1088 | luaK_error(ls, "<statement> expected"); | 1077 | namestat(ls); |
| 1089 | return 0; /* to avoid warnings */ | 1078 | return 0; /* to avoid warnings */ |
| 1090 | } | 1079 | } |
| 1091 | } | 1080 | } |
