mirror of https://github.com/rusefi/lua.git
new syntax: |label|
This commit is contained in:
parent
c3b73cbeb8
commit
0810bc707f
149
lparser.c
149
lparser.c
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
** $Id: lparser.c,v 1.78 2000/04/07 13:13:11 roberto Exp roberto $
|
** $Id: lparser.c,v 1.79 2000/04/07 19:35:20 roberto Exp roberto $
|
||||||
** LL(1) Parser and code generator for Lua
|
** LL(1) Parser and code generator for Lua
|
||||||
** See Copyright Notice in lua.h
|
** See Copyright Notice in lua.h
|
||||||
*/
|
*/
|
||||||
|
@ -36,6 +36,7 @@ typedef struct Constdesc {
|
||||||
|
|
||||||
typedef struct Breaklabel {
|
typedef struct Breaklabel {
|
||||||
struct Breaklabel *previous; /* chain */
|
struct Breaklabel *previous; /* chain */
|
||||||
|
TString *label;
|
||||||
int breaklist;
|
int breaklist;
|
||||||
int stacklevel;
|
int stacklevel;
|
||||||
} Breaklabel;
|
} Breaklabel;
|
||||||
|
@ -171,6 +172,14 @@ static TString *str_checkname (LexState *ls) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static TString *optionalname (LexState *ls) {
|
||||||
|
if (ls->token == TK_NAME)
|
||||||
|
return str_checkname(ls);
|
||||||
|
else
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static void luaI_registerlocalvar (LexState *ls, TString *varname,
|
static void luaI_registerlocalvar (LexState *ls, TString *varname,
|
||||||
int line) {
|
int line) {
|
||||||
FuncState *fs = ls->fs;
|
FuncState *fs = ls->fs;
|
||||||
|
@ -317,6 +326,7 @@ static int getvarname (LexState *ls, expdesc *var) {
|
||||||
|
|
||||||
static void enterbreak (FuncState *fs, Breaklabel *bl) {
|
static void enterbreak (FuncState *fs, Breaklabel *bl) {
|
||||||
bl->stacklevel = fs->stacklevel;
|
bl->stacklevel = fs->stacklevel;
|
||||||
|
bl->label = NULL;
|
||||||
bl->breaklist = NO_JUMP;
|
bl->breaklist = NO_JUMP;
|
||||||
bl->previous = fs->bl;
|
bl->previous = fs->bl;
|
||||||
fs->bl = bl;
|
fs->bl = bl;
|
||||||
|
@ -330,6 +340,20 @@ static void leavebreak (FuncState *fs, Breaklabel *bl) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static Breaklabel *findlabel (FuncState *fs, TString *name) {
|
||||||
|
Breaklabel *bl;
|
||||||
|
for (bl=fs->bl; bl; bl=bl->previous) {
|
||||||
|
if (bl->label == name)
|
||||||
|
return bl;
|
||||||
|
}
|
||||||
|
if (name) /* label not found: choose appropriate error message */
|
||||||
|
luaX_syntaxerror(fs->ls, "break not inside given label", name->str);
|
||||||
|
else
|
||||||
|
luaK_error(fs->ls, "break not inside while or repeat loop");
|
||||||
|
return NULL; /* to avoid warnings */
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static void func_onstack (LexState *ls, FuncState *func) {
|
static void func_onstack (LexState *ls, FuncState *func) {
|
||||||
FuncState *fs = ls->fs;
|
FuncState *fs = ls->fs;
|
||||||
Proto *f = fs->f;
|
Proto *f = fs->f;
|
||||||
|
@ -419,7 +443,7 @@ static int explist1 (LexState *ls) {
|
||||||
expr(ls, &v);
|
expr(ls, &v);
|
||||||
n++;
|
n++;
|
||||||
}
|
}
|
||||||
luaK_tostack(ls, &v, 0);
|
luaK_tostack(ls, &v, 0); /* keep open number of values of last expression */
|
||||||
return n;
|
return n;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -427,12 +451,12 @@ static int explist1 (LexState *ls) {
|
||||||
static int explist (LexState *ls) {
|
static int explist (LexState *ls) {
|
||||||
/* explist -> [ explist1 ] */
|
/* explist -> [ explist1 ] */
|
||||||
switch (ls->token) {
|
switch (ls->token) {
|
||||||
case TK_ELSE: case TK_ELSEIF: case TK_END: case TK_UNTIL:
|
case TK_NUMBER: case TK_STRING: case TK_NIL: case '{':
|
||||||
case TK_EOS: case ';': case ')':
|
case TK_FUNCTION: case '(': case TK_NAME: case '%':
|
||||||
return 0; /* empty list */
|
case TK_NOT: case '-': /* first `expr' */
|
||||||
|
|
||||||
default:
|
|
||||||
return explist1(ls);
|
return explist1(ls);
|
||||||
|
default:
|
||||||
|
return 0; /* empty list */
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -998,44 +1022,73 @@ static void namestat (LexState *ls) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void retstat (LexState *ls) {
|
||||||
|
/* stat -> RETURN explist */
|
||||||
|
FuncState *fs = ls->fs;
|
||||||
|
setline_and_next(ls); /* skip RETURN */
|
||||||
|
explist(ls);
|
||||||
|
luaK_code1(fs, OP_RETURN, ls->fs->nlocalvar);
|
||||||
|
fs->stacklevel = fs->nlocalvar; /* removes all temp values */
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void breakstat (LexState *ls) {
|
||||||
|
/* stat -> BREAK [NAME] */
|
||||||
|
FuncState *fs = ls->fs;
|
||||||
|
Breaklabel *bl;
|
||||||
|
int currentlevel = fs->stacklevel;
|
||||||
|
setline_and_next(ls); /* skip BREAK */
|
||||||
|
bl = findlabel(fs, optionalname(ls));
|
||||||
|
luaK_adjuststack(fs, currentlevel - bl->stacklevel);
|
||||||
|
luaK_concat(fs, &bl->breaklist, luaK_jump(fs));
|
||||||
|
fs->stacklevel = currentlevel;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static int stat (LexState *ls) {
|
static int stat (LexState *ls) {
|
||||||
int line = ls->linenumber; /* may be needed for error messages */
|
int line = ls->linenumber; /* may be needed for error messages */
|
||||||
switch (ls->token) {
|
switch (ls->token) {
|
||||||
case TK_IF: /* stat -> ifstat */
|
case TK_IF: /* stat -> ifstat */
|
||||||
ifstat(ls, line);
|
ifstat(ls, line);
|
||||||
break;
|
return 1;
|
||||||
|
|
||||||
case TK_WHILE: /* stat -> whilestat */
|
case TK_WHILE: /* stat -> whilestat */
|
||||||
whilestat(ls, line);
|
whilestat(ls, line);
|
||||||
break;
|
return 1;
|
||||||
|
|
||||||
case TK_DO: { /* stat -> DO block END */
|
case TK_DO: /* stat -> DO block END */
|
||||||
setline_and_next(ls); /* skip DO */
|
setline_and_next(ls); /* skip DO */
|
||||||
block(ls);
|
block(ls);
|
||||||
check_END(ls, TK_DO, line);
|
check_END(ls, TK_DO, line);
|
||||||
break;
|
return 1;
|
||||||
}
|
|
||||||
|
|
||||||
case TK_REPEAT: /* stat -> repeatstat */
|
case TK_REPEAT: /* stat -> repeatstat */
|
||||||
repeatstat(ls, line);
|
repeatstat(ls, line);
|
||||||
break;
|
return 1;
|
||||||
|
|
||||||
case TK_FUNCTION: /* stat -> funcstat */
|
case TK_FUNCTION: /* stat -> funcstat */
|
||||||
funcstat(ls, line);
|
funcstat(ls, line);
|
||||||
break;
|
return 1;
|
||||||
|
|
||||||
case TK_LOCAL: /* stat -> localstat */
|
case TK_LOCAL: /* stat -> localstat */
|
||||||
localstat(ls);
|
localstat(ls);
|
||||||
break;
|
return 1;
|
||||||
|
|
||||||
case TK_NAME: case '%': /* stat -> namestat */
|
case TK_NAME: case '%': /* stat -> namestat */
|
||||||
namestat(ls);
|
namestat(ls);
|
||||||
break;
|
return 1;
|
||||||
|
|
||||||
|
case TK_RETURN: /* stat -> retstat */
|
||||||
|
retstat(ls);
|
||||||
|
return 2; /* must be last statement */
|
||||||
|
|
||||||
|
case TK_BREAK: /* stat -> breakstat */
|
||||||
|
breakstat(ls);
|
||||||
|
return 2; /* must be last statement */
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return 0; /* no statement */
|
return 0; /* no statement */
|
||||||
}
|
}
|
||||||
return 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -1092,44 +1145,36 @@ static void body (LexState *ls, int needself, int line) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void ret (LexState *ls) {
|
|
||||||
/* ret -> [RETURN explist sc | BREAK sc] */
|
|
||||||
FuncState *fs = ls->fs;
|
|
||||||
switch (ls->token) {
|
|
||||||
case TK_RETURN: {
|
|
||||||
setline_and_next(ls); /* skip RETURN */
|
|
||||||
explist(ls);
|
|
||||||
luaK_code1(fs, OP_RETURN, ls->fs->nlocalvar);
|
|
||||||
fs->stacklevel = fs->nlocalvar; /* removes all temp values */
|
|
||||||
optional(ls, ';');
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case TK_BREAK: {
|
|
||||||
Breaklabel *bl = fs->bl;
|
|
||||||
int currentlevel = fs->stacklevel;
|
|
||||||
if (bl == NULL)
|
|
||||||
luaK_error(ls, "break not inside while or repeat loop");
|
|
||||||
|
|
||||||
setline_and_next(ls); /* skip BREAK */
|
|
||||||
luaK_adjuststack(fs, currentlevel - bl->stacklevel);
|
|
||||||
luaK_concat(fs, &bl->breaklist, luaK_jump(fs));
|
|
||||||
optional(ls, ';');
|
|
||||||
fs->stacklevel = currentlevel;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* }====================================================================== */
|
/* }====================================================================== */
|
||||||
|
|
||||||
|
|
||||||
static void chunk (LexState *ls) {
|
static void label (LexState *ls, Breaklabel *bl) {
|
||||||
/* chunk -> { stat [;] } ret */
|
/* label -> [ '|' NAME '|' ] */
|
||||||
while (stat(ls)) {
|
if (optional(ls, '|')) {
|
||||||
LUA_ASSERT(ls->L, ls->fs->stacklevel == ls->fs->nlocalvar,
|
enterbreak(ls->fs, bl);
|
||||||
"stack size != # local vars");
|
bl->label = str_checkname(ls);
|
||||||
optional(ls, ';');
|
check(ls, '|');
|
||||||
}
|
}
|
||||||
ret(ls); /* optional return */
|
else
|
||||||
|
bl->label = NULL; /* there is no label */
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void chunk (LexState *ls) {
|
||||||
|
/* chunk -> { [label] stat [';'] } */
|
||||||
|
Breaklabel bl;
|
||||||
|
int a;
|
||||||
|
do {
|
||||||
|
label(ls, &bl);
|
||||||
|
a = stat(ls);
|
||||||
|
if (a != 0)
|
||||||
|
optional(ls, ';');
|
||||||
|
else if (bl.label)
|
||||||
|
luaK_error(ls, "label without a statement");
|
||||||
|
LUA_ASSERT(ls->L, ls->fs->stacklevel == ls->fs->nlocalvar,
|
||||||
|
"stack size != # local vars");
|
||||||
|
if (bl.label)
|
||||||
|
leavebreak(ls->fs, &bl);
|
||||||
|
} while (a == 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue