diff options
author | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 1999-01-29 11:48:58 -0200 |
---|---|---|
committer | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 1999-01-29 11:48:58 -0200 |
commit | 68267ed878a2ea668aa97b40c5d9cacbe0e57831 (patch) | |
tree | 5cc3b833ef1561482818b51131f5510c1b15d5b0 /lparser.c | |
parent | fd25d4ad85302a84551ac6ed915435c035a978e4 (diff) | |
download | lua-68267ed878a2ea668aa97b40c5d9cacbe0e57831.tar.gz lua-68267ed878a2ea668aa97b40c5d9cacbe0e57831.tar.bz2 lua-68267ed878a2ea668aa97b40c5d9cacbe0e57831.zip |
negative numerals do not need a MINUSOPeration; go directly to contant
table.
Diffstat (limited to 'lparser.c')
-rw-r--r-- | lparser.c | 95 |
1 files changed, 51 insertions, 44 deletions
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lparser.c,v 1.8 1999/01/15 11:38:33 roberto Exp roberto $ | 2 | ** $Id: lparser.c,v 1.9 1999/01/21 18:38:39 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 | */ |
@@ -123,7 +123,6 @@ static void parlist (LexState *ls); | |||
123 | static void part (LexState *ls, constdesc *cd); | 123 | static void part (LexState *ls, constdesc *cd); |
124 | static void recfield (LexState *ls); | 124 | static void recfield (LexState *ls); |
125 | static void ret (LexState *ls); | 125 | static void ret (LexState *ls); |
126 | static void simpleexp (LexState *ls, vardesc *v); | ||
127 | static void statlist (LexState *ls); | 126 | static void statlist (LexState *ls); |
128 | static void var_or_func (LexState *ls, vardesc *v); | 127 | static void var_or_func (LexState *ls, vardesc *v); |
129 | static void var_or_func_tail (LexState *ls, vardesc *v); | 128 | static void var_or_func_tail (LexState *ls, vardesc *v); |
@@ -262,7 +261,7 @@ static int real_constant (FuncState *fs, real r) { | |||
262 | 261 | ||
263 | static void code_number (LexState *ls, real f) { | 262 | static void code_number (LexState *ls, real f) { |
264 | int i; | 263 | int i; |
265 | if (f >= 0 && f <= (real)MAX_WORD && (real)(i=(int)f) == f) | 264 | if (0 <= f && f <= (real)MAX_WORD && (real)(i=(int)f) == f) |
266 | code_oparg(ls, PUSHNUMBER, 3, i, 1); /* f has a short integer value */ | 265 | code_oparg(ls, PUSHNUMBER, 3, i, 1); /* f has a short integer value */ |
267 | else | 266 | else |
268 | code_constant(ls, real_constant(ls->fs, f)); | 267 | code_constant(ls, real_constant(ls->fs, f)); |
@@ -900,6 +899,9 @@ static int priority [POW+1] = {5, 5, 1, 1, 1, 1, 1, 1, 2, 3, 3, 4, 4, 6}; | |||
900 | static OpCode opcodes [POW+1] = {NOTOP, MINUSOP, EQOP, NEQOP, GTOP, LTOP, | 899 | static OpCode opcodes [POW+1] = {NOTOP, MINUSOP, EQOP, NEQOP, GTOP, LTOP, |
901 | LEOP, GEOP, CONCOP, ADDOP, SUBOP, MULTOP, DIVOP, POWOP}; | 900 | LEOP, GEOP, CONCOP, ADDOP, SUBOP, MULTOP, DIVOP, POWOP}; |
902 | 901 | ||
902 | #define INDNOT 0 | ||
903 | #define INDMINUS 1 | ||
904 | |||
903 | #define MAXOPS 20 | 905 | #define MAXOPS 20 |
904 | 906 | ||
905 | typedef struct { | 907 | typedef struct { |
@@ -941,7 +943,7 @@ static void push (LexState *ls, stack_op *s, int op) { | |||
941 | 943 | ||
942 | static void prefix (LexState *ls, stack_op *s) { | 944 | static void prefix (LexState *ls, stack_op *s) { |
943 | while (ls->token == NOT || ls->token == '-') { | 945 | while (ls->token == NOT || ls->token == '-') { |
944 | push(ls, s, ls->token==NOT?0:1); | 946 | push(ls, s, ls->token==NOT?INDNOT:INDMINUS); |
945 | next(ls); | 947 | next(ls); |
946 | } | 948 | } |
947 | } | 949 | } |
@@ -954,80 +956,85 @@ static void pop_to (LexState *ls, stack_op *s, int prio) { | |||
954 | } | 956 | } |
955 | } | 957 | } |
956 | 958 | ||
957 | static void exp2 (LexState *ls, vardesc *v) { | 959 | static void simpleexp (LexState *ls, vardesc *v, stack_op *s) { |
958 | stack_op s; | ||
959 | int op; | ||
960 | s.top = 0; | ||
961 | prefix(ls, &s); | ||
962 | simpleexp(ls, v); | ||
963 | while ((op = is_in(ls->token, binop)) >= 0) { | ||
964 | op += FIRSTBIN; | ||
965 | lua_pushvar(ls, v); | ||
966 | /* '^' is right associative, so must 'simulate' a higher priority */ | ||
967 | pop_to(ls, &s, (op == POW)?priority[op]+1:priority[op]); | ||
968 | push(ls, &s, op); | ||
969 | next(ls); | ||
970 | prefix(ls, &s); | ||
971 | simpleexp(ls, v); | ||
972 | lua_pushvar(ls, v); | ||
973 | } | ||
974 | if (s.top > 0) { | ||
975 | lua_pushvar(ls, v); | ||
976 | pop_to(ls, &s, 0); | ||
977 | } | ||
978 | } | ||
979 | |||
980 | |||
981 | static void simpleexp (LexState *ls, vardesc *v) { | ||
982 | check_debugline(ls); | 960 | check_debugline(ls); |
983 | switch (ls->token) { | 961 | switch (ls->token) { |
984 | case '(': /* simpleexp -> '(' exp0 ')' */ | 962 | case NUMBER: { /* simpleexp -> NUMBER */ |
963 | real r = ls->seminfo.r; | ||
985 | next(ls); | 964 | next(ls); |
986 | exp0(ls, v); | 965 | /* dirty trick: check whether is a -NUMBER not followed by "^" */ |
987 | check(ls, ')'); | 966 | /* (because the priority of "^" is closer than "-"...) */ |
988 | break; | 967 | if (s->top > 0 && s->ops[s->top-1] == INDMINUS && ls->token != '^') { |
989 | 968 | s->top--; | |
990 | case NUMBER: /* simpleexp -> NUMBER */ | 969 | r = -r; |
991 | code_number(ls, ls->seminfo.r); | 970 | } |
992 | next(ls); | 971 | code_number(ls, r); |
993 | v->k = VEXP; v->info = 0; | ||
994 | break; | 972 | break; |
973 | } | ||
995 | 974 | ||
996 | case STRING: /* simpleexp -> STRING */ | 975 | case STRING: /* simpleexp -> STRING */ |
997 | code_string(ls, ls->seminfo.ts); /* must use before "next" */ | 976 | code_string(ls, ls->seminfo.ts); /* must use before "next" */ |
998 | next(ls); | 977 | next(ls); |
999 | v->k = VEXP; v->info = 0; | ||
1000 | break; | 978 | break; |
1001 | 979 | ||
1002 | case NIL: /* simpleexp -> NIL */ | 980 | case NIL: /* simpleexp -> NIL */ |
1003 | adjuststack(ls, -1); | 981 | adjuststack(ls, -1); |
1004 | next(ls); | 982 | next(ls); |
1005 | v->k = VEXP; v->info = 0; | ||
1006 | break; | 983 | break; |
1007 | 984 | ||
1008 | case '{': /* simpleexp -> constructor */ | 985 | case '{': /* simpleexp -> constructor */ |
1009 | constructor(ls); | 986 | constructor(ls); |
1010 | v->k = VEXP; v->info = 0; | ||
1011 | break; | 987 | break; |
1012 | 988 | ||
1013 | case FUNCTION: { /* simpleexp -> FUNCTION body */ | 989 | case FUNCTION: { /* simpleexp -> FUNCTION body */ |
1014 | int line = ls->linenumber; | 990 | int line = ls->linenumber; |
1015 | next(ls); | 991 | next(ls); |
1016 | body(ls, 0, line); | 992 | body(ls, 0, line); |
1017 | v->k = VEXP; v->info = 0; | ||
1018 | break; | 993 | break; |
1019 | } | 994 | } |
1020 | 995 | ||
996 | case '(': /* simpleexp -> '(' exp0 ')' */ | ||
997 | next(ls); | ||
998 | exp0(ls, v); | ||
999 | check(ls, ')'); | ||
1000 | return; | ||
1001 | |||
1021 | case NAME: case '%': | 1002 | case NAME: case '%': |
1022 | var_or_func(ls, v); | 1003 | var_or_func(ls, v); |
1023 | break; | 1004 | return; |
1024 | 1005 | ||
1025 | default: | 1006 | default: |
1026 | luaX_error(ls, "<expression> expected"); | 1007 | luaX_error(ls, "<expression> expected"); |
1027 | break; | 1008 | return; |
1009 | } | ||
1010 | v->k = VEXP; v->info = 0; | ||
1011 | } | ||
1012 | |||
1013 | |||
1014 | static void exp2 (LexState *ls, vardesc *v) { | ||
1015 | stack_op s; | ||
1016 | int op; | ||
1017 | s.top = 0; | ||
1018 | prefix(ls, &s); | ||
1019 | simpleexp(ls, v, &s); | ||
1020 | while ((op = is_in(ls->token, binop)) >= 0) { | ||
1021 | op += FIRSTBIN; | ||
1022 | lua_pushvar(ls, v); | ||
1023 | /* '^' is right associative, so must 'simulate' a higher priority */ | ||
1024 | pop_to(ls, &s, (op == POW)?priority[op]+1:priority[op]); | ||
1025 | push(ls, &s, op); | ||
1026 | next(ls); | ||
1027 | prefix(ls, &s); | ||
1028 | simpleexp(ls, v, &s); | ||
1029 | lua_pushvar(ls, v); | ||
1030 | } | ||
1031 | if (s.top > 0) { | ||
1032 | lua_pushvar(ls, v); | ||
1033 | pop_to(ls, &s, 0); | ||
1028 | } | 1034 | } |
1029 | } | 1035 | } |
1030 | 1036 | ||
1037 | |||
1031 | static void var_or_func (LexState *ls, vardesc *v) { | 1038 | static void var_or_func (LexState *ls, vardesc *v) { |
1032 | /* var_or_func -> ['%'] NAME var_or_func_tail */ | 1039 | /* var_or_func -> ['%'] NAME var_or_func_tail */ |
1033 | if (optional(ls, '%')) { /* upvalue? */ | 1040 | if (optional(ls, '%')) { /* upvalue? */ |