From 7e59a8901d063dbea4eb0693c9c2d85bda1fc5f6 Mon Sep 17 00:00:00 2001 From: Roberto Ierusalimschy Date: Wed, 27 May 1998 10:08:34 -0300 Subject: NEW LL(1) PARSER --- lua.stx | 940 ---------------------------------------------------------------- 1 file changed, 940 deletions(-) delete mode 100644 lua.stx (limited to 'lua.stx') diff --git a/lua.stx b/lua.stx deleted file mode 100644 index 41aff108..00000000 --- a/lua.stx +++ /dev/null @@ -1,940 +0,0 @@ -%{ -/* -** $Id: lua.stx,v 1.36 1998/03/25 18:52:29 roberto Exp roberto $ -** Syntax analizer and code generator -** See Copyright Notice in lua.h -*/ - - -#include -#include - -#include "lauxlib.h" -#include "ldo.h" -#include "lfunc.h" -#include "llex.h" -#include "lmem.h" -#include "lopcodes.h" -#include "lparser.h" -#include "lstate.h" -#include "lstring.h" -#include "lua.h" -#include "luadebug.h" -#include "lzio.h" - - -int luaY_parse (void); - - -#define MES_LIM(x) "(limit=" x ")" - - -/* size of a "normal" jump instruction: OpCode + 1 byte */ -#define JMPSIZE 2 - -/* maximum number of local variables */ -#define MAXLOCALS 32 -#define SMAXLOCALS "32" - -#define MINGLOBAL (MAXLOCALS+1) - -/* maximum number of variables in a multiple assignment */ -#define MAXVAR 32 -#define SMAXVAR "32" - -/* maximum number of nested functions */ -#define MAXSTATES 6 -#define SMAXSTATES "6" - -/* maximum number of upvalues */ -#define MAXUPVALUES 16 -#define SMAXUPVALUES "16" - - - -/* -** Variable descriptor: -** if 0locvars */ - int maxcode; /* size of f->code */ - int maxvars; /* size of f->locvars (-1 if no debug information) */ - int maxconsts; /* size of f->consts */ - vardesc varbuffer[MAXVAR]; /* variables in an assignment list */ - vardesc upvalues[MAXUPVALUES]; /* upvalues */ -} FuncState; - - - -#define YYPURE 1 - - -void luaY_syntaxerror (char *s, char *token) -{ - if (token[0] == 0) - token = ""; - luaL_verror("%.100s;\n last token read: \"%.50s\" at line %d in file %.50s", - s, token, L->lexstate->linenumber, L->mainState->f->fileName->str); -} - - -void luaY_error (char *s) -{ - luaY_syntaxerror(s, luaX_lasttoken()); -} - - -static void check_pc (int n) -{ - FuncState *fs = L->currState; - if (fs->pc+n > fs->maxcode) - fs->maxcode = luaM_growvector(&fs->f->code, fs->maxcode, - Byte, codeEM, MAX_INT); -} - - -static void code_byte (Byte c) -{ - check_pc(1); - L->currState->f->code[L->currState->pc++] = c; -} - - -static void deltastack (int delta) -{ - FuncState *fs = L->currState; - fs->stacksize += delta; - if (fs->stacksize > fs->maxstacksize) { - if (fs->stacksize > 255) - luaY_error("function/expression too complex"); - fs->maxstacksize = fs->stacksize; - } -} - - -static int code_oparg_at (int pc, OpCode op, int builtin, int arg, int delta) -{ - Byte *code = L->currState->f->code; - deltastack(delta); - if (arg < builtin) { - code[pc] = op+1+arg; - return 1; - } - else if (arg <= 255) { - code[pc] = op; - code[pc+1] = arg; - return 2; - } - else if (arg <= MAX_WORD) { - code[pc] = op+1+builtin; - code[pc+1] = arg>>8; - code[pc+2] = arg&0xFF; - return 3; - } - else luaY_error("code too long " MES_LIM("64K")); - return 0; /* to avoid warnings */ -} - - -static int fix_opcode (int pc, OpCode op, int builtin, int arg) -{ - FuncState *fs = L->currState; - if (arg < builtin) { /* close space */ - luaO_memdown(fs->f->code+pc+1, fs->f->code+pc+2, fs->pc-(pc+2)); - fs->pc--; - } - else if (arg > 255) { /* open space */ - check_pc(1); - luaO_memup(fs->f->code+pc+1, fs->f->code+pc, fs->pc-pc); - fs->pc++; - } - return code_oparg_at(pc, op, builtin, arg, 0) - 2; -} - - -static void code_oparg (OpCode op, int builtin, int arg, int delta) -{ - check_pc(3); /* maximum code size */ - L->currState->pc += code_oparg_at(L->currState->pc, op, builtin, arg, delta); -} - - -static void code_opcode (OpCode op, int delta) -{ - deltastack(delta); - code_byte(op); -} - - -static void code_pop (OpCode op) -{ - code_opcode(op, -1); -} - -/* binary operations get 2 arguments and leave one, so they pop one */ -#define code_binop(op) code_pop(op) - - -static void code_neutralop (OpCode op) -{ - code_opcode(op, 0); -} - -/* unary operations get 1 argument and leave one, so they are neutral */ -#define code_unop(op) code_neutralop(op) - - -static void code_constant (int c) -{ - code_oparg(PUSHCONSTANT, 8, c, 1); -} - - -static int next_constant (FuncState *cs) -{ - TProtoFunc *f = cs->f; - if (f->nconsts >= cs->maxconsts) { - cs->maxconsts = luaM_growvector(&f->consts, cs->maxconsts, TObject, - constantEM, MAX_WORD); - } - return f->nconsts++; -} - - -static int string_constant (TaggedString *s, FuncState *cs) -{ - TProtoFunc *f = cs->f; - int c = s->constindex; - if (!(c < f->nconsts && - ttype(&f->consts[c]) == LUA_T_STRING && tsvalue(&f->consts[c]) == s)) { - c = next_constant(cs); - ttype(&f->consts[c]) = LUA_T_STRING; - tsvalue(&f->consts[c]) = s; - s->constindex = c; /* hint for next time */ - } - return c; -} - - -static void code_string (TaggedString *s) -{ - code_constant(string_constant(s, L->currState)); -} - - -#define LIM 20 -static int real_constant (real r) -{ - /* check whether 'r' has appeared within the last LIM entries */ - TObject *cnt = L->currState->f->consts; - int c = L->currState->f->nconsts; - int lim = c < LIM ? 0 : c-LIM; - while (--c >= lim) { - if (ttype(&cnt[c]) == LUA_T_NUMBER && nvalue(&cnt[c]) == r) - return c; - } - /* not found; create a luaM_new entry */ - c = next_constant(L->currState); - cnt = L->currState->f->consts; /* 'next_constant' may reallocate this vector */ - ttype(&cnt[c]) = LUA_T_NUMBER; - nvalue(&cnt[c]) = r; - return c; -} - - -static void code_number (real f) -{ - int i; - if (f >= 0 && f <= (real)MAX_WORD && (real)(i=(int)f) == f) - code_oparg(PUSHNUMBER, 3, i, 1); /* f has an (short) integer value */ - else - code_constant(real_constant(f)); -} - - -static void flush_record (int n) -{ - if (n > 0) - code_oparg(SETMAP, 1, n-1, -2*n); -} - -static void flush_list (int m, int n) -{ - if (n == 0) return; - code_oparg(SETLIST, 1, m, -n); - code_byte(n); -} - - -static void luaI_registerlocalvar (TaggedString *varname, int line) -{ - FuncState *fs = L->currState; - if (fs->maxvars != -1) { /* debug information? */ - if (fs->nvars >= fs->maxvars) - fs->maxvars = luaM_growvector(&fs->f->locvars, fs->maxvars, - LocVar, "", MAX_WORD); - fs->f->locvars[fs->nvars].varname = varname; - fs->f->locvars[fs->nvars].line = line; - fs->nvars++; - } -} - - -static void luaI_unregisterlocalvar (int line) -{ - luaI_registerlocalvar(NULL, line); -} - - -static void store_localvar (TaggedString *name, int n) -{ - if (L->currState->nlocalvar+n < MAXLOCALS) - L->currState->localvar[L->currState->nlocalvar+n] = name; - else - luaY_error("too many local variables " MES_LIM(SMAXLOCALS)); - luaI_registerlocalvar(name, L->lexstate->linenumber); -} - -static void add_localvar (TaggedString *name) -{ - store_localvar(name, 0); - L->currState->nlocalvar++; -} - - -/* -** dotted variables must be stored like regular indexed vars -*/ -static vardesc var2store (vardesc var) -{ - if (isdot(var)) { - code_constant(dotindex(var)); - var = 0; - } - return var; -} - - -static void add_varbuffer (vardesc var, int n) -{ - if (n >= MAXVAR) - luaY_error("variable buffer overflow " MES_LIM(SMAXVAR)); - L->currState->varbuffer[n] = var2store(var); -} - - -static int aux_localname (TaggedString *n, FuncState *st) -{ - int i; - for (i=st->nlocalvar-1; i >= 0; i--) - if (n == st->localvar[i]) return i; /* local var index */ - return -1; /* not found */ -} - - -static vardesc singlevar (TaggedString *n, FuncState *st) -{ - int i = aux_localname(n, st); - if (i == -1) { /* check shadowing */ - int l; - for (l=1; l<=(st-L->mainState); l++) - if (aux_localname(n, st-l) >= 0) - luaY_syntaxerror("cannot access a variable in outer scope", n->str); - return string_constant(n, st)+MINGLOBAL; /* global value */ - } - else return i+1; /* local value */ -} - - -static int indexupvalue (TaggedString *n) -{ - vardesc v = singlevar(n, L->currState-1); - int i; - for (i=0; icurrState->nupvalues; i++) { - if (L->currState->upvalues[i] == v) - return i; - } - /* new one */ - if (++(L->currState->nupvalues) > MAXUPVALUES) - luaY_error("too many upvalues in a single function " MES_LIM(SMAXUPVALUES)); - L->currState->upvalues[i] = v; /* i = L->currState->nupvalues - 1 */ - return i; -} - - -static void pushupvalue (TaggedString *n) -{ - int i; - if (L->currState == L->mainState) - luaY_error("cannot access upvalue in main"); - if (aux_localname(n, L->currState) >= 0) - luaY_syntaxerror("cannot access an upvalue in current scope", n->str); - i = indexupvalue(n); - code_oparg(PUSHUPVALUE, 2, i, 1); -} - - -void luaY_codedebugline (int line) -{ - if (lua_debug && line != L->lexstate->lastline) { - code_oparg(SETLINE, 0, line, 0); - L->lexstate->lastline = line; - } -} - - -static void adjuststack (int n) -{ - if (n > 0) - code_oparg(POP, 2, n-1, -n); - else if (n < 0) - code_oparg(PUSHNIL, 1, (-n)-1, -n); -} - - -static long adjust_functioncall (long exp, int nresults) -{ - if (exp <= 0) - return -exp; /* exp is -list length */ - else { - int temp = L->currState->f->code[exp]; - int nparams = L->currState->f->code[exp-1]; - exp += fix_opcode(exp-2, CALLFUNC, 2, nresults); - L->currState->f->code[exp] = nparams; - if (nresults != MULT_RET) - deltastack(nresults); - deltastack(-(nparams+1)); - return temp+nresults; - } -} - - -static void adjust_mult_assign (int vars, long exps) -{ - if (exps > 0) { /* must correct function call */ - int diff = L->currState->f->code[exps] - vars; - if (diff < 0) - adjust_functioncall(exps, -diff); - else { - adjust_functioncall(exps, 0); - adjuststack(diff); - } - } - else adjuststack((-exps)-vars); -} - - -static void code_args (int nparams, int dots) -{ - L->currState->nlocalvar += nparams; /* "self" may already be there */ - nparams = L->currState->nlocalvar; - if (!dots) { - L->currState->f->code[1] = nparams; /* fill-in arg information */ - deltastack(nparams); - } - else { - L->currState->f->code[1] = nparams+ZEROVARARG; - deltastack(nparams+1); - add_localvar(luaS_new("arg")); - } -} - - -static void lua_pushvar (vardesc var) -{ - if (isglobal(var)) - code_oparg(GETGLOBAL, 8, globalindex(var), 1); - else if (islocal(var)) - code_oparg(PUSHLOCAL, 8, localindex(var), 1); - else if (isdot(var)) - code_oparg(GETDOTTED, 8, dotindex(var), 0); - else - code_pop(GETTABLE); -} - - -static void storevar (vardesc var) -{ - if (var == 0) /* indexed var */ - code_opcode(SETTABLE0, -3); - else if (isglobal(var)) - code_oparg(SETGLOBAL, 8, globalindex(var), -1); - else /* local var */ - code_oparg(SETLOCAL, 8, localindex(var), -1); -} - - -/* returns how many elements are left as 'garbage' on the stack */ -static int lua_codestore (int i, int left) -{ - if (L->currState->varbuffer[i] != 0 || /* global or local var or */ - left+i == 0) { /* indexed var without values in between */ - storevar(L->currState->varbuffer[i]); - return left; - } - else { /* indexed var with values in between*/ - code_oparg(SETTABLE, 0, left+i, -1); - return left+2; /* table/index are not popped, since they are not on top */ - } -} - - -static int fix_jump (int pc, OpCode op, int n) -{ - /* jump is relative to position following jump instruction */ - return fix_opcode(pc, op, 0, n-(pc+JMPSIZE)); -} - - -static void fix_upjmp (OpCode op, int pos) -{ - int delta = L->currState->pc+JMPSIZE - pos; /* jump is relative */ - if (delta > 255) delta++; - code_oparg(op, 0, delta, 0); -} - - -static void codeIf (int thenAdd, int elseAdd) -{ - int elseinit = elseAdd+JMPSIZE; - if (L->currState->pc == elseinit) { /* no else part */ - L->currState->pc -= JMPSIZE; - elseinit = L->currState->pc; - } - else - elseinit += fix_jump(elseAdd, JMP, L->currState->pc); - fix_jump(thenAdd, IFFJMP, elseinit); -} - - -static void code_shortcircuit (int pc, OpCode op) -{ - fix_jump(pc, op, L->currState->pc); -} - - -static void codereturn (void) -{ - code_oparg(RETCODE, 0, L->currState->nlocalvar, 0); - L->currState->stacksize = L->currState->nlocalvar; -} - - -static void func_onstack (TProtoFunc *f) -{ - int i; - int nupvalues = (L->currState+1)->nupvalues; - int c = next_constant(L->currState); - ttype(&L->currState->f->consts[c]) = LUA_T_PROTO; - L->currState->f->consts[c].value.tf = (L->currState+1)->f; - if (nupvalues == 0) - code_constant(c); - else { - for (i=0; icurrState+1)->upvalues[i]); - code_oparg(CLOSURE, 0, c, -nupvalues+1); - code_byte(nupvalues); - } -} - - -static void init_state (TaggedString *filename) -{ - TProtoFunc *f = luaF_newproto(); - FuncState *fs = L->currState; - fs->stacksize = 0; - fs->maxstacksize = 0; - fs->nlocalvar = 0; - fs->nupvalues = 0; - fs->f = f; - f->fileName = filename; - fs->pc = 0; - fs->maxcode = 0; - f->code = NULL; - fs->maxconsts = 0; - if (lua_debug) { - fs->nvars = 0; - fs->maxvars = 0; - } - else - fs->maxvars = -1; /* flag no debug information */ - code_byte(0); /* to be filled with stacksize */ - code_byte(0); /* to be filled with arg information */ - L->lexstate->lastline = 0; /* invalidate it */ -} - - -static void init_func (void) -{ - if (L->currState-L->mainState >= MAXSTATES-1) - luaY_error("too many nested functions " MES_LIM(SMAXSTATES)); - L->currState++; - init_state(L->mainState->f->fileName); - luaY_codedebugline(L->lexstate->linenumber); - L->currState->f->lineDefined = L->lexstate->linenumber; -} - -static TProtoFunc *close_func (void) -{ - TProtoFunc *f = L->currState->f; - code_neutralop(ENDCODE); - f->code[0] = L->currState->maxstacksize; - f->code = luaM_reallocvector(f->code, L->currState->pc, Byte); - f->consts = luaM_reallocvector(f->consts, f->nconsts, TObject); - if (L->currState->maxvars != -1) { /* debug information? */ - luaI_registerlocalvar(NULL, -1); /* flag end of vector */ - f->locvars = luaM_reallocvector(f->locvars, L->currState->nvars, LocVar); - } - L->currState--; - return f; -} - - -/* -** Parse Lua code. -*/ -TProtoFunc *luaY_parser (ZIO *z) -{ - struct LexState lexstate; - FuncState state[MAXSTATES]; - L->currState = L->mainState = &state[0]; - L->lexstate = &lexstate; - luaX_setinput(z); - init_state(luaS_new(zname(z))); - if (luaY_parse()) lua_error("parse error"); - return close_func(); -} - - -%} - - -%union -{ - int vInt; - real vReal; - char *pChar; - long vLong; - TaggedString *pTStr; - TProtoFunc *pFunc; -} - -%start chunk - -%token NIL -%token IF THEN ELSE ELSEIF WHILE DO REPEAT UNTIL END -%token RETURN -%token LOCAL -%token FUNCTION -%token DOTS -%token NUMBER -%token NAME STRING - -%type SaveWord, cond, GetPC, SaveWordPop, SaveWordPush -%type exprlist, exprlist1 /* if > 0, points to function return - counter (which has list length); if <= 0, -list lenght */ -%type functioncall, expr, sexp /* if != 0, points to function return - counter */ -%type varlist1, funcParams, funcvalue -%type fieldlist, localnamelist, decinit -%type ffieldlist1, lfieldlist1, ffieldlist, lfieldlist, part -%type var, varname, funcname /* vardesc */ - - -%left AND OR -%left EQ NE '>' '<' LE GE -%left CONC -%left '+' '-' -%left '*' '/' -%left UNARY NOT -%right '^' - - -%% /* beginning of rules section */ - - -chunk : statlist ret ; - -statlist : /* empty */ - | statlist stat sc - { LUA_ASSERT(L->currState->stacksize == L->currState->nlocalvar, - "stack size != # local vars"); } - ; - -sc : /* empty */ | ';' ; - -stat : IF cond THEN block SaveWord elsepart END { codeIf($2, $5); } - - | DO block END - - | WHILE GetPC cond DO block END - {{ - FuncState *fs = L->currState; - int expsize = $3-$2; - int newpos = $2+JMPSIZE; - check_pc(expsize); - memcpy(fs->f->code+fs->pc, fs->f->code+$2, expsize); - luaO_memdown(fs->f->code+$2, fs->f->code+$3, fs->pc-$2); - newpos += fix_jump($2, JMP, fs->pc-expsize); - fix_upjmp(IFTUPJMP, newpos); - }} - - | REPEAT GetPC block UNTIL expr1 - { - fix_upjmp(IFFUPJMP, $2); - deltastack(-1); /* pops condition */ - } - - | varlist1 '=' exprlist1 - {{ - int i; - int left = 0; - adjust_mult_assign($1, $3); - for (i=$1-1; i>=0; i--) - left = lua_codestore(i, left); - adjuststack(left); /* remove eventual 'garbage' left on stack */ - }} - - | functioncall { adjust_functioncall($1, 0); } - - | LOCAL localnamelist decinit - { - L->currState->nlocalvar += $2; - adjust_mult_assign($2, $3); - } - - | FUNCTION funcname body { storevar($2); } - ; - -block : {$$ = L->currState->nlocalvar;} chunk - { - adjuststack(L->currState->nlocalvar - $1); - for (; L->currState->nlocalvar > $1; L->currState->nlocalvar--) - luaI_unregisterlocalvar(L->lexstate->linenumber); - } - ; - -funcname : varname { $$ = $1; init_func(); } - | fvarname '.' fname - { - $$ = 0; /* flag indexed variable */ - init_func(); - } - | fvarname ':' fname - { - $$ = 0; /* flag indexed variable */ - init_func(); - add_localvar(luaS_new("self")); - } - ; - -fvarname : varname { lua_pushvar($1); } ; - -fname : NAME { code_string($1); } ; - -body : '(' parlist ')' chunk END { func_onstack(close_func()); } ; - -elsepart : /* empty */ - | ELSE block - | ELSEIF cond THEN block SaveWord elsepart { codeIf($2, $5); } - ; - -ret : /* empty */ - | RETURN exprlist sc - { - adjust_functioncall($2, MULT_RET); - codereturn(); - } - ; - -GetPC : /* empty */ { $$ = L->currState->pc; } ; - -SaveWord : /* empty */ - { $$ = L->currState->pc; - check_pc(JMPSIZE); - L->currState->pc += JMPSIZE; /* open space */ - } - ; - -SaveWordPop : SaveWord { $$ = $1; deltastack(-1); /* pop condition */ } ; - -SaveWordPush : SaveWord { $$ = $1; deltastack(1); /* push a value */ } ; - -cond : expr1 SaveWordPop { $$ = $2; } ; - -expr1 : expr { adjust_functioncall($1, 1); } ; - -expr : '(' expr ')' { $$ = $2; } - | expr1 EQ expr1 { code_binop(EQOP); $$ = 0; } - | expr1 '<' expr1 { code_binop(LTOP); $$ = 0; } - | expr1 '>' expr1 { code_binop(GTOP); $$ = 0; } - | expr1 NE expr1 { code_binop(NEQOP); $$ = 0; } - | expr1 LE expr1 { code_binop(LEOP); $$ = 0; } - | expr1 GE expr1 { code_binop(GEOP); $$ = 0; } - | expr1 '+' expr1 { code_binop(ADDOP); $$ = 0; } - | expr1 '-' expr1 { code_binop(SUBOP); $$ = 0; } - | expr1 '*' expr1 { code_binop(MULTOP); $$ = 0; } - | expr1 '/' expr1 { code_binop(DIVOP); $$ = 0; } - | expr1 '^' expr1 { code_binop(POWOP); $$ = 0; } - | expr1 CONC expr1 { code_binop(CONCOP); $$ = 0; } - | '-' expr1 %prec UNARY { code_unop(MINUSOP); $$ = 0;} - | NOT expr1 { code_unop(NOTOP); $$ = 0;} - | sexp { $$ = $1; /* simple expressions */ } - | table { $$ = 0; } - | NUMBER { code_number($1); $$ = 0; } - | STRING { code_string($1); $$ = 0; } - | NIL { adjuststack(-1); $$ = 0; } - | FUNCTION { init_func(); } body { $$ = 0; } - | expr1 AND SaveWordPop expr1 { code_shortcircuit($3, ONFJMP); $$ = 0; } - | expr1 OR SaveWordPop expr1 { code_shortcircuit($3, ONTJMP); $$ = 0; } - ; - -sexp1 : sexp { adjust_functioncall($1, 1); } ; - -sexp : var { lua_pushvar($1); $$ = 0; } - | '%' NAME { pushupvalue($2); $$ = 0; } - | functioncall { $$ = $1; } - ; - -var : varname { $$ = $1; } - | sexp1 '[' expr1 ']' { $$ = 0; } /* indexed variable */ - | sexp1 '.' NAME { $$ = (-string_constant($3, L->currState))-1; } - ; - -varname : NAME { $$ = singlevar($1, L->currState); } ; - -table : '{' SaveWordPush fieldlist '}' { fix_opcode($2, CREATEARRAY, 2, $3); } ; - -functioncall : funcvalue funcParams - { - code_byte(0); /* save space for opcode */ - code_byte($1+$2); /* number of parameters */ - $$ = L->currState->pc; - code_byte(0); /* must be adjusted by other rules */ - } - ; - -funcvalue : sexp1 { $$ = 0; } - | sexp1 ':' NAME - { - code_oparg(PUSHSELF, 8, string_constant($3, L->currState), 1); - $$ = 1; - } - ; - -funcParams : '(' exprlist ')' { $$ = adjust_functioncall($2, 1); } - | table { $$ = 1; } - | STRING { code_string($1); $$ = 1; } - ; - -exprlist : /* empty */ { $$ = 0; } - | exprlist1 { $$ = $1; } - ; - -exprlist1 : expr { if ($1 != 0) $$ = $1; else $$ = -1; } - | exprlist1 ',' { $$ = adjust_functioncall($1, 1); } expr - { - if ($4 == 0) $$ = -($3 + 1); /* -length */ - else { - L->currState->f->code[$4] = $3; /* store list length */ - $$ = $4; - } - } - ; - -parlist : /* empty */ { code_args(0, 0); } - | DOTS { code_args(0, 1); } - | localnamelist { code_args($1, 0); } - | localnamelist ',' DOTS { code_args($1, 1); } - ; - -fieldlist : part { $$ = abs($1); } - | part ';' part - { - if ($1*$3 > 0) /* repeated parts? */ - luaY_error("invalid constructor syntax"); - $$ = abs($1)+abs($3); - } - ; - -part : /* empty */ { $$ = 0; } - | ffieldlist { $$ = $1; } - | lfieldlist { $$ = $1; } - ; - -lastcomma : /* empty */ | ',' ; - -ffieldlist : ffieldlist1 lastcomma - { - flush_record($1%RFIELDS_PER_FLUSH); - $$ = -$1; /* negative signals a "record" part */ - } - ; - -lfieldlist : lfieldlist1 lastcomma - { - flush_list($1/LFIELDS_PER_FLUSH, $1%LFIELDS_PER_FLUSH); - $$ = $1; - } - ; - -ffieldlist1 : ffield {$$=1;} - | ffieldlist1 ',' ffield - { - $$=$1+1; - if ($$%RFIELDS_PER_FLUSH == 0) - flush_record(RFIELDS_PER_FLUSH); - } - ; - -ffield : ffieldkey '=' expr1 ; - -ffieldkey : '[' expr1 ']' - | fname - ; - -lfieldlist1 : expr1 {$$=1;} - | lfieldlist1 ',' expr1 - { - $$=$1+1; - if ($$%LFIELDS_PER_FLUSH == 0) - flush_list($$/LFIELDS_PER_FLUSH - 1, LFIELDS_PER_FLUSH); - } - ; - -varlist1 : var { $$ = 1; add_varbuffer($1, 0); } - | varlist1 ',' var { add_varbuffer($3, $1); $$ = $1+1; } - ; - -localnamelist : NAME {store_localvar($1, 0); $$ = 1;} - | localnamelist ',' NAME { store_localvar($3, $1); $$ = $1+1; } - ; - -decinit : /* empty */ { $$ = 0; } - | '=' exprlist1 { $$ = $2; } - ; - -%% - -- cgit v1.2.3-55-g6feb