diff options
| author | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2003-08-27 18:01:44 -0300 |
|---|---|---|
| committer | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2003-08-27 18:01:44 -0300 |
| commit | 8332d5c8a5059b85da1adaa3f0197d0f57afae81 (patch) | |
| tree | 8a2f59ff0803da3afbc7e8a409911c920d624e94 /lparser.c | |
| parent | 885961be1d8e3f703b54d1d19e6c63617cd2ed24 (diff) | |
| download | lua-8332d5c8a5059b85da1adaa3f0197d0f57afae81.tar.gz lua-8332d5c8a5059b85da1adaa3f0197d0f57afae81.tar.bz2 lua-8332d5c8a5059b85da1adaa3f0197d0f57afae81.zip | |
parser fully reentrant(!)
Diffstat (limited to 'lparser.c')
| -rw-r--r-- | lparser.c | 46 |
1 files changed, 36 insertions, 10 deletions
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | ** $Id: lparser.c,v 1.215 2003/07/29 18:51:00 roberto Exp roberto $ | 2 | ** $Id: lparser.c,v 1.216 2003/08/25 19:51:54 roberto Exp roberto $ |
| 3 | ** Lua Parser | 3 | ** Lua Parser |
| 4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
| 5 | */ | 5 | */ |
| @@ -13,6 +13,7 @@ | |||
| 13 | 13 | ||
| 14 | #include "lcode.h" | 14 | #include "lcode.h" |
| 15 | #include "ldebug.h" | 15 | #include "ldebug.h" |
| 16 | #include "ldo.h" | ||
| 16 | #include "lfunc.h" | 17 | #include "lfunc.h" |
| 17 | #include "llex.h" | 18 | #include "llex.h" |
| 18 | #include "lmem.h" | 19 | #include "lmem.h" |
| @@ -71,6 +72,14 @@ static void lookahead (LexState *ls) { | |||
| 71 | } | 72 | } |
| 72 | 73 | ||
| 73 | 74 | ||
| 75 | static void anchor_token (LexState *ls) { | ||
| 76 | if (ls->t.token == TK_NAME || ls->t.token == TK_STRING) { | ||
| 77 | TString *ts = ls->t.seminfo.ts; | ||
| 78 | luaX_newstring(ls, getstr(ts), ts->tsv.len); | ||
| 79 | } | ||
| 80 | } | ||
| 81 | |||
| 82 | |||
| 74 | static void error_expected (LexState *ls, int token) { | 83 | static void error_expected (LexState *ls, int token) { |
| 75 | luaX_syntaxerror(ls, | 84 | luaX_syntaxerror(ls, |
| 76 | luaO_pushfstring(ls->L, "`%s' expected", luaX_token2str(ls, token))); | 85 | luaO_pushfstring(ls->L, "`%s' expected", luaX_token2str(ls, token))); |
| @@ -138,9 +147,11 @@ static void checkname(LexState *ls, expdesc *e) { | |||
| 138 | static int luaI_registerlocalvar (LexState *ls, TString *varname) { | 147 | static int luaI_registerlocalvar (LexState *ls, TString *varname) { |
| 139 | FuncState *fs = ls->fs; | 148 | FuncState *fs = ls->fs; |
| 140 | Proto *f = fs->f; | 149 | Proto *f = fs->f; |
| 150 | int oldsize = f->sizelocvars; | ||
| 141 | luaM_growvector(ls->L, f->locvars, fs->nlocvars, f->sizelocvars, | 151 | luaM_growvector(ls->L, f->locvars, fs->nlocvars, f->sizelocvars, |
| 142 | LocVar, USHRT_MAX, "too many local variables"); | 152 | LocVar, USHRT_MAX, "too many local variables"); |
| 143 | f->locvars[fs->nlocvars].varname = varname; | 153 | while (oldsize < f->sizelocvars) f->locvars[oldsize++].varname = NULL; |
| 154 | f->locvars[fs->nlocvars].varname = varname; /* write barrier */ | ||
| 144 | return fs->nlocvars++; | 155 | return fs->nlocvars++; |
| 145 | } | 156 | } |
| 146 | 157 | ||
| @@ -170,24 +181,27 @@ static void removevars (LexState *ls, int tolevel) { | |||
| 170 | 181 | ||
| 171 | 182 | ||
| 172 | static void new_localvarstr (LexState *ls, const char *name, int n) { | 183 | static void new_localvarstr (LexState *ls, const char *name, int n) { |
| 173 | new_localvar(ls, luaS_new(ls->L, name), n); | 184 | TString *ts = luaX_newstring(ls, name, strlen(name)); |
| 185 | new_localvar(ls, ts, n); | ||
| 174 | } | 186 | } |
| 175 | 187 | ||
| 176 | 188 | ||
| 177 | static int indexupvalue (FuncState *fs, TString *name, expdesc *v) { | 189 | static int indexupvalue (FuncState *fs, TString *name, expdesc *v) { |
| 178 | int i; | 190 | int i; |
| 179 | Proto *f = fs->f; | 191 | Proto *f = fs->f; |
| 192 | int oldsize = f->sizeupvalues; | ||
| 180 | for (i=0; i<f->nups; i++) { | 193 | for (i=0; i<f->nups; i++) { |
| 181 | if (fs->upvalues[i].k == v->k && fs->upvalues[i].info == v->info) { | 194 | if (fs->upvalues[i].k == v->k && fs->upvalues[i].info == v->info) { |
| 182 | lua_assert(fs->f->upvalues[i] == name); | 195 | lua_assert(f->upvalues[i] == name); |
| 183 | return i; | 196 | return i; |
| 184 | } | 197 | } |
| 185 | } | 198 | } |
| 186 | /* new one */ | 199 | /* new one */ |
| 187 | luaX_checklimit(fs->ls, f->nups + 1, MAXUPVALUES, "upvalues"); | 200 | luaX_checklimit(fs->ls, f->nups + 1, MAXUPVALUES, "upvalues"); |
| 188 | luaM_growvector(fs->L, fs->f->upvalues, f->nups, fs->f->sizeupvalues, | 201 | luaM_growvector(fs->L, f->upvalues, f->nups, f->sizeupvalues, |
| 189 | TString *, MAX_INT, ""); | 202 | TString *, MAX_INT, ""); |
| 190 | fs->f->upvalues[f->nups] = name; | 203 | while (oldsize < f->sizeupvalues) f->upvalues[oldsize++] = NULL; |
| 204 | f->upvalues[f->nups] = name; /* write barrier */ | ||
| 191 | lua_assert(v->k == VLOCAL || v->k == VUPVAL); | 205 | lua_assert(v->k == VLOCAL || v->k == VUPVAL); |
| 192 | fs->upvalues[f->nups].k = cast(lu_byte, v->k); | 206 | fs->upvalues[f->nups].k = cast(lu_byte, v->k); |
| 193 | fs->upvalues[f->nups].info = cast(lu_byte, v->info); | 207 | fs->upvalues[f->nups].info = cast(lu_byte, v->info); |
| @@ -290,10 +304,12 @@ static void leaveblock (FuncState *fs) { | |||
| 290 | static void pushclosure (LexState *ls, FuncState *func, expdesc *v) { | 304 | static void pushclosure (LexState *ls, FuncState *func, expdesc *v) { |
| 291 | FuncState *fs = ls->fs; | 305 | FuncState *fs = ls->fs; |
| 292 | Proto *f = fs->f; | 306 | Proto *f = fs->f; |
| 307 | int oldsize = f->sizep; | ||
| 293 | int i; | 308 | int i; |
| 294 | luaM_growvector(ls->L, f->p, fs->np, f->sizep, Proto *, | 309 | luaM_growvector(ls->L, f->p, fs->np, f->sizep, Proto *, |
| 295 | MAXARG_Bx, "constant table overflow"); | 310 | MAXARG_Bx, "constant table overflow"); |
| 296 | f->p[fs->np++] = func->f; | 311 | while (oldsize < f->sizep) f->p[oldsize++] = NULL; |
| 312 | f->p[fs->np++] = func->f; /* write barrier */ | ||
| 297 | init_exp(v, VRELOCABLE, luaK_codeABx(fs, OP_CLOSURE, 0, fs->np-1)); | 313 | init_exp(v, VRELOCABLE, luaK_codeABx(fs, OP_CLOSURE, 0, fs->np-1)); |
| 298 | for (i=0; i<func->f->nups; i++) { | 314 | for (i=0; i<func->f->nups; i++) { |
| 299 | OpCode o = (func->upvalues[i].k == VLOCAL) ? OP_MOVE : OP_GETUPVAL; | 315 | OpCode o = (func->upvalues[i].k == VLOCAL) ? OP_MOVE : OP_GETUPVAL; |
| @@ -303,24 +319,30 @@ static void pushclosure (LexState *ls, FuncState *func, expdesc *v) { | |||
| 303 | 319 | ||
| 304 | 320 | ||
| 305 | static void open_func (LexState *ls, FuncState *fs) { | 321 | static void open_func (LexState *ls, FuncState *fs) { |
| 322 | lua_State *L = ls->L; | ||
| 306 | Proto *f = luaF_newproto(ls->L); | 323 | Proto *f = luaF_newproto(ls->L); |
| 307 | fs->f = f; | 324 | fs->f = f; |
| 308 | fs->prev = ls->fs; /* linked list of funcstates */ | 325 | fs->prev = ls->fs; /* linked list of funcstates */ |
| 309 | fs->ls = ls; | 326 | fs->ls = ls; |
| 310 | fs->L = ls->L; | 327 | fs->L = L; |
| 311 | ls->fs = fs; | 328 | ls->fs = fs; |
| 312 | fs->pc = 0; | 329 | fs->pc = 0; |
| 313 | fs->lasttarget = 0; | 330 | fs->lasttarget = 0; |
| 314 | fs->jpc = NO_JUMP; | 331 | fs->jpc = NO_JUMP; |
| 315 | fs->freereg = 0; | 332 | fs->freereg = 0; |
| 316 | fs->nk = 0; | 333 | fs->nk = 0; |
| 317 | fs->h = luaH_new(ls->L, 0, 0); | ||
| 318 | fs->np = 0; | 334 | fs->np = 0; |
| 319 | fs->nlocvars = 0; | 335 | fs->nlocvars = 0; |
| 320 | fs->nactvar = 0; | 336 | fs->nactvar = 0; |
| 321 | fs->bl = NULL; | 337 | fs->bl = NULL; |
| 322 | f->source = ls->source; | 338 | f->source = ls->source; |
| 323 | f->maxstacksize = 2; /* registers 0/1 are always valid */ | 339 | f->maxstacksize = 2; /* registers 0/1 are always valid */ |
| 340 | fs->h = luaH_new(L, 0, 0); | ||
| 341 | /* anchor table of constants and prototype (to avoid being collected) */ | ||
| 342 | sethvalue2s(L->top, fs->h); | ||
| 343 | incr_top(L); | ||
| 344 | setptvalue2s(L->top, f); | ||
| 345 | incr_top(L); | ||
| 324 | } | 346 | } |
| 325 | 347 | ||
| 326 | 348 | ||
| @@ -345,6 +367,9 @@ static void close_func (LexState *ls) { | |||
| 345 | lua_assert(luaG_checkcode(f)); | 367 | lua_assert(luaG_checkcode(f)); |
| 346 | lua_assert(fs->bl == NULL); | 368 | lua_assert(fs->bl == NULL); |
| 347 | ls->fs = fs->prev; | 369 | ls->fs = fs->prev; |
| 370 | L->top -= 2; /* remove table and prototype from the stack */ | ||
| 371 | /* last token read was anchored in defunct function; must reanchor it */ | ||
| 372 | if (fs) anchor_token(ls); | ||
| 348 | } | 373 | } |
| 349 | 374 | ||
| 350 | 375 | ||
| @@ -362,6 +387,7 @@ Proto *luaY_parser (lua_State *L, ZIO *z, Mbuffer *buff, const char *name) { | |||
| 362 | lua_assert(funcstate.prev == NULL); | 387 | lua_assert(funcstate.prev == NULL); |
| 363 | lua_assert(funcstate.f->nups == 0); | 388 | lua_assert(funcstate.f->nups == 0); |
| 364 | lua_assert(lexstate.nestlevel == 0); | 389 | lua_assert(lexstate.nestlevel == 0); |
| 390 | lua_assert(lexstate.fs == NULL); | ||
| 365 | return funcstate.f; | 391 | return funcstate.f; |
| 366 | } | 392 | } |
| 367 | 393 | ||
| @@ -530,7 +556,7 @@ static void parlist (LexState *ls) { | |||
| 530 | case TK_DOTS: { /* param -> `...' */ | 556 | case TK_DOTS: { /* param -> `...' */ |
| 531 | next(ls); | 557 | next(ls); |
| 532 | /* use `arg' as default name */ | 558 | /* use `arg' as default name */ |
| 533 | new_localvar(ls, luaS_new(ls->L, "arg"), nparams++); | 559 | new_localvarstr(ls, "arg", nparams++); |
| 534 | f->is_vararg = 1; | 560 | f->is_vararg = 1; |
| 535 | break; | 561 | break; |
| 536 | } | 562 | } |
