|
@ -1,5 +1,5 @@ |
|
|
/*
|
|
|
/*
|
|
|
** $Id: lparser.c,v 2.133 2013/04/26 13:07:53 roberto Exp roberto $ |
|
|
** $Id: lparser.c,v 2.134 2013/08/16 18:55:49 roberto Exp roberto $ |
|
|
** Lua Parser |
|
|
** Lua Parser |
|
|
** See Copyright Notice in lua.h |
|
|
** See Copyright Notice in lua.h |
|
|
*/ |
|
|
*/ |
|
@ -35,6 +35,10 @@ |
|
|
#define hasmultret(k) ((k) == VCALL || (k) == VVARARG) |
|
|
#define hasmultret(k) ((k) == VCALL || (k) == VVARARG) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* because all strings are unified by the scanner, the parser
|
|
|
|
|
|
can use pointer equality for string equality */ |
|
|
|
|
|
#define eqstr(a,b) ((a) == (b)) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
/*
|
|
|
** nodes for block list (list of active blocks) |
|
|
** nodes for block list (list of active blocks) |
|
@ -57,16 +61,6 @@ static void statement (LexState *ls); |
|
|
static void expr (LexState *ls, expdesc *v); |
|
|
static void expr (LexState *ls, expdesc *v); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static void anchor_token (LexState *ls) { |
|
|
|
|
|
/* last token from outer function must be EOS */ |
|
|
|
|
|
lua_assert(ls->fs != NULL || ls->t.token == TK_EOS); |
|
|
|
|
|
if (ls->t.token == TK_NAME || ls->t.token == TK_STRING) { |
|
|
|
|
|
TString *ts = ls->t.seminfo.ts; |
|
|
|
|
|
luaX_newstring(ls, getstr(ts), ts->tsv.len); |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* semantic error */ |
|
|
/* semantic error */ |
|
|
static l_noret semerror (LexState *ls, const char *msg) { |
|
|
static l_noret semerror (LexState *ls, const char *msg) { |
|
|
ls->t.token = 0; /* remove 'near to' from final message */ |
|
|
ls->t.token = 0; /* remove 'near to' from final message */ |
|
@ -222,7 +216,7 @@ static int searchupvalue (FuncState *fs, TString *name) { |
|
|
int i; |
|
|
int i; |
|
|
Upvaldesc *up = fs->f->upvalues; |
|
|
Upvaldesc *up = fs->f->upvalues; |
|
|
for (i = 0; i < fs->nups; i++) { |
|
|
for (i = 0; i < fs->nups; i++) { |
|
|
if (luaS_eqstr(up[i].name, name)) return i; |
|
|
if (eqstr(up[i].name, name)) return i; |
|
|
} |
|
|
} |
|
|
return -1; /* not found */ |
|
|
return -1; /* not found */ |
|
|
} |
|
|
} |
|
@ -246,7 +240,7 @@ static int newupvalue (FuncState *fs, TString *name, expdesc *v) { |
|
|
static int searchvar (FuncState *fs, TString *n) { |
|
|
static int searchvar (FuncState *fs, TString *n) { |
|
|
int i; |
|
|
int i; |
|
|
for (i = cast_int(fs->nactvar) - 1; i >= 0; i--) { |
|
|
for (i = cast_int(fs->nactvar) - 1; i >= 0; i--) { |
|
|
if (luaS_eqstr(n, getlocvar(fs, i)->varname)) |
|
|
if (eqstr(n, getlocvar(fs, i)->varname)) |
|
|
return i; |
|
|
return i; |
|
|
} |
|
|
} |
|
|
return -1; /* not found */ |
|
|
return -1; /* not found */ |
|
@ -342,7 +336,7 @@ static void closegoto (LexState *ls, int g, Labeldesc *label) { |
|
|
FuncState *fs = ls->fs; |
|
|
FuncState *fs = ls->fs; |
|
|
Labellist *gl = &ls->dyd->gt; |
|
|
Labellist *gl = &ls->dyd->gt; |
|
|
Labeldesc *gt = &gl->arr[g]; |
|
|
Labeldesc *gt = &gl->arr[g]; |
|
|
lua_assert(luaS_eqstr(gt->name, label->name)); |
|
|
lua_assert(eqstr(gt->name, label->name)); |
|
|
if (gt->nactvar < label->nactvar) { |
|
|
if (gt->nactvar < label->nactvar) { |
|
|
TString *vname = getlocvar(fs, gt->nactvar)->varname; |
|
|
TString *vname = getlocvar(fs, gt->nactvar)->varname; |
|
|
const char *msg = luaO_pushfstring(ls->L, |
|
|
const char *msg = luaO_pushfstring(ls->L, |
|
@ -369,7 +363,7 @@ static int findlabel (LexState *ls, int g) { |
|
|
/* check labels in current block for a match */ |
|
|
/* check labels in current block for a match */ |
|
|
for (i = bl->firstlabel; i < dyd->label.n; i++) { |
|
|
for (i = bl->firstlabel; i < dyd->label.n; i++) { |
|
|
Labeldesc *lb = &dyd->label.arr[i]; |
|
|
Labeldesc *lb = &dyd->label.arr[i]; |
|
|
if (luaS_eqstr(lb->name, gt->name)) { /* correct label? */ |
|
|
if (eqstr(lb->name, gt->name)) { /* correct label? */ |
|
|
if (gt->nactvar > lb->nactvar && |
|
|
if (gt->nactvar > lb->nactvar && |
|
|
(bl->upval || dyd->label.n > bl->firstlabel)) |
|
|
(bl->upval || dyd->label.n > bl->firstlabel)) |
|
|
luaK_patchclose(ls->fs, gt->pc, lb->nactvar); |
|
|
luaK_patchclose(ls->fs, gt->pc, lb->nactvar); |
|
@ -403,7 +397,7 @@ static void findgotos (LexState *ls, Labeldesc *lb) { |
|
|
Labellist *gl = &ls->dyd->gt; |
|
|
Labellist *gl = &ls->dyd->gt; |
|
|
int i = ls->fs->bl->firstgoto; |
|
|
int i = ls->fs->bl->firstgoto; |
|
|
while (i < gl->n) { |
|
|
while (i < gl->n) { |
|
|
if (luaS_eqstr(gl->arr[i].name, lb->name)) |
|
|
if (eqstr(gl->arr[i].name, lb->name)) |
|
|
closegoto(ls, i, lb); |
|
|
closegoto(ls, i, lb); |
|
|
else |
|
|
else |
|
|
i++; |
|
|
i++; |
|
@ -525,7 +519,6 @@ static void codeclosure (LexState *ls, expdesc *v) { |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static void open_func (LexState *ls, FuncState *fs, BlockCnt *bl) { |
|
|
static void open_func (LexState *ls, FuncState *fs, BlockCnt *bl) { |
|
|
lua_State *L = ls->L; |
|
|
|
|
|
Proto *f; |
|
|
Proto *f; |
|
|
fs->prev = ls->fs; /* linked list of funcstates */ |
|
|
fs->prev = ls->fs; /* linked list of funcstates */ |
|
|
fs->ls = ls; |
|
|
fs->ls = ls; |
|
@ -544,10 +537,6 @@ static void open_func (LexState *ls, FuncState *fs, BlockCnt *bl) { |
|
|
f = fs->f; |
|
|
f = fs->f; |
|
|
f->source = ls->source; |
|
|
f->source = ls->source; |
|
|
f->maxstacksize = 2; /* registers 0/1 are always valid */ |
|
|
f->maxstacksize = 2; /* registers 0/1 are always valid */ |
|
|
fs->h = luaH_new(L); |
|
|
|
|
|
/* anchor table of constants (to avoid being collected) */ |
|
|
|
|
|
sethvalue2s(L, L->top, fs->h); |
|
|
|
|
|
incr_top(L); |
|
|
|
|
|
enterblock(fs, bl, 0); |
|
|
enterblock(fs, bl, 0); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
@ -572,9 +561,6 @@ static void close_func (LexState *ls) { |
|
|
f->sizeupvalues = fs->nups; |
|
|
f->sizeupvalues = fs->nups; |
|
|
lua_assert(fs->bl == NULL); |
|
|
lua_assert(fs->bl == NULL); |
|
|
ls->fs = fs->prev; |
|
|
ls->fs = fs->prev; |
|
|
/* last token read was anchored in defunct function; must re-anchor it */ |
|
|
|
|
|
anchor_token(ls); |
|
|
|
|
|
L->top--; /* pop table of constants */ |
|
|
|
|
|
luaC_checkGC(L); |
|
|
luaC_checkGC(L); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
@ -1202,7 +1188,7 @@ static void gotostat (LexState *ls, int pc) { |
|
|
static void checkrepeated (FuncState *fs, Labellist *ll, TString *label) { |
|
|
static void checkrepeated (FuncState *fs, Labellist *ll, TString *label) { |
|
|
int i; |
|
|
int i; |
|
|
for (i = fs->bl->firstlabel; i < ll->n; i++) { |
|
|
for (i = fs->bl->firstlabel; i < ll->n; i++) { |
|
|
if (luaS_eqstr(label, ll->arr[i].name)) { |
|
|
if (eqstr(label, ll->arr[i].name)) { |
|
|
const char *msg = luaO_pushfstring(fs->ls->L, |
|
|
const char *msg = luaO_pushfstring(fs->ls->L, |
|
|
"label " LUA_QS " already defined on line %d", |
|
|
"label " LUA_QS " already defined on line %d", |
|
|
getstr(label), ll->arr[i].line); |
|
|
getstr(label), ll->arr[i].line); |
|
@ -1627,8 +1613,10 @@ Closure *luaY_parser (lua_State *L, ZIO *z, Mbuffer *buff, |
|
|
LexState lexstate; |
|
|
LexState lexstate; |
|
|
FuncState funcstate; |
|
|
FuncState funcstate; |
|
|
Closure *cl = luaF_newLclosure(L, 1); /* create main closure */ |
|
|
Closure *cl = luaF_newLclosure(L, 1); /* create main closure */ |
|
|
/* anchor closure (to avoid being collected) */ |
|
|
setclLvalue(L, L->top, cl); /* anchor it (to avoid being collected) */ |
|
|
setclLvalue(L, L->top, cl); |
|
|
incr_top(L); |
|
|
|
|
|
lexstate.h = luaH_new(L); /* create table for scanner */ |
|
|
|
|
|
sethvalue(L, L->top, lexstate.h); /* anchor it */ |
|
|
incr_top(L); |
|
|
incr_top(L); |
|
|
funcstate.f = cl->l.p = luaF_newproto(L); |
|
|
funcstate.f = cl->l.p = luaF_newproto(L); |
|
|
funcstate.f->source = luaS_new(L, name); /* create and anchor TString */ |
|
|
funcstate.f->source = luaS_new(L, name); /* create and anchor TString */ |
|
@ -1641,6 +1629,7 @@ Closure *luaY_parser (lua_State *L, ZIO *z, Mbuffer *buff, |
|
|
lua_assert(!funcstate.prev && funcstate.nups == 1 && !lexstate.fs); |
|
|
lua_assert(!funcstate.prev && funcstate.nups == 1 && !lexstate.fs); |
|
|
/* all scopes should be correctly finished */ |
|
|
/* all scopes should be correctly finished */ |
|
|
lua_assert(dyd->actvar.n == 0 && dyd->gt.n == 0 && dyd->label.n == 0); |
|
|
lua_assert(dyd->actvar.n == 0 && dyd->gt.n == 0 && dyd->label.n == 0); |
|
|
return cl; /* it's on the stack too */ |
|
|
L->top--; /* remove scanner's table */ |
|
|
|
|
|
return cl; /* closure is on the stack, too */ |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|