diff options
author | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2025-01-13 11:23:07 -0300 |
---|---|---|
committer | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2025-01-13 11:23:07 -0300 |
commit | 10e931da82268a9d190c17a9bdb9b1a4b48c2947 (patch) | |
tree | 219fa0c6d517893f4d1bef506d7dd50b1ea958aa /lparser.c | |
parent | 4b107a87760ee5f85185a904c9088ca476b94be5 (diff) | |
download | lua-10e931da82268a9d190c17a9bdb9b1a4b48c2947.tar.gz lua-10e931da82268a9d190c17a9bdb9b1a4b48c2947.tar.bz2 lua-10e931da82268a9d190c17a9bdb9b1a4b48c2947.zip |
Error "break outside loop" made a syntax error
Syntax errors are easier to handle than semantic errors.
Diffstat (limited to 'lparser.c')
-rw-r--r-- | lparser.c | 25 |
1 files changed, 14 insertions, 11 deletions
@@ -52,7 +52,7 @@ typedef struct BlockCnt { | |||
52 | int firstgoto; /* index of first pending goto in this block */ | 52 | int firstgoto; /* index of first pending goto in this block */ |
53 | lu_byte nactvar; /* # active locals outside the block */ | 53 | lu_byte nactvar; /* # active locals outside the block */ |
54 | lu_byte upval; /* true if some variable in the block is an upvalue */ | 54 | lu_byte upval; /* true if some variable in the block is an upvalue */ |
55 | lu_byte isloop; /* true if 'block' is a loop */ | 55 | lu_byte isloop; /* 1 if 'block' is a loop; 2 if it has pending breaks */ |
56 | lu_byte insidetbc; /* true if inside the scope of a to-be-closed var. */ | 56 | lu_byte insidetbc; /* true if inside the scope of a to-be-closed var. */ |
57 | } BlockCnt; | 57 | } BlockCnt; |
58 | 58 | ||
@@ -677,15 +677,10 @@ static void enterblock (FuncState *fs, BlockCnt *bl, lu_byte isloop) { | |||
677 | ** generates an error for an undefined 'goto'. | 677 | ** generates an error for an undefined 'goto'. |
678 | */ | 678 | */ |
679 | static l_noret undefgoto (LexState *ls, Labeldesc *gt) { | 679 | static l_noret undefgoto (LexState *ls, Labeldesc *gt) { |
680 | const char *msg; | 680 | const char *msg = "no visible label '%s' for <goto> at line %d"; |
681 | if (eqstr(gt->name, luaS_newliteral(ls->L, "break"))) { | 681 | msg = luaO_pushfstring(ls->L, msg, getstr(gt->name), gt->line); |
682 | msg = "break outside loop at line %d"; | 682 | /* breaks are checked when created, cannot be undefined */ |
683 | msg = luaO_pushfstring(ls->L, msg, gt->line); | 683 | lua_assert(!eqstr(gt->name, luaS_newliteral(ls->L, "break"))); |
684 | } | ||
685 | else { | ||
686 | msg = "no visible label '%s' for <goto> at line %d"; | ||
687 | msg = luaO_pushfstring(ls->L, msg, getstr(gt->name), gt->line); | ||
688 | } | ||
689 | luaK_semerror(ls, msg); | 684 | luaK_semerror(ls, msg); |
690 | } | 685 | } |
691 | 686 | ||
@@ -699,7 +694,7 @@ static void leaveblock (FuncState *fs) { | |||
699 | fs->freereg = stklevel; /* free registers */ | 694 | fs->freereg = stklevel; /* free registers */ |
700 | removevars(fs, bl->nactvar); /* remove block locals */ | 695 | removevars(fs, bl->nactvar); /* remove block locals */ |
701 | lua_assert(bl->nactvar == fs->nactvar); /* back to level on entry */ | 696 | lua_assert(bl->nactvar == fs->nactvar); /* back to level on entry */ |
702 | if (bl->isloop) /* has to fix pending breaks? */ | 697 | if (bl->isloop == 2) /* has to fix pending breaks? */ |
703 | createlabel(ls, luaS_newliteral(ls->L, "break"), 0, 0); | 698 | createlabel(ls, luaS_newliteral(ls->L, "break"), 0, 0); |
704 | solvegotos(fs, bl); | 699 | solvegotos(fs, bl); |
705 | if (bl->previous == NULL) { /* was it the last block? */ | 700 | if (bl->previous == NULL) { /* was it the last block? */ |
@@ -1465,6 +1460,14 @@ static void gotostat (LexState *ls, int line) { | |||
1465 | ** Break statement. Semantically equivalent to "goto break". | 1460 | ** Break statement. Semantically equivalent to "goto break". |
1466 | */ | 1461 | */ |
1467 | static void breakstat (LexState *ls, int line) { | 1462 | static void breakstat (LexState *ls, int line) { |
1463 | BlockCnt *bl; /* to look for an enclosing loop */ | ||
1464 | for (bl = ls->fs->bl; bl != NULL; bl = bl->previous) { | ||
1465 | if (bl->isloop) /* found one? */ | ||
1466 | goto ok; | ||
1467 | } | ||
1468 | luaX_syntaxerror(ls, "break outside loop"); | ||
1469 | ok: | ||
1470 | bl->isloop = 2; /* signal that block has pending breaks */ | ||
1468 | luaX_next(ls); /* skip break */ | 1471 | luaX_next(ls); /* skip break */ |
1469 | newgotoentry(ls, luaS_newliteral(ls->L, "break"), line); | 1472 | newgotoentry(ls, luaS_newliteral(ls->L, "break"), line); |
1470 | } | 1473 | } |