diff options
| -rw-r--r-- | lparser.c | 172 |
1 files changed, 96 insertions, 76 deletions
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | ** $Id: lparser.c,v 1.39 1999/08/16 20:52:00 roberto Exp roberto $ | 2 | ** $Id: lparser.c,v 1.40 1999/09/02 13:13:22 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 | */ |
| @@ -8,18 +8,15 @@ | |||
| 8 | #include <stdio.h> | 8 | #include <stdio.h> |
| 9 | #include <string.h> | 9 | #include <string.h> |
| 10 | 10 | ||
| 11 | #include "lauxlib.h" | ||
| 12 | #include "ldo.h" | 11 | #include "ldo.h" |
| 13 | #include "lfunc.h" | 12 | #include "lfunc.h" |
| 14 | #include "llex.h" | 13 | #include "llex.h" |
| 15 | #include "lmem.h" | 14 | #include "lmem.h" |
| 15 | #include "lobject.h" | ||
| 16 | #include "lopcodes.h" | 16 | #include "lopcodes.h" |
| 17 | #include "lparser.h" | 17 | #include "lparser.h" |
| 18 | #include "lstate.h" | 18 | #include "lstate.h" |
| 19 | #include "lstring.h" | 19 | #include "lstring.h" |
| 20 | #include "lua.h" | ||
| 21 | #include "luadebug.h" | ||
| 22 | #include "lzio.h" | ||
| 23 | 20 | ||
| 24 | 21 | ||
| 25 | 22 | ||
| @@ -136,7 +133,6 @@ static void parlist (LexState *ls); | |||
| 136 | static void part (LexState *ls, constdesc *cd); | 133 | static void part (LexState *ls, constdesc *cd); |
| 137 | static void recfield (LexState *ls); | 134 | static void recfield (LexState *ls); |
| 138 | static void ret (LexState *ls); | 135 | static void ret (LexState *ls); |
| 139 | static void statlist (LexState *ls); | ||
| 140 | static void var_or_func (LexState *ls, vardesc *v); | 136 | static void var_or_func (LexState *ls, vardesc *v); |
| 141 | static void var_or_func_tail (LexState *ls, vardesc *v); | 137 | static void var_or_func_tail (LexState *ls, vardesc *v); |
| 142 | 138 | ||
| @@ -699,46 +695,108 @@ TProtoFunc *luaY_parser (ZIO *z) { | |||
| 699 | /* GRAMAR RULES */ | 695 | /* GRAMAR RULES */ |
| 700 | /*============================================================*/ | 696 | /*============================================================*/ |
| 701 | 697 | ||
| 702 | static void chunk (LexState *ls) { | ||
| 703 | /* chunk -> statlist ret */ | ||
| 704 | statlist(ls); | ||
| 705 | ret(ls); | ||
| 706 | } | ||
| 707 | 698 | ||
| 708 | static void statlist (LexState *ls) { | 699 | static void chunk (LexState *ls) { |
| 709 | /* statlist -> { stat [;] } */ | 700 | /* chunk -> { stat [;] } ret */ |
| 710 | while (stat(ls)) { | 701 | while (stat(ls)) { |
| 711 | LUA_ASSERT(ls->fs->stacksize == ls->fs->nlocalvar, | 702 | LUA_ASSERT(ls->fs->stacksize == ls->fs->nlocalvar, |
| 712 | "stack size != # local vars"); | 703 | "stack size != # local vars"); |
| 713 | optional(ls, ';'); | 704 | optional(ls, ';'); |
| 714 | } | 705 | } |
| 706 | ret(ls); /* optional return */ | ||
| 707 | } | ||
| 708 | |||
| 709 | |||
| 710 | static void whilestat (LexState *ls, int line) { | ||
| 711 | /* whilestat -> WHILE cond DO block END */ | ||
| 712 | FuncState *fs = ls->fs; | ||
| 713 | TProtoFunc *f = fs->f; | ||
| 714 | int while_init = fs->pc; | ||
| 715 | int cond_end, cond_size; | ||
| 716 | next(ls); | ||
| 717 | cond_end = cond(ls); | ||
| 718 | check(ls, DO); | ||
| 719 | block(ls); | ||
| 720 | check_match(ls, END, WHILE, line); | ||
| 721 | cond_size = cond_end-while_init; | ||
| 722 | check_pc(fs, cond_size); | ||
| 723 | memcpy(f->code+fs->pc, f->code+while_init, cond_size); | ||
| 724 | luaO_memdown(f->code+while_init, f->code+cond_end, fs->pc-while_init); | ||
| 725 | while_init += JMPSIZE + fix_jump(ls, while_init, JMP, fs->pc-cond_size); | ||
| 726 | fix_upjmp(ls, IFTUPJMP, while_init); | ||
| 727 | } | ||
| 728 | |||
| 729 | |||
| 730 | static void repeatstat (LexState *ls, int line) { | ||
| 731 | /* repeatstat -> REPEAT block UNTIL exp1 */ | ||
| 732 | FuncState *fs = ls->fs; | ||
| 733 | int repeat_init = fs->pc; | ||
| 734 | next(ls); | ||
| 735 | block(ls); | ||
| 736 | check_match(ls, UNTIL, REPEAT, line); | ||
| 737 | exp1(ls); | ||
| 738 | fix_upjmp(ls, IFFUPJMP, repeat_init); | ||
| 739 | deltastack(ls, -1); /* pops condition */ | ||
| 740 | } | ||
| 741 | |||
| 742 | |||
| 743 | static void localstat (LexState *ls) { | ||
| 744 | /* stat -> LOCAL localnamelist decinit */ | ||
| 745 | FuncState *fs = ls->fs; | ||
| 746 | listdesc d; | ||
| 747 | int nvars; | ||
| 748 | check_debugline(ls); | ||
| 749 | next(ls); | ||
| 750 | nvars = localnamelist(ls); | ||
| 751 | decinit(ls, &d); | ||
| 752 | fs->nlocalvar += nvars; | ||
| 753 | correctvarlines(ls, nvars); /* vars will be alive only after decinit */ | ||
| 754 | adjust_mult_assign(ls, nvars, &d); | ||
| 755 | } | ||
| 756 | |||
| 757 | |||
| 758 | static int funcstat (LexState *ls, int line) { | ||
| 759 | /* funcstat -> FUNCTION funcname body */ | ||
| 760 | int needself; | ||
| 761 | vardesc v; | ||
| 762 | if (ls->fs->prev) /* inside other function? */ | ||
| 763 | return 0; | ||
| 764 | check_debugline(ls); | ||
| 765 | next(ls); | ||
| 766 | needself = funcname(ls, &v); | ||
| 767 | body(ls, needself, line); | ||
| 768 | storevar(ls, &v); | ||
| 769 | return 1; | ||
| 770 | } | ||
| 771 | |||
| 772 | |||
| 773 | static void namestat (LexState *ls) { | ||
| 774 | /* stat -> func | ['%'] NAME assignment */ | ||
| 775 | vardesc v; | ||
| 776 | check_debugline(ls); | ||
| 777 | var_or_func(ls, &v); | ||
| 778 | if (v.k == VEXP) { /* stat -> func */ | ||
| 779 | if (v.info == 0) /* is just an upper value? */ | ||
| 780 | luaX_error(ls, "syntax error"); | ||
| 781 | close_exp(ls, v.info, 0); | ||
| 782 | } | ||
| 783 | else { /* stat -> ['%'] NAME assignment */ | ||
| 784 | int left = assignment(ls, &v, 1); | ||
| 785 | adjuststack(ls, left); /* remove eventual garbage left on stack */ | ||
| 786 | } | ||
| 715 | } | 787 | } |
| 716 | 788 | ||
| 789 | |||
| 717 | static int stat (LexState *ls) { | 790 | static int stat (LexState *ls) { |
| 718 | int line = ls->linenumber; /* may be needed for error messages */ | 791 | int line = ls->linenumber; /* may be needed for error messages */ |
| 719 | FuncState *fs = ls->fs; | ||
| 720 | switch (ls->token) { | 792 | switch (ls->token) { |
| 721 | case IF: /* stat -> IF ifpart END */ | 793 | case IF: /* stat -> IF ifpart END */ |
| 722 | ifpart(ls, line); | 794 | ifpart(ls, line); |
| 723 | return 1; | 795 | return 1; |
| 724 | 796 | ||
| 725 | case WHILE: { /* stat -> WHILE cond DO block END */ | 797 | case WHILE: /* stat -> whilestat */ |
| 726 | TProtoFunc *f = fs->f; | 798 | whilestat(ls, line); |
| 727 | int while_init = fs->pc; | ||
| 728 | int cond_end, cond_size; | ||
| 729 | next(ls); | ||
| 730 | cond_end = cond(ls); | ||
| 731 | check(ls, DO); | ||
| 732 | block(ls); | ||
| 733 | check_match(ls, END, WHILE, line); | ||
| 734 | cond_size = cond_end-while_init; | ||
| 735 | check_pc(fs, cond_size); | ||
| 736 | memcpy(f->code+fs->pc, f->code+while_init, cond_size); | ||
| 737 | luaO_memdown(f->code+while_init, f->code+cond_end, fs->pc-while_init); | ||
| 738 | while_init += JMPSIZE + fix_jump(ls, while_init, JMP, fs->pc-cond_size); | ||
| 739 | fix_upjmp(ls, IFTUPJMP, while_init); | ||
| 740 | return 1; | 799 | return 1; |
| 741 | } | ||
| 742 | 800 | ||
| 743 | case DO: { /* stat -> DO block END */ | 801 | case DO: { /* stat -> DO block END */ |
| 744 | next(ls); | 802 | next(ls); |
| @@ -747,58 +805,20 @@ static int stat (LexState *ls) { | |||
| 747 | return 1; | 805 | return 1; |
| 748 | } | 806 | } |
| 749 | 807 | ||
| 750 | case REPEAT: { /* stat -> REPEAT block UNTIL exp1 */ | 808 | case REPEAT: /* stat -> repeatstat */ |
| 751 | int repeat_init = fs->pc; | 809 | repeatstat(ls, line); |
| 752 | next(ls); | ||
| 753 | block(ls); | ||
| 754 | check_match(ls, UNTIL, REPEAT, line); | ||
| 755 | exp1(ls); | ||
| 756 | fix_upjmp(ls, IFFUPJMP, repeat_init); | ||
| 757 | deltastack(ls, -1); /* pops condition */ | ||
| 758 | return 1; | 810 | return 1; |
| 759 | } | ||
| 760 | 811 | ||
| 761 | case FUNCTION: { /* stat -> FUNCTION funcname body */ | 812 | case FUNCTION: /* stat -> funcstat */ |
| 762 | int needself; | 813 | return funcstat(ls, line); |
| 763 | vardesc v; | ||
| 764 | if (ls->fs->prev) /* inside other function? */ | ||
| 765 | return 0; | ||
| 766 | check_debugline(ls); | ||
| 767 | next(ls); | ||
| 768 | needself = funcname(ls, &v); | ||
| 769 | body(ls, needself, line); | ||
| 770 | storevar(ls, &v); | ||
| 771 | return 1; | ||
| 772 | } | ||
| 773 | 814 | ||
| 774 | case LOCAL: { /* stat -> LOCAL localnamelist decinit */ | 815 | case LOCAL: /* stat -> localstat */ |
| 775 | listdesc d; | 816 | localstat(ls); |
| 776 | int nvars; | ||
| 777 | check_debugline(ls); | ||
| 778 | next(ls); | ||
| 779 | nvars = localnamelist(ls); | ||
| 780 | decinit(ls, &d); | ||
| 781 | fs->nlocalvar += nvars; | ||
| 782 | correctvarlines(ls, nvars); /* vars will be alive only after decinit */ | ||
| 783 | adjust_mult_assign(ls, nvars, &d); | ||
| 784 | return 1; | 817 | return 1; |
| 785 | } | ||
| 786 | 818 | ||
| 787 | case NAME: case '%': { /* stat -> func | ['%'] NAME assignment */ | 819 | case NAME: case '%': /* stat -> namestat */ |
| 788 | vardesc v; | 820 | namestat(ls); |
| 789 | check_debugline(ls); | ||
| 790 | var_or_func(ls, &v); | ||
| 791 | if (v.k == VEXP) { /* stat -> func */ | ||
| 792 | if (v.info == 0) /* is just an upper value? */ | ||
| 793 | luaX_error(ls, "syntax error"); | ||
| 794 | close_exp(ls, v.info, 0); | ||
| 795 | } | ||
| 796 | else { /* stat -> ['%'] NAME assignment */ | ||
| 797 | int left = assignment(ls, &v, 1); | ||
| 798 | adjuststack(ls, left); /* remove eventual garbage left on stack */ | ||
| 799 | } | ||
| 800 | return 1; | 821 | return 1; |
| 801 | } | ||
| 802 | 822 | ||
| 803 | case RETURN: case ';': case ELSE: case ELSEIF: | 823 | case RETURN: case ';': case ELSE: case ELSEIF: |
| 804 | case END: case UNTIL: case EOS: /* 'stat' follow */ | 824 | case END: case UNTIL: case EOS: /* 'stat' follow */ |
