aboutsummaryrefslogtreecommitdiff
path: root/lparser.c
diff options
context:
space:
mode:
authorRoberto Ierusalimschy <roberto@inf.puc-rio.br>2025-01-13 11:23:07 -0300
committerRoberto Ierusalimschy <roberto@inf.puc-rio.br>2025-01-13 11:23:07 -0300
commit10e931da82268a9d190c17a9bdb9b1a4b48c2947 (patch)
tree219fa0c6d517893f4d1bef506d7dd50b1ea958aa /lparser.c
parent4b107a87760ee5f85185a904c9088ca476b94be5 (diff)
downloadlua-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.c25
1 files changed, 14 insertions, 11 deletions
diff --git a/lparser.c b/lparser.c
index 036f133b..83e341ed 100644
--- a/lparser.c
+++ b/lparser.c
@@ -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*/
679static l_noret undefgoto (LexState *ls, Labeldesc *gt) { 679static 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*/
1467static void breakstat (LexState *ls, int line) { 1462static 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}