diff options
| author | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 1998-05-27 10:08:34 -0300 |
|---|---|---|
| committer | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 1998-05-27 10:08:34 -0300 |
| commit | 7e59a8901d063dbea4eb0693c9c2d85bda1fc5f6 (patch) | |
| tree | 1834168cd16e821a017e3d8408978f89e6c2ddaf | |
| parent | abc6eac404da8181ad945ac6950f61a65ba7dfa5 (diff) | |
| download | lua-7e59a8901d063dbea4eb0693c9c2d85bda1fc5f6.tar.gz lua-7e59a8901d063dbea4eb0693c9c2d85bda1fc5f6.tar.bz2 lua-7e59a8901d063dbea4eb0693c9c2d85bda1fc5f6.zip | |
NEW LL(1) PARSER
Diffstat (limited to '')
| -rw-r--r-- | llex.c | 138 | ||||
| -rw-r--r-- | llex.h | 31 | ||||
| -rw-r--r-- | lparser.c | 1332 | ||||
| -rw-r--r-- | lstate.h | 4 | ||||
| -rw-r--r-- | lua.stx | 940 | ||||
| -rw-r--r-- | makefile | 22 |
6 files changed, 1442 insertions, 1025 deletions
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | ** $Id: llex.c,v 1.17 1998/03/09 17:22:49 roberto Exp roberto $ | 2 | ** $Id: llex.c,v 1.18 1998/03/20 14:18:18 roberto Exp roberto $ |
| 3 | ** Lexical Analizer | 3 | ** Lexical Analizer |
| 4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
| 5 | */ | 5 | */ |
| @@ -15,7 +15,6 @@ | |||
| 15 | #include "lparser.h" | 15 | #include "lparser.h" |
| 16 | #include "lstate.h" | 16 | #include "lstate.h" |
| 17 | #include "lstring.h" | 17 | #include "lstring.h" |
| 18 | #include "lstx.h" | ||
| 19 | #include "luadebug.h" | 18 | #include "luadebug.h" |
| 20 | #include "lzio.h" | 19 | #include "lzio.h" |
| 21 | 20 | ||
| @@ -27,23 +26,53 @@ int lua_debug=0; | |||
| 27 | #define next(LS) (LS->current = zgetc(LS->lex_z)) | 26 | #define next(LS) (LS->current = zgetc(LS->lex_z)) |
| 28 | 27 | ||
| 29 | 28 | ||
| 30 | static struct { | 29 | #define save(c) luaL_addchar(c) |
| 31 | char *name; | 30 | #define save_and_next(LS) (save(LS->current), next(LS)) |
| 32 | int token; | 31 | |
| 33 | } reserved [] = { | 32 | |
| 34 | {"and", AND}, {"do", DO}, {"else", ELSE}, {"elseif", ELSEIF}, | 33 | char *reserved [] = {"and", "do", "else", "elseif", "end", "function", |
| 35 | {"end", END}, {"function", FUNCTION}, {"if", IF}, {"local", LOCAL}, | 34 | "if", "local", "nil", "not", "or", "repeat", "return", "then", |
| 36 | {"nil", NIL}, {"not", NOT}, {"or", OR}, {"repeat", REPEAT}, | 35 | "until", "while"}; |
| 37 | {"return", RETURN}, {"then", THEN}, {"until", UNTIL}, {"while", WHILE} | 36 | |
| 38 | }; | ||
| 39 | 37 | ||
| 40 | void luaX_init (void) | 38 | void luaX_init (void) |
| 41 | { | 39 | { |
| 42 | int i; | 40 | int i; |
| 43 | for (i=0; i<(sizeof(reserved)/sizeof(reserved[0])); i++) { | 41 | for (i=0; i<(sizeof(reserved)/sizeof(reserved[0])); i++) { |
| 44 | TaggedString *ts = luaS_new(reserved[i].name); | 42 | TaggedString *ts = luaS_new(reserved[i]); |
| 45 | ts->head.marked = reserved[i].token; /* reserved word (always > 255) */ | 43 | ts->head.marked = FIRST_RESERVED+i; /* reserved word (always > 255) */ |
| 44 | } | ||
| 45 | } | ||
| 46 | |||
| 47 | |||
| 48 | void luaX_syntaxerror (LexState *ls, char *s, char *token) { | ||
| 49 | if (token[0] == 0) | ||
| 50 | token = "<eof>"; | ||
| 51 | luaL_verror("%.100s;\n last token read: `%.50s' at line %d in file %.50s", | ||
| 52 | s, token, ls->linenumber, zname(ls->lex_z)); | ||
| 53 | } | ||
| 54 | |||
| 55 | |||
| 56 | void luaX_error (LexState *ls, char *s) { | ||
| 57 | save(0); | ||
| 58 | luaX_syntaxerror(ls, s, luaL_buffer()); | ||
| 59 | } | ||
| 60 | |||
| 61 | |||
| 62 | void luaX_token2str (LexState *ls, int token, char *s) { | ||
| 63 | if (token < 255) { | ||
| 64 | s[0] = token; | ||
| 65 | s[1] = 0; | ||
| 46 | } | 66 | } |
| 67 | else | ||
| 68 | strcpy(s, reserved[token-FIRST_RESERVED]); | ||
| 69 | } | ||
| 70 | |||
| 71 | |||
| 72 | static void luaX_invalidchar (LexState *ls, int c) { | ||
| 73 | char buff[10]; | ||
| 74 | sprintf(buff, "0x%X", c); | ||
| 75 | luaX_syntaxerror(ls, "invalid control char", buff); | ||
| 47 | } | 76 | } |
| 48 | 77 | ||
| 49 | 78 | ||
| @@ -56,16 +85,15 @@ static void firstline (LexState *LS) | |||
| 56 | } | 85 | } |
| 57 | 86 | ||
| 58 | 87 | ||
| 59 | void luaX_setinput (ZIO *z) | 88 | void luaX_setinput (LexState *LS, ZIO *z) |
| 60 | { | 89 | { |
| 61 | LexState *LS = L->lexstate; | ||
| 62 | LS->current = '\n'; | 90 | LS->current = '\n'; |
| 63 | LS->linelasttoken = 0; | ||
| 64 | LS->linenumber = 0; | 91 | LS->linenumber = 0; |
| 65 | LS->iflevel = 0; | 92 | LS->iflevel = 0; |
| 66 | LS->ifstate[0].skip = 0; | 93 | LS->ifstate[0].skip = 0; |
| 67 | LS->ifstate[0].elsepart = 1; /* to avoid a free $else */ | 94 | LS->ifstate[0].elsepart = 1; /* to avoid a free $else */ |
| 68 | LS->lex_z = z; | 95 | LS->lex_z = z; |
| 96 | LS->fs = NULL; | ||
| 69 | firstline(LS); | 97 | firstline(LS); |
| 70 | luaL_resetbuffer(); | 98 | luaL_resetbuffer(); |
| 71 | } | 99 | } |
| @@ -87,7 +115,7 @@ static void skipspace (LexState *LS) | |||
| 87 | } | 115 | } |
| 88 | 116 | ||
| 89 | 117 | ||
| 90 | static int checkcond (char *buff) | 118 | static int checkcond (LexState *LS, char *buff) |
| 91 | { | 119 | { |
| 92 | static char *opts[] = {"nil", "1", NULL}; | 120 | static char *opts[] = {"nil", "1", NULL}; |
| 93 | int i = luaO_findstring(buff, opts); | 121 | int i = luaO_findstring(buff, opts); |
| @@ -95,7 +123,7 @@ static int checkcond (char *buff) | |||
| 95 | else if (isalpha((unsigned char)buff[0]) || buff[0] == '_') | 123 | else if (isalpha((unsigned char)buff[0]) || buff[0] == '_') |
| 96 | return luaS_globaldefined(buff); | 124 | return luaS_globaldefined(buff); |
| 97 | else { | 125 | else { |
| 98 | luaY_syntaxerror("invalid $if condition", buff); | 126 | luaX_syntaxerror(LS, "invalid $if condition", buff); |
| 99 | return 0; /* to avoid warnings */ | 127 | return 0; /* to avoid warnings */ |
| 100 | } | 128 | } |
| 101 | } | 129 | } |
| @@ -108,7 +136,7 @@ static void readname (LexState *LS, char *buff) | |||
| 108 | while (isalnum(LS->current) || LS->current == '_') { | 136 | while (isalnum(LS->current) || LS->current == '_') { |
| 109 | if (i >= PRAGMASIZE) { | 137 | if (i >= PRAGMASIZE) { |
| 110 | buff[PRAGMASIZE] = 0; | 138 | buff[PRAGMASIZE] = 0; |
| 111 | luaY_syntaxerror("pragma too long", buff); | 139 | luaX_syntaxerror(LS, "pragma too long", buff); |
| 112 | } | 140 | } |
| 113 | buff[i++] = LS->current; | 141 | buff[i++] = LS->current; |
| 114 | next(LS); | 142 | next(LS); |
| @@ -126,7 +154,7 @@ static void ifskip (LexState *LS) | |||
| 126 | if (LS->current == '\n') | 154 | if (LS->current == '\n') |
| 127 | inclinenumber(LS); | 155 | inclinenumber(LS); |
| 128 | else if (LS->current == EOZ) | 156 | else if (LS->current == EOZ) |
| 129 | luaY_error("input ends inside a $if"); | 157 | luaX_error(LS, "input ends inside a $if"); |
| 130 | else next(LS); | 158 | else next(LS); |
| 131 | } | 159 | } |
| 132 | } | 160 | } |
| @@ -159,35 +187,35 @@ static void inclinenumber (LexState *LS) | |||
| 159 | break; | 187 | break; |
| 160 | case 3: /* end */ | 188 | case 3: /* end */ |
| 161 | if (LS->iflevel-- == 0) | 189 | if (LS->iflevel-- == 0) |
| 162 | luaY_syntaxerror("unmatched $end", "$end"); | 190 | luaX_syntaxerror(LS, "unmatched $end", "$end"); |
| 163 | break; | 191 | break; |
| 164 | case 4: /* ifnot */ | 192 | case 4: /* ifnot */ |
| 165 | ifnot = 1; | 193 | ifnot = 1; |
| 166 | /* go through */ | 194 | /* go through */ |
| 167 | case 5: /* if */ | 195 | case 5: /* if */ |
| 168 | if (LS->iflevel == MAX_IFS-1) | 196 | if (LS->iflevel == MAX_IFS-1) |
| 169 | luaY_syntaxerror("too many nested $ifs", "$if"); | 197 | luaX_syntaxerror(LS, "too many nested $ifs", "$if"); |
| 170 | readname(LS, buff); | 198 | readname(LS, buff); |
| 171 | LS->iflevel++; | 199 | LS->iflevel++; |
| 172 | LS->ifstate[LS->iflevel].elsepart = 0; | 200 | LS->ifstate[LS->iflevel].elsepart = 0; |
| 173 | LS->ifstate[LS->iflevel].condition = checkcond(buff) ? !ifnot : ifnot; | 201 | LS->ifstate[LS->iflevel].condition = checkcond(LS, buff) ? !ifnot : ifnot; |
| 174 | LS->ifstate[LS->iflevel].skip = skip || !LS->ifstate[LS->iflevel].condition; | 202 | LS->ifstate[LS->iflevel].skip = skip || !LS->ifstate[LS->iflevel].condition; |
| 175 | break; | 203 | break; |
| 176 | case 6: /* else */ | 204 | case 6: /* else */ |
| 177 | if (LS->ifstate[LS->iflevel].elsepart) | 205 | if (LS->ifstate[LS->iflevel].elsepart) |
| 178 | luaY_syntaxerror("unmatched $else", "$else"); | 206 | luaX_syntaxerror(LS, "unmatched $else", "$else"); |
| 179 | LS->ifstate[LS->iflevel].elsepart = 1; | 207 | LS->ifstate[LS->iflevel].elsepart = 1; |
| 180 | LS->ifstate[LS->iflevel].skip = LS->ifstate[LS->iflevel-1].skip || | 208 | LS->ifstate[LS->iflevel].skip = LS->ifstate[LS->iflevel-1].skip || |
| 181 | LS->ifstate[LS->iflevel].condition; | 209 | LS->ifstate[LS->iflevel].condition; |
| 182 | break; | 210 | break; |
| 183 | default: | 211 | default: |
| 184 | luaY_syntaxerror("unknown pragma", buff); | 212 | luaX_syntaxerror(LS, "unknown pragma", buff); |
| 185 | } | 213 | } |
| 186 | skipspace(LS); | 214 | skipspace(LS); |
| 187 | if (LS->current == '\n') /* pragma must end with a '\n' ... */ | 215 | if (LS->current == '\n') /* pragma must end with a '\n' ... */ |
| 188 | inclinenumber(LS); | 216 | inclinenumber(LS); |
| 189 | else if (LS->current != EOZ) /* or eof */ | 217 | else if (LS->current != EOZ) /* or eof */ |
| 190 | luaY_syntaxerror("invalid pragma format", buff); | 218 | luaX_syntaxerror(LS, "invalid pragma format", buff); |
| 191 | ifskip(LS); | 219 | ifskip(LS); |
| 192 | } | 220 | } |
| 193 | } | 221 | } |
| @@ -201,25 +229,16 @@ static void inclinenumber (LexState *LS) | |||
| 201 | 229 | ||
| 202 | 230 | ||
| 203 | 231 | ||
| 204 | #define save(c) luaL_addchar(c) | ||
| 205 | #define save_and_next(LS) (save(LS->current), next(LS)) | ||
| 206 | |||
| 207 | |||
| 208 | char *luaX_lasttoken (void) | ||
| 209 | { | ||
| 210 | save(0); | ||
| 211 | return luaL_buffer(); | ||
| 212 | } | ||
| 213 | 232 | ||
| 214 | 233 | ||
| 215 | static int read_long_string (LexState *LS, YYSTYPE *l) | 234 | static int read_long_string (LexState *LS) |
| 216 | { | 235 | { |
| 217 | int cont = 0; | 236 | int cont = 0; |
| 218 | while (1) { | 237 | while (1) { |
| 219 | switch (LS->current) { | 238 | switch (LS->current) { |
| 220 | case EOZ: | 239 | case EOZ: |
| 221 | luaY_error("unfinished long string"); | 240 | luaX_error(LS, "unfinished long string"); |
| 222 | return 0; /* to avoid warnings */ | 241 | return EOS; /* to avoid warnings */ |
| 223 | case '[': | 242 | case '[': |
| 224 | save_and_next(LS); | 243 | save_and_next(LS); |
| 225 | if (LS->current == '[') { | 244 | if (LS->current == '[') { |
| @@ -244,25 +263,15 @@ static int read_long_string (LexState *LS, YYSTYPE *l) | |||
| 244 | } | 263 | } |
| 245 | } endloop: | 264 | } endloop: |
| 246 | save_and_next(LS); /* pass the second ']' */ | 265 | save_and_next(LS); /* pass the second ']' */ |
| 247 | l->pTStr = luaS_newlstr(L->Mbuffbase+2, | 266 | LS->seminfo.ts = luaS_newlstr(L->Mbuffbase+2, |
| 248 | L->Mbuffnext-(L->Mbuffbase-L->Mbuffer)-4); | 267 | L->Mbuffnext-(L->Mbuffbase-L->Mbuffer)-4); |
| 249 | return STRING; | 268 | return STRING; |
| 250 | } | 269 | } |
| 251 | 270 | ||
| 252 | 271 | ||
| 253 | /* to avoid warnings; this declaration cannot be public since YYSTYPE | 272 | int luaX_lex (LexState *LS) { |
| 254 | ** cannot be visible in llex.h (otherwise there is an error, since | ||
| 255 | ** the parser body redefines it!) | ||
| 256 | */ | ||
| 257 | int luaY_lex (YYSTYPE *l); | ||
| 258 | int luaY_lex (YYSTYPE *l) | ||
| 259 | { | ||
| 260 | LexState *LS = L->lexstate; | ||
| 261 | double a; | 273 | double a; |
| 262 | luaL_resetbuffer(); | 274 | luaL_resetbuffer(); |
| 263 | if (lua_debug) | ||
| 264 | luaY_codedebugline(LS->linelasttoken); | ||
| 265 | LS->linelasttoken = LS->linenumber; | ||
| 266 | while (1) { | 275 | while (1) { |
| 267 | switch (LS->current) { | 276 | switch (LS->current) { |
| 268 | 277 | ||
| @@ -272,7 +281,6 @@ int luaY_lex (YYSTYPE *l) | |||
| 272 | 281 | ||
| 273 | case '\n': | 282 | case '\n': |
| 274 | inclinenumber(LS); | 283 | inclinenumber(LS); |
| 275 | LS->linelasttoken = LS->linenumber; | ||
| 276 | continue; | 284 | continue; |
| 277 | 285 | ||
| 278 | case '-': | 286 | case '-': |
| @@ -287,7 +295,7 @@ int luaY_lex (YYSTYPE *l) | |||
| 287 | if (LS->current != '[') return '['; | 295 | if (LS->current != '[') return '['; |
| 288 | else { | 296 | else { |
| 289 | save_and_next(LS); /* pass the second '[' */ | 297 | save_and_next(LS); /* pass the second '[' */ |
| 290 | return read_long_string(LS, l); | 298 | return read_long_string(LS); |
| 291 | } | 299 | } |
| 292 | 300 | ||
| 293 | case '=': | 301 | case '=': |
| @@ -318,8 +326,8 @@ int luaY_lex (YYSTYPE *l) | |||
| 318 | switch (LS->current) { | 326 | switch (LS->current) { |
| 319 | case EOZ: | 327 | case EOZ: |
| 320 | case '\n': | 328 | case '\n': |
| 321 | luaY_error("unfinished string"); | 329 | luaX_error(LS, "unfinished string"); |
| 322 | return 0; /* to avoid warnings */ | 330 | return EOS; /* to avoid warnings */ |
| 323 | case '\\': | 331 | case '\\': |
| 324 | next(LS); /* do not save the '\' */ | 332 | next(LS); /* do not save the '\' */ |
| 325 | switch (LS->current) { | 333 | switch (LS->current) { |
| @@ -345,13 +353,13 @@ int luaY_lex (YYSTYPE *l) | |||
| 345 | next(LS); | 353 | next(LS); |
| 346 | } while (++i<3 && isdigit(LS->current)); | 354 | } while (++i<3 && isdigit(LS->current)); |
| 347 | if (c >= 256) | 355 | if (c >= 256) |
| 348 | luaY_error("escape sequence too large"); | 356 | luaX_error(LS, "escape sequence too large"); |
| 349 | save(c); | 357 | save(c); |
| 350 | } | 358 | } |
| 351 | else { | 359 | else { |
| 352 | save('\\'); | 360 | save('\\'); |
| 353 | save(LS->current); | 361 | save(LS->current); |
| 354 | luaY_error("invalid escape sequence"); | 362 | luaX_error(LS, "invalid escape sequence"); |
| 355 | } | 363 | } |
| 356 | break; | 364 | break; |
| 357 | } | 365 | } |
| @@ -362,7 +370,7 @@ int luaY_lex (YYSTYPE *l) | |||
| 362 | } | 370 | } |
| 363 | } | 371 | } |
| 364 | save_and_next(LS); /* skip delimiter */ | 372 | save_and_next(LS); /* skip delimiter */ |
| 365 | l->pTStr = luaS_newlstr(L->Mbuffbase+1, | 373 | LS->seminfo.ts = luaS_newlstr(L->Mbuffbase+1, |
| 366 | L->Mbuffnext-(L->Mbuffbase-L->Mbuffer)-2); | 374 | L->Mbuffnext-(L->Mbuffbase-L->Mbuffer)-2); |
| 367 | return STRING; | 375 | return STRING; |
| 368 | } | 376 | } |
| @@ -395,7 +403,7 @@ int luaY_lex (YYSTYPE *l) | |||
| 395 | save_and_next(LS); | 403 | save_and_next(LS); |
| 396 | if (LS->current == '.') { | 404 | if (LS->current == '.') { |
| 397 | save('.'); | 405 | save('.'); |
| 398 | luaY_error( | 406 | luaX_error(LS, |
| 399 | "ambiguous syntax (decimal point x string concatenation)"); | 407 | "ambiguous syntax (decimal point x string concatenation)"); |
| 400 | } | 408 | } |
| 401 | } | 409 | } |
| @@ -415,7 +423,7 @@ int luaY_lex (YYSTYPE *l) | |||
| 415 | neg = (LS->current=='-'); | 423 | neg = (LS->current=='-'); |
| 416 | if (LS->current == '+' || LS->current == '-') save_and_next(LS); | 424 | if (LS->current == '+' || LS->current == '-') save_and_next(LS); |
| 417 | if (!isdigit(LS->current)) | 425 | if (!isdigit(LS->current)) |
| 418 | luaY_error("invalid numeral format"); | 426 | luaX_error(LS, "invalid numeral format"); |
| 419 | do { | 427 | do { |
| 420 | e = 10.0*e + (LS->current-'0'); | 428 | e = 10.0*e + (LS->current-'0'); |
| 421 | save_and_next(LS); | 429 | save_and_next(LS); |
| @@ -426,18 +434,20 @@ int luaY_lex (YYSTYPE *l) | |||
| 426 | ea *= ea; | 434 | ea *= ea; |
| 427 | } | 435 | } |
| 428 | } | 436 | } |
| 429 | l->vReal = a; | 437 | LS->seminfo.r = a; |
| 430 | return NUMBER; | 438 | return NUMBER; |
| 431 | } | 439 | } |
| 432 | 440 | ||
| 433 | case EOZ: | 441 | case EOZ: |
| 434 | if (LS->iflevel > 0) | 442 | if (LS->iflevel > 0) |
| 435 | luaY_error("input ends inside a $if"); | 443 | luaX_error(LS, "input ends inside a $if"); |
| 436 | return 0; | 444 | return EOS; |
| 437 | 445 | ||
| 438 | default: | 446 | default: |
| 439 | if (LS->current != '_' && !isalpha(LS->current)) { | 447 | if (LS->current != '_' && !isalpha(LS->current)) { |
| 440 | int c = LS->current; | 448 | int c = LS->current; |
| 449 | if (iscntrl(c)) | ||
| 450 | luaX_invalidchar(LS, c); | ||
| 441 | save_and_next(LS); | 451 | save_and_next(LS); |
| 442 | return c; | 452 | return c; |
| 443 | } | 453 | } |
| @@ -448,9 +458,9 @@ int luaY_lex (YYSTYPE *l) | |||
| 448 | } while (isalnum(LS->current) || LS->current == '_'); | 458 | } while (isalnum(LS->current) || LS->current == '_'); |
| 449 | save(0); | 459 | save(0); |
| 450 | ts = luaS_new(L->Mbuffbase); | 460 | ts = luaS_new(L->Mbuffbase); |
| 451 | if (ts->head.marked > 255) | 461 | if (ts->head.marked >= 'A') |
| 452 | return ts->head.marked; /* reserved word */ | 462 | return ts->head.marked; /* reserved word */ |
| 453 | l->pTStr = ts; | 463 | LS->seminfo.ts = ts; |
| 454 | return NAME; | 464 | return NAME; |
| 455 | } | 465 | } |
| 456 | } | 466 | } |
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | ** $Id: llex.h,v 1.6 1997/12/17 20:48:58 roberto Exp roberto $ | 2 | ** $Id: llex.h,v 1.7 1998/01/09 14:57:43 roberto Exp $ |
| 3 | ** Lexical Analizer | 3 | ** Lexical Analizer |
| 4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
| 5 | */ | 5 | */ |
| @@ -11,6 +11,20 @@ | |||
| 11 | #include "lzio.h" | 11 | #include "lzio.h" |
| 12 | 12 | ||
| 13 | 13 | ||
| 14 | #define FIRST_RESERVED 260 | ||
| 15 | |||
| 16 | /* maximum length of a reserved word (+1 for terminal 0) */ | ||
| 17 | #define TOKEN_LEN 15 | ||
| 18 | |||
| 19 | enum RESERVED { | ||
| 20 | /* terminal symbols denoted by reserved words */ | ||
| 21 | AND = FIRST_RESERVED, | ||
| 22 | DO, ELSE, ELSEIF, END, FUNCTION, IF, LOCAL, NIL, NOT, OR, | ||
| 23 | REPEAT, RETURN, THEN, UNTIL, WHILE, | ||
| 24 | /* other terminal symbols */ | ||
| 25 | NAME, CONC, DOTS, EQ, GE, LE, NE, NUMBER, STRING, EOS}; | ||
| 26 | |||
| 27 | |||
| 14 | #define MAX_IFS 5 | 28 | #define MAX_IFS 5 |
| 15 | 29 | ||
| 16 | /* "ifstate" keeps the state of each nested $if the lexical is dealing with. */ | 30 | /* "ifstate" keeps the state of each nested $if the lexical is dealing with. */ |
| @@ -24,18 +38,25 @@ struct ifState { | |||
| 24 | 38 | ||
| 25 | typedef struct LexState { | 39 | typedef struct LexState { |
| 26 | int current; /* look ahead character */ | 40 | int current; /* look ahead character */ |
| 41 | int token; /* look ahead token */ | ||
| 42 | struct FuncState *fs; /* 'FuncState' is private for the parser */ | ||
| 43 | union { | ||
| 44 | real r; | ||
| 45 | TaggedString *ts; | ||
| 46 | } seminfo; /* semantics information */ | ||
| 27 | struct zio *lex_z; /* input stream */ | 47 | struct zio *lex_z; /* input stream */ |
| 28 | int linenumber; /* input line counter */ | 48 | int linenumber; /* input line counter */ |
| 29 | int linelasttoken; /* line where last token was read */ | ||
| 30 | int lastline; /* last line wherein a SETLINE was generated */ | ||
| 31 | int iflevel; /* level of nested $if's (for lexical analysis) */ | 49 | int iflevel; /* level of nested $if's (for lexical analysis) */ |
| 32 | struct ifState ifstate[MAX_IFS]; | 50 | struct ifState ifstate[MAX_IFS]; |
| 33 | } LexState; | 51 | } LexState; |
| 34 | 52 | ||
| 35 | 53 | ||
| 36 | void luaX_init (void); | 54 | void luaX_init (void); |
| 37 | void luaX_setinput (ZIO *z); | 55 | void luaX_setinput (LexState *LS, ZIO *z); |
| 38 | char *luaX_lasttoken (void); | 56 | int luaX_lex (LexState *LS); |
| 57 | void luaX_syntaxerror (LexState *ls, char *s, char *token); | ||
| 58 | void luaX_error (LexState *ls, char *s); | ||
| 59 | void luaX_token2str (LexState *ls, int token, char *s); | ||
| 39 | 60 | ||
| 40 | 61 | ||
| 41 | #endif | 62 | #endif |
diff --git a/lparser.c b/lparser.c new file mode 100644 index 00000000..0eefb204 --- /dev/null +++ b/lparser.c | |||
| @@ -0,0 +1,1332 @@ | |||
| 1 | /* | ||
| 2 | ** $Id: $ | ||
| 3 | ** LL(1) Parser and code generator for Lua | ||
| 4 | ** See Copyright Notice in lua.h | ||
| 5 | */ | ||
| 6 | |||
| 7 | |||
| 8 | #include <stdio.h> | ||
| 9 | |||
| 10 | #include "lauxlib.h" | ||
| 11 | #include "ldo.h" | ||
| 12 | #include "lfunc.h" | ||
| 13 | #include "llex.h" | ||
| 14 | #include "lmem.h" | ||
| 15 | #include "lopcodes.h" | ||
| 16 | #include "lparser.h" | ||
| 17 | #include "lstate.h" | ||
| 18 | #include "lstring.h" | ||
| 19 | #include "lua.h" | ||
| 20 | #include "luadebug.h" | ||
| 21 | #include "lzio.h" | ||
| 22 | |||
| 23 | |||
| 24 | /* for limit numbers in error messages */ | ||
| 25 | #define MES_LIM(x) "(limit=" x ")" | ||
| 26 | |||
| 27 | |||
| 28 | /* size of a "normal" jump instruction: OpCode + 1 byte */ | ||
| 29 | #define JMPSIZE 2 | ||
| 30 | |||
| 31 | /* maximum number of local variables */ | ||
| 32 | #define MAXLOCALS 32 | ||
| 33 | #define SMAXLOCALS "32" | ||
| 34 | |||
| 35 | |||
| 36 | /* maximum number of upvalues */ | ||
| 37 | #define MAXUPVALUES 16 | ||
| 38 | #define SMAXUPVALUES "16" | ||
| 39 | |||
| 40 | |||
| 41 | /* | ||
| 42 | ** Variable descriptor: | ||
| 43 | ** must include a "exp" option because LL(1) cannot distinguish | ||
| 44 | ** between variables, upvalues and function calls on first sight. | ||
| 45 | ** VGLOBAL: info is constant index of global name | ||
| 46 | ** VLOCAL: info is stack index | ||
| 47 | ** VDOT: info is constant index of index name | ||
| 48 | ** VEXP: info is pc index of "nparam" of function call (or 0 if exp is closed) | ||
| 49 | */ | ||
| 50 | typedef enum {VGLOBAL, VLOCAL, VDOT, VINDEXED, VEXP} varkind; | ||
| 51 | |||
| 52 | typedef struct { | ||
| 53 | varkind k; | ||
| 54 | int info; | ||
| 55 | } vardesc; | ||
| 56 | |||
| 57 | |||
| 58 | /* | ||
| 59 | ** Expression List descriptor: | ||
| 60 | ** tells number of expressions in the list, | ||
| 61 | ** and, if last expression is open (a function call), | ||
| 62 | ** where is its pc index of "nparam" | ||
| 63 | */ | ||
| 64 | typedef struct { | ||
| 65 | int n; | ||
| 66 | int pc; /* 0 if last expression is closed */ | ||
| 67 | } listdesc; | ||
| 68 | |||
| 69 | |||
| 70 | /* | ||
| 71 | ** Constructors descriptor: | ||
| 72 | ** "n" indicates number of elements, and "k" signals whether | ||
| 73 | ** it is a list constructor (k = 0) or a record constructor (k = 1) | ||
| 74 | ** or empty (k = ';' or '}') | ||
| 75 | */ | ||
| 76 | typedef struct { | ||
| 77 | int n; | ||
| 78 | int k; | ||
| 79 | } constdesc; | ||
| 80 | |||
| 81 | |||
| 82 | /* state needed to generate code for a given function */ | ||
| 83 | typedef struct FuncState { | ||
| 84 | TProtoFunc *f; /* current function header */ | ||
| 85 | struct FuncState *prev; /* enclosuring function */ | ||
| 86 | int pc; /* next position to code */ | ||
| 87 | int stacksize; /* number of values on activation register */ | ||
| 88 | int maxstacksize; /* maximum number of values on activation register */ | ||
| 89 | int nlocalvar; /* number of active local variables */ | ||
| 90 | int nupvalues; /* number of upvalues */ | ||
| 91 | int nvars; /* number of entries in f->locvars */ | ||
| 92 | int maxcode; /* size of f->code */ | ||
| 93 | int maxvars; /* size of f->locvars (-1 if no debug information) */ | ||
| 94 | int maxconsts; /* size of f->consts */ | ||
| 95 | int lastsetline; /* line where last SETLINE was issued */ | ||
| 96 | vardesc upvalues[MAXUPVALUES]; /* upvalues */ | ||
| 97 | TaggedString *localvar[MAXLOCALS]; /* store local variable names */ | ||
| 98 | } FuncState; | ||
| 99 | |||
| 100 | |||
| 101 | static int assignment (LexState *ls, vardesc *v, int nvars); | ||
| 102 | static int cond (LexState *ls); | ||
| 103 | static int funcname (LexState *ls, vardesc *v); | ||
| 104 | static int funcparams (LexState *ls, int slf); | ||
| 105 | static int listfields (LexState *ls); | ||
| 106 | static int localnamelist (LexState *ls); | ||
| 107 | static int optional (LexState *ls, int c); | ||
| 108 | static int recfields (LexState *ls); | ||
| 109 | static int stat (LexState *ls); | ||
| 110 | static void block (LexState *ls); | ||
| 111 | static void body (LexState *ls, int needself, int line); | ||
| 112 | static void chunk (LexState *ls); | ||
| 113 | static void constructor (LexState *ls); | ||
| 114 | static void decinit (LexState *ls, listdesc *d); | ||
| 115 | static void exp (LexState *ls, vardesc *v); | ||
| 116 | static void exp1 (LexState *ls); | ||
| 117 | static void exp2 (LexState *ls, vardesc *v); | ||
| 118 | static void explist (LexState *ls, listdesc *e); | ||
| 119 | static void explist1 (LexState *ls, listdesc *e); | ||
| 120 | static void ifpart (LexState *ls); | ||
| 121 | static void parlist (LexState *ls); | ||
| 122 | static void part (LexState *ls, constdesc *cd); | ||
| 123 | static void recfield (LexState *ls); | ||
| 124 | static void ret (LexState *ls); | ||
| 125 | static void simpleexp (LexState *ls, vardesc *v); | ||
| 126 | static void statlist (LexState *ls); | ||
| 127 | static void var_or_func (LexState *ls, vardesc *v); | ||
| 128 | static void var_or_func_tail (LexState *ls, vardesc *v); | ||
| 129 | |||
| 130 | |||
| 131 | |||
| 132 | static void check_pc (FuncState *fs, int n) { | ||
| 133 | if (fs->pc+n > fs->maxcode) | ||
| 134 | fs->maxcode = luaM_growvector(&fs->f->code, fs->maxcode, | ||
| 135 | Byte, codeEM, MAX_INT); | ||
| 136 | } | ||
| 137 | |||
| 138 | |||
| 139 | static void code_byte (FuncState *fs, Byte c) { | ||
| 140 | check_pc(fs, 1); | ||
| 141 | fs->f->code[fs->pc++] = c; | ||
| 142 | } | ||
| 143 | |||
| 144 | |||
| 145 | static void deltastack (LexState *ls, int delta) { | ||
| 146 | FuncState *fs = ls->fs; | ||
| 147 | fs->stacksize += delta; | ||
| 148 | if (fs->stacksize > fs->maxstacksize) { | ||
| 149 | if (fs->stacksize > 255) | ||
| 150 | luaX_error(ls, "function/expression too complex"); | ||
| 151 | fs->maxstacksize = fs->stacksize; | ||
| 152 | } | ||
| 153 | } | ||
| 154 | |||
| 155 | |||
| 156 | static int code_oparg_at (LexState *ls, int pc, OpCode op, int builtin, | ||
| 157 | int arg, int delta) { | ||
| 158 | Byte *code = ls->fs->f->code; | ||
| 159 | deltastack(ls, delta); | ||
| 160 | if (arg < builtin) { | ||
| 161 | code[pc] = op+1+arg; | ||
| 162 | return 1; | ||
| 163 | } | ||
| 164 | else if (arg <= 255) { | ||
| 165 | code[pc] = op; | ||
| 166 | code[pc+1] = arg; | ||
| 167 | return 2; | ||
| 168 | } | ||
| 169 | else if (arg <= MAX_WORD) { | ||
| 170 | code[pc] = op+1+builtin; | ||
| 171 | code[pc+1] = arg>>8; | ||
| 172 | code[pc+2] = arg&0xFF; | ||
| 173 | return 3; | ||
| 174 | } | ||
| 175 | else luaX_error(ls, "code too long " MES_LIM("64K")); | ||
| 176 | return 0; /* to avoid warnings */ | ||
| 177 | } | ||
| 178 | |||
| 179 | |||
| 180 | static int fix_opcode (LexState *ls, int pc, OpCode op, int builtin, int arg) { | ||
| 181 | FuncState *fs = ls->fs; | ||
| 182 | TProtoFunc *f = fs->f; | ||
| 183 | if (arg < builtin) { /* close space */ | ||
| 184 | luaO_memdown(f->code+pc+1, f->code+pc+2, fs->pc-(pc+2)); | ||
| 185 | fs->pc--; | ||
| 186 | } | ||
| 187 | else if (arg > 255) { /* open space */ | ||
| 188 | check_pc(fs, 1); | ||
| 189 | luaO_memup(f->code+pc+1, f->code+pc, fs->pc-pc); | ||
| 190 | fs->pc++; | ||
| 191 | } | ||
| 192 | return code_oparg_at(ls, pc, op, builtin, arg, 0) - 2; | ||
| 193 | } | ||
| 194 | |||
| 195 | static void code_oparg (LexState *ls, OpCode op, int builtin, int arg, | ||
| 196 | int delta) { | ||
| 197 | check_pc(ls->fs, 3); /* maximum code size */ | ||
| 198 | ls->fs->pc += code_oparg_at(ls, ls->fs->pc, op, builtin, arg, delta); | ||
| 199 | } | ||
| 200 | |||
| 201 | |||
| 202 | static void code_opcode (LexState *ls, OpCode op, int delta) { | ||
| 203 | deltastack(ls, delta); | ||
| 204 | code_byte(ls->fs, op); | ||
| 205 | } | ||
| 206 | |||
| 207 | |||
| 208 | static void code_constant (LexState *ls, int c) { | ||
| 209 | code_oparg(ls, PUSHCONSTANT, 8, c, 1); | ||
| 210 | } | ||
| 211 | |||
| 212 | |||
| 213 | static int next_constant (FuncState *fs) { | ||
| 214 | TProtoFunc *f = fs->f; | ||
| 215 | if (f->nconsts >= fs->maxconsts) { | ||
| 216 | fs->maxconsts = luaM_growvector(&f->consts, fs->maxconsts, TObject, | ||
| 217 | constantEM, MAX_WORD); | ||
| 218 | } | ||
| 219 | return f->nconsts++; | ||
| 220 | } | ||
| 221 | |||
| 222 | |||
| 223 | static int string_constant (FuncState *fs, TaggedString *s) { | ||
| 224 | TProtoFunc *f = fs->f; | ||
| 225 | int c = s->constindex; | ||
| 226 | if (!(c < f->nconsts && | ||
| 227 | ttype(&f->consts[c]) == LUA_T_STRING && tsvalue(&f->consts[c]) == s)) { | ||
| 228 | c = next_constant(fs); | ||
| 229 | ttype(&f->consts[c]) = LUA_T_STRING; | ||
| 230 | tsvalue(&f->consts[c]) = s; | ||
| 231 | s->constindex = c; /* hint for next time */ | ||
| 232 | } | ||
| 233 | return c; | ||
| 234 | } | ||
| 235 | |||
| 236 | |||
| 237 | static void code_string (LexState *ls, TaggedString *s) { | ||
| 238 | code_constant(ls, string_constant(ls->fs, s)); | ||
| 239 | } | ||
| 240 | |||
| 241 | |||
| 242 | #define LIM 20 | ||
| 243 | static int real_constant (FuncState *fs, real r) { | ||
| 244 | /* check whether 'r' has appeared within the last LIM entries */ | ||
| 245 | TObject *cnt = fs->f->consts; | ||
| 246 | int c = fs->f->nconsts; | ||
| 247 | int lim = c < LIM ? 0 : c-LIM; | ||
| 248 | while (--c >= lim) { | ||
| 249 | if (ttype(&cnt[c]) == LUA_T_NUMBER && nvalue(&cnt[c]) == r) | ||
| 250 | return c; | ||
| 251 | } | ||
| 252 | /* not found; create a luaM_new entry */ | ||
| 253 | c = next_constant(fs); | ||
| 254 | cnt = fs->f->consts; /* 'next_constant' may reallocate this vector */ | ||
| 255 | ttype(&cnt[c]) = LUA_T_NUMBER; | ||
| 256 | nvalue(&cnt[c]) = r; | ||
| 257 | return c; | ||
| 258 | } | ||
| 259 | |||
| 260 | |||
| 261 | static void code_number (LexState *ls, real f) { | ||
| 262 | int i; | ||
| 263 | if (f >= 0 && f <= (real)MAX_WORD && (real)(i=(int)f) == f) | ||
| 264 | code_oparg(ls, PUSHNUMBER, 3, i, 1); /* f has a short integer value */ | ||
| 265 | else | ||
| 266 | code_constant(ls, real_constant(ls->fs, f)); | ||
| 267 | } | ||
| 268 | |||
| 269 | |||
| 270 | static void flush_record (LexState *ls, int n) { | ||
| 271 | if (n > 0) | ||
| 272 | code_oparg(ls, SETMAP, 1, n-1, -2*n); | ||
| 273 | } | ||
| 274 | |||
| 275 | |||
| 276 | static void flush_list (LexState *ls, int m, int n) { | ||
| 277 | if (n == 0) return; | ||
| 278 | code_oparg(ls, SETLIST, 1, m, -n); | ||
| 279 | code_byte(ls->fs, n); | ||
| 280 | } | ||
| 281 | |||
| 282 | |||
| 283 | static void luaI_registerlocalvar (FuncState *fs, TaggedString *varname, | ||
| 284 | int line) { | ||
| 285 | if (fs->maxvars != -1) { /* debug information? */ | ||
| 286 | TProtoFunc *f = fs->f; | ||
| 287 | if (fs->nvars >= fs->maxvars) | ||
| 288 | fs->maxvars = luaM_growvector(&f->locvars, fs->maxvars, | ||
| 289 | LocVar, "", MAX_WORD); | ||
| 290 | f->locvars[fs->nvars].varname = varname; | ||
| 291 | f->locvars[fs->nvars].line = line; | ||
| 292 | fs->nvars++; | ||
| 293 | } | ||
| 294 | } | ||
| 295 | |||
| 296 | |||
| 297 | static void luaI_unregisterlocalvar (FuncState *fs, int line) { | ||
| 298 | luaI_registerlocalvar(fs, NULL, line); | ||
| 299 | } | ||
| 300 | |||
| 301 | |||
| 302 | static void store_localvar (LexState *ls, TaggedString *name, int n) { | ||
| 303 | FuncState *fs = ls->fs; | ||
| 304 | if (fs->nlocalvar+n < MAXLOCALS) | ||
| 305 | fs->localvar[fs->nlocalvar+n] = name; | ||
| 306 | else | ||
| 307 | luaX_error(ls, "too many local variables " MES_LIM(SMAXLOCALS)); | ||
| 308 | luaI_registerlocalvar(fs, name, ls->linenumber); | ||
| 309 | } | ||
| 310 | |||
| 311 | |||
| 312 | static void add_localvar (LexState *ls, TaggedString *name) { | ||
| 313 | store_localvar(ls, name, 0); | ||
| 314 | ls->fs->nlocalvar++; | ||
| 315 | } | ||
| 316 | |||
| 317 | |||
| 318 | static int aux_localname (FuncState *fs, TaggedString *n) { | ||
| 319 | int i; | ||
| 320 | for (i=fs->nlocalvar-1; i >= 0; i--) | ||
| 321 | if (n == fs->localvar[i]) return i; /* local var index */ | ||
| 322 | return -1; /* not found */ | ||
| 323 | } | ||
| 324 | |||
| 325 | |||
| 326 | static void singlevar (LexState *ls, TaggedString *n, vardesc *var, int prev) { | ||
| 327 | FuncState *fs = prev ? ls->fs->prev : ls->fs; | ||
| 328 | int i = aux_localname(fs, n); | ||
| 329 | if (i >= 0) { /* local value */ | ||
| 330 | var->k = VLOCAL; | ||
| 331 | var->info = i; | ||
| 332 | } | ||
| 333 | else { /* check shadowing */ | ||
| 334 | FuncState *level = fs; | ||
| 335 | while ((level = level->prev) != NULL) | ||
| 336 | if (aux_localname(level, n) >= 0) | ||
| 337 | luaX_syntaxerror(ls, "cannot access a variable in outer scope", n->str); | ||
| 338 | var->k = VGLOBAL; | ||
| 339 | var->info = string_constant(fs, n); | ||
| 340 | } | ||
| 341 | } | ||
| 342 | |||
| 343 | |||
| 344 | static int indexupvalue (LexState *ls, TaggedString *n) { | ||
| 345 | FuncState *fs = ls->fs; | ||
| 346 | vardesc v; | ||
| 347 | int i; | ||
| 348 | singlevar(ls, n, &v, 1); | ||
| 349 | for (i=0; i<fs->nupvalues; i++) { | ||
| 350 | if (fs->upvalues[i].k == v.k && fs->upvalues[i].info == v.info) | ||
| 351 | return i; | ||
| 352 | } | ||
| 353 | /* new one */ | ||
| 354 | if (++(fs->nupvalues) > MAXUPVALUES) | ||
| 355 | luaX_error(ls, "too many upvalues in a single function " | ||
| 356 | MES_LIM(SMAXUPVALUES)); | ||
| 357 | fs->upvalues[i] = v; /* i = fs->nupvalues - 1 */ | ||
| 358 | return i; | ||
| 359 | } | ||
| 360 | |||
| 361 | |||
| 362 | static void pushupvalue (LexState *ls, TaggedString *n) { | ||
| 363 | int i; | ||
| 364 | if (ls->fs->prev == NULL) | ||
| 365 | luaX_syntaxerror(ls, "cannot access upvalue in main", n->str); | ||
| 366 | if (aux_localname(ls->fs, n) >= 0) | ||
| 367 | luaX_syntaxerror(ls, "cannot access an upvalue in current scope", n->str); | ||
| 368 | i = indexupvalue(ls, n); | ||
| 369 | code_oparg(ls, PUSHUPVALUE, 2, i, 1); | ||
| 370 | } | ||
| 371 | |||
| 372 | |||
| 373 | |||
| 374 | static void check_debugline (LexState *ls) { | ||
| 375 | if (lua_debug && ls->linenumber != ls->fs->lastsetline) { | ||
| 376 | code_oparg(ls, SETLINE, 0, ls->linenumber, 0); | ||
| 377 | ls->fs->lastsetline = ls->linenumber; | ||
| 378 | } | ||
| 379 | } | ||
| 380 | |||
| 381 | |||
| 382 | static void adjuststack (LexState *ls, int n) { | ||
| 383 | if (n > 0) | ||
| 384 | code_oparg(ls, POP, 2, n-1, -n); | ||
| 385 | else if (n < 0) | ||
| 386 | code_oparg(ls, PUSHNIL, 1, (-n)-1, -n); | ||
| 387 | } | ||
| 388 | |||
| 389 | |||
| 390 | static void close_exp (LexState *ls, int pc, int nresults) { | ||
| 391 | if (pc > 0) { /* expression is an open function call */ | ||
| 392 | Byte *code = ls->fs->f->code; | ||
| 393 | int nparams = code[pc]; /* save nparams */ | ||
| 394 | pc += fix_opcode(ls, pc-2, CALLFUNC, 2, nresults); | ||
| 395 | code[pc] = nparams; /* restore nparams */ | ||
| 396 | if (nresults != MULT_RET) | ||
| 397 | deltastack(ls, nresults); /* "push" results */ | ||
| 398 | deltastack(ls, -(nparams+1)); /* "pop" params and function */ | ||
| 399 | } | ||
| 400 | } | ||
| 401 | |||
| 402 | |||
| 403 | static void adjust_mult_assign (LexState *ls, int nvars, listdesc *d) { | ||
| 404 | int diff = d->n - nvars; | ||
| 405 | if (d->pc == 0) { /* list is closed */ | ||
| 406 | /* push or pop eventual difference between list lengths */ | ||
| 407 | adjuststack(ls, diff); | ||
| 408 | } | ||
| 409 | else { /* must correct function call */ | ||
| 410 | diff--; /* do not count function call itself */ | ||
| 411 | if (diff < 0) { /* more variables than values */ | ||
| 412 | /* function call must provide extra values */ | ||
| 413 | close_exp(ls, d->pc, -diff); | ||
| 414 | } | ||
| 415 | else { /* more values than variables */ | ||
| 416 | close_exp(ls, d->pc, 0); /* call should provide no value */ | ||
| 417 | adjuststack(ls, diff); /* pop eventual extra values */ | ||
| 418 | } | ||
| 419 | } | ||
| 420 | } | ||
| 421 | |||
| 422 | |||
| 423 | static void code_args (LexState *ls, int nparams, int dots) { | ||
| 424 | FuncState *fs = ls->fs; | ||
| 425 | fs->nlocalvar += nparams; /* "self" may already be there */ | ||
| 426 | nparams = fs->nlocalvar; | ||
| 427 | if (!dots) { | ||
| 428 | fs->f->code[1] = nparams; /* fill-in arg information */ | ||
| 429 | deltastack(ls, nparams); | ||
| 430 | } | ||
| 431 | else { | ||
| 432 | fs->f->code[1] = nparams+ZEROVARARG; | ||
| 433 | deltastack(ls, nparams+1); | ||
| 434 | add_localvar(ls, luaS_new("arg")); | ||
| 435 | } | ||
| 436 | } | ||
| 437 | |||
| 438 | |||
| 439 | static void lua_pushvar (LexState *ls, vardesc *var) { | ||
| 440 | switch (var->k) { | ||
| 441 | case VLOCAL: | ||
| 442 | code_oparg(ls, PUSHLOCAL, 8, var->info, 1); | ||
| 443 | break; | ||
| 444 | case VGLOBAL: | ||
| 445 | code_oparg(ls, GETGLOBAL, 8, var->info, 1); | ||
| 446 | break; | ||
| 447 | case VDOT: | ||
| 448 | code_oparg(ls, GETDOTTED, 8, var->info, 0); | ||
| 449 | break; | ||
| 450 | case VINDEXED: | ||
| 451 | code_opcode(ls, GETTABLE, -1); | ||
| 452 | break; | ||
| 453 | case VEXP: | ||
| 454 | close_exp(ls, var->info, 1); /* function must return 1 value */ | ||
| 455 | break; | ||
| 456 | } | ||
| 457 | var->k = VEXP; | ||
| 458 | var->info = 0; /* now this is a closed expression */ | ||
| 459 | } | ||
| 460 | |||
| 461 | |||
| 462 | static void storevar (LexState *ls, vardesc *var) { | ||
| 463 | switch (var->k) { | ||
| 464 | case VLOCAL: | ||
| 465 | code_oparg(ls, SETLOCAL, 8, var->info, -1); | ||
| 466 | break; | ||
| 467 | case VGLOBAL: | ||
| 468 | code_oparg(ls, SETGLOBAL, 8, var->info, -1); | ||
| 469 | break; | ||
| 470 | case VINDEXED: | ||
| 471 | code_opcode(ls, SETTABLE0, -3); | ||
| 472 | break; | ||
| 473 | default: | ||
| 474 | LUA_INTERNALERROR("invalid var kind to store"); | ||
| 475 | } | ||
| 476 | } | ||
| 477 | |||
| 478 | |||
| 479 | static int fix_jump (LexState *ls, int pc, OpCode op, int n) { | ||
| 480 | /* jump is relative to position following jump instruction */ | ||
| 481 | return fix_opcode(ls, pc, op, 0, n-(pc+JMPSIZE)); | ||
| 482 | } | ||
| 483 | |||
| 484 | |||
| 485 | static void fix_upjmp (LexState *ls, OpCode op, int pos) { | ||
| 486 | int delta = ls->fs->pc+JMPSIZE - pos; /* jump is relative */ | ||
| 487 | if (delta > 255) delta++; | ||
| 488 | code_oparg(ls, op, 0, delta, 0); | ||
| 489 | } | ||
| 490 | |||
| 491 | |||
| 492 | static void codeIf (LexState *ls, int thenAdd, int elseAdd) { | ||
| 493 | FuncState *fs = ls->fs; | ||
| 494 | int elseinit = elseAdd+JMPSIZE; | ||
| 495 | if (fs->pc == elseinit) { /* no else part */ | ||
| 496 | fs->pc -= JMPSIZE; | ||
| 497 | elseinit = fs->pc; | ||
| 498 | } | ||
| 499 | else | ||
| 500 | elseinit += fix_jump(ls, elseAdd, JMP, fs->pc); | ||
| 501 | fix_jump(ls, thenAdd, IFFJMP, elseinit); | ||
| 502 | } | ||
| 503 | |||
| 504 | |||
| 505 | static void func_onstack (LexState *ls, FuncState *func) { | ||
| 506 | FuncState *fs = ls->fs; | ||
| 507 | int i; | ||
| 508 | int c = next_constant(fs); | ||
| 509 | ttype(&fs->f->consts[c]) = LUA_T_PROTO; | ||
| 510 | fs->f->consts[c].value.tf = func->f; | ||
| 511 | if (func->nupvalues == 0) | ||
| 512 | code_constant(ls, c); | ||
| 513 | else { | ||
| 514 | for (i=0; i<func->nupvalues; i++) | ||
| 515 | lua_pushvar(ls, &func->upvalues[i]); | ||
| 516 | code_oparg(ls, CLOSURE, 0, c, -func->nupvalues+1); | ||
| 517 | code_byte(fs, func->nupvalues); | ||
| 518 | } | ||
| 519 | } | ||
| 520 | |||
| 521 | |||
| 522 | static void init_state (LexState *ls, FuncState *fs, TaggedString *filename) { | ||
| 523 | TProtoFunc *f = luaF_newproto(); | ||
| 524 | fs->prev = ls->fs; /* linked list of funcstates */ | ||
| 525 | ls->fs = fs; | ||
| 526 | fs->stacksize = 0; | ||
| 527 | fs->maxstacksize = 0; | ||
| 528 | fs->nlocalvar = 0; | ||
| 529 | fs->nupvalues = 0; | ||
| 530 | fs->lastsetline = 0; | ||
| 531 | fs->f = f; | ||
| 532 | f->fileName = filename; | ||
| 533 | fs->pc = 0; | ||
| 534 | fs->maxcode = 0; | ||
| 535 | f->code = NULL; | ||
| 536 | fs->maxconsts = 0; | ||
| 537 | if (lua_debug) | ||
| 538 | fs->nvars = fs->maxvars = 0; | ||
| 539 | else | ||
| 540 | fs->maxvars = -1; /* flag no debug information */ | ||
| 541 | code_byte(fs, 0); /* to be filled with stacksize */ | ||
| 542 | code_byte(fs, 0); /* to be filled with arg information */ | ||
| 543 | } | ||
| 544 | |||
| 545 | |||
| 546 | static void close_func (LexState *ls) { | ||
| 547 | FuncState *fs = ls->fs; | ||
| 548 | TProtoFunc *f = fs->f; | ||
| 549 | code_opcode(ls, ENDCODE, 0); | ||
| 550 | f->code[0] = fs->maxstacksize; | ||
| 551 | f->code = luaM_reallocvector(f->code, fs->pc, Byte); | ||
| 552 | f->consts = luaM_reallocvector(f->consts, f->nconsts, TObject); | ||
| 553 | if (fs->maxvars != -1) { /* debug information? */ | ||
| 554 | luaI_registerlocalvar(fs, NULL, -1); /* flag end of vector */ | ||
| 555 | f->locvars = luaM_reallocvector(f->locvars, fs->nvars, LocVar); | ||
| 556 | } | ||
| 557 | ls->fs = fs->prev; | ||
| 558 | } | ||
| 559 | |||
| 560 | |||
| 561 | |||
| 562 | static int expfollow [] = {ELSE, ELSEIF, THEN, IF, WHILE, REPEAT, DO, NAME, | ||
| 563 | LOCAL, FUNCTION, END, UNTIL, RETURN, ')', ']', '}', ';', EOS, ',', 0}; | ||
| 564 | |||
| 565 | static int is_in (int tok, int *toks) { | ||
| 566 | int *t = toks; | ||
| 567 | while (*t) { | ||
| 568 | if (*t == tok) | ||
| 569 | return t-toks; | ||
| 570 | t++; | ||
| 571 | } | ||
| 572 | return -1; | ||
| 573 | } | ||
| 574 | |||
| 575 | |||
| 576 | static void next (LexState *ls) { | ||
| 577 | ls->token = luaX_lex(ls); | ||
| 578 | } | ||
| 579 | |||
| 580 | |||
| 581 | static void error_expected (LexState *ls, int token) { | ||
| 582 | char buff[100], t[TOKEN_LEN]; | ||
| 583 | luaX_token2str(ls, token, t); | ||
| 584 | sprintf(buff, "`%s' expected", t); | ||
| 585 | luaX_error(ls, buff); | ||
| 586 | } | ||
| 587 | |||
| 588 | static void error_unmatched (LexState *ls, int what, int who, int where) { | ||
| 589 | if (where == ls->linenumber) | ||
| 590 | error_expected(ls, what); | ||
| 591 | else { | ||
| 592 | char buff[100]; | ||
| 593 | char t_what[TOKEN_LEN], t_who[TOKEN_LEN]; | ||
| 594 | luaX_token2str(ls, what, t_what); | ||
| 595 | luaX_token2str(ls, who, t_who); | ||
| 596 | sprintf(buff, "`%s' expected (to close `%s' at line %d)", | ||
| 597 | t_what, t_who, where); | ||
| 598 | luaX_error(ls, buff); | ||
| 599 | } | ||
| 600 | } | ||
| 601 | |||
| 602 | static void check (LexState *ls, int c) { | ||
| 603 | if (ls->token != c) | ||
| 604 | error_expected(ls, c); | ||
| 605 | next(ls); | ||
| 606 | } | ||
| 607 | |||
| 608 | static void check_match (LexState *ls, int what, int who, int where) { | ||
| 609 | if (ls->token != what) | ||
| 610 | error_unmatched(ls, what, who, where); | ||
| 611 | check_debugline(ls); /* to 'mark' the 'what' */ | ||
| 612 | next(ls); | ||
| 613 | } | ||
| 614 | |||
| 615 | static TaggedString *checkname (LexState *ls) { | ||
| 616 | TaggedString *ts; | ||
| 617 | if (ls->token != NAME) | ||
| 618 | luaX_error(ls, "`NAME' expected"); | ||
| 619 | ts = ls->seminfo.ts; | ||
| 620 | next(ls); | ||
| 621 | return ts; | ||
| 622 | } | ||
| 623 | |||
| 624 | |||
| 625 | static int optional (LexState *ls, int c) { | ||
| 626 | if (ls->token == c) { | ||
| 627 | next(ls); | ||
| 628 | return 1; | ||
| 629 | } | ||
| 630 | else return 0; | ||
| 631 | } | ||
| 632 | |||
| 633 | |||
| 634 | TProtoFunc *luaY_parser (ZIO *z) { | ||
| 635 | struct LexState lexstate; | ||
| 636 | struct FuncState funcstate; | ||
| 637 | luaX_setinput(&lexstate, z); | ||
| 638 | init_state(&lexstate, &funcstate, luaS_new(zname(z))); | ||
| 639 | next(&lexstate); /* read first token */ | ||
| 640 | chunk(&lexstate); | ||
| 641 | if (lexstate.token != EOS) | ||
| 642 | luaX_error(&lexstate, "<eof> expected"); | ||
| 643 | close_func(&lexstate); | ||
| 644 | return funcstate.f; | ||
| 645 | } | ||
| 646 | |||
| 647 | |||
| 648 | |||
| 649 | /*============================================================*/ | ||
| 650 | /* GRAMAR RULES */ | ||
| 651 | /*============================================================*/ | ||
| 652 | |||
| 653 | static void chunk (LexState *ls) { | ||
| 654 | /* chunk -> statlist ret */ | ||
| 655 | statlist(ls); | ||
| 656 | ret(ls); | ||
| 657 | } | ||
| 658 | |||
| 659 | static void statlist (LexState *ls) { | ||
| 660 | /* statlist -> { stat [;] } */ | ||
| 661 | while (stat(ls)) { | ||
| 662 | LUA_ASSERT(ls->fs->stacksize == ls->fs->nlocalvar, | ||
| 663 | "stack size != # local vars"); | ||
| 664 | optional(ls, ';'); | ||
| 665 | } | ||
| 666 | } | ||
| 667 | |||
| 668 | static int stat (LexState *ls) { | ||
| 669 | int line = ls->linenumber; /* may be needed for error messages */ | ||
| 670 | FuncState *fs = ls->fs; | ||
| 671 | switch (ls->token) { | ||
| 672 | case IF: { /* stat -> IF ifpart END */ | ||
| 673 | next(ls); | ||
| 674 | ifpart(ls); | ||
| 675 | check_match(ls, END, IF, line); | ||
| 676 | return 1; | ||
| 677 | } | ||
| 678 | |||
| 679 | case WHILE: { /* stat -> WHILE cond DO block END */ | ||
| 680 | TProtoFunc *f = fs->f; | ||
| 681 | int while_init = fs->pc; | ||
| 682 | int cond_end, cond_size; | ||
| 683 | next(ls); | ||
| 684 | cond_end = cond(ls); | ||
| 685 | check(ls, DO); | ||
| 686 | block(ls); | ||
| 687 | check_match(ls, END, WHILE, line); | ||
| 688 | cond_size = cond_end-while_init; | ||
| 689 | check_pc(fs, cond_size); | ||
| 690 | memcpy(f->code+fs->pc, f->code+while_init, cond_size); | ||
| 691 | luaO_memdown(f->code+while_init, f->code+cond_end, fs->pc-while_init); | ||
| 692 | while_init += JMPSIZE + fix_jump(ls, while_init, JMP, fs->pc-cond_size); | ||
| 693 | fix_upjmp(ls, IFTUPJMP, while_init); | ||
| 694 | return 1; | ||
| 695 | } | ||
| 696 | |||
| 697 | case DO: { /* stat -> DO block END */ | ||
| 698 | next(ls); | ||
| 699 | block(ls); | ||
| 700 | check_match(ls, END, DO, line); | ||
| 701 | return 1; | ||
| 702 | } | ||
| 703 | |||
| 704 | case REPEAT: { /* stat -> REPEAT block UNTIL exp1 */ | ||
| 705 | int repeat_init = fs->pc; | ||
| 706 | next(ls); | ||
| 707 | block(ls); | ||
| 708 | check_match(ls, UNTIL, REPEAT, line); | ||
| 709 | exp1(ls); | ||
| 710 | fix_upjmp(ls, IFFUPJMP, repeat_init); | ||
| 711 | deltastack(ls, -1); /* pops condition */ | ||
| 712 | return 1; | ||
| 713 | } | ||
| 714 | |||
| 715 | case FUNCTION: { /* stat -> FUNCTION funcname body */ | ||
| 716 | int needself; | ||
| 717 | vardesc v; | ||
| 718 | if (ls->fs->prev) /* inside other function? */ | ||
| 719 | return 0; | ||
| 720 | check_debugline(ls); | ||
| 721 | next(ls); | ||
| 722 | needself = funcname(ls, &v); | ||
| 723 | body(ls, needself, line); | ||
| 724 | storevar(ls, &v); | ||
| 725 | return 1; | ||
| 726 | } | ||
| 727 | |||
| 728 | case LOCAL: { /* stat -> LOCAL localnamelist decinit */ | ||
| 729 | listdesc d; | ||
| 730 | int nvars; | ||
| 731 | check_debugline(ls); | ||
| 732 | next(ls); | ||
| 733 | nvars = localnamelist(ls); | ||
| 734 | decinit(ls, &d); | ||
| 735 | ls->fs->nlocalvar += nvars; | ||
| 736 | adjust_mult_assign(ls, nvars, &d); | ||
| 737 | return 1; | ||
| 738 | } | ||
| 739 | |||
| 740 | case NAME: case '%': { /* stat -> func | ['%'] NAME assignment */ | ||
| 741 | vardesc v; | ||
| 742 | check_debugline(ls); | ||
| 743 | var_or_func(ls, &v); | ||
| 744 | if (v.k == VEXP) { /* stat -> func */ | ||
| 745 | if (v.info == 0) /* is just an upper value? */ | ||
| 746 | luaX_error(ls, "syntax error"); | ||
| 747 | close_exp(ls, v.info, 0); | ||
| 748 | } | ||
| 749 | else { | ||
| 750 | int left = assignment(ls, &v, 1); /* stat -> ['%'] NAME assignment */ | ||
| 751 | adjuststack(ls, left); /* remove eventual 'garbage' left on stack */ | ||
| 752 | } | ||
| 753 | return 1; | ||
| 754 | } | ||
| 755 | |||
| 756 | case RETURN: case ';': case ELSE: case ELSEIF: | ||
| 757 | case END: case UNTIL: case EOS: /* 'stat' follow */ | ||
| 758 | return 0; | ||
| 759 | |||
| 760 | default: | ||
| 761 | luaX_error(ls, "<statement> expected"); | ||
| 762 | return 0; /* to avoid warnings */ | ||
| 763 | } | ||
| 764 | } | ||
| 765 | |||
| 766 | static int SaveWord (LexState *ls) { | ||
| 767 | int res = ls->fs->pc; | ||
| 768 | check_pc(ls->fs, JMPSIZE); | ||
| 769 | ls->fs->pc += JMPSIZE; /* open space */ | ||
| 770 | return res; | ||
| 771 | } | ||
| 772 | |||
| 773 | static int SaveWordPop (LexState *ls) { | ||
| 774 | deltastack(ls, -1); /* pop condition */ | ||
| 775 | return SaveWord(ls); | ||
| 776 | } | ||
| 777 | |||
| 778 | static int cond (LexState *ls) { | ||
| 779 | /* cond -> exp1 */ | ||
| 780 | exp1(ls); | ||
| 781 | return SaveWordPop(ls); | ||
| 782 | } | ||
| 783 | |||
| 784 | static void block (LexState *ls) { | ||
| 785 | /* block -> chunk */ | ||
| 786 | FuncState *fs = ls->fs; | ||
| 787 | int nlocalvar = fs->nlocalvar; | ||
| 788 | chunk(ls); | ||
| 789 | adjuststack(ls, fs->nlocalvar - nlocalvar); | ||
| 790 | for (; fs->nlocalvar > nlocalvar; fs->nlocalvar--) | ||
| 791 | luaI_unregisterlocalvar(fs, ls->linenumber); | ||
| 792 | } | ||
| 793 | |||
| 794 | static int funcname (LexState *ls, vardesc *v) { | ||
| 795 | /* funcname -> NAME [':' NAME | '.' NAME] */ | ||
| 796 | int needself = 0; | ||
| 797 | singlevar(ls, checkname(ls), v, 0); | ||
| 798 | if (ls->token == ':' || ls->token == '.') { | ||
| 799 | needself = (ls->token == ':'); | ||
| 800 | next(ls); | ||
| 801 | lua_pushvar(ls, v); | ||
| 802 | code_string(ls, checkname(ls)); | ||
| 803 | v->k = VINDEXED; | ||
| 804 | } | ||
| 805 | return needself; | ||
| 806 | } | ||
| 807 | |||
| 808 | static void body (LexState *ls, int needself, int line) { | ||
| 809 | /* body -> '(' parlist ')' chunk END */ | ||
| 810 | FuncState newfs; | ||
| 811 | init_state(ls, &newfs, ls->fs->f->fileName); | ||
| 812 | newfs.f->lineDefined = line; | ||
| 813 | check(ls, '('); | ||
| 814 | if (needself) | ||
| 815 | add_localvar(ls, luaS_new("self")); | ||
| 816 | parlist(ls); | ||
| 817 | check(ls, ')'); | ||
| 818 | chunk(ls); | ||
| 819 | check_match(ls, END, FUNCTION, line); | ||
| 820 | close_func(ls); | ||
| 821 | func_onstack(ls, &newfs); | ||
| 822 | } | ||
| 823 | |||
| 824 | static void ifpart (LexState *ls) { | ||
| 825 | /* ifpart -> cond THEN block [ELSE block | ELSEIF ifpart] */ | ||
| 826 | int c = cond(ls); | ||
| 827 | int e; | ||
| 828 | check(ls, THEN); | ||
| 829 | block(ls); | ||
| 830 | e = SaveWord(ls); | ||
| 831 | switch (ls->token) { | ||
| 832 | case ELSE: | ||
| 833 | next(ls); | ||
| 834 | block(ls); | ||
| 835 | break; | ||
| 836 | |||
| 837 | case ELSEIF: | ||
| 838 | next(ls); | ||
| 839 | ifpart(ls); | ||
| 840 | break; | ||
| 841 | } | ||
| 842 | codeIf(ls, c, e); | ||
| 843 | } | ||
| 844 | |||
| 845 | static void ret (LexState *ls) { | ||
| 846 | /* ret -> [RETURN explist sc] */ | ||
| 847 | if (ls->token == RETURN) { | ||
| 848 | listdesc e; | ||
| 849 | check_debugline(ls); | ||
| 850 | next(ls); | ||
| 851 | explist(ls, &e); | ||
| 852 | close_exp(ls, e.pc, MULT_RET); | ||
| 853 | code_oparg(ls, RETCODE, 0, ls->fs->nlocalvar, 0); | ||
| 854 | ls->fs->stacksize = ls->fs->nlocalvar; /* removes all temp values */ | ||
| 855 | optional(ls, ';'); | ||
| 856 | } | ||
| 857 | } | ||
| 858 | |||
| 859 | |||
| 860 | /* | ||
| 861 | ** For parsing expressions, we use a classic stack with priorities. | ||
| 862 | ** Each binary operator is represented by its index in "binop" + FIRSTBIN | ||
| 863 | ** (EQ=2, NE=3, ... '^'=13). The unary NOT is 0 and UNMINUS is 1. | ||
| 864 | */ | ||
| 865 | |||
| 866 | /* code of first binary operator */ | ||
| 867 | #define FIRSTBIN 2 | ||
| 868 | |||
| 869 | /* code for power operator (last operator) | ||
| 870 | ** '^' needs special treatment because it is right associative | ||
| 871 | */ | ||
| 872 | #define POW 13 | ||
| 873 | |||
| 874 | static int binop [] = {EQ, NE, '>', '<', LE, GE, CONC, | ||
| 875 | '+', '-', '*', '/', '^', 0}; | ||
| 876 | |||
| 877 | static int priority [POW+1] = {5, 5, 1, 1, 1, 1, 1, 1, 2, 3, 3, 4, 4, 6}; | ||
| 878 | |||
| 879 | static OpCode opcodes [POW+1] = {NOTOP, MINUSOP, EQOP, NEQOP, GTOP, LTOP, | ||
| 880 | LEOP, GEOP, CONCOP, ADDOP, SUBOP, MULTOP, DIVOP, POWOP}; | ||
| 881 | |||
| 882 | #define MAXOPS 20 | ||
| 883 | |||
| 884 | typedef struct { | ||
| 885 | int ops[MAXOPS]; | ||
| 886 | int top; | ||
| 887 | } stack_op; | ||
| 888 | |||
| 889 | |||
| 890 | static void exp1 (LexState *ls) { | ||
| 891 | vardesc v; | ||
| 892 | exp(ls, &v); | ||
| 893 | lua_pushvar(ls, &v); | ||
| 894 | if (is_in(ls->token, expfollow) < 0) | ||
| 895 | luaX_error(ls, "ill formed expression"); | ||
| 896 | } | ||
| 897 | |||
| 898 | |||
| 899 | static void exp (LexState *ls, vardesc *v) { | ||
| 900 | exp2(ls, v); | ||
| 901 | while (ls->token == AND || ls->token == OR) { | ||
| 902 | int is_and = (ls->token == AND); | ||
| 903 | int pc; | ||
| 904 | lua_pushvar(ls, v); | ||
| 905 | next(ls); | ||
| 906 | pc = SaveWordPop(ls); | ||
| 907 | exp2(ls, v); | ||
| 908 | lua_pushvar(ls, v); | ||
| 909 | fix_jump(ls, pc, (is_and?ONFJMP:ONTJMP), ls->fs->pc); | ||
| 910 | } | ||
| 911 | } | ||
| 912 | |||
| 913 | |||
| 914 | static void push (LexState *ls, stack_op *s, int op) { | ||
| 915 | if (s->top == MAXOPS) | ||
| 916 | luaX_error(ls, "expression too complex"); | ||
| 917 | s->ops[s->top++] = op; | ||
| 918 | } | ||
| 919 | |||
| 920 | |||
| 921 | static void prefix (LexState *ls, stack_op *s) { | ||
| 922 | while (ls->token == NOT || ls->token == '-') { | ||
| 923 | push(ls, s, ls->token==NOT?0:1); | ||
| 924 | next(ls); | ||
| 925 | } | ||
| 926 | } | ||
| 927 | |||
| 928 | static void pop_to (LexState *ls, stack_op *s, int prio) { | ||
| 929 | int op; | ||
| 930 | while (s->top > 0 && priority[(op=s->ops[s->top-1])] >= prio) { | ||
| 931 | code_opcode(ls, opcodes[op], op<FIRSTBIN?0:-1); | ||
| 932 | s->top--; | ||
| 933 | } | ||
| 934 | } | ||
| 935 | |||
| 936 | static void exp2 (LexState *ls, vardesc *v) { | ||
| 937 | stack_op s; | ||
| 938 | int op; | ||
| 939 | s.top = 0; | ||
| 940 | prefix(ls, &s); | ||
| 941 | simpleexp(ls, v); | ||
| 942 | while ((op = is_in(ls->token, binop)) >= 0) { | ||
| 943 | op += FIRSTBIN; | ||
| 944 | lua_pushvar(ls, v); | ||
| 945 | /* '^' is right associative, so must 'simulate' a higher priority */ | ||
| 946 | pop_to(ls, &s, (op == POW)?priority[op]+1:priority[op]); | ||
| 947 | push(ls, &s, op); | ||
| 948 | next(ls); | ||
| 949 | prefix(ls, &s); | ||
| 950 | simpleexp(ls, v); | ||
| 951 | lua_pushvar(ls, v); | ||
| 952 | } | ||
| 953 | if (s.top > 0) { | ||
| 954 | lua_pushvar(ls, v); | ||
| 955 | pop_to(ls, &s, 0); | ||
| 956 | } | ||
| 957 | } | ||
| 958 | |||
| 959 | |||
| 960 | static void simpleexp (LexState *ls, vardesc *v) { | ||
| 961 | check_debugline(ls); | ||
| 962 | switch (ls->token) { | ||
| 963 | case '(': /* simpleexp -> '(' exp ')' */ | ||
| 964 | next(ls); | ||
| 965 | exp(ls, v); | ||
| 966 | check(ls, ')'); | ||
| 967 | break; | ||
| 968 | |||
| 969 | case NUMBER: /* simpleexp -> NUMBER */ | ||
| 970 | code_number(ls, ls->seminfo.r); | ||
| 971 | next(ls); | ||
| 972 | v->k = VEXP; v->info = 0; | ||
| 973 | break; | ||
| 974 | |||
| 975 | case STRING: /* simpleexp -> STRING */ | ||
| 976 | code_string(ls, ls->seminfo.ts); | ||
| 977 | next(ls); | ||
| 978 | v->k = VEXP; v->info = 0; | ||
| 979 | break; | ||
| 980 | |||
| 981 | case NIL: /* simpleexp -> NIL */ | ||
| 982 | adjuststack(ls, -1); | ||
| 983 | next(ls); | ||
| 984 | v->k = VEXP; v->info = 0; | ||
| 985 | break; | ||
| 986 | |||
| 987 | case '{': /* simpleexp -> constructor */ | ||
| 988 | constructor(ls); | ||
| 989 | v->k = VEXP; v->info = 0; | ||
| 990 | break; | ||
| 991 | |||
| 992 | case FUNCTION: { /* simpleexp -> FUNCTION body */ | ||
| 993 | int line = ls->linenumber; | ||
| 994 | next(ls); | ||
| 995 | body(ls, 0, line); | ||
| 996 | v->k = VEXP; v->info = 0; | ||
| 997 | break; | ||
| 998 | } | ||
| 999 | |||
| 1000 | case NAME: case '%': | ||
| 1001 | var_or_func(ls, v); | ||
| 1002 | break; | ||
| 1003 | |||
| 1004 | default: | ||
| 1005 | luaX_error(ls, "<expression> expected"); | ||
| 1006 | break; | ||
| 1007 | } | ||
| 1008 | } | ||
| 1009 | |||
| 1010 | static void var_or_func (LexState *ls, vardesc *v) { | ||
| 1011 | /* var_or_func -> ['%'] NAME var_or_func_tail */ | ||
| 1012 | if (optional(ls, '%')) { /* upvalue? */ | ||
| 1013 | pushupvalue(ls, checkname(ls)); | ||
| 1014 | v->k = VEXP; | ||
| 1015 | v->info = 0; /* closed expression */ | ||
| 1016 | } | ||
| 1017 | else /* variable name */ | ||
| 1018 | singlevar(ls, checkname(ls), v, 0); | ||
| 1019 | var_or_func_tail(ls, v); | ||
| 1020 | } | ||
| 1021 | |||
| 1022 | static void var_or_func_tail (LexState *ls, vardesc *v) { | ||
| 1023 | for (;;) { | ||
| 1024 | switch (ls->token) { | ||
| 1025 | case '.': /* var_or_func_tail -> '.' NAME */ | ||
| 1026 | next(ls); | ||
| 1027 | lua_pushvar(ls, v); /* 'v' must be on stack */ | ||
| 1028 | v->k = VDOT; | ||
| 1029 | v->info = string_constant(ls->fs, checkname(ls)); | ||
| 1030 | break; | ||
| 1031 | |||
| 1032 | case '[': /* var_or_func_tail -> '[' exp1 ']' */ | ||
| 1033 | next(ls); | ||
| 1034 | lua_pushvar(ls, v); /* 'v' must be on stack */ | ||
| 1035 | exp1(ls); | ||
| 1036 | check(ls, ']'); | ||
| 1037 | v->k = VINDEXED; | ||
| 1038 | break; | ||
| 1039 | |||
| 1040 | case ':': /* var_or_func_tail -> ':' NAME funcparams */ | ||
| 1041 | next(ls); | ||
| 1042 | lua_pushvar(ls, v); /* 'v' must be on stack */ | ||
| 1043 | code_oparg(ls, PUSHSELF, 8, string_constant(ls->fs, checkname(ls)), 1); | ||
| 1044 | v->k = VEXP; | ||
| 1045 | v->info = funcparams(ls, 1); | ||
| 1046 | break; | ||
| 1047 | |||
| 1048 | case '(': case STRING: case '{': /* var_or_func_tail -> funcparams */ | ||
| 1049 | lua_pushvar(ls, v); /* 'v' must be on stack */ | ||
| 1050 | v->k = VEXP; | ||
| 1051 | v->info = funcparams(ls, 0); | ||
| 1052 | break; | ||
| 1053 | |||
| 1054 | default: return; /* should be follow... */ | ||
| 1055 | } | ||
| 1056 | } | ||
| 1057 | } | ||
| 1058 | |||
| 1059 | static int funcparams (LexState *ls, int slf) { | ||
| 1060 | FuncState *fs = ls->fs; | ||
| 1061 | int nparams = 1; /* default value */ | ||
| 1062 | switch (ls->token) { | ||
| 1063 | case '(': { /* funcparams -> '(' explist ')' */ | ||
| 1064 | listdesc e; | ||
| 1065 | next(ls); | ||
| 1066 | explist(ls, &e); | ||
| 1067 | check(ls, ')'); | ||
| 1068 | close_exp(ls, e.pc, 1); | ||
| 1069 | nparams = e.n; | ||
| 1070 | break; | ||
| 1071 | } | ||
| 1072 | |||
| 1073 | case '{': /* funcparams -> constructor */ | ||
| 1074 | constructor(ls); | ||
| 1075 | break; | ||
| 1076 | |||
| 1077 | case STRING: /* funcparams -> STRING */ | ||
| 1078 | next(ls); | ||
| 1079 | break; | ||
| 1080 | |||
| 1081 | default: | ||
| 1082 | luaX_error(ls, "function arguments expected"); | ||
| 1083 | break; | ||
| 1084 | } | ||
| 1085 | code_byte(fs, 0); /* save space for opcode */ | ||
| 1086 | code_byte(fs, 0); /* and nresult */ | ||
| 1087 | code_byte(fs, nparams+slf); | ||
| 1088 | return fs->pc-1; | ||
| 1089 | } | ||
| 1090 | |||
| 1091 | static void explist (LexState *ls, listdesc *d) { | ||
| 1092 | switch (ls->token) { | ||
| 1093 | case ELSE: case ELSEIF: case END: case UNTIL: | ||
| 1094 | case EOS: case ';': case ')': | ||
| 1095 | d->pc = 0; | ||
| 1096 | d->n = 0; | ||
| 1097 | break; | ||
| 1098 | |||
| 1099 | default: | ||
| 1100 | explist1(ls, d); | ||
| 1101 | } | ||
| 1102 | } | ||
| 1103 | |||
| 1104 | static void explist1 (LexState *ls, listdesc *d) { | ||
| 1105 | vardesc v; | ||
| 1106 | exp(ls, &v); | ||
| 1107 | d->n = 1; | ||
| 1108 | while (ls->token == ',') { | ||
| 1109 | d->n++; | ||
| 1110 | lua_pushvar(ls, &v); | ||
| 1111 | next(ls); | ||
| 1112 | exp(ls, &v); | ||
| 1113 | } | ||
| 1114 | if (v.k == VEXP) | ||
| 1115 | d->pc = v.info; | ||
| 1116 | else { | ||
| 1117 | lua_pushvar(ls, &v); | ||
| 1118 | d->pc = 0; | ||
| 1119 | } | ||
| 1120 | } | ||
| 1121 | |||
| 1122 | static void parlist (LexState *ls) { | ||
| 1123 | int nparams = 0; | ||
| 1124 | int dots = 0; | ||
| 1125 | switch (ls->token) { | ||
| 1126 | case DOTS: /* parlist -> DOTS */ | ||
| 1127 | next(ls); | ||
| 1128 | dots = 1; | ||
| 1129 | break; | ||
| 1130 | |||
| 1131 | case NAME: /* parlist, tailparlist -> NAME [',' tailparlist] */ | ||
| 1132 | init: | ||
| 1133 | store_localvar(ls, checkname(ls), nparams++); | ||
| 1134 | if (ls->token == ',') { | ||
| 1135 | next(ls); | ||
| 1136 | switch (ls->token) { | ||
| 1137 | case DOTS: /* tailparlist -> DOTS */ | ||
| 1138 | next(ls); | ||
| 1139 | dots = 1; | ||
| 1140 | break; | ||
| 1141 | |||
| 1142 | case NAME: /* tailparlist -> NAME [',' tailparlist] */ | ||
| 1143 | goto init; | ||
| 1144 | |||
| 1145 | default: luaX_error(ls, "NAME or `...' expected"); | ||
| 1146 | } | ||
| 1147 | } | ||
| 1148 | break; | ||
| 1149 | |||
| 1150 | case ')': break; /* parlist -> empty */ | ||
| 1151 | |||
| 1152 | default: luaX_error(ls, "NAME or `...' expected"); | ||
| 1153 | } | ||
| 1154 | code_args(ls, nparams, dots); | ||
| 1155 | } | ||
| 1156 | |||
| 1157 | static int localnamelist (LexState *ls) { | ||
| 1158 | /* localnamelist -> NAME {',' NAME} */ | ||
| 1159 | int i = 1; | ||
| 1160 | store_localvar(ls, checkname(ls), 0); | ||
| 1161 | while (ls->token == ',') { | ||
| 1162 | next(ls); | ||
| 1163 | store_localvar(ls, checkname(ls), i++); | ||
| 1164 | } | ||
| 1165 | return i; | ||
| 1166 | } | ||
| 1167 | |||
| 1168 | static void decinit (LexState *ls, listdesc *d) { | ||
| 1169 | /* decinit -> ['=' explist1] */ | ||
| 1170 | if (ls->token == '=') { | ||
| 1171 | next(ls); | ||
| 1172 | explist1(ls, d); | ||
| 1173 | } | ||
| 1174 | else { | ||
| 1175 | d->n = 0; | ||
| 1176 | d->pc = 0; | ||
| 1177 | } | ||
| 1178 | } | ||
| 1179 | |||
| 1180 | static int assignment (LexState *ls, vardesc *v, int nvars) { | ||
| 1181 | int left = 0; | ||
| 1182 | /* dotted variables <a.x> must be stored like regular indexed vars <a["x"]> */ | ||
| 1183 | if (v->k == VDOT) { | ||
| 1184 | code_constant(ls, v->info); | ||
| 1185 | v->k = VINDEXED; | ||
| 1186 | } | ||
| 1187 | if (ls->token == ',') { /* assignment -> ',' NAME assignment */ | ||
| 1188 | vardesc nv; | ||
| 1189 | next(ls); | ||
| 1190 | var_or_func(ls, &nv); | ||
| 1191 | if (nv.k == VEXP) | ||
| 1192 | luaX_error(ls, "syntax error"); | ||
| 1193 | left = assignment(ls, &nv, nvars+1); | ||
| 1194 | } | ||
| 1195 | else { /* assignment -> '=' explist1 */ | ||
| 1196 | listdesc d; | ||
| 1197 | check(ls, '='); | ||
| 1198 | explist1(ls, &d); | ||
| 1199 | adjust_mult_assign(ls, nvars, &d); | ||
| 1200 | } | ||
| 1201 | if (v->k != VINDEXED || left+(nvars-1) == 0) { | ||
| 1202 | /* global/local var or indexed var without values in between */ | ||
| 1203 | storevar(ls, v); | ||
| 1204 | } | ||
| 1205 | else { /* indexed var with values in between*/ | ||
| 1206 | code_oparg(ls, SETTABLE, 0, left+(nvars-1), -1); | ||
| 1207 | left += 2; /* table/index are not popped, because they aren't on top */ | ||
| 1208 | } | ||
| 1209 | return left; | ||
| 1210 | } | ||
| 1211 | |||
| 1212 | static void constructor (LexState *ls) { | ||
| 1213 | /* constructor -> '{' part [';' part] '}' */ | ||
| 1214 | int line = ls->linenumber; | ||
| 1215 | int pc = SaveWord(ls); | ||
| 1216 | int nelems; | ||
| 1217 | constdesc cd; | ||
| 1218 | deltastack(ls, 1); | ||
| 1219 | check(ls, '{'); | ||
| 1220 | part(ls, &cd); | ||
| 1221 | nelems = cd.n; | ||
| 1222 | if (ls->token == ';') { | ||
| 1223 | constdesc other_cd; | ||
| 1224 | next(ls); | ||
| 1225 | part(ls, &other_cd); | ||
| 1226 | if (cd.k == other_cd.k) /* repeated parts? */ | ||
| 1227 | luaX_error(ls, "invalid constructor syntax"); | ||
| 1228 | nelems += other_cd.n; | ||
| 1229 | } | ||
| 1230 | check_match(ls, '}', '{', line); | ||
| 1231 | fix_opcode(ls, pc, CREATEARRAY, 2, nelems); | ||
| 1232 | } | ||
| 1233 | |||
| 1234 | static void part (LexState *ls, constdesc *cd) { | ||
| 1235 | switch (ls->token) { | ||
| 1236 | case ';': case '}': /* part -> empty */ | ||
| 1237 | cd->n = 0; | ||
| 1238 | cd->k = ls->token; | ||
| 1239 | return; | ||
| 1240 | |||
| 1241 | case NAME: { | ||
| 1242 | vardesc v; | ||
| 1243 | exp(ls, &v); | ||
| 1244 | if (ls->token == '=') { | ||
| 1245 | switch (v.k) { | ||
| 1246 | case VGLOBAL: | ||
| 1247 | code_constant(ls, v.info); | ||
| 1248 | break; | ||
| 1249 | case VLOCAL: | ||
| 1250 | code_string(ls, ls->fs->localvar[v.info]); | ||
| 1251 | break; | ||
| 1252 | default: | ||
| 1253 | luaX_error(ls, "`=' unexpected"); | ||
| 1254 | } | ||
| 1255 | next(ls); | ||
| 1256 | exp1(ls); | ||
| 1257 | cd->n = recfields(ls); | ||
| 1258 | cd->k = 1; /* record */ | ||
| 1259 | } | ||
| 1260 | else { | ||
| 1261 | lua_pushvar(ls, &v); | ||
| 1262 | cd->n = listfields(ls); | ||
| 1263 | cd->k = 0; /* list */ | ||
| 1264 | } | ||
| 1265 | break; | ||
| 1266 | } | ||
| 1267 | |||
| 1268 | case '[': /* part -> recfield recfields */ | ||
| 1269 | recfield(ls); | ||
| 1270 | cd->n = recfields(ls); | ||
| 1271 | cd->k = 1; /* record */ | ||
| 1272 | break; | ||
| 1273 | |||
| 1274 | default: /* part -> exp1 listfields */ | ||
| 1275 | exp1(ls); | ||
| 1276 | cd->n = listfields(ls); | ||
| 1277 | cd->k = 0; /* list */ | ||
| 1278 | break; | ||
| 1279 | } | ||
| 1280 | } | ||
| 1281 | |||
| 1282 | static int recfields (LexState *ls) { | ||
| 1283 | /* recfields -> { ',' recfield } [','] */ | ||
| 1284 | int n = 1; /* one has been read before */ | ||
| 1285 | while (ls->token == ',') { | ||
| 1286 | next(ls); | ||
| 1287 | if (ls->token == ';' || ls->token == '}') | ||
| 1288 | break; | ||
| 1289 | recfield(ls); | ||
| 1290 | n++; | ||
| 1291 | if (n%RFIELDS_PER_FLUSH == 0) | ||
| 1292 | flush_record(ls, RFIELDS_PER_FLUSH); | ||
| 1293 | } | ||
| 1294 | flush_record(ls, n%RFIELDS_PER_FLUSH); | ||
| 1295 | return n; | ||
| 1296 | } | ||
| 1297 | |||
| 1298 | static int listfields (LexState *ls) { | ||
| 1299 | /* listfields -> { ',' exp1 } [','] */ | ||
| 1300 | int n = 1; /* one has been read before */ | ||
| 1301 | while (ls->token == ',') { | ||
| 1302 | next(ls); | ||
| 1303 | if (ls->token == ';' || ls->token == '}') | ||
| 1304 | break; | ||
| 1305 | exp1(ls); | ||
| 1306 | n++; | ||
| 1307 | if (n%LFIELDS_PER_FLUSH == 0) | ||
| 1308 | flush_list(ls, n/LFIELDS_PER_FLUSH - 1, LFIELDS_PER_FLUSH); | ||
| 1309 | } | ||
| 1310 | flush_list(ls, n/LFIELDS_PER_FLUSH, n%LFIELDS_PER_FLUSH); | ||
| 1311 | return n; | ||
| 1312 | } | ||
| 1313 | |||
| 1314 | static void recfield (LexState *ls) { | ||
| 1315 | /* recfield -> (NAME | '['exp1']') = exp1 */ | ||
| 1316 | switch (ls->token) { | ||
| 1317 | case NAME: | ||
| 1318 | code_string(ls, checkname(ls)); | ||
| 1319 | break; | ||
| 1320 | |||
| 1321 | case '[': | ||
| 1322 | next(ls); | ||
| 1323 | exp1(ls); | ||
| 1324 | check(ls, ']'); | ||
| 1325 | break; | ||
| 1326 | |||
| 1327 | default: luaX_error(ls, "NAME or `[' expected"); | ||
| 1328 | } | ||
| 1329 | check(ls, '='); | ||
| 1330 | exp1(ls); | ||
| 1331 | } | ||
| 1332 | |||
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | ** $Id: lstate.h,v 1.6 1997/12/17 20:48:58 roberto Exp roberto $ | 2 | ** $Id: lstate.h,v 1.7 1998/01/09 14:57:43 roberto Exp $ |
| 3 | ** Global State | 3 | ** Global State |
| 4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
| 5 | */ | 5 | */ |
| @@ -57,8 +57,6 @@ typedef struct LState { | |||
| 57 | struct IM *IMtable; /* table for tag methods */ | 57 | struct IM *IMtable; /* table for tag methods */ |
| 58 | int IMtable_size; /* size of IMtable */ | 58 | int IMtable_size; /* size of IMtable */ |
| 59 | int last_tag; /* last used tag in IMtable */ | 59 | int last_tag; /* last used tag in IMtable */ |
| 60 | struct FuncState *mainState, *currState; /* point to local structs in yacc */ | ||
| 61 | struct LexState *lexstate; /* point to local struct in yacc */ | ||
| 62 | struct ref *refArray; /* locked objects */ | 60 | struct ref *refArray; /* locked objects */ |
| 63 | int refSize; /* size of refArray */ | 61 | int refSize; /* size of refArray */ |
| 64 | unsigned long GCthreshold; | 62 | unsigned long GCthreshold; |
diff --git a/lua.stx b/lua.stx deleted file mode 100644 index 41aff108..00000000 --- a/lua.stx +++ /dev/null | |||
| @@ -1,940 +0,0 @@ | |||
| 1 | %{ | ||
| 2 | /* | ||
| 3 | ** $Id: lua.stx,v 1.36 1998/03/25 18:52:29 roberto Exp roberto $ | ||
| 4 | ** Syntax analizer and code generator | ||
| 5 | ** See Copyright Notice in lua.h | ||
| 6 | */ | ||
| 7 | |||
| 8 | |||
| 9 | #include <stdlib.h> | ||
| 10 | #include <string.h> | ||
| 11 | |||
| 12 | #include "lauxlib.h" | ||
| 13 | #include "ldo.h" | ||
| 14 | #include "lfunc.h" | ||
| 15 | #include "llex.h" | ||
| 16 | #include "lmem.h" | ||
| 17 | #include "lopcodes.h" | ||
| 18 | #include "lparser.h" | ||
| 19 | #include "lstate.h" | ||
| 20 | #include "lstring.h" | ||
| 21 | #include "lua.h" | ||
| 22 | #include "luadebug.h" | ||
| 23 | #include "lzio.h" | ||
| 24 | |||
| 25 | |||
| 26 | int luaY_parse (void); | ||
| 27 | |||
| 28 | |||
| 29 | #define MES_LIM(x) "(limit=" x ")" | ||
| 30 | |||
| 31 | |||
| 32 | /* size of a "normal" jump instruction: OpCode + 1 byte */ | ||
| 33 | #define JMPSIZE 2 | ||
| 34 | |||
| 35 | /* maximum number of local variables */ | ||
| 36 | #define MAXLOCALS 32 | ||
| 37 | #define SMAXLOCALS "32" | ||
| 38 | |||
| 39 | #define MINGLOBAL (MAXLOCALS+1) | ||
| 40 | |||
| 41 | /* maximum number of variables in a multiple assignment */ | ||
| 42 | #define MAXVAR 32 | ||
| 43 | #define SMAXVAR "32" | ||
| 44 | |||
| 45 | /* maximum number of nested functions */ | ||
| 46 | #define MAXSTATES 6 | ||
| 47 | #define SMAXSTATES "6" | ||
| 48 | |||
| 49 | /* maximum number of upvalues */ | ||
| 50 | #define MAXUPVALUES 16 | ||
| 51 | #define SMAXUPVALUES "16" | ||
| 52 | |||
| 53 | |||
| 54 | |||
| 55 | /* | ||
| 56 | ** Variable descriptor: | ||
| 57 | ** if 0<n<MINGLOBAL, represents local variable indexed by (n-1); | ||
| 58 | ** if MINGLOBAL<=n, represents global variable at position (n-MINGLOBAL); | ||
| 59 | ** if n<0, indexed variable with index (-n)-1 (table on top of stack); | ||
| 60 | ** if n==0, an indexed variable (table and index on top of stack) | ||
| 61 | ** Must be long to store negative Word values. | ||
| 62 | */ | ||
| 63 | typedef long vardesc; | ||
| 64 | |||
| 65 | #define isglobal(v) (MINGLOBAL<=(v)) | ||
| 66 | #define globalindex(v) ((v)-MINGLOBAL) | ||
| 67 | #define islocal(v) (0<(v) && (v)<MINGLOBAL) | ||
| 68 | #define localindex(v) ((v)-1) | ||
| 69 | #define isdot(v) (v<0) | ||
| 70 | #define dotindex(v) ((-(v))-1) | ||
| 71 | |||
| 72 | /* state needed to generate code for a given function */ | ||
| 73 | typedef struct FuncState { | ||
| 74 | TProtoFunc *f; /* current function header */ | ||
| 75 | int pc; /* next position to code */ | ||
| 76 | TaggedString *localvar[MAXLOCALS]; /* store local variable names */ | ||
| 77 | int stacksize; /* number of values on activation register */ | ||
| 78 | int maxstacksize; /* maximum number of values on activation register */ | ||
| 79 | int nlocalvar; /* number of active local variables */ | ||
| 80 | int nupvalues; /* number of upvalues */ | ||
| 81 | int nvars; /* number of entries in f->locvars */ | ||
| 82 | int maxcode; /* size of f->code */ | ||
| 83 | int maxvars; /* size of f->locvars (-1 if no debug information) */ | ||
| 84 | int maxconsts; /* size of f->consts */ | ||
| 85 | vardesc varbuffer[MAXVAR]; /* variables in an assignment list */ | ||
| 86 | vardesc upvalues[MAXUPVALUES]; /* upvalues */ | ||
| 87 | } FuncState; | ||
| 88 | |||
| 89 | |||
| 90 | |||
| 91 | #define YYPURE 1 | ||
| 92 | |||
| 93 | |||
| 94 | void luaY_syntaxerror (char *s, char *token) | ||
| 95 | { | ||
| 96 | if (token[0] == 0) | ||
| 97 | token = "<eof>"; | ||
| 98 | luaL_verror("%.100s;\n last token read: \"%.50s\" at line %d in file %.50s", | ||
| 99 | s, token, L->lexstate->linenumber, L->mainState->f->fileName->str); | ||
| 100 | } | ||
| 101 | |||
| 102 | |||
| 103 | void luaY_error (char *s) | ||
| 104 | { | ||
| 105 | luaY_syntaxerror(s, luaX_lasttoken()); | ||
| 106 | } | ||
| 107 | |||
| 108 | |||
| 109 | static void check_pc (int n) | ||
| 110 | { | ||
| 111 | FuncState *fs = L->currState; | ||
| 112 | if (fs->pc+n > fs->maxcode) | ||
| 113 | fs->maxcode = luaM_growvector(&fs->f->code, fs->maxcode, | ||
| 114 | Byte, codeEM, MAX_INT); | ||
| 115 | } | ||
| 116 | |||
| 117 | |||
| 118 | static void code_byte (Byte c) | ||
| 119 | { | ||
| 120 | check_pc(1); | ||
| 121 | L->currState->f->code[L->currState->pc++] = c; | ||
| 122 | } | ||
| 123 | |||
| 124 | |||
| 125 | static void deltastack (int delta) | ||
| 126 | { | ||
| 127 | FuncState *fs = L->currState; | ||
| 128 | fs->stacksize += delta; | ||
| 129 | if (fs->stacksize > fs->maxstacksize) { | ||
| 130 | if (fs->stacksize > 255) | ||
| 131 | luaY_error("function/expression too complex"); | ||
| 132 | fs->maxstacksize = fs->stacksize; | ||
| 133 | } | ||
| 134 | } | ||
| 135 | |||
| 136 | |||
| 137 | static int code_oparg_at (int pc, OpCode op, int builtin, int arg, int delta) | ||
| 138 | { | ||
| 139 | Byte *code = L->currState->f->code; | ||
| 140 | deltastack(delta); | ||
| 141 | if (arg < builtin) { | ||
| 142 | code[pc] = op+1+arg; | ||
| 143 | return 1; | ||
| 144 | } | ||
| 145 | else if (arg <= 255) { | ||
| 146 | code[pc] = op; | ||
| 147 | code[pc+1] = arg; | ||
| 148 | return 2; | ||
| 149 | } | ||
| 150 | else if (arg <= MAX_WORD) { | ||
| 151 | code[pc] = op+1+builtin; | ||
| 152 | code[pc+1] = arg>>8; | ||
| 153 | code[pc+2] = arg&0xFF; | ||
| 154 | return 3; | ||
| 155 | } | ||
| 156 | else luaY_error("code too long " MES_LIM("64K")); | ||
| 157 | return 0; /* to avoid warnings */ | ||
| 158 | } | ||
| 159 | |||
| 160 | |||
| 161 | static int fix_opcode (int pc, OpCode op, int builtin, int arg) | ||
| 162 | { | ||
| 163 | FuncState *fs = L->currState; | ||
| 164 | if (arg < builtin) { /* close space */ | ||
| 165 | luaO_memdown(fs->f->code+pc+1, fs->f->code+pc+2, fs->pc-(pc+2)); | ||
| 166 | fs->pc--; | ||
| 167 | } | ||
| 168 | else if (arg > 255) { /* open space */ | ||
| 169 | check_pc(1); | ||
| 170 | luaO_memup(fs->f->code+pc+1, fs->f->code+pc, fs->pc-pc); | ||
| 171 | fs->pc++; | ||
| 172 | } | ||
| 173 | return code_oparg_at(pc, op, builtin, arg, 0) - 2; | ||
| 174 | } | ||
| 175 | |||
| 176 | |||
| 177 | static void code_oparg (OpCode op, int builtin, int arg, int delta) | ||
| 178 | { | ||
| 179 | check_pc(3); /* maximum code size */ | ||
| 180 | L->currState->pc += code_oparg_at(L->currState->pc, op, builtin, arg, delta); | ||
| 181 | } | ||
| 182 | |||
| 183 | |||
| 184 | static void code_opcode (OpCode op, int delta) | ||
| 185 | { | ||
| 186 | deltastack(delta); | ||
| 187 | code_byte(op); | ||
| 188 | } | ||
| 189 | |||
| 190 | |||
| 191 | static void code_pop (OpCode op) | ||
| 192 | { | ||
| 193 | code_opcode(op, -1); | ||
| 194 | } | ||
| 195 | |||
| 196 | /* binary operations get 2 arguments and leave one, so they pop one */ | ||
| 197 | #define code_binop(op) code_pop(op) | ||
| 198 | |||
| 199 | |||
| 200 | static void code_neutralop (OpCode op) | ||
| 201 | { | ||
| 202 | code_opcode(op, 0); | ||
| 203 | } | ||
| 204 | |||
| 205 | /* unary operations get 1 argument and leave one, so they are neutral */ | ||
| 206 | #define code_unop(op) code_neutralop(op) | ||
| 207 | |||
| 208 | |||
| 209 | static void code_constant (int c) | ||
| 210 | { | ||
| 211 | code_oparg(PUSHCONSTANT, 8, c, 1); | ||
| 212 | } | ||
| 213 | |||
| 214 | |||
| 215 | static int next_constant (FuncState *cs) | ||
| 216 | { | ||
| 217 | TProtoFunc *f = cs->f; | ||
| 218 | if (f->nconsts >= cs->maxconsts) { | ||
| 219 | cs->maxconsts = luaM_growvector(&f->consts, cs->maxconsts, TObject, | ||
| 220 | constantEM, MAX_WORD); | ||
| 221 | } | ||
| 222 | return f->nconsts++; | ||
| 223 | } | ||
| 224 | |||
| 225 | |||
| 226 | static int string_constant (TaggedString *s, FuncState *cs) | ||
| 227 | { | ||
| 228 | TProtoFunc *f = cs->f; | ||
| 229 | int c = s->constindex; | ||
| 230 | if (!(c < f->nconsts && | ||
| 231 | ttype(&f->consts[c]) == LUA_T_STRING && tsvalue(&f->consts[c]) == s)) { | ||
| 232 | c = next_constant(cs); | ||
| 233 | ttype(&f->consts[c]) = LUA_T_STRING; | ||
| 234 | tsvalue(&f->consts[c]) = s; | ||
| 235 | s->constindex = c; /* hint for next time */ | ||
| 236 | } | ||
| 237 | return c; | ||
| 238 | } | ||
| 239 | |||
| 240 | |||
| 241 | static void code_string (TaggedString *s) | ||
| 242 | { | ||
| 243 | code_constant(string_constant(s, L->currState)); | ||
| 244 | } | ||
| 245 | |||
| 246 | |||
| 247 | #define LIM 20 | ||
| 248 | static int real_constant (real r) | ||
| 249 | { | ||
| 250 | /* check whether 'r' has appeared within the last LIM entries */ | ||
| 251 | TObject *cnt = L->currState->f->consts; | ||
| 252 | int c = L->currState->f->nconsts; | ||
| 253 | int lim = c < LIM ? 0 : c-LIM; | ||
| 254 | while (--c >= lim) { | ||
| 255 | if (ttype(&cnt[c]) == LUA_T_NUMBER && nvalue(&cnt[c]) == r) | ||
| 256 | return c; | ||
| 257 | } | ||
| 258 | /* not found; create a luaM_new entry */ | ||
| 259 | c = next_constant(L->currState); | ||
| 260 | cnt = L->currState->f->consts; /* 'next_constant' may reallocate this vector */ | ||
| 261 | ttype(&cnt[c]) = LUA_T_NUMBER; | ||
| 262 | nvalue(&cnt[c]) = r; | ||
| 263 | return c; | ||
| 264 | } | ||
| 265 | |||
| 266 | |||
| 267 | static void code_number (real f) | ||
| 268 | { | ||
| 269 | int i; | ||
| 270 | if (f >= 0 && f <= (real)MAX_WORD && (real)(i=(int)f) == f) | ||
| 271 | code_oparg(PUSHNUMBER, 3, i, 1); /* f has an (short) integer value */ | ||
| 272 | else | ||
| 273 | code_constant(real_constant(f)); | ||
| 274 | } | ||
| 275 | |||
| 276 | |||
| 277 | static void flush_record (int n) | ||
| 278 | { | ||
| 279 | if (n > 0) | ||
| 280 | code_oparg(SETMAP, 1, n-1, -2*n); | ||
| 281 | } | ||
| 282 | |||
| 283 | static void flush_list (int m, int n) | ||
| 284 | { | ||
| 285 | if (n == 0) return; | ||
| 286 | code_oparg(SETLIST, 1, m, -n); | ||
| 287 | code_byte(n); | ||
| 288 | } | ||
| 289 | |||
| 290 | |||
| 291 | static void luaI_registerlocalvar (TaggedString *varname, int line) | ||
| 292 | { | ||
| 293 | FuncState *fs = L->currState; | ||
| 294 | if (fs->maxvars != -1) { /* debug information? */ | ||
| 295 | if (fs->nvars >= fs->maxvars) | ||
| 296 | fs->maxvars = luaM_growvector(&fs->f->locvars, fs->maxvars, | ||
| 297 | LocVar, "", MAX_WORD); | ||
| 298 | fs->f->locvars[fs->nvars].varname = varname; | ||
| 299 | fs->f->locvars[fs->nvars].line = line; | ||
| 300 | fs->nvars++; | ||
| 301 | } | ||
| 302 | } | ||
| 303 | |||
| 304 | |||
| 305 | static void luaI_unregisterlocalvar (int line) | ||
| 306 | { | ||
| 307 | luaI_registerlocalvar(NULL, line); | ||
| 308 | } | ||
| 309 | |||
| 310 | |||
| 311 | static void store_localvar (TaggedString *name, int n) | ||
| 312 | { | ||
| 313 | if (L->currState->nlocalvar+n < MAXLOCALS) | ||
| 314 | L->currState->localvar[L->currState->nlocalvar+n] = name; | ||
| 315 | else | ||
| 316 | luaY_error("too many local variables " MES_LIM(SMAXLOCALS)); | ||
| 317 | luaI_registerlocalvar(name, L->lexstate->linenumber); | ||
| 318 | } | ||
| 319 | |||
| 320 | static void add_localvar (TaggedString *name) | ||
| 321 | { | ||
| 322 | store_localvar(name, 0); | ||
| 323 | L->currState->nlocalvar++; | ||
| 324 | } | ||
| 325 | |||
| 326 | |||
| 327 | /* | ||
| 328 | ** dotted variables <a.x> must be stored like regular indexed vars <a["x"]> | ||
| 329 | */ | ||
| 330 | static vardesc var2store (vardesc var) | ||
| 331 | { | ||
| 332 | if (isdot(var)) { | ||
| 333 | code_constant(dotindex(var)); | ||
| 334 | var = 0; | ||
| 335 | } | ||
| 336 | return var; | ||
| 337 | } | ||
| 338 | |||
| 339 | |||
| 340 | static void add_varbuffer (vardesc var, int n) | ||
| 341 | { | ||
| 342 | if (n >= MAXVAR) | ||
| 343 | luaY_error("variable buffer overflow " MES_LIM(SMAXVAR)); | ||
| 344 | L->currState->varbuffer[n] = var2store(var); | ||
| 345 | } | ||
| 346 | |||
| 347 | |||
| 348 | static int aux_localname (TaggedString *n, FuncState *st) | ||
| 349 | { | ||
| 350 | int i; | ||
| 351 | for (i=st->nlocalvar-1; i >= 0; i--) | ||
| 352 | if (n == st->localvar[i]) return i; /* local var index */ | ||
| 353 | return -1; /* not found */ | ||
| 354 | } | ||
| 355 | |||
| 356 | |||
| 357 | static vardesc singlevar (TaggedString *n, FuncState *st) | ||
| 358 | { | ||
| 359 | int i = aux_localname(n, st); | ||
| 360 | if (i == -1) { /* check shadowing */ | ||
| 361 | int l; | ||
| 362 | for (l=1; l<=(st-L->mainState); l++) | ||
| 363 | if (aux_localname(n, st-l) >= 0) | ||
| 364 | luaY_syntaxerror("cannot access a variable in outer scope", n->str); | ||
| 365 | return string_constant(n, st)+MINGLOBAL; /* global value */ | ||
| 366 | } | ||
| 367 | else return i+1; /* local value */ | ||
| 368 | } | ||
| 369 | |||
| 370 | |||
| 371 | static int indexupvalue (TaggedString *n) | ||
| 372 | { | ||
| 373 | vardesc v = singlevar(n, L->currState-1); | ||
| 374 | int i; | ||
| 375 | for (i=0; i<L->currState->nupvalues; i++) { | ||
| 376 | if (L->currState->upvalues[i] == v) | ||
| 377 | return i; | ||
| 378 | } | ||
| 379 | /* new one */ | ||
| 380 | if (++(L->currState->nupvalues) > MAXUPVALUES) | ||
| 381 | luaY_error("too many upvalues in a single function " MES_LIM(SMAXUPVALUES)); | ||
| 382 | L->currState->upvalues[i] = v; /* i = L->currState->nupvalues - 1 */ | ||
| 383 | return i; | ||
| 384 | } | ||
| 385 | |||
| 386 | |||
| 387 | static void pushupvalue (TaggedString *n) | ||
| 388 | { | ||
| 389 | int i; | ||
| 390 | if (L->currState == L->mainState) | ||
| 391 | luaY_error("cannot access upvalue in main"); | ||
| 392 | if (aux_localname(n, L->currState) >= 0) | ||
| 393 | luaY_syntaxerror("cannot access an upvalue in current scope", n->str); | ||
| 394 | i = indexupvalue(n); | ||
| 395 | code_oparg(PUSHUPVALUE, 2, i, 1); | ||
| 396 | } | ||
| 397 | |||
| 398 | |||
| 399 | void luaY_codedebugline (int line) | ||
| 400 | { | ||
| 401 | if (lua_debug && line != L->lexstate->lastline) { | ||
| 402 | code_oparg(SETLINE, 0, line, 0); | ||
| 403 | L->lexstate->lastline = line; | ||
| 404 | } | ||
| 405 | } | ||
| 406 | |||
| 407 | |||
| 408 | static void adjuststack (int n) | ||
| 409 | { | ||
| 410 | if (n > 0) | ||
| 411 | code_oparg(POP, 2, n-1, -n); | ||
| 412 | else if (n < 0) | ||
| 413 | code_oparg(PUSHNIL, 1, (-n)-1, -n); | ||
| 414 | } | ||
| 415 | |||
| 416 | |||
| 417 | static long adjust_functioncall (long exp, int nresults) | ||
| 418 | { | ||
| 419 | if (exp <= 0) | ||
| 420 | return -exp; /* exp is -list length */ | ||
| 421 | else { | ||
| 422 | int temp = L->currState->f->code[exp]; | ||
| 423 | int nparams = L->currState->f->code[exp-1]; | ||
| 424 | exp += fix_opcode(exp-2, CALLFUNC, 2, nresults); | ||
| 425 | L->currState->f->code[exp] = nparams; | ||
| 426 | if (nresults != MULT_RET) | ||
| 427 | deltastack(nresults); | ||
| 428 | deltastack(-(nparams+1)); | ||
| 429 | return temp+nresults; | ||
| 430 | } | ||
| 431 | } | ||
| 432 | |||
| 433 | |||
| 434 | static void adjust_mult_assign (int vars, long exps) | ||
| 435 | { | ||
| 436 | if (exps > 0) { /* must correct function call */ | ||
| 437 | int diff = L->currState->f->code[exps] - vars; | ||
| 438 | if (diff < 0) | ||
| 439 | adjust_functioncall(exps, -diff); | ||
| 440 | else { | ||
| 441 | adjust_functioncall(exps, 0); | ||
| 442 | adjuststack(diff); | ||
| 443 | } | ||
| 444 | } | ||
| 445 | else adjuststack((-exps)-vars); | ||
| 446 | } | ||
| 447 | |||
| 448 | |||
| 449 | static void code_args (int nparams, int dots) | ||
| 450 | { | ||
| 451 | L->currState->nlocalvar += nparams; /* "self" may already be there */ | ||
| 452 | nparams = L->currState->nlocalvar; | ||
| 453 | if (!dots) { | ||
| 454 | L->currState->f->code[1] = nparams; /* fill-in arg information */ | ||
| 455 | deltastack(nparams); | ||
| 456 | } | ||
| 457 | else { | ||
| 458 | L->currState->f->code[1] = nparams+ZEROVARARG; | ||
| 459 | deltastack(nparams+1); | ||
| 460 | add_localvar(luaS_new("arg")); | ||
| 461 | } | ||
| 462 | } | ||
| 463 | |||
| 464 | |||
| 465 | static void lua_pushvar (vardesc var) | ||
| 466 | { | ||
| 467 | if (isglobal(var)) | ||
| 468 | code_oparg(GETGLOBAL, 8, globalindex(var), 1); | ||
| 469 | else if (islocal(var)) | ||
| 470 | code_oparg(PUSHLOCAL, 8, localindex(var), 1); | ||
| 471 | else if (isdot(var)) | ||
| 472 | code_oparg(GETDOTTED, 8, dotindex(var), 0); | ||
| 473 | else | ||
| 474 | code_pop(GETTABLE); | ||
| 475 | } | ||
| 476 | |||
| 477 | |||
| 478 | static void storevar (vardesc var) | ||
| 479 | { | ||
| 480 | if (var == 0) /* indexed var */ | ||
| 481 | code_opcode(SETTABLE0, -3); | ||
| 482 | else if (isglobal(var)) | ||
| 483 | code_oparg(SETGLOBAL, 8, globalindex(var), -1); | ||
| 484 | else /* local var */ | ||
| 485 | code_oparg(SETLOCAL, 8, localindex(var), -1); | ||
| 486 | } | ||
| 487 | |||
| 488 | |||
| 489 | /* returns how many elements are left as 'garbage' on the stack */ | ||
| 490 | static int lua_codestore (int i, int left) | ||
| 491 | { | ||
| 492 | if (L->currState->varbuffer[i] != 0 || /* global or local var or */ | ||
| 493 | left+i == 0) { /* indexed var without values in between */ | ||
| 494 | storevar(L->currState->varbuffer[i]); | ||
| 495 | return left; | ||
| 496 | } | ||
| 497 | else { /* indexed var with values in between*/ | ||
| 498 | code_oparg(SETTABLE, 0, left+i, -1); | ||
| 499 | return left+2; /* table/index are not popped, since they are not on top */ | ||
| 500 | } | ||
| 501 | } | ||
| 502 | |||
| 503 | |||
| 504 | static int fix_jump (int pc, OpCode op, int n) | ||
| 505 | { | ||
| 506 | /* jump is relative to position following jump instruction */ | ||
| 507 | return fix_opcode(pc, op, 0, n-(pc+JMPSIZE)); | ||
| 508 | } | ||
| 509 | |||
| 510 | |||
| 511 | static void fix_upjmp (OpCode op, int pos) | ||
| 512 | { | ||
| 513 | int delta = L->currState->pc+JMPSIZE - pos; /* jump is relative */ | ||
| 514 | if (delta > 255) delta++; | ||
| 515 | code_oparg(op, 0, delta, 0); | ||
| 516 | } | ||
| 517 | |||
| 518 | |||
| 519 | static void codeIf (int thenAdd, int elseAdd) | ||
| 520 | { | ||
| 521 | int elseinit = elseAdd+JMPSIZE; | ||
| 522 | if (L->currState->pc == elseinit) { /* no else part */ | ||
| 523 | L->currState->pc -= JMPSIZE; | ||
| 524 | elseinit = L->currState->pc; | ||
| 525 | } | ||
| 526 | else | ||
| 527 | elseinit += fix_jump(elseAdd, JMP, L->currState->pc); | ||
| 528 | fix_jump(thenAdd, IFFJMP, elseinit); | ||
| 529 | } | ||
| 530 | |||
| 531 | |||
| 532 | static void code_shortcircuit (int pc, OpCode op) | ||
| 533 | { | ||
| 534 | fix_jump(pc, op, L->currState->pc); | ||
| 535 | } | ||
| 536 | |||
| 537 | |||
| 538 | static void codereturn (void) | ||
| 539 | { | ||
| 540 | code_oparg(RETCODE, 0, L->currState->nlocalvar, 0); | ||
| 541 | L->currState->stacksize = L->currState->nlocalvar; | ||
| 542 | } | ||
| 543 | |||
| 544 | |||
| 545 | static void func_onstack (TProtoFunc *f) | ||
| 546 | { | ||
| 547 | int i; | ||
| 548 | int nupvalues = (L->currState+1)->nupvalues; | ||
| 549 | int c = next_constant(L->currState); | ||
| 550 | ttype(&L->currState->f->consts[c]) = LUA_T_PROTO; | ||
| 551 | L->currState->f->consts[c].value.tf = (L->currState+1)->f; | ||
| 552 | if (nupvalues == 0) | ||
| 553 | code_constant(c); | ||
| 554 | else { | ||
| 555 | for (i=0; i<nupvalues; i++) | ||
| 556 | lua_pushvar((L->currState+1)->upvalues[i]); | ||
| 557 | code_oparg(CLOSURE, 0, c, -nupvalues+1); | ||
| 558 | code_byte(nupvalues); | ||
| 559 | } | ||
| 560 | } | ||
| 561 | |||
| 562 | |||
| 563 | static void init_state (TaggedString *filename) | ||
| 564 | { | ||
| 565 | TProtoFunc *f = luaF_newproto(); | ||
| 566 | FuncState *fs = L->currState; | ||
| 567 | fs->stacksize = 0; | ||
| 568 | fs->maxstacksize = 0; | ||
| 569 | fs->nlocalvar = 0; | ||
| 570 | fs->nupvalues = 0; | ||
| 571 | fs->f = f; | ||
| 572 | f->fileName = filename; | ||
| 573 | fs->pc = 0; | ||
| 574 | fs->maxcode = 0; | ||
| 575 | f->code = NULL; | ||
| 576 | fs->maxconsts = 0; | ||
| 577 | if (lua_debug) { | ||
| 578 | fs->nvars = 0; | ||
| 579 | fs->maxvars = 0; | ||
| 580 | } | ||
| 581 | else | ||
| 582 | fs->maxvars = -1; /* flag no debug information */ | ||
| 583 | code_byte(0); /* to be filled with stacksize */ | ||
| 584 | code_byte(0); /* to be filled with arg information */ | ||
| 585 | L->lexstate->lastline = 0; /* invalidate it */ | ||
| 586 | } | ||
| 587 | |||
| 588 | |||
| 589 | static void init_func (void) | ||
| 590 | { | ||
| 591 | if (L->currState-L->mainState >= MAXSTATES-1) | ||
| 592 | luaY_error("too many nested functions " MES_LIM(SMAXSTATES)); | ||
| 593 | L->currState++; | ||
| 594 | init_state(L->mainState->f->fileName); | ||
| 595 | luaY_codedebugline(L->lexstate->linenumber); | ||
| 596 | L->currState->f->lineDefined = L->lexstate->linenumber; | ||
| 597 | } | ||
| 598 | |||
| 599 | static TProtoFunc *close_func (void) | ||
| 600 | { | ||
| 601 | TProtoFunc *f = L->currState->f; | ||
| 602 | code_neutralop(ENDCODE); | ||
| 603 | f->code[0] = L->currState->maxstacksize; | ||
| 604 | f->code = luaM_reallocvector(f->code, L->currState->pc, Byte); | ||
| 605 | f->consts = luaM_reallocvector(f->consts, f->nconsts, TObject); | ||
| 606 | if (L->currState->maxvars != -1) { /* debug information? */ | ||
| 607 | luaI_registerlocalvar(NULL, -1); /* flag end of vector */ | ||
| 608 | f->locvars = luaM_reallocvector(f->locvars, L->currState->nvars, LocVar); | ||
| 609 | } | ||
| 610 | L->currState--; | ||
| 611 | return f; | ||
| 612 | } | ||
| 613 | |||
| 614 | |||
| 615 | /* | ||
| 616 | ** Parse Lua code. | ||
| 617 | */ | ||
| 618 | TProtoFunc *luaY_parser (ZIO *z) | ||
| 619 | { | ||
| 620 | struct LexState lexstate; | ||
| 621 | FuncState state[MAXSTATES]; | ||
| 622 | L->currState = L->mainState = &state[0]; | ||
| 623 | L->lexstate = &lexstate; | ||
| 624 | luaX_setinput(z); | ||
| 625 | init_state(luaS_new(zname(z))); | ||
| 626 | if (luaY_parse()) lua_error("parse error"); | ||
| 627 | return close_func(); | ||
| 628 | } | ||
| 629 | |||
| 630 | |||
| 631 | %} | ||
| 632 | |||
| 633 | |||
| 634 | %union | ||
| 635 | { | ||
| 636 | int vInt; | ||
| 637 | real vReal; | ||
| 638 | char *pChar; | ||
| 639 | long vLong; | ||
| 640 | TaggedString *pTStr; | ||
| 641 | TProtoFunc *pFunc; | ||
| 642 | } | ||
| 643 | |||
| 644 | %start chunk | ||
| 645 | |||
| 646 | %token NIL | ||
| 647 | %token IF THEN ELSE ELSEIF WHILE DO REPEAT UNTIL END | ||
| 648 | %token RETURN | ||
| 649 | %token LOCAL | ||
| 650 | %token FUNCTION | ||
| 651 | %token DOTS | ||
| 652 | %token <vReal> NUMBER | ||
| 653 | %token <pTStr> NAME STRING | ||
| 654 | |||
| 655 | %type <vInt> SaveWord, cond, GetPC, SaveWordPop, SaveWordPush | ||
| 656 | %type <vLong> exprlist, exprlist1 /* if > 0, points to function return | ||
| 657 | counter (which has list length); if <= 0, -list lenght */ | ||
| 658 | %type <vLong> functioncall, expr, sexp /* if != 0, points to function return | ||
| 659 | counter */ | ||
| 660 | %type <vInt> varlist1, funcParams, funcvalue | ||
| 661 | %type <vInt> fieldlist, localnamelist, decinit | ||
| 662 | %type <vInt> ffieldlist1, lfieldlist1, ffieldlist, lfieldlist, part | ||
| 663 | %type <vLong> var, varname, funcname /* vardesc */ | ||
| 664 | |||
| 665 | |||
| 666 | %left AND OR | ||
| 667 | %left EQ NE '>' '<' LE GE | ||
| 668 | %left CONC | ||
| 669 | %left '+' '-' | ||
| 670 | %left '*' '/' | ||
| 671 | %left UNARY NOT | ||
| 672 | %right '^' | ||
| 673 | |||
| 674 | |||
| 675 | %% /* beginning of rules section */ | ||
| 676 | |||
| 677 | |||
| 678 | chunk : statlist ret ; | ||
| 679 | |||
| 680 | statlist : /* empty */ | ||
| 681 | | statlist stat sc | ||
| 682 | { LUA_ASSERT(L->currState->stacksize == L->currState->nlocalvar, | ||
| 683 | "stack size != # local vars"); } | ||
| 684 | ; | ||
| 685 | |||
| 686 | sc : /* empty */ | ';' ; | ||
| 687 | |||
| 688 | stat : IF cond THEN block SaveWord elsepart END { codeIf($2, $5); } | ||
| 689 | |||
| 690 | | DO block END | ||
| 691 | |||
| 692 | | WHILE GetPC cond DO block END | ||
| 693 | {{ | ||
| 694 | FuncState *fs = L->currState; | ||
| 695 | int expsize = $3-$2; | ||
| 696 | int newpos = $2+JMPSIZE; | ||
| 697 | check_pc(expsize); | ||
| 698 | memcpy(fs->f->code+fs->pc, fs->f->code+$2, expsize); | ||
| 699 | luaO_memdown(fs->f->code+$2, fs->f->code+$3, fs->pc-$2); | ||
| 700 | newpos += fix_jump($2, JMP, fs->pc-expsize); | ||
| 701 | fix_upjmp(IFTUPJMP, newpos); | ||
| 702 | }} | ||
| 703 | |||
| 704 | | REPEAT GetPC block UNTIL expr1 | ||
| 705 | { | ||
| 706 | fix_upjmp(IFFUPJMP, $2); | ||
| 707 | deltastack(-1); /* pops condition */ | ||
| 708 | } | ||
| 709 | |||
| 710 | | varlist1 '=' exprlist1 | ||
| 711 | {{ | ||
| 712 | int i; | ||
| 713 | int left = 0; | ||
| 714 | adjust_mult_assign($1, $3); | ||
| 715 | for (i=$1-1; i>=0; i--) | ||
| 716 | left = lua_codestore(i, left); | ||
| 717 | adjuststack(left); /* remove eventual 'garbage' left on stack */ | ||
| 718 | }} | ||
| 719 | |||
| 720 | | functioncall { adjust_functioncall($1, 0); } | ||
| 721 | |||
| 722 | | LOCAL localnamelist decinit | ||
| 723 | { | ||
| 724 | L->currState->nlocalvar += $2; | ||
| 725 | adjust_mult_assign($2, $3); | ||
| 726 | } | ||
| 727 | |||
| 728 | | FUNCTION funcname body { storevar($2); } | ||
| 729 | ; | ||
| 730 | |||
| 731 | block : {$<vInt>$ = L->currState->nlocalvar;} chunk | ||
| 732 | { | ||
| 733 | adjuststack(L->currState->nlocalvar - $<vInt>1); | ||
| 734 | for (; L->currState->nlocalvar > $<vInt>1; L->currState->nlocalvar--) | ||
| 735 | luaI_unregisterlocalvar(L->lexstate->linenumber); | ||
| 736 | } | ||
| 737 | ; | ||
| 738 | |||
| 739 | funcname : varname { $$ = $1; init_func(); } | ||
| 740 | | fvarname '.' fname | ||
| 741 | { | ||
| 742 | $$ = 0; /* flag indexed variable */ | ||
| 743 | init_func(); | ||
| 744 | } | ||
| 745 | | fvarname ':' fname | ||
| 746 | { | ||
| 747 | $$ = 0; /* flag indexed variable */ | ||
| 748 | init_func(); | ||
| 749 | add_localvar(luaS_new("self")); | ||
| 750 | } | ||
| 751 | ; | ||
| 752 | |||
| 753 | fvarname : varname { lua_pushvar($1); } ; | ||
| 754 | |||
| 755 | fname : NAME { code_string($1); } ; | ||
| 756 | |||
| 757 | body : '(' parlist ')' chunk END { func_onstack(close_func()); } ; | ||
| 758 | |||
| 759 | elsepart : /* empty */ | ||
| 760 | | ELSE block | ||
| 761 | | ELSEIF cond THEN block SaveWord elsepart { codeIf($2, $5); } | ||
| 762 | ; | ||
| 763 | |||
| 764 | ret : /* empty */ | ||
| 765 | | RETURN exprlist sc | ||
| 766 | { | ||
| 767 | adjust_functioncall($2, MULT_RET); | ||
| 768 | codereturn(); | ||
| 769 | } | ||
| 770 | ; | ||
| 771 | |||
| 772 | GetPC : /* empty */ { $$ = L->currState->pc; } ; | ||
| 773 | |||
| 774 | SaveWord : /* empty */ | ||
| 775 | { $$ = L->currState->pc; | ||
| 776 | check_pc(JMPSIZE); | ||
| 777 | L->currState->pc += JMPSIZE; /* open space */ | ||
| 778 | } | ||
| 779 | ; | ||
| 780 | |||
| 781 | SaveWordPop : SaveWord { $$ = $1; deltastack(-1); /* pop condition */ } ; | ||
| 782 | |||
| 783 | SaveWordPush : SaveWord { $$ = $1; deltastack(1); /* push a value */ } ; | ||
| 784 | |||
| 785 | cond : expr1 SaveWordPop { $$ = $2; } ; | ||
| 786 | |||
| 787 | expr1 : expr { adjust_functioncall($1, 1); } ; | ||
| 788 | |||
| 789 | expr : '(' expr ')' { $$ = $2; } | ||
| 790 | | expr1 EQ expr1 { code_binop(EQOP); $$ = 0; } | ||
| 791 | | expr1 '<' expr1 { code_binop(LTOP); $$ = 0; } | ||
| 792 | | expr1 '>' expr1 { code_binop(GTOP); $$ = 0; } | ||
| 793 | | expr1 NE expr1 { code_binop(NEQOP); $$ = 0; } | ||
| 794 | | expr1 LE expr1 { code_binop(LEOP); $$ = 0; } | ||
| 795 | | expr1 GE expr1 { code_binop(GEOP); $$ = 0; } | ||
| 796 | | expr1 '+' expr1 { code_binop(ADDOP); $$ = 0; } | ||
| 797 | | expr1 '-' expr1 { code_binop(SUBOP); $$ = 0; } | ||
| 798 | | expr1 '*' expr1 { code_binop(MULTOP); $$ = 0; } | ||
| 799 | | expr1 '/' expr1 { code_binop(DIVOP); $$ = 0; } | ||
| 800 | | expr1 '^' expr1 { code_binop(POWOP); $$ = 0; } | ||
| 801 | | expr1 CONC expr1 { code_binop(CONCOP); $$ = 0; } | ||
| 802 | | '-' expr1 %prec UNARY { code_unop(MINUSOP); $$ = 0;} | ||
| 803 | | NOT expr1 { code_unop(NOTOP); $$ = 0;} | ||
| 804 | | sexp { $$ = $1; /* simple expressions */ } | ||
| 805 | | table { $$ = 0; } | ||
| 806 | | NUMBER { code_number($1); $$ = 0; } | ||
| 807 | | STRING { code_string($1); $$ = 0; } | ||
| 808 | | NIL { adjuststack(-1); $$ = 0; } | ||
| 809 | | FUNCTION { init_func(); } body { $$ = 0; } | ||
| 810 | | expr1 AND SaveWordPop expr1 { code_shortcircuit($3, ONFJMP); $$ = 0; } | ||
| 811 | | expr1 OR SaveWordPop expr1 { code_shortcircuit($3, ONTJMP); $$ = 0; } | ||
| 812 | ; | ||
| 813 | |||
| 814 | sexp1 : sexp { adjust_functioncall($1, 1); } ; | ||
| 815 | |||
| 816 | sexp : var { lua_pushvar($1); $$ = 0; } | ||
| 817 | | '%' NAME { pushupvalue($2); $$ = 0; } | ||
| 818 | | functioncall { $$ = $1; } | ||
| 819 | ; | ||
| 820 | |||
| 821 | var : varname { $$ = $1; } | ||
| 822 | | sexp1 '[' expr1 ']' { $$ = 0; } /* indexed variable */ | ||
| 823 | | sexp1 '.' NAME { $$ = (-string_constant($3, L->currState))-1; } | ||
| 824 | ; | ||
| 825 | |||
| 826 | varname : NAME { $$ = singlevar($1, L->currState); } ; | ||
| 827 | |||
| 828 | table : '{' SaveWordPush fieldlist '}' { fix_opcode($2, CREATEARRAY, 2, $3); } ; | ||
| 829 | |||
| 830 | functioncall : funcvalue funcParams | ||
| 831 | { | ||
| 832 | code_byte(0); /* save space for opcode */ | ||
| 833 | code_byte($1+$2); /* number of parameters */ | ||
| 834 | $$ = L->currState->pc; | ||
| 835 | code_byte(0); /* must be adjusted by other rules */ | ||
| 836 | } | ||
| 837 | ; | ||
| 838 | |||
| 839 | funcvalue : sexp1 { $$ = 0; } | ||
| 840 | | sexp1 ':' NAME | ||
| 841 | { | ||
| 842 | code_oparg(PUSHSELF, 8, string_constant($3, L->currState), 1); | ||
| 843 | $$ = 1; | ||
| 844 | } | ||
| 845 | ; | ||
| 846 | |||
| 847 | funcParams : '(' exprlist ')' { $$ = adjust_functioncall($2, 1); } | ||
| 848 | | table { $$ = 1; } | ||
| 849 | | STRING { code_string($1); $$ = 1; } | ||
| 850 | ; | ||
| 851 | |||
| 852 | exprlist : /* empty */ { $$ = 0; } | ||
| 853 | | exprlist1 { $$ = $1; } | ||
| 854 | ; | ||
| 855 | |||
| 856 | exprlist1 : expr { if ($1 != 0) $$ = $1; else $$ = -1; } | ||
| 857 | | exprlist1 ',' { $<vLong>$ = adjust_functioncall($1, 1); } expr | ||
| 858 | { | ||
| 859 | if ($4 == 0) $$ = -($<vLong>3 + 1); /* -length */ | ||
| 860 | else { | ||
| 861 | L->currState->f->code[$4] = $<vLong>3; /* store list length */ | ||
| 862 | $$ = $4; | ||
| 863 | } | ||
| 864 | } | ||
| 865 | ; | ||
| 866 | |||
| 867 | parlist : /* empty */ { code_args(0, 0); } | ||
| 868 | | DOTS { code_args(0, 1); } | ||
| 869 | | localnamelist { code_args($1, 0); } | ||
| 870 | | localnamelist ',' DOTS { code_args($1, 1); } | ||
| 871 | ; | ||
| 872 | |||
| 873 | fieldlist : part { $$ = abs($1); } | ||
| 874 | | part ';' part | ||
| 875 | { | ||
| 876 | if ($1*$3 > 0) /* repeated parts? */ | ||
| 877 | luaY_error("invalid constructor syntax"); | ||
| 878 | $$ = abs($1)+abs($3); | ||
| 879 | } | ||
| 880 | ; | ||
| 881 | |||
| 882 | part : /* empty */ { $$ = 0; } | ||
| 883 | | ffieldlist { $$ = $1; } | ||
| 884 | | lfieldlist { $$ = $1; } | ||
| 885 | ; | ||
| 886 | |||
| 887 | lastcomma : /* empty */ | ',' ; | ||
| 888 | |||
| 889 | ffieldlist : ffieldlist1 lastcomma | ||
| 890 | { | ||
| 891 | flush_record($1%RFIELDS_PER_FLUSH); | ||
| 892 | $$ = -$1; /* negative signals a "record" part */ | ||
| 893 | } | ||
| 894 | ; | ||
| 895 | |||
| 896 | lfieldlist : lfieldlist1 lastcomma | ||
| 897 | { | ||
| 898 | flush_list($1/LFIELDS_PER_FLUSH, $1%LFIELDS_PER_FLUSH); | ||
| 899 | $$ = $1; | ||
| 900 | } | ||
| 901 | ; | ||
| 902 | |||
| 903 | ffieldlist1 : ffield {$$=1;} | ||
| 904 | | ffieldlist1 ',' ffield | ||
| 905 | { | ||
| 906 | $$=$1+1; | ||
| 907 | if ($$%RFIELDS_PER_FLUSH == 0) | ||
| 908 | flush_record(RFIELDS_PER_FLUSH); | ||
| 909 | } | ||
| 910 | ; | ||
| 911 | |||
| 912 | ffield : ffieldkey '=' expr1 ; | ||
| 913 | |||
| 914 | ffieldkey : '[' expr1 ']' | ||
| 915 | | fname | ||
| 916 | ; | ||
| 917 | |||
| 918 | lfieldlist1 : expr1 {$$=1;} | ||
| 919 | | lfieldlist1 ',' expr1 | ||
| 920 | { | ||
| 921 | $$=$1+1; | ||
| 922 | if ($$%LFIELDS_PER_FLUSH == 0) | ||
| 923 | flush_list($$/LFIELDS_PER_FLUSH - 1, LFIELDS_PER_FLUSH); | ||
| 924 | } | ||
| 925 | ; | ||
| 926 | |||
| 927 | varlist1 : var { $$ = 1; add_varbuffer($1, 0); } | ||
| 928 | | varlist1 ',' var { add_varbuffer($3, $1); $$ = $1+1; } | ||
| 929 | ; | ||
| 930 | |||
| 931 | localnamelist : NAME {store_localvar($1, 0); $$ = 1;} | ||
| 932 | | localnamelist ',' NAME { store_localvar($3, $1); $$ = $1+1; } | ||
| 933 | ; | ||
| 934 | |||
| 935 | decinit : /* empty */ { $$ = 0; } | ||
| 936 | | '=' exprlist1 { $$ = $2; } | ||
| 937 | ; | ||
| 938 | |||
| 939 | %% | ||
| 940 | |||
| @@ -1,5 +1,5 @@ | |||
| 1 | # | 1 | # |
| 2 | ## $Id: makefile,v 1.10 1998/01/05 17:12:54 roberto Exp roberto $ | 2 | ## $Id: makefile,v 1.11 1998/05/18 22:26:03 roberto Exp roberto $ |
| 3 | ## Makefile | 3 | ## Makefile |
| 4 | ## See Copyright Notice in lua.h | 4 | ## See Copyright Notice in lua.h |
| 5 | # | 5 | # |
| @@ -18,7 +18,7 @@ | |||
| 18 | # define LUA_COMPAT2_5 if yous system does need to be compatible with | 18 | # define LUA_COMPAT2_5 if yous system does need to be compatible with |
| 19 | # version 2.5 (or older) | 19 | # version 2.5 (or older) |
| 20 | # | 20 | # |
| 21 | #define LUA_NUM_TYPE if you need numbers to be different from double | 21 | # define LUA_NUM_TYPE if you need numbers to be different from double |
| 22 | 22 | ||
| 23 | CONFIG = -DPOPEN -D_POSIX_SOURCE | 23 | CONFIG = -DPOPEN -D_POSIX_SOURCE |
| 24 | #CONFIG = -DLUA_COMPAT2_5 -DOLD_ANSI -DDEBUG | 24 | #CONFIG = -DLUA_COMPAT2_5 -DOLD_ANSI -DDEBUG |
| @@ -46,8 +46,8 @@ LUAOBJS = \ | |||
| 46 | llex.o \ | 46 | llex.o \ |
| 47 | lmem.o \ | 47 | lmem.o \ |
| 48 | lobject.o \ | 48 | lobject.o \ |
| 49 | lparser.o \ | ||
| 49 | lstate.o \ | 50 | lstate.o \ |
| 50 | lstx.o \ | ||
| 51 | lstring.o \ | 51 | lstring.o \ |
| 52 | ltable.o \ | 52 | ltable.o \ |
| 53 | ltm.o \ | 53 | ltm.o \ |
| @@ -75,16 +75,11 @@ liblualib.a : $(LIBOBJS) | |||
| 75 | liblua.so.1.0 : lua.o | 75 | liblua.so.1.0 : lua.o |
| 76 | ld -o liblua.so.1.0 $(LUAOBJS) | 76 | ld -o liblua.so.1.0 $(LUAOBJS) |
| 77 | 77 | ||
| 78 | lstx.c lstx.h : lua.stx | ||
| 79 | bison -o lstx.c -p luaY_ -d lua.stx | ||
| 80 | # yacc -d lua.stx | ||
| 81 | # sed -e 's/yy/luaY_/g' -e 's/malloc\.h/stdlib\.h/g' y.tab.c > lstx.c | ||
| 82 | # sed -e 's/yy/luaY_/g' y.tab.h > lstx.h | ||
| 83 | 78 | ||
| 84 | clear : | 79 | clear : |
| 85 | rcsclean | 80 | rcsclean |
| 86 | rm -f *.o | 81 | rm -f *.o |
| 87 | rm -f lstx.c lstx.h | 82 | rm -f |
| 88 | co lua.h lualib.h luadebug.h | 83 | co lua.h lualib.h luadebug.h |
| 89 | 84 | ||
| 90 | 85 | ||
| @@ -94,6 +89,7 @@ clear : | |||
| 94 | %.c : RCS/%.c,v | 89 | %.c : RCS/%.c,v |
| 95 | co $@ | 90 | co $@ |
| 96 | 91 | ||
| 92 | |||
| 97 | lapi.o: lapi.c lapi.h lua.h lobject.h lauxlib.h ldo.h lstate.h lfunc.h \ | 93 | lapi.o: lapi.c lapi.h lua.h lobject.h lauxlib.h ldo.h lstate.h lfunc.h \ |
| 98 | lgc.h lmem.h lstring.h ltable.h ltm.h luadebug.h lvm.h | 94 | lgc.h lmem.h lstring.h ltable.h ltm.h luadebug.h lvm.h |
| 99 | lauxlib.o: lauxlib.c lauxlib.h lua.h luadebug.h | 95 | lauxlib.o: lauxlib.c lauxlib.h lua.h luadebug.h |
| @@ -107,18 +103,18 @@ lgc.o: lgc.c ldo.h lobject.h lua.h lstate.h lfunc.h lgc.h lmem.h \ | |||
| 107 | lstring.h ltable.h ltm.h | 103 | lstring.h ltable.h ltm.h |
| 108 | liolib.o: liolib.c lauxlib.h lua.h luadebug.h lualib.h | 104 | liolib.o: liolib.c lauxlib.h lua.h luadebug.h lualib.h |
| 109 | llex.o: llex.c lauxlib.h lua.h llex.h lobject.h lzio.h lmem.h \ | 105 | llex.o: llex.c lauxlib.h lua.h llex.h lobject.h lzio.h lmem.h \ |
| 110 | lparser.h lstate.h lstring.h lstx.h luadebug.h | 106 | lparser.h lstate.h lstring.h luadebug.h |
| 111 | lmathlib.o: lmathlib.c lauxlib.h lua.h lualib.h | 107 | lmathlib.o: lmathlib.c lauxlib.h lua.h lualib.h |
| 112 | lmem.o: lmem.c lmem.h lstate.h lobject.h lua.h | 108 | lmem.o: lmem.c lmem.h lstate.h lobject.h lua.h |
| 113 | lobject.o: lobject.c lobject.h lua.h | 109 | lobject.o: lobject.c lobject.h lua.h |
| 110 | lparser.o: lparser.c lauxlib.h lua.h ldo.h lobject.h lstate.h lfunc.h \ | ||
| 111 | llex.h lzio.h lmem.h lopcodes.h lparser.h lstring.h luadebug.h | ||
| 114 | lstate.o: lstate.c lbuiltin.h ldo.h lobject.h lua.h lstate.h lfunc.h \ | 112 | lstate.o: lstate.c lbuiltin.h ldo.h lobject.h lua.h lstate.h lfunc.h \ |
| 115 | lgc.h llex.h lzio.h lmem.h lstring.h ltable.h ltm.h | 113 | lgc.h llex.h lzio.h lmem.h lstring.h ltable.h ltm.h |
| 116 | lstring.o: lstring.c lmem.h lobject.h lua.h lstate.h lstring.h | 114 | lstring.o: lstring.c lmem.h lobject.h lua.h lstate.h lstring.h |
| 117 | lstrlib.o: lstrlib.c lauxlib.h lua.h lualib.h | 115 | lstrlib.o: lstrlib.c lauxlib.h lua.h lualib.h |
| 118 | lstx.o: lstx.c lauxlib.h lua.h ldo.h lobject.h lstate.h lfunc.h llex.h \ | ||
| 119 | lzio.h lmem.h lopcodes.h lparser.h lstring.h luadebug.h | ||
| 120 | ltable.o: ltable.c lauxlib.h lua.h lmem.h lobject.h lstate.h ltable.h | 116 | ltable.o: ltable.c lauxlib.h lua.h lmem.h lobject.h lstate.h ltable.h |
| 121 | ltm.o: ltm.c lauxlib.h lua.h lmem.h lobject.h lstate.h ltm.h lapi.h | 117 | ltm.o: ltm.c lauxlib.h lua.h lmem.h lobject.h lstate.h ltm.h |
| 122 | lua.o: lua.c lua.h luadebug.h lualib.h | 118 | lua.o: lua.c lua.h luadebug.h lualib.h |
| 123 | lundump.o: lundump.c lauxlib.h lua.h lfunc.h lobject.h lmem.h \ | 119 | lundump.o: lundump.c lauxlib.h lua.h lfunc.h lobject.h lmem.h \ |
| 124 | lstring.h lundump.h lzio.h | 120 | lstring.h lundump.h lzio.h |
