1
0
mirror of https://github.com/lua/lua.git synced 2025-02-04 06:13:04 +08:00

Error "break outside loop" made a syntax error

Syntax errors are easier to handle than semantic errors.
This commit is contained in:
Roberto Ierusalimschy 2025-01-13 11:23:07 -03:00
parent 4b107a8776
commit 10e931da82

View File

@ -52,7 +52,7 @@ typedef struct BlockCnt {
int firstgoto; /* index of first pending goto in this block */
lu_byte nactvar; /* # active locals outside the block */
lu_byte upval; /* true if some variable in the block is an upvalue */
lu_byte isloop; /* true if 'block' is a loop */
lu_byte isloop; /* 1 if 'block' is a loop; 2 if it has pending breaks */
lu_byte insidetbc; /* true if inside the scope of a to-be-closed var. */
} BlockCnt;
@ -677,15 +677,10 @@ static void enterblock (FuncState *fs, BlockCnt *bl, lu_byte isloop) {
** generates an error for an undefined 'goto'.
*/
static l_noret undefgoto (LexState *ls, Labeldesc *gt) {
const char *msg;
if (eqstr(gt->name, luaS_newliteral(ls->L, "break"))) {
msg = "break outside loop at line %d";
msg = luaO_pushfstring(ls->L, msg, gt->line);
}
else {
msg = "no visible label '%s' for <goto> at line %d";
msg = luaO_pushfstring(ls->L, msg, getstr(gt->name), gt->line);
}
const char *msg = "no visible label '%s' for <goto> at line %d";
msg = luaO_pushfstring(ls->L, msg, getstr(gt->name), gt->line);
/* breaks are checked when created, cannot be undefined */
lua_assert(!eqstr(gt->name, luaS_newliteral(ls->L, "break")));
luaK_semerror(ls, msg);
}
@ -699,7 +694,7 @@ static void leaveblock (FuncState *fs) {
fs->freereg = stklevel; /* free registers */
removevars(fs, bl->nactvar); /* remove block locals */
lua_assert(bl->nactvar == fs->nactvar); /* back to level on entry */
if (bl->isloop) /* has to fix pending breaks? */
if (bl->isloop == 2) /* has to fix pending breaks? */
createlabel(ls, luaS_newliteral(ls->L, "break"), 0, 0);
solvegotos(fs, bl);
if (bl->previous == NULL) { /* was it the last block? */
@ -1465,6 +1460,14 @@ static void gotostat (LexState *ls, int line) {
** Break statement. Semantically equivalent to "goto break".
*/
static void breakstat (LexState *ls, int line) {
BlockCnt *bl; /* to look for an enclosing loop */
for (bl = ls->fs->bl; bl != NULL; bl = bl->previous) {
if (bl->isloop) /* found one? */
goto ok;
}
luaX_syntaxerror(ls, "break outside loop");
ok:
bl->isloop = 2; /* signal that block has pending breaks */
luaX_next(ls); /* skip break */
newgotoentry(ls, luaS_newliteral(ls->L, "break"), line);
}