diff options
author | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2000-01-25 16:44:21 -0200 |
---|---|---|
committer | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2000-01-25 16:44:21 -0200 |
commit | d83c2a84550221c30a48647fde9c433c65af1802 (patch) | |
tree | ea525b29eaabb7cacd54bf7d42ab9e57533e4b5a /lparser.c | |
parent | d11e5adf55b11a446671775a6c7803e066fc94e8 (diff) | |
download | lua-d83c2a84550221c30a48647fde9c433c65af1802.tar.gz lua-d83c2a84550221c30a48647fde9c433c65af1802.tar.bz2 lua-d83c2a84550221c30a48647fde9c433c65af1802.zip |
performance details.
Diffstat (limited to 'lparser.c')
-rw-r--r-- | lparser.c | 87 |
1 files changed, 47 insertions, 40 deletions
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lparser.c,v 1.54 2000/01/12 16:24:39 roberto Exp roberto $ | 2 | ** $Id: lparser.c,v 1.55 2000/01/25 13:57:18 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 | */ |
@@ -119,11 +119,16 @@ static void exp1 (LexState *ls); | |||
119 | 119 | ||
120 | 120 | ||
121 | 121 | ||
122 | static void luaY_error (LexState *ls, const char *msg) { | ||
123 | luaX_error(ls, msg, ls->token); | ||
124 | } | ||
125 | |||
126 | |||
122 | static void checklimit (LexState *ls, int val, int limit, const char *msg) { | 127 | static void checklimit (LexState *ls, int val, int limit, const char *msg) { |
123 | if (val > limit) { | 128 | if (val > limit) { |
124 | char buff[100]; | 129 | char buff[100]; |
125 | sprintf(buff, "too many %.50s (limit=%d)", msg, limit); | 130 | sprintf(buff, "too many %.50s (limit=%d)", msg, limit); |
126 | luaX_error(ls, buff); | 131 | luaY_error(ls, buff); |
127 | } | 132 | } |
128 | } | 133 | } |
129 | 134 | ||
@@ -145,7 +150,7 @@ static void deltastack (LexState *ls, int delta) { | |||
145 | fs->stacksize += delta; | 150 | fs->stacksize += delta; |
146 | if (fs->stacksize > fs->maxstacksize) { | 151 | if (fs->stacksize > fs->maxstacksize) { |
147 | if (fs->stacksize > MAX_BYTE) | 152 | if (fs->stacksize > MAX_BYTE) |
148 | luaX_error(ls, "function/expression too complex"); | 153 | luaY_error(ls, "function/expression too complex"); |
149 | fs->maxstacksize = fs->stacksize; | 154 | fs->maxstacksize = fs->stacksize; |
150 | } | 155 | } |
151 | } | 156 | } |
@@ -160,7 +165,7 @@ static void code_oparg_at (LexState *ls, int pc, OpCode op, | |||
160 | code[pc+1] = (Byte)arg; | 165 | code[pc+1] = (Byte)arg; |
161 | } | 166 | } |
162 | else if (arg > MAX_ARG) | 167 | else if (arg > MAX_ARG) |
163 | luaX_error(ls, "code too long"); | 168 | luaY_error(ls, "code too long"); |
164 | else { /* MAX_BYTE < arg < MAX_ARG */ | 169 | else { /* MAX_BYTE < arg < MAX_ARG */ |
165 | if (arg > MAX_WORD) { | 170 | if (arg > MAX_WORD) { |
166 | code[pc] = (Byte)LONGARG; | 171 | code[pc] = (Byte)LONGARG; |
@@ -599,20 +604,6 @@ static void close_func (LexState *ls) { | |||
599 | } | 604 | } |
600 | 605 | ||
601 | 606 | ||
602 | |||
603 | static const int expfollow [] = {ELSE, ELSEIF, THEN, IF, WHILE, REPEAT, | ||
604 | DO, NAME, LOCAL, FUNCTION, END, UNTIL, RETURN, ')', ']', '}', ';', | ||
605 | EOS, ',', 0}; | ||
606 | |||
607 | |||
608 | static int is_in (int tok, const int *toks) { | ||
609 | const int *t; | ||
610 | for (t=toks; *t; t++) | ||
611 | if (*t == tok) return t-toks; | ||
612 | return -1; | ||
613 | } | ||
614 | |||
615 | |||
616 | static void next (LexState *ls) { | 607 | static void next (LexState *ls) { |
617 | ls->token = luaX_lex(ls); | 608 | ls->token = luaX_lex(ls); |
618 | } | 609 | } |
@@ -622,12 +613,12 @@ static void error_expected (LexState *ls, int token) { | |||
622 | char buff[100], t[TOKEN_LEN]; | 613 | char buff[100], t[TOKEN_LEN]; |
623 | luaX_token2str(token, t); | 614 | luaX_token2str(token, t); |
624 | sprintf(buff, "`%.20s' expected", t); | 615 | sprintf(buff, "`%.20s' expected", t); |
625 | luaX_error(ls, buff); | 616 | luaY_error(ls, buff); |
626 | } | 617 | } |
627 | 618 | ||
628 | 619 | ||
629 | static void error_unexpected (LexState *ls) { | 620 | static void error_unexpected (LexState *ls) { |
630 | luaX_error(ls, "unexpected token"); | 621 | luaY_error(ls, "unexpected token"); |
631 | } | 622 | } |
632 | 623 | ||
633 | 624 | ||
@@ -641,7 +632,7 @@ static void error_unmatched (LexState *ls, int what, int who, int where) { | |||
641 | luaX_token2str(who, t_who); | 632 | luaX_token2str(who, t_who); |
642 | sprintf(buff, "`%.20s' expected (to close `%.20s' at line %d)", | 633 | sprintf(buff, "`%.20s' expected (to close `%.20s' at line %d)", |
643 | t_what, t_who, where); | 634 | t_what, t_who, where); |
644 | luaX_error(ls, buff); | 635 | luaY_error(ls, buff); |
645 | } | 636 | } |
646 | } | 637 | } |
647 | 638 | ||
@@ -661,7 +652,7 @@ static void check_match (LexState *ls, int what, int who, int where) { | |||
661 | static int checkname (LexState *ls) { | 652 | static int checkname (LexState *ls) { |
662 | int sc; | 653 | int sc; |
663 | if (ls->token != NAME) | 654 | if (ls->token != NAME) |
664 | luaX_error(ls, "<name> expected"); | 655 | luaY_error(ls, "<name> expected"); |
665 | sc = string_constant(ls, ls->fs, ls->seminfo.ts); | 656 | sc = string_constant(ls, ls->fs, ls->seminfo.ts); |
666 | next(ls); | 657 | next(ls); |
667 | return sc; | 658 | return sc; |
@@ -691,7 +682,7 @@ TProtoFunc *luaY_parser (lua_State *L, ZIO *z) { | |||
691 | next(&lexstate); /* read first token */ | 682 | next(&lexstate); /* read first token */ |
692 | chunk(&lexstate); | 683 | chunk(&lexstate); |
693 | if (lexstate.token != EOS) | 684 | if (lexstate.token != EOS) |
694 | luaX_error(&lexstate, "<eof> expected"); | 685 | luaY_error(&lexstate, "<eof> expected"); |
695 | close_func(&lexstate); | 686 | close_func(&lexstate); |
696 | return funcstate.f; | 687 | return funcstate.f; |
697 | } | 688 | } |
@@ -782,7 +773,7 @@ static int funcparams (LexState *ls, int slf, vardesc *v) { | |||
782 | break; | 773 | break; |
783 | 774 | ||
784 | default: | 775 | default: |
785 | luaX_error(ls, "function arguments expected"); | 776 | luaY_error(ls, "function arguments expected"); |
786 | break; | 777 | break; |
787 | } | 778 | } |
788 | code_setname(ls, v); | 779 | code_setname(ls, v); |
@@ -871,7 +862,7 @@ static void recfield (LexState *ls) { | |||
871 | check(ls, ']'); | 862 | check(ls, ']'); |
872 | break; | 863 | break; |
873 | 864 | ||
874 | default: luaX_error(ls, "<name> or `[' expected"); | 865 | default: luaY_error(ls, "<name> or `[' expected"); |
875 | } | 866 | } |
876 | check(ls, '='); | 867 | check(ls, '='); |
877 | exp1(ls); | 868 | exp1(ls); |
@@ -977,7 +968,7 @@ static void constructor (LexState *ls) { | |||
977 | next(ls); | 968 | next(ls); |
978 | constructor_part(ls, &other_cd); | 969 | constructor_part(ls, &other_cd); |
979 | if (cd.k == other_cd.k) /* repeated parts? */ | 970 | if (cd.k == other_cd.k) /* repeated parts? */ |
980 | luaX_error(ls, "invalid constructor syntax"); | 971 | luaY_error(ls, "invalid constructor syntax"); |
981 | nelems += other_cd.n; | 972 | nelems += other_cd.n; |
982 | } | 973 | } |
983 | check_match(ls, '}', '{', line); | 974 | check_match(ls, '}', '{', line); |
@@ -992,8 +983,8 @@ static void constructor (LexState *ls) { | |||
992 | /* | 983 | /* |
993 | ** {====================================================================== | 984 | ** {====================================================================== |
994 | ** For parsing expressions, we use a classic stack with priorities. | 985 | ** For parsing expressions, we use a classic stack with priorities. |
995 | ** Each binary operator is represented by its index in `binop' + FIRSTBIN | 986 | ** Each binary operator is represented by an index: EQ=2, NE=3, ... '^'=13. |
996 | ** (EQ=2, NE=3, ... '^'=13). The unary NOT is 0 and UNMINUS is 1. | 987 | ** The unary NOT is 0 and UNMINUS is 1. |
997 | ** ======================================================================= | 988 | ** ======================================================================= |
998 | */ | 989 | */ |
999 | 990 | ||
@@ -1008,8 +999,6 @@ static void constructor (LexState *ls) { | |||
1008 | */ | 999 | */ |
1009 | #define POW 13 | 1000 | #define POW 13 |
1010 | 1001 | ||
1011 | static const int binop [] = {EQ, NE, '>', '<', LE, GE, CONC, | ||
1012 | '+', '-', '*', '/', '^', 0}; | ||
1013 | 1002 | ||
1014 | static const int priority [POW+1] = {5, 5, 1, 1, 1, 1, 1, 1, 2, 3, 3, 4, 4, 6}; | 1003 | static const int priority [POW+1] = {5, 5, 1, 1, 1, 1, 1, 1, 2, 3, 3, 4, 4, 6}; |
1015 | 1004 | ||
@@ -1024,10 +1013,31 @@ typedef struct stack_op { | |||
1024 | } stack_op; | 1013 | } stack_op; |
1025 | 1014 | ||
1026 | 1015 | ||
1016 | /* | ||
1017 | ** returns the index of a binary operator | ||
1018 | */ | ||
1019 | static int binop (int op) { | ||
1020 | switch (op) { | ||
1021 | case EQ: return FIRSTBIN; | ||
1022 | case NE: return FIRSTBIN+1; | ||
1023 | case '>': return FIRSTBIN+2; | ||
1024 | case '<': return FIRSTBIN+3; | ||
1025 | case LE: return FIRSTBIN+4; | ||
1026 | case GE: return FIRSTBIN+5; | ||
1027 | case CONC: return FIRSTBIN+6; | ||
1028 | case '+': return FIRSTBIN+7; | ||
1029 | case '-': return FIRSTBIN+8; | ||
1030 | case '*': return FIRSTBIN+9; | ||
1031 | case '/': return FIRSTBIN+10; | ||
1032 | case '^': return FIRSTBIN+11; | ||
1033 | default: return -1; | ||
1034 | } | ||
1035 | } | ||
1036 | |||
1027 | 1037 | ||
1028 | static void push (LexState *ls, stack_op *s, int op) { | 1038 | static void push (LexState *ls, stack_op *s, int op) { |
1029 | if (s->top >= MAXOPS) | 1039 | if (s->top >= MAXOPS) |
1030 | luaX_error(ls, "expression too complex"); | 1040 | luaY_error(ls, "expression too complex"); |
1031 | s->ops[s->top++] = op; | 1041 | s->ops[s->top++] = op; |
1032 | } | 1042 | } |
1033 | 1043 | ||
@@ -1086,7 +1096,7 @@ static void simpleexp (LexState *ls, vardesc *v, stack_op *s) { | |||
1086 | return; | 1096 | return; |
1087 | 1097 | ||
1088 | default: | 1098 | default: |
1089 | luaX_error(ls, "<expression> expected"); | 1099 | luaY_error(ls, "<expression> expected"); |
1090 | return; | 1100 | return; |
1091 | } | 1101 | } |
1092 | v->k = VEXP; v->info = 0; | 1102 | v->k = VEXP; v->info = 0; |
@@ -1108,8 +1118,7 @@ static void arith_exp (LexState *ls, vardesc *v) { | |||
1108 | int op; | 1118 | int op; |
1109 | s.top = 0; | 1119 | s.top = 0; |
1110 | prefixexp(ls, v, &s); | 1120 | prefixexp(ls, v, &s); |
1111 | while ((op = is_in(ls->token, binop)) >= 0) { | 1121 | while ((op = binop(ls->token)) >= 0) { |
1112 | op += FIRSTBIN; | ||
1113 | lua_pushvar(ls, v); | 1122 | lua_pushvar(ls, v); |
1114 | /* '^' is right associative, so must 'simulate' a higher priority */ | 1123 | /* '^' is right associative, so must 'simulate' a higher priority */ |
1115 | pop_to(ls, &s, (op == POW)?priority[op]+1:priority[op]); | 1124 | pop_to(ls, &s, (op == POW)?priority[op]+1:priority[op]); |
@@ -1129,8 +1138,6 @@ static void exp1 (LexState *ls) { | |||
1129 | vardesc v; | 1138 | vardesc v; |
1130 | expr(ls, &v); | 1139 | expr(ls, &v); |
1131 | lua_pushvar(ls, &v); | 1140 | lua_pushvar(ls, &v); |
1132 | if (is_in(ls->token, expfollow) < 0) | ||
1133 | luaX_error(ls, "malformed expression"); | ||
1134 | } | 1141 | } |
1135 | 1142 | ||
1136 | 1143 | ||
@@ -1180,7 +1187,7 @@ static int assignment (LexState *ls, vardesc *v, int nvars) { | |||
1180 | next(ls); | 1187 | next(ls); |
1181 | var_or_func(ls, &nv); | 1188 | var_or_func(ls, &nv); |
1182 | if (nv.k == VEXP) | 1189 | if (nv.k == VEXP) |
1183 | luaX_error(ls, "syntax error"); | 1190 | luaY_error(ls, "syntax error"); |
1184 | left = assignment(ls, &nv, nvars+1); | 1191 | left = assignment(ls, &nv, nvars+1); |
1185 | } | 1192 | } |
1186 | else { /* assignment -> '=' explist1 */ | 1193 | else { /* assignment -> '=' explist1 */ |
@@ -1313,7 +1320,7 @@ static void namestat (LexState *ls) { | |||
1313 | var_or_func(ls, &v); | 1320 | var_or_func(ls, &v); |
1314 | if (v.k == VEXP) { /* stat -> func */ | 1321 | if (v.k == VEXP) { /* stat -> func */ |
1315 | if (v.info == 0) /* is just an upper value? */ | 1322 | if (v.info == 0) /* is just an upper value? */ |
1316 | luaX_error(ls, "syntax error"); | 1323 | luaY_error(ls, "syntax error"); |
1317 | close_exp(ls, v.info, 0); | 1324 | close_exp(ls, v.info, 0); |
1318 | } | 1325 | } |
1319 | else { /* stat -> ['%'] NAME assignment */ | 1326 | else { /* stat -> ['%'] NAME assignment */ |
@@ -1410,14 +1417,14 @@ static void parlist (LexState *ls) { | |||
1410 | case NAME: /* tailparlist -> NAME [',' tailparlist] */ | 1417 | case NAME: /* tailparlist -> NAME [',' tailparlist] */ |
1411 | goto init; | 1418 | goto init; |
1412 | 1419 | ||
1413 | default: luaX_error(ls, "<name> or `...' expected"); | 1420 | default: luaY_error(ls, "<name> or `...' expected"); |
1414 | } | 1421 | } |
1415 | } | 1422 | } |
1416 | break; | 1423 | break; |
1417 | 1424 | ||
1418 | case ')': break; /* parlist -> empty */ | 1425 | case ')': break; /* parlist -> empty */ |
1419 | 1426 | ||
1420 | default: luaX_error(ls, "<name> or `...' expected"); | 1427 | default: luaY_error(ls, "<name> or `...' expected"); |
1421 | } | 1428 | } |
1422 | code_args(ls, nparams, dots); | 1429 | code_args(ls, nparams, dots); |
1423 | } | 1430 | } |