From 677313da32d58b418c15dc5f4a6ff435fb63d365 Mon Sep 17 00:00:00 2001 From: Roberto Ierusalimschy Date: Wed, 24 May 2000 15:04:17 -0300 Subject: [PATCH] bug: record-constructor starting with an upvalue name gets an error --- bugs | 8 ++ lcode.c | 4 +- llex.c | 13 +-- llex.h | 17 +-- lparser.c | 315 +++++++++++++++++++++++++++--------------------------- 5 files changed, 183 insertions(+), 174 deletions(-) diff --git a/bugs b/bugs index 0824384c..04149f18 100644 --- a/bugs +++ b/bugs @@ -179,4 +179,12 @@ Tue May 2 15:27:58 EST 2000 ** lparser.c Fri May 12 15:11:12 EST 2000 >> first element in a list constructor is not adjusted to one value +>> (e.g. «a = {gsub('a','a','')}») (by Tomas; since 4.0a) + +** lparser.c +Wed May 24 14:50:16 EST 2000 +>> record-constructor starting with an upvalue name gets an error +>> (e.g. «local a; function f() x = {a=1} end») +(by Edgar Toernig; since 3.1) + diff --git a/lcode.c b/lcode.c index 8577824b..e471ffd1 100644 --- a/lcode.c +++ b/lcode.c @@ -1,5 +1,5 @@ /* -** $Id: lcode.c,v 1.31 2000/05/22 18:44:46 roberto Exp roberto $ +** $Id: lcode.c,v 1.32 2000/05/24 13:54:49 roberto Exp roberto $ ** Code generator for Lua ** See Copyright Notice in lua.h */ @@ -19,7 +19,7 @@ void luaK_error (LexState *ls, const char *msg) { - luaX_error(ls, msg, ls->token); + luaX_error(ls, msg, ls->t.token); } diff --git a/llex.c b/llex.c index 00a248a9..e5275682 100644 --- a/llex.c +++ b/llex.c @@ -1,5 +1,5 @@ /* -** $Id: llex.c,v 1.58 2000/05/08 19:32:53 roberto Exp roberto $ +** $Id: llex.c,v 1.59 2000/05/24 13:54:49 roberto Exp roberto $ ** Lexical Analyzer ** See Copyright Notice in lua.h */ @@ -54,7 +54,7 @@ void luaX_checklimit (LexState *ls, int val, int limit, const char *msg) { if (val > limit) { char buff[100]; sprintf(buff, "too many %.50s (limit=%d)", msg, limit); - luaX_error(ls, buff, ls->token); + luaX_error(ls, buff, ls->t.token); } } @@ -108,6 +108,7 @@ static void firstline (LexState *LS) void luaX_setinput (lua_State *L, LexState *LS, ZIO *z) { LS->L = L; LS->current = '\n'; + LS->next.token = TK_EOS; /* no next token */ LS->linenumber = 0; LS->iflevel = 0; LS->ifstate[0].skip = 0; @@ -281,7 +282,7 @@ static void read_long_string (lua_State *L, LexState *LS) { } } endloop: save_and_next(L, LS); /* skip the second ']' */ - LS->seminfo.ts = luaS_newlstr(L, L->Mbuffer+(L->Mbuffbase+2), + LS->t.seminfo.ts = luaS_newlstr(L, L->Mbuffer+(L->Mbuffbase+2), L->Mbuffnext-L->Mbuffbase-4); } @@ -327,7 +328,7 @@ static void read_string (lua_State *L, LexState *LS, int del) { } } save_and_next(L, LS); /* skip delimiter */ - LS->seminfo.ts = luaS_newlstr(L, L->Mbuffer+(L->Mbuffbase+1), + LS->t.seminfo.ts = luaS_newlstr(L, L->Mbuffer+(L->Mbuffbase+1), L->Mbuffnext-L->Mbuffbase-2); } @@ -426,7 +427,7 @@ int luaX_lex (LexState *LS) { save_and_next(L, LS); } save(L, '\0'); - if (!luaO_str2d(L->Mbuffer+L->Mbuffbase, &LS->seminfo.r)) + if (!luaO_str2d(L->Mbuffer+L->Mbuffbase, &LS->t.seminfo.r)) luaX_error(LS, "malformed number", TK_NUMBER); return TK_NUMBER; @@ -455,7 +456,7 @@ int luaX_lex (LexState *LS) { ts = luaS_new(L, L->Mbuffer+L->Mbuffbase); if (ts->marked >= RESERVEDMARK) /* reserved word? */ return ts->marked-RESERVEDMARK+FIRST_RESERVED; - LS->seminfo.ts = ts; + LS->t.seminfo.ts = ts; return TK_NAME; } } diff --git a/llex.h b/llex.h index b0f0fc8c..7235bdc8 100644 --- a/llex.h +++ b/llex.h @@ -1,5 +1,5 @@ /* -** $Id: llex.h,v 1.24 2000/04/12 18:57:19 roberto Exp roberto $ +** $Id: llex.h,v 1.25 2000/05/24 13:54:49 roberto Exp roberto $ ** Lexical Analyzer ** See Copyright Notice in lua.h */ @@ -44,15 +44,20 @@ struct ifState { }; -typedef struct LexState { - int current; /* look ahead character */ - int token; /* look ahead token */ - struct FuncState *fs; /* `FuncState' is private to the parser */ - struct lua_State *L; +typedef struct Token { + int token; union { Number r; TString *ts; } seminfo; /* semantics information */ +} Token; + +typedef struct LexState { + int current; /* look ahead character */ + Token t; /* look ahead token */ + Token next; /* to `unget' a token */ + struct FuncState *fs; /* `FuncState' is private to the parser */ + struct lua_State *L; struct zio *z; /* input stream */ int linenumber; /* input line counter */ int iflevel; /* level of nested $if's (for lexical analysis) */ diff --git a/lparser.c b/lparser.c index 72fe2f13..08790266 100644 --- a/lparser.c +++ b/lparser.c @@ -1,5 +1,5 @@ /* -** $Id: lparser.c,v 1.88 2000/05/22 18:44:46 roberto Exp roberto $ +** $Id: lparser.c,v 1.89 2000/05/24 13:54:49 roberto Exp roberto $ ** LL(1) Parser and code generator for Lua ** See Copyright Notice in lua.h */ @@ -54,8 +54,20 @@ static void expr (LexState *ls, expdesc *v); static void exp1 (LexState *ls); + static void next (LexState *ls) { - ls->token = luaX_lex(ls); + if (ls->next.token != TK_EOS) { /* is there an `unget' token? */ + ls->t = ls->next; /* use this one */ + ls->next.token = TK_EOS; /* and discharge it */ + } + else + ls->t.token = luaX_lex(ls); /* read next token */ +} + + +static void ungettoken (LexState *ls, Token *t) { + ls->next = ls->t; + ls->t = *t; } @@ -73,7 +85,7 @@ static void error_unexpected (LexState *ls) { static void check (LexState *ls, int c) { - if (ls->token != c) + if (ls->t.token != c) error_expected(ls, c); next(ls); } @@ -90,7 +102,7 @@ static void setline (LexState *ls) { static int optional (LexState *ls, int c) { - if (ls->token == c) { + if (ls->t.token == c) { next(ls); return 1; } @@ -99,7 +111,7 @@ static int optional (LexState *ls, int c) { static void check_match (LexState *ls, int what, int who, int where) { - if (ls->token != what) { + if (ls->t.token != what) { if (where == ls->linenumber) error_expected(ls, what); else { @@ -149,9 +161,9 @@ static void code_string (LexState *ls, TString *s) { static int checkname (LexState *ls) { int sc; - if (ls->token != TK_NAME) + if (ls->t.token != TK_NAME) luaK_error(ls, " expected"); - sc = string_constant(ls->fs, ls->seminfo.ts); + sc = string_constant(ls->fs, ls->t.seminfo.ts); next(ls); return sc; } @@ -164,7 +176,7 @@ static TString *str_checkname (LexState *ls) { static TString *optionalname (LexState *ls) { - if (ls->token == TK_NAME) + if (ls->t.token == TK_NAME) return str_checkname(ls); else return NULL; @@ -296,6 +308,7 @@ static void adjust_mult_assign (LexState *ls, int nvars, int nexps) { static void code_args (LexState *ls, int nparams, int dots) { FuncState *fs = ls->fs; + nparams -= dots; /* do not count `...' as a parameter */ adjustlocalvars(ls, nparams); luaX_checklimit(ls, fs->nlocalvar, MAXPARAMS, "parameters"); nparams = fs->nlocalvar; /* `self' could be there already */ @@ -310,19 +323,6 @@ static void code_args (LexState *ls, int nparams, int dots) { } -static int getvarname (LexState *ls, expdesc *var) { - switch (var->k) { - case VGLOBAL: - return var->u.index; - case VLOCAL: - return string_constant(ls->fs, ls->fs->localvar[var->u.index]); - default: - error_unexpected(ls); /* there is no `var name' */ - return 0; /* to avoid warnings */ - } -} - - static void enterbreak (FuncState *fs, Breaklabel *bl) { bl->stacklevel = fs->stacklevel; bl->label = NULL; @@ -417,7 +417,7 @@ Proto *luaY_parser (lua_State *L, ZIO *z) { init_state(&lexstate, &funcstate, luaS_new(L, zname(z))); next(&lexstate); /* read first token */ chunk(&lexstate); - if (lexstate.token != TK_EOS) + if (lexstate.t.token != TK_EOS) luaK_error(&lexstate, " expected"); close_func(&lexstate); LUA_ASSERT(L, funcstate.prev == NULL, "wrong list end"); @@ -436,7 +436,7 @@ static int explist1 (LexState *ls) { int n = 1; /* at least one expression */ expdesc v; expr(ls, &v); - while (ls->token == ',') { + while (ls->t.token == ',') { luaK_tostack(ls, &v, 1); /* gets only 1 value from previous expression */ next(ls); /* skip comma */ expr(ls, &v); @@ -449,7 +449,7 @@ static int explist1 (LexState *ls) { static int explist (LexState *ls) { /* explist -> [ explist1 ] */ - switch (ls->token) { + switch (ls->t.token) { case TK_NUMBER: case TK_STRING: case TK_NIL: case '{': case TK_FUNCTION: case '(': case TK_NAME: case '%': case TK_NOT: case '-': /* first `expr' */ @@ -463,7 +463,7 @@ static int explist (LexState *ls) { static void funcargs (LexState *ls, int slf) { FuncState *fs = ls->fs; int slevel = fs->stacklevel - slf - 1; /* where is func in the stack */ - switch (ls->token) { + switch (ls->t.token) { case '(': { /* funcargs -> '(' explist ')' */ int line = ls->linenumber; int nargs; @@ -478,19 +478,19 @@ static void funcargs (LexState *ls, int slf) { #endif break; } - - case '{': /* funcargs -> constructor */ + case '{': { /* funcargs -> constructor */ constructor(ls); break; - - case TK_STRING: /* funcargs -> STRING */ - code_string(ls, ls->seminfo.ts); /* must use `seminfo' before `next' */ + } + case TK_STRING: { /* funcargs -> STRING */ + code_string(ls, ls->t.seminfo.ts); /* must use `seminfo' before `next' */ next(ls); break; - - default: + } + default: { luaK_error(ls, "function arguments expected"); break; + } } fs->stacklevel = slevel; /* call will remove function and arguments */ luaK_code2(fs, OP_CALL, slevel, MULT_RET); @@ -499,22 +499,22 @@ static void funcargs (LexState *ls, int slf) { static void var_or_func_tail (LexState *ls, expdesc *v) { for (;;) { - switch (ls->token) { - case '.': /* var_or_func_tail -> '.' NAME */ + switch (ls->t.token) { + case '.': { /* var_or_func_tail -> '.' NAME */ next(ls); luaK_tostack(ls, v, 1); /* `v' must be on stack */ luaK_kstr(ls, checkname(ls)); v->k = VINDEXED; break; - - case '[': /* var_or_func_tail -> '[' exp1 ']' */ + } + case '[': { /* var_or_func_tail -> '[' exp1 ']' */ next(ls); luaK_tostack(ls, v, 1); /* `v' must be on stack */ v->k = VINDEXED; exp1(ls); check(ls, ']'); break; - + } case ':': { /* var_or_func_tail -> ':' NAME funcargs */ int name; next(ls); @@ -526,14 +526,13 @@ static void var_or_func_tail (LexState *ls, expdesc *v) { v->u.l.t = v->u.l.f = NO_JUMP; break; } - - case '(': case TK_STRING: case '{': /* var_or_func_tail -> funcargs */ + case '(': case TK_STRING: case '{': { /* var_or_func_tail -> funcargs */ luaK_tostack(ls, v, 1); /* `v' must be on stack */ funcargs(ls, 0); v->k = VEXP; v->u.l.t = v->u.l.f = NO_JUMP; break; - + } default: return; /* should be follow... */ } } @@ -563,17 +562,17 @@ static void var_or_func (LexState *ls, expdesc *v) { static void recfield (LexState *ls) { /* recfield -> (NAME | '['exp1']') = exp1 */ - switch (ls->token) { - case TK_NAME: + switch (ls->t.token) { + case TK_NAME: { luaK_kstr(ls, checkname(ls)); break; - - case '[': + } + case '[': { next(ls); exp1(ls); check(ls, ']'); break; - + } default: luaK_error(ls, " or `[' expected"); } check(ls, '='); @@ -582,13 +581,14 @@ static void recfield (LexState *ls) { static int recfields (LexState *ls) { - /* recfields -> { ',' recfield } [','] */ + /* recfields -> recfield { ',' recfield } [','] */ FuncState *fs = ls->fs; - int n = 1; /* one has been read before */ + int n = 1; /* at least one element */ int mod_n = 1; /* mod_n == n%RFIELDS_PER_FLUSH */ - while (ls->token == ',') { + recfield(ls); + while (ls->t.token == ',') { next(ls); - if (ls->token == ';' || ls->token == '}') + if (ls->t.token == ';' || ls->t.token == '}') break; recfield(ls); n++; @@ -604,13 +604,14 @@ static int recfields (LexState *ls) { static int listfields (LexState *ls) { - /* listfields -> { ',' exp1 } [','] */ + /* listfields -> exp1 { ',' exp1 } [','] */ FuncState *fs = ls->fs; - int n = 1; /* one has been read before */ + int n = 1; /* at least one element */ int mod_n = 1; /* mod_n == n%LFIELDS_PER_FLUSH */ - while (ls->token == ',') { + exp1(ls); + while (ls->t.token == ',') { next(ls); - if (ls->token == ';' || ls->token == '}') + if (ls->t.token == ';' || ls->t.token == '}') break; exp1(ls); n++; @@ -629,41 +630,34 @@ static int listfields (LexState *ls) { static void constructor_part (LexState *ls, Constdesc *cd) { - switch (ls->token) { - case ';': case '}': /* constructor_part -> empty */ + switch (ls->t.token) { + case ';': case '}': { /* constructor_part -> empty */ cd->n = 0; - cd->k = ls->token; - return; - - case TK_NAME: { - expdesc v; - expr(ls, &v); - if (ls->token == '=') { - luaK_kstr(ls, getvarname(ls, &v)); - next(ls); /* skip '=' */ - exp1(ls); - cd->n = recfields(ls); - cd->k = 1; /* record */ - } - else { - luaK_tostack(ls, &v, 1); - cd->n = listfields(ls); - cd->k = 0; /* list */ - } + cd->k = ls->t.token; break; } - - case '[': /* constructor_part -> recfield recfields */ - recfield(ls); + case TK_NAME: { /* may be listfields or recfields */ + Token current; + int nexttoken; /* to get the look ahead */ + current = ls->t; /* save for `unget' */ + next(ls); + nexttoken = ls->t.token; + ungettoken(ls, ¤t); + if (nexttoken != '=') /* expression? */ + goto case_default; + /* else go through to recfields */ + } + case '[': { /* constructor_part -> recfields */ cd->n = recfields(ls); cd->k = 1; /* record */ break; - - default: /* constructor_part -> exp1 listfields */ - exp1(ls); + } + default: { /* constructor_part -> listfields */ + case_default: cd->n = listfields(ls); cd->k = 0; /* list */ break; + } } } @@ -678,7 +672,7 @@ static void constructor (LexState *ls) { check(ls, '{'); constructor_part(ls, &cd); nelems = cd.n; - if (ls->token == ';') { + if (ls->t.token == ';') { Constdesc other_cd; next(ls); constructor_part(ls, &other_cd); @@ -707,46 +701,46 @@ static void constructor (LexState *ls) { static void simpleexp (LexState *ls, expdesc *v) { FuncState *fs = ls->fs; setline(ls); - switch (ls->token) { + switch (ls->t.token) { case TK_NUMBER: { /* simpleexp -> NUMBER */ - Number r = ls->seminfo.r; + Number r = ls->t.seminfo.r; next(ls); luaK_number(fs, r); break; } - - case TK_STRING: /* simpleexp -> STRING */ - code_string(ls, ls->seminfo.ts); /* must use `seminfo' before `next' */ + case TK_STRING: { /* simpleexp -> STRING */ + code_string(ls, ls->t.seminfo.ts); /* must use `seminfo' before `next' */ next(ls); break; - - case TK_NIL: /* simpleexp -> NIL */ + } + case TK_NIL: { /* simpleexp -> NIL */ luaK_adjuststack(fs, -1); next(ls); break; - - case '{': /* simpleexp -> constructor */ + } + case '{': { /* simpleexp -> constructor */ constructor(ls); break; - - case TK_FUNCTION: /* simpleexp -> FUNCTION body */ + } + case TK_FUNCTION: { /* simpleexp -> FUNCTION body */ next(ls); body(ls, 0, ls->linenumber); break; - - case '(': /* simpleexp -> '(' expr ')' */ + } + case '(': { /* simpleexp -> '(' expr ')' */ next(ls); expr(ls, v); check(ls, ')'); return; - - case TK_NAME: case '%': + } + case TK_NAME: case '%': { var_or_func(ls, v); return; - - default: + } + default: { luaK_error(ls, " expected"); return; + } } v->k = VEXP; v->u.l.t = v->u.l.f = NO_JUMP; @@ -793,17 +787,17 @@ static int get_priority (int op, int *rp) { */ static void subexpr (LexState *ls, expdesc *v, int limit) { int rp; - if (ls->token == '-' || ls->token == TK_NOT) { - int op = ls->token; /* operator */ + if (ls->t.token == '-' || ls->t.token == TK_NOT) { + int op = ls->t.token; /* operator */ next(ls); subexpr(ls, v, UNARY_PRIORITY); luaK_prefix(ls, op, v); } else simpleexp(ls, v); /* expand while operators have priorities higher than `limit' */ - while (get_priority(ls->token, &rp) > limit) { + while (get_priority(ls->t.token, &rp) > limit) { expdesc v2; - int op = ls->token; /* current operator (with priority == `rp') */ + int op = ls->t.token; /* current operator (with priority == `rp') */ next(ls); luaK_infix(ls, op, v); subexpr(ls, &v2, rp); /* read sub-expression with priority > `rp' */ @@ -839,7 +833,7 @@ static void block (LexState *ls) { static int assignment (LexState *ls, expdesc *v, int nvars) { int left = 0; luaX_checklimit(ls, nvars, MAXVARSLH, "variables in a multiple assignment"); - if (ls->token == ',') { /* assignment -> ',' NAME assignment */ + if (ls->t.token == ',') { /* assignment -> ',' NAME assignment */ expdesc nv; next(ls); var_or_func(ls, &nv); @@ -849,7 +843,7 @@ static int assignment (LexState *ls, expdesc *v, int nvars) { } else { /* assignment -> '=' explist1 */ int nexps;; - if (ls->token != '=') + if (ls->t.token != '=') error_unexpected(ls); next(ls); nexps = explist1(ls); @@ -936,7 +930,7 @@ static void forlist (LexState *ls, TString *indexname) { check(ls, ','); valname = str_checkname(ls); /* next test is dirty, but avoids `in' being a reserved word */ - if (ls->token != TK_NAME || ls->seminfo.ts != luaS_new(ls->L, "in")) + if (ls->t.token != TK_NAME || ls->t.seminfo.ts != luaS_new(ls->L, "in")) luaK_error(ls, "`in' expected"); next(ls); /* skip `in' */ exp1(ls); /* table */ @@ -959,7 +953,7 @@ static void forstat (LexState *ls, int line) { enterbreak(fs, &bl); setline_and_next(ls); /* skip `for' */ varname = str_checkname(ls); /* first variable name */ - switch (ls->token) { + switch (ls->t.token) { case '=': fornum(ls, varname); break; case ',': forlist(ls, varname); break; default: luaK_error(ls, "`=' or `,' expected"); @@ -986,12 +980,12 @@ static void ifstat (LexState *ls, int line) { expdesc v; int escapelist = NO_JUMP; test_and_block(ls, &v); /* IF cond THEN block */ - while (ls->token == TK_ELSEIF) { + while (ls->t.token == TK_ELSEIF) { luaK_concat(fs, &escapelist, luaK_jump(fs)); luaK_patchlist(fs, v.u.l.f, luaK_getlabel(fs)); test_and_block(ls, &v); /* ELSEIF cond THEN block */ } - if (ls->token == TK_ELSE) { + if (ls->t.token == TK_ELSE) { luaK_concat(fs, &escapelist, luaK_jump(fs)); luaK_patchlist(fs, v.u.l.f, luaK_getlabel(fs)); setline_and_next(ls); /* skip ELSE */ @@ -1008,7 +1002,7 @@ static int localnamelist (LexState *ls) { /* localnamelist -> NAME {',' NAME} */ int i = 1; store_localvar(ls, str_checkname(ls), 0); - while (ls->token == ',') { + while (ls->t.token == ',') { next(ls); store_localvar(ls, str_checkname(ls), i++); } @@ -1018,7 +1012,7 @@ static int localnamelist (LexState *ls) { static int decinit (LexState *ls) { /* decinit -> ['=' explist1] */ - if (ls->token == '=') { + if (ls->t.token == '=') { next(ls); return explist1(ls); } @@ -1043,8 +1037,8 @@ static int funcname (LexState *ls, expdesc *v) { /* funcname -> NAME [':' NAME | '.' NAME] */ int needself = 0; singlevar(ls, str_checkname(ls), v, 0); - if (ls->token == ':' || ls->token == '.') { - needself = (ls->token == ':'); + if (ls->t.token == ':' || ls->t.token == '.') { + needself = (ls->t.token == ':'); next(ls); luaK_tostack(ls, v, 1); luaK_kstr(ls, checkname(ls)); @@ -1110,86 +1104,87 @@ static void breakstat (LexState *ls) { static int stat (LexState *ls) { int line = ls->linenumber; /* may be needed for error messages */ - switch (ls->token) { - case TK_IF: /* stat -> ifstat */ + switch (ls->t.token) { + case TK_IF: { /* stat -> ifstat */ ifstat(ls, line); return 1; - - case TK_WHILE: /* stat -> whilestat */ + } + case TK_WHILE: { /* stat -> whilestat */ whilestat(ls, line); return 1; - - case TK_DO: /* stat -> DO block END */ + } + case TK_DO: { /* stat -> DO block END */ setline_and_next(ls); /* skip DO */ block(ls); check_END(ls, TK_DO, line); return 1; - - case TK_FOR: /* stat -> forstat */ + } + case TK_FOR: { /* stat -> forstat */ forstat(ls, line); return 1; - - case TK_REPEAT: /* stat -> repeatstat */ + } + case TK_REPEAT: { /* stat -> repeatstat */ repeatstat(ls, line); return 1; - - case TK_FUNCTION: /* stat -> funcstat */ + } + case TK_FUNCTION: { /* stat -> funcstat */ funcstat(ls, line); return 1; - - case TK_LOCAL: /* stat -> localstat */ + } + case TK_LOCAL: { /* stat -> localstat */ localstat(ls); return 1; - - case TK_NAME: case '%': /* stat -> namestat */ + } + case TK_NAME: case '%': { /* stat -> namestat */ namestat(ls); return 1; - - case TK_RETURN: /* stat -> retstat */ + } + case TK_RETURN: { /* stat -> retstat */ retstat(ls); return 2; /* must be last statement */ - - case TK_BREAK: /* stat -> breakstat */ + } + case TK_BREAK: { /* stat -> breakstat */ breakstat(ls); return 2; /* must be last statement */ - - default: + } + default: { return 0; /* no statement */ + } + } +} + + +static int param (LexState *ls, int n) { + /* param -> NAME | DOTS */ + switch (ls->t.token) { + case TK_DOTS: { + next(ls); + return 1; + } + case TK_NAME: { + store_localvar(ls, str_checkname(ls), n); + return 0; + } + default: { + luaK_error(ls, " or `...' expected"); + return 0; /* to avoid warnings */ + } } } static void parlist (LexState *ls) { + /* parlist -> [ param { ',' param } ] */ int nparams = 0; int dots = 0; - switch (ls->token) { - case TK_DOTS: /* parlist -> DOTS */ + if (ls->t.token != ')') { /* is `parlist' not empty? */ + dots = param(ls, nparams); + nparams++; + while (ls->t.token == ',' && !dots) { next(ls); - dots = 1; - break; - - case TK_NAME: /* parlist, tailparlist -> NAME [',' tailparlist] */ - init: - store_localvar(ls, str_checkname(ls), nparams++); - if (ls->token == ',') { - next(ls); - switch (ls->token) { - case TK_DOTS: /* tailparlist -> DOTS */ - next(ls); - dots = 1; - break; - - case TK_NAME: /* tailparlist -> NAME [',' tailparlist] */ - goto init; - - default: luaK_error(ls, " or `...' expected"); - } - } - break; - - case ')': break; /* parlist -> empty */ - - default: luaK_error(ls, " or `...' expected"); + dots = param(ls, nparams); + nparams++; + } } code_args(ls, nparams, dots); }