aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author_ov4 <ov4@ov4.org>2026-10-22 15:11:15 +0000
committer_ov4 <ov4@ov4.org>2026-10-22 15:33:15 +0000
commitee615b2b3b2b7b336fdd4334dba68801681c9c7b (patch)
tree6a3d7047780e1bced0db07b22643c261290ad734
parent713a313b06256a13ddefa5e257e3b80f8aa808ba (diff)
fix(parser): accept bare NEXT and read its identifier only from the same line
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
-rw-r--r--doc/language/keyword/cpsc-keyword-for.7.md4
-rw-r--r--lib/Parser/ParserControlFlow.cc19
2 files changed, 11 insertions, 12 deletions
diff --git a/doc/language/keyword/cpsc-keyword-for.7.md b/doc/language/keyword/cpsc-keyword-for.7.md
index e278cd9..0a4e5c7 100644
--- a/doc/language/keyword/cpsc-keyword-for.7.md
+++ b/doc/language/keyword/cpsc-keyword-for.7.md
@@ -9,12 +9,12 @@ cpsc-keyword-for, cpsc-keyword-to, cpsc-keyword-step, cpsc-keyword-next - iterat
```text
FOR variable <- start TO finish [STEP increment]
statements
-NEXT variable
+NEXT [variable]
```
# DESCRIPTION
-The loop variable must already be declared INTEGER. Both endpoints are inclusive. STEP defaults to 1; use a negative value to count down. STEP is evaluated once, while the finish expression is evaluated each iteration. NEXT must name the same variable. Use a nonzero STEP. TO, STEP, and NEXT belong to this syntax.
+The loop variable must already be declared INTEGER. Both endpoints are inclusive. STEP defaults to 1; use a negative value to count down. STEP is evaluated once, while the finish expression is evaluated each iteration. The variable after NEXT is optional. If present, it must be on the same line as NEXT and name the loop variable. Use a nonzero STEP. TO, STEP, and NEXT belong to this syntax.
# EXAMPLE
diff --git a/lib/Parser/ParserControlFlow.cc b/lib/Parser/ParserControlFlow.cc
index feedf44..7caf555 100644
--- a/lib/Parser/ParserControlFlow.cc
+++ b/lib/Parser/ParserControlFlow.cc
@@ -124,18 +124,17 @@ std::unique_ptr<StmtAST> Parser::ParseForStmt() {
return nullptr;
}
getNextToken();
-
- if (CurTok != tok_identifier) {
- cps::sourceError(Lex.getLine(), "expected identifier after NEXT (e.g., NEXT %s)", VarName.c_str());
- return nullptr;
- }
- if (!sameIdentifier(Lex.IdentifierStr, VarName)) {
- cps::sourceError(Lex.getLine(), "NEXT identifier '%s' does not match FOR variable '%s'",
- Lex.IdentifierStr.c_str(), VarName.c_str());
- return nullptr;
+ // The identifier after NEXT is optional; one on the next line starts a
+ // new statement.
+ if (CurTok == tok_identifier && !StartsLine) {
+ if (!sameIdentifier(Lex.IdentifierStr, VarName)) {
+ cps::sourceError(Lex.getLine(), "NEXT identifier '%s' does not match FOR variable '%s'",
+ Lex.IdentifierStr.c_str(), VarName.c_str());
+ return nullptr;
+ }
+ getNextToken();
}
- getNextToken();
return std::make_unique<ForStmtAST>(VarName, std::move(Start), std::move(End), std::move(Step), std::move(Body));
}