Summary
The parser accepts LABEL syntactically anywhere but only registers labels that appear at the top level of the script. A LABEL placed inside IF/ELSE/WHILE/REPEAT/DEF is silently discarded, and any subsequent GOTO to that label fails with a misleading GOTO target '<name>' not found error that points at the GOTO, not at the misplaced LABEL.
Location
- File:
src/script_parser.cpp
- Lines / functions:
ScriptParser::parse() at L155–L164 (label collection walks only root->children)
- Related: L98–L101 (
DEF is explicitly rejected inside blocks; LABEL is not)
Category
state-management
Severity
medium
Impact: scripts that mistakenly place LABEL inside a block fail at parse time with a confusing, misdirected error. The language reference (PROMPT.md) documents LABEL name / GOTO name (top-level only), so the constraint is intended but not enforced at the point it is violated.
Reproduction / Evidence
Verified by code analysis and runtime test:
ScriptParser parser;
auto r = parser.parse(
"IF $X == \"1\"\n"
" LABEL inside\n"
"ENDIF\n"
"GOTO inside\n"
);
// r.errors: [ line 4: "GOTO target 'inside' not found" ]
// r.labels: empty
The LABEL node is appended to the enclosing block's children (parser.cpp L108–L114). Label resolution at L155–L164 iterates only root->children, so the nested LABEL is never added to result.labels. Validation at L170–L175 then flags the GOTO as dangling.
Expected Behavior
The parser should emit a clear error at the LABEL line stating that LABEL must be at the top level (matching the existing handling of DEF at L98–L101). No error should then be emitted against the GOTO, or — if it is — it should be evidently secondary.
Actual Behavior
Nested LABEL is silently dropped. The only error the user sees references the GOTO line, making the root cause hard to diagnose.
Root Cause
The label-collection loop only examines root->children and does not recurse; the grammar does not refuse LABEL inside a block at the point it is parsed.
Summary
The parser accepts
LABELsyntactically anywhere but only registers labels that appear at the top level of the script. ALABELplaced insideIF/ELSE/WHILE/REPEAT/DEFis silently discarded, and any subsequentGOTOto that label fails with a misleadingGOTO target '<name>' not founderror that points at theGOTO, not at the misplacedLABEL.Location
src/script_parser.cppScriptParser::parse()at L155–L164 (label collection walks onlyroot->children)DEFis explicitly rejected inside blocks;LABELis not)Category
state-managementSeverity
mediumImpact: scripts that mistakenly place
LABELinside a block fail at parse time with a confusing, misdirected error. The language reference (PROMPT.md) documentsLABEL name / GOTO name (top-level only), so the constraint is intended but not enforced at the point it is violated.Reproduction / Evidence
Verified by code analysis and runtime test:
The
LABELnode is appended to the enclosing block'schildren(parser.cpp L108–L114). Label resolution at L155–L164 iterates onlyroot->children, so the nestedLABELis never added toresult.labels. Validation at L170–L175 then flags theGOTOas dangling.Expected Behavior
The parser should emit a clear error at the
LABELline stating thatLABELmust be at the top level (matching the existing handling ofDEFat L98–L101). No error should then be emitted against theGOTO, or — if it is — it should be evidently secondary.Actual Behavior
Nested
LABELis silently dropped. The only error the user sees references theGOTOline, making the root cause hard to diagnose.Root Cause
The label-collection loop only examines
root->childrenand does not recurse; the grammar does not refuseLABELinside a block at the point it is parsed.