restricted syntax for function call/table accesses prefixes

This commit is contained in:
Roberto Ierusalimschy 2001-09-25 14:06:48 -03:00
parent c04d9b9ecb
commit 328d53e77b
1 changed files with 55 additions and 42 deletions

View File

@ -1,5 +1,5 @@
/* /*
** $Id: lparser.c,v 1.154 2001/08/27 15:16:28 roberto Exp $ ** $Id: lparser.c,v 1.156 2001/09/07 17:39:10 roberto Exp $
** Lua Parser ** Lua Parser
** See Copyright Notice in lua.h ** See Copyright Notice in lua.h
*/ */
@ -419,6 +419,8 @@ static void funcargs (LexState *ls, expdesc *f) {
switch (ls->t.token) { switch (ls->t.token) {
case l_c('('): { /* funcargs -> `(' [ explist1 ] `)' */ case l_c('('): { /* funcargs -> `(' [ explist1 ] `)' */
int line = ls->linenumber; int line = ls->linenumber;
if (line != ls->lastline)
luaK_error(ls, l_s("ambiguous syntax (function call x new statement)"));
next(ls); next(ls);
if (ls->t.token == l_c(')')) /* arg list is empty? */ if (ls->t.token == l_c(')')) /* arg list is empty? */
args.k = VVOID; args.k = VVOID;
@ -605,33 +607,10 @@ static void constructor (LexState *ls, expdesc *t) {
** ======================================================================= ** =======================================================================
*/ */
static void primaryexp (LexState *ls, expdesc *v) {
static void prefixexp (LexState *ls, expdesc *v) {
/* prefixexp -> NAME | '(' expr ')' */
switch (ls->t.token) { switch (ls->t.token) {
case TK_NUMBER: {
init_exp(v, VNUMBER, 0);
v->u.n = ls->t.seminfo.r;
next(ls); /* must use `seminfo' before `next' */
break;
}
case TK_STRING: {
codestring(ls, v, ls->t.seminfo.ts);
next(ls); /* must use `seminfo' before `next' */
break;
}
case TK_NIL: {
init_exp(v, VNIL, 0);
next(ls);
break;
}
case l_c('{'): { /* constructor */
constructor(ls, v);
break;
}
case TK_FUNCTION: {
next(ls);
body(ls, v, 0, ls->linenumber);
break;
}
case l_c('('): { case l_c('('): {
next(ls); next(ls);
expr(ls, v); expr(ls, v);
@ -651,7 +630,6 @@ static void primaryexp (LexState *ls, expdesc *v) {
next(ls); next(ls);
return; return;
} }
default: { default: {
luaK_error(ls, l_s("unexpected symbol")); luaK_error(ls, l_s("unexpected symbol"));
return; return;
@ -660,11 +638,11 @@ static void primaryexp (LexState *ls, expdesc *v) {
} }
static void simpleexp (LexState *ls, expdesc *v) { static void primaryexp (LexState *ls, expdesc *v) {
/* simpleexp -> /* primaryexp ->
primaryexp { `.' NAME | `[' exp `]' | `:' NAME funcargs | funcargs } */ prefixexp { `.' NAME | `[' exp `]' | `:' NAME funcargs | funcargs } */
FuncState *fs = ls->fs; FuncState *fs = ls->fs;
primaryexp(ls, v); prefixexp(ls, v);
for (;;) { for (;;) {
switch (ls->t.token) { switch (ls->t.token) {
case l_c('.'): { /* field */ case l_c('.'): { /* field */
@ -691,12 +669,51 @@ static void simpleexp (LexState *ls, expdesc *v) {
funcargs(ls, v); funcargs(ls, v);
break; break;
} }
default: return; /* should be follow... */ default: return;
} }
} }
} }
static void simpleexp (LexState *ls, expdesc *v) {
/* simpleexp -> NUMBER | STRING | NIL | constructor | FUNCTION body
| primaryexp */
switch (ls->t.token) {
case TK_NUMBER: {
init_exp(v, VNUMBER, 0);
v->u.n = ls->t.seminfo.r;
next(ls); /* must use `seminfo' before `next' */
break;
}
case TK_STRING: {
codestring(ls, v, ls->t.seminfo.ts);
next(ls); /* must use `seminfo' before `next' */
break;
}
case TK_NIL: {
init_exp(v, VNIL, 0);
next(ls);
break;
}
case l_c('{'): { /* constructor */
constructor(ls, v);
break;
}
case TK_FUNCTION: {
next(ls);
body(ls, v, 0, ls->linenumber);
break;
}
default: {
primaryexp(ls, v);
break;
}
}
}
static UnOpr getunopr (int op) { static UnOpr getunopr (int op) {
switch (op) { switch (op) {
case TK_NOT: return OPR_NOT; case TK_NOT: return OPR_NOT;
@ -846,12 +863,12 @@ static void check_conflict (LexState *ls, struct LHS_assign *lh, expdesc *v) {
static void assignment (LexState *ls, struct LHS_assign *lh, int nvars) { static void assignment (LexState *ls, struct LHS_assign *lh, int nvars) {
expdesc e; expdesc e;
check_condition(ls, VLOCAL <= lh->v.k && lh->v.k <= VINDEXED, check_condition(ls, VLOCAL <= lh->v.k && lh->v.k <= VINDEXED,
l_s("syntax error!!")); l_s("syntax error!"));
if (ls->t.token == l_c(',')) { /* assignment -> `,' simpleexp assignment */ if (ls->t.token == l_c(',')) { /* assignment -> `,' primaryexp assignment */
struct LHS_assign nv; struct LHS_assign nv;
nv.prev = lh; nv.prev = lh;
next(ls); next(ls);
simpleexp(ls, &nv.v); primaryexp(ls, &nv.v);
if (nv.v.k == VLOCAL) if (nv.v.k == VLOCAL)
check_conflict(ls, lh, &nv.v); check_conflict(ls, lh, &nv.v);
assignment(ls, &nv, nvars+1); assignment(ls, &nv, nvars+1);
@ -1079,7 +1096,7 @@ static void exprstat (LexState *ls) {
/* stat -> func | assignment */ /* stat -> func | assignment */
FuncState *fs = ls->fs; FuncState *fs = ls->fs;
struct LHS_assign v; struct LHS_assign v;
simpleexp(ls, &v.v); primaryexp(ls, &v.v);
if (v.v.k == VCALL) { /* stat -> func */ if (v.v.k == VCALL) { /* stat -> func */
luaK_setcallreturns(fs, &v.v, 0); /* call statement uses no results */ luaK_setcallreturns(fs, &v.v, 0); /* call statement uses no results */
} }
@ -1155,11 +1172,7 @@ static int statement (LexState *ls) {
return 0; return 0;
} }
case TK_FUNCTION: { case TK_FUNCTION: {
lookahead(ls); funcstat(ls, line); /* stat -> funcstat */
if (ls->lookahead.token == '(')
exprstat(ls);
else
funcstat(ls, line); /* stat -> funcstat */
return 0; return 0;
} }
case TK_LOCAL: { /* stat -> localstat */ case TK_LOCAL: { /* stat -> localstat */