diff options
Diffstat (limited to 'lparser.c')
-rw-r--r-- | lparser.c | 169 |
1 files changed, 112 insertions, 57 deletions
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lparser.c,v 1.74 2000/03/29 20:19:20 roberto Exp roberto $ | 2 | ** $Id: lparser.c,v 1.75 2000/04/03 13:44:55 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 | */ |
@@ -28,10 +28,17 @@ | |||
28 | ** it is a list constructor (k = 0) or a record constructor (k = 1) | 28 | ** it is a list constructor (k = 0) or a record constructor (k = 1) |
29 | ** or empty (k = ';' or '}') | 29 | ** or empty (k = ';' or '}') |
30 | */ | 30 | */ |
31 | typedef struct constdesc { | 31 | typedef struct Constdesc { |
32 | int n; | 32 | int n; |
33 | int k; | 33 | int k; |
34 | } constdesc; | 34 | } Constdesc; |
35 | |||
36 | |||
37 | typedef struct Breaklabel { | ||
38 | struct Breaklabel *previous; /* chain */ | ||
39 | int breaklist; | ||
40 | int stacklevel; | ||
41 | } Breaklabel; | ||
35 | 42 | ||
36 | 43 | ||
37 | 44 | ||
@@ -311,6 +318,21 @@ static int getvarname (LexState *ls, expdesc *var) { | |||
311 | } | 318 | } |
312 | 319 | ||
313 | 320 | ||
321 | static void enterbreak (FuncState *fs, Breaklabel *bl) { | ||
322 | bl->stacklevel = fs->stacklevel; | ||
323 | bl->breaklist = NO_JUMP; | ||
324 | bl->previous = fs->bl; | ||
325 | fs->bl = bl; | ||
326 | } | ||
327 | |||
328 | |||
329 | static void leavebreak (FuncState *fs, Breaklabel *bl) { | ||
330 | fs->bl = bl->previous; | ||
331 | LUA_ASSERT(fs->L, bl->stacklevel == fs->stacklevel, "wrong levels"); | ||
332 | luaK_patchlist(fs, bl->breaklist, luaK_getlabel(fs)); | ||
333 | } | ||
334 | |||
335 | |||
314 | static void func_onstack (LexState *ls, FuncState *func) { | 336 | static void func_onstack (LexState *ls, FuncState *func) { |
315 | FuncState *fs = ls->fs; | 337 | FuncState *fs = ls->fs; |
316 | Proto *f = fs->f; | 338 | Proto *f = fs->f; |
@@ -332,10 +354,11 @@ static void init_state (LexState *ls, FuncState *fs, TString *source) { | |||
332 | fs->ls = ls; | 354 | fs->ls = ls; |
333 | fs->L = ls->L; | 355 | fs->L = ls->L; |
334 | ls->fs = fs; | 356 | ls->fs = fs; |
335 | fs->stacksize = 0; | 357 | fs->stacklevel = 0; |
336 | fs->nlocalvar = 0; | 358 | fs->nlocalvar = 0; |
337 | fs->nupvalues = 0; | 359 | fs->nupvalues = 0; |
338 | fs->lastsetline = 0; | 360 | fs->lastsetline = 0; |
361 | fs->bl = NULL; | ||
339 | fs->f = f; | 362 | fs->f = f; |
340 | f->source = source; | 363 | f->source = source; |
341 | fs->pc = 0; | 364 | fs->pc = 0; |
@@ -362,6 +385,7 @@ static void close_func (LexState *ls) { | |||
362 | luaM_reallocvector(L, f->locvars, fs->nvars, LocVar); | 385 | luaM_reallocvector(L, f->locvars, fs->nvars, LocVar); |
363 | } | 386 | } |
364 | ls->fs = fs->prev; | 387 | ls->fs = fs->prev; |
388 | LUA_ASSERT(L, fs->bl == NULL, "wrong list end"); | ||
365 | } | 389 | } |
366 | 390 | ||
367 | 391 | ||
@@ -375,6 +399,7 @@ Proto *luaY_parser (lua_State *L, ZIO *z) { | |||
375 | if (lexstate.token != TK_EOS) | 399 | if (lexstate.token != TK_EOS) |
376 | luaK_error(&lexstate, "<eof> expected"); | 400 | luaK_error(&lexstate, "<eof> expected"); |
377 | close_func(&lexstate); | 401 | close_func(&lexstate); |
402 | LUA_ASSERT(L, funcstate.prev == NULL, "wrong list end"); | ||
378 | return funcstate.f; | 403 | return funcstate.f; |
379 | } | 404 | } |
380 | 405 | ||
@@ -416,7 +441,7 @@ static int explist (LexState *ls) { | |||
416 | 441 | ||
417 | static void funcargs (LexState *ls, int slf) { | 442 | static void funcargs (LexState *ls, int slf) { |
418 | FuncState *fs = ls->fs; | 443 | FuncState *fs = ls->fs; |
419 | int slevel = fs->stacksize - slf - 1; /* where is func in the stack */ | 444 | int slevel = fs->stacklevel - slf - 1; /* where is func in the stack */ |
420 | switch (ls->token) { | 445 | switch (ls->token) { |
421 | case '(': { /* funcargs -> '(' explist ')' */ | 446 | case '(': { /* funcargs -> '(' explist ')' */ |
422 | int line = ls->linenumber; | 447 | int line = ls->linenumber; |
@@ -444,7 +469,7 @@ static void funcargs (LexState *ls, int slf) { | |||
444 | luaK_error(ls, "function arguments expected"); | 469 | luaK_error(ls, "function arguments expected"); |
445 | break; | 470 | break; |
446 | } | 471 | } |
447 | fs->stacksize = slevel; /* call will remove function and arguments */ | 472 | fs->stacklevel = slevel; /* call will remove function and arguments */ |
448 | luaK_AB(fs, OP_CALL, slevel, MULT_RET, 0); | 473 | luaK_AB(fs, OP_CALL, slevel, MULT_RET, 0); |
449 | } | 474 | } |
450 | 475 | ||
@@ -581,7 +606,7 @@ static int listfields (LexState *ls) { | |||
581 | 606 | ||
582 | 607 | ||
583 | 608 | ||
584 | static void constructor_part (LexState *ls, constdesc *cd) { | 609 | static void constructor_part (LexState *ls, Constdesc *cd) { |
585 | switch (ls->token) { | 610 | switch (ls->token) { |
586 | case ';': case '}': /* constructor_part -> empty */ | 611 | case ';': case '}': /* constructor_part -> empty */ |
587 | cd->n = 0; | 612 | cd->n = 0; |
@@ -627,12 +652,12 @@ static void constructor (LexState *ls) { | |||
627 | int line = ls->linenumber; | 652 | int line = ls->linenumber; |
628 | int pc = luaK_U(fs, OP_CREATETABLE, 0, 1); | 653 | int pc = luaK_U(fs, OP_CREATETABLE, 0, 1); |
629 | int nelems; | 654 | int nelems; |
630 | constdesc cd; | 655 | Constdesc cd; |
631 | check(ls, '{'); | 656 | check(ls, '{'); |
632 | constructor_part(ls, &cd); | 657 | constructor_part(ls, &cd); |
633 | nelems = cd.n; | 658 | nelems = cd.n; |
634 | if (ls->token == ';') { | 659 | if (ls->token == ';') { |
635 | constdesc other_cd; | 660 | Constdesc other_cd; |
636 | next(ls); | 661 | next(ls); |
637 | constructor_part(ls, &other_cd); | 662 | constructor_part(ls, &other_cd); |
638 | if (cd.k == other_cd.k) /* repeated parts? */ | 663 | if (cd.k == other_cd.k) /* repeated parts? */ |
@@ -825,14 +850,17 @@ static void whilestat (LexState *ls, int line) { | |||
825 | FuncState *fs = ls->fs; | 850 | FuncState *fs = ls->fs; |
826 | int while_init = luaK_getlabel(fs); | 851 | int while_init = luaK_getlabel(fs); |
827 | expdesc v; | 852 | expdesc v; |
853 | Breaklabel bl; | ||
854 | enterbreak(fs, &bl); | ||
828 | setline_and_next(ls); /* trace WHILE when looping */ | 855 | setline_and_next(ls); /* trace WHILE when looping */ |
829 | expr(ls, &v); /* read condition */ | 856 | expr(ls, &v); /* read condition */ |
830 | luaK_goiftrue(fs, &v, 0); | 857 | luaK_goiftrue(fs, &v, 0); |
831 | check(ls, TK_DO); | 858 | check(ls, TK_DO); |
832 | block(ls); | 859 | block(ls); |
833 | luaK_fixjump(fs, luaK_S(fs, OP_JMP, 0, 0), while_init); | 860 | luaK_patchlist(fs, luaK_jump(fs), while_init); |
834 | luaK_patchlist(fs, v.u.l.f, luaK_getlabel(fs)); | 861 | luaK_patchlist(fs, v.u.l.f, luaK_getlabel(fs)); |
835 | check_END(ls, TK_WHILE, line); | 862 | check_END(ls, TK_WHILE, line); |
863 | leavebreak(fs, &bl); | ||
836 | } | 864 | } |
837 | 865 | ||
838 | 866 | ||
@@ -841,12 +869,55 @@ static void repeatstat (LexState *ls, int line) { | |||
841 | FuncState *fs = ls->fs; | 869 | FuncState *fs = ls->fs; |
842 | int repeat_init = luaK_getlabel(fs); | 870 | int repeat_init = luaK_getlabel(fs); |
843 | expdesc v; | 871 | expdesc v; |
872 | Breaklabel bl; | ||
873 | enterbreak(fs, &bl); | ||
844 | setline_and_next(ls); /* trace REPEAT when looping */ | 874 | setline_and_next(ls); /* trace REPEAT when looping */ |
845 | block(ls); | 875 | block(ls); |
846 | check_match(ls, TK_UNTIL, TK_REPEAT, line); | 876 | if (ls->token == TK_END) { |
847 | expr(ls, &v); | 877 | luaK_patchlist(fs, luaK_jump(fs), repeat_init); |
848 | luaK_goiftrue(fs, &v, 0); | 878 | next(ls); |
849 | luaK_patchlist(fs, v.u.l.f, repeat_init); | 879 | } |
880 | else { | ||
881 | check_match(ls, TK_UNTIL, TK_REPEAT, line); | ||
882 | expr(ls, &v); | ||
883 | luaK_goiftrue(fs, &v, 0); | ||
884 | luaK_patchlist(fs, v.u.l.f, repeat_init); | ||
885 | } | ||
886 | leavebreak(fs, &bl); | ||
887 | } | ||
888 | |||
889 | |||
890 | static void test_and_bock (LexState *ls, expdesc *v) { | ||
891 | setline_and_next(ls); /* skip IF or ELSEIF */ | ||
892 | expr(ls, v); /* cond */ | ||
893 | luaK_goiftrue(ls->fs, v, 0); | ||
894 | setline(ls); /* to trace the THEN */ | ||
895 | check(ls, TK_THEN); | ||
896 | block(ls); /* `then' part */ | ||
897 | } | ||
898 | |||
899 | |||
900 | static void ifstat (LexState *ls, int line) { | ||
901 | /* ifstat -> IF cond THEN block {ELSEIF cond THEN block} [ELSE block] END */ | ||
902 | FuncState *fs = ls->fs; | ||
903 | expdesc v; | ||
904 | int escapelist = NO_JUMP; | ||
905 | test_and_bock(ls, &v); /* IF cond THEN block */ | ||
906 | while (ls->token == TK_ELSEIF) { | ||
907 | luaK_concat(fs, &escapelist, luaK_jump(fs)); | ||
908 | luaK_patchlist(fs, v.u.l.f, luaK_getlabel(fs)); | ||
909 | test_and_bock(ls, &v); /* ELSEIF cond THEN block */ | ||
910 | } | ||
911 | if (ls->token == TK_ELSE) { | ||
912 | luaK_concat(fs, &escapelist, luaK_jump(fs)); | ||
913 | luaK_patchlist(fs, v.u.l.f, luaK_getlabel(fs)); | ||
914 | setline_and_next(ls); /* skip ELSE */ | ||
915 | block(ls); /* `else' part */ | ||
916 | } | ||
917 | else | ||
918 | luaK_concat(fs, &escapelist, v.u.l.f); | ||
919 | luaK_patchlist(fs, escapelist, luaK_getlabel(fs)); | ||
920 | check_END(ls, TK_IF, line); | ||
850 | } | 921 | } |
851 | 922 | ||
852 | 923 | ||
@@ -932,42 +1003,11 @@ static void namestat (LexState *ls) { | |||
932 | } | 1003 | } |
933 | 1004 | ||
934 | 1005 | ||
935 | static void ifpart (LexState *ls) { | ||
936 | /* ifpart -> cond THEN block (ELSEIF ifpart | [ELSE block] END) */ | ||
937 | FuncState *fs = ls->fs; | ||
938 | expdesc v; | ||
939 | int elseinit; | ||
940 | setline_and_next(ls); /* skip IF or ELSEIF */ | ||
941 | expr(ls, &v); /* cond */ | ||
942 | luaK_goiftrue(fs, &v, 0); | ||
943 | setline(ls); /* to trace the THEN */ | ||
944 | check(ls, TK_THEN); | ||
945 | block(ls); /* `then' part */ | ||
946 | luaK_S(fs, OP_JMP, 0, 0); /* 2nd jump: over `else' part */ | ||
947 | elseinit = luaK_getlabel(fs); /* address of 2nd jump == elseinit-1 */ | ||
948 | if (ls->token == TK_ELSEIF) | ||
949 | ifpart(ls); | ||
950 | else if (ls->token == TK_ELSE) { | ||
951 | setline_and_next(ls); /* skip ELSE */ | ||
952 | block(ls); /* `else' part */ | ||
953 | } | ||
954 | if (fs->pc > elseinit) { /* is there an `else' part? */ | ||
955 | luaK_fixjump(fs, elseinit-1, luaK_getlabel(fs)); /* fix 2nd jump */ | ||
956 | } | ||
957 | else { /* no else part */ | ||
958 | fs->pc--; /* remove 2nd jump */ | ||
959 | elseinit = luaK_getlabel(fs); /* `elseinit' points to end */ | ||
960 | } | ||
961 | luaK_patchlist(fs, v.u.l.f, elseinit); /* fix 1st jump to `else' part */ | ||
962 | } | ||
963 | |||
964 | |||
965 | static int stat (LexState *ls) { | 1006 | static int stat (LexState *ls) { |
966 | int line = ls->linenumber; /* may be needed for error messages */ | 1007 | int line = ls->linenumber; /* may be needed for error messages */ |
967 | switch (ls->token) { | 1008 | switch (ls->token) { |
968 | case TK_IF: /* stat -> IF ifpart END */ | 1009 | case TK_IF: /* stat -> ifstat */ |
969 | ifpart(ls); | 1010 | ifstat(ls, line); |
970 | check_END(ls, TK_IF, line); | ||
971 | break; | 1011 | break; |
972 | 1012 | ||
973 | case TK_WHILE: /* stat -> whilestat */ | 1013 | case TK_WHILE: /* stat -> whilestat */ |
@@ -1058,15 +1098,30 @@ static void body (LexState *ls, int needself, int line) { | |||
1058 | 1098 | ||
1059 | 1099 | ||
1060 | static void ret (LexState *ls) { | 1100 | static void ret (LexState *ls) { |
1061 | /* ret -> [RETURN explist sc] */ | 1101 | /* ret -> [RETURN explist sc | BREAK sc] */ |
1062 | if (ls->token == TK_RETURN) { | 1102 | FuncState *fs = ls->fs; |
1063 | FuncState *fs = ls->fs; | 1103 | switch (ls->token) { |
1064 | int nexps; /* number of expressions returned */ | 1104 | case TK_RETURN: { |
1065 | setline_and_next(ls); /* skip RETURN */ | 1105 | int nexps; /* number of expressions returned */ |
1066 | nexps = explist(ls); | 1106 | setline_and_next(ls); /* skip RETURN */ |
1067 | luaK_retcode(fs, ls->fs->nlocalvar, nexps); | 1107 | nexps = explist(ls); |
1068 | fs->stacksize = fs->nlocalvar; /* removes all temp values */ | 1108 | luaK_retcode(fs, ls->fs->nlocalvar, nexps); |
1069 | optional(ls, ';'); | 1109 | fs->stacklevel = fs->nlocalvar; /* removes all temp values */ |
1110 | optional(ls, ';'); | ||
1111 | break; | ||
1112 | } | ||
1113 | case TK_BREAK: { | ||
1114 | Breaklabel *bl = fs->bl; | ||
1115 | int currentlevel = fs->stacklevel; | ||
1116 | if (bl == NULL) | ||
1117 | luaK_error(ls, "no breakable structure to break"); | ||
1118 | setline_and_next(ls); /* skip BREAK */ | ||
1119 | luaK_adjuststack(fs, currentlevel - bl->stacklevel); | ||
1120 | luaK_concat(fs, &bl->breaklist, luaK_jump(fs)); | ||
1121 | optional(ls, ';'); | ||
1122 | fs->stacklevel = currentlevel; | ||
1123 | break; | ||
1124 | } | ||
1070 | } | 1125 | } |
1071 | } | 1126 | } |
1072 | 1127 | ||
@@ -1076,7 +1131,7 @@ static void ret (LexState *ls) { | |||
1076 | static void chunk (LexState *ls) { | 1131 | static void chunk (LexState *ls) { |
1077 | /* chunk -> { stat [;] } ret */ | 1132 | /* chunk -> { stat [;] } ret */ |
1078 | while (stat(ls)) { | 1133 | while (stat(ls)) { |
1079 | LUA_ASSERT(ls->L, ls->fs->stacksize == ls->fs->nlocalvar, | 1134 | LUA_ASSERT(ls->L, ls->fs->stacklevel == ls->fs->nlocalvar, |
1080 | "stack size != # local vars"); | 1135 | "stack size != # local vars"); |
1081 | optional(ls, ';'); | 1136 | optional(ls, ';'); |
1082 | } | 1137 | } |