Phase 22.3: Fix parser infinite loop and Stage-B JSON contamination
Fix A: Stage-B output contamination
- Add NYASH_JSON_ONLY=1 to suppress RC output
- Add awk '/^{/,/^}$/' to extract clean JSON only
- File: tools/hakorune_emit_mir.sh:46-49
Fix B: Parser infinite loop in static method parameters
- Replace must_advance! with explicit match on current_token()
- Ensure forward progress in all branches (IDENTIFIER/COMMA/NEWLINE/RPAREN)
- Add NYASH_PARSER_METHOD_PARAM_STRICT=1 for strict mode (default: tolerant)
- File: src/parser/declarations/static_def/members.rs:79-108
Acceptance criteria:
- Stage-B output has no 'RC:' contamination
- phase2231/hakorune_emit_mir_return42_canary_vm.sh passes (rc=42)
- Existing quick tests remain green (backward compatible)
This commit is contained in:
@ -77,12 +77,36 @@ pub(crate) fn try_parse_method_or_field(
|
|||||||
p.advance(); // consume '('
|
p.advance(); // consume '('
|
||||||
let mut params = Vec::new();
|
let mut params = Vec::new();
|
||||||
while !p.match_token(&TokenType::RPAREN) && !p.is_at_end() {
|
while !p.match_token(&TokenType::RPAREN) && !p.is_at_end() {
|
||||||
crate::must_advance!(p, _unused, "static method parameter parsing");
|
// Peek at the current token to ensure forward progress
|
||||||
if let TokenType::IDENTIFIER(param) = &p.current_token().token_type {
|
match p.current_token().token_type {
|
||||||
params.push(param.clone());
|
TokenType::IDENTIFIER(ref param) => {
|
||||||
p.advance();
|
params.push(param.clone());
|
||||||
|
p.advance();
|
||||||
|
}
|
||||||
|
TokenType::COMMA => {
|
||||||
|
p.advance();
|
||||||
|
}
|
||||||
|
TokenType::NEWLINE => {
|
||||||
|
// Stage-3 tolerant mode: allow newlines in parameter list
|
||||||
|
p.advance();
|
||||||
|
}
|
||||||
|
TokenType::RPAREN => {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
// Unexpected token handling
|
||||||
|
if std::env::var("NYASH_PARSER_METHOD_PARAM_STRICT").ok().as_deref() == Some("1") {
|
||||||
|
return Err(ParseError::UnexpectedToken {
|
||||||
|
found: p.current_token().token_type.clone(),
|
||||||
|
expected: "parameter identifier, comma, or )".to_string(),
|
||||||
|
line: p.current_token().line,
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
// Tolerant mode: skip unexpected token to avoid infinite loop
|
||||||
|
p.advance();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if p.match_token(&TokenType::COMMA) { p.advance(); }
|
|
||||||
}
|
}
|
||||||
p.consume(TokenType::RPAREN)?;
|
p.consume(TokenType::RPAREN)?;
|
||||||
// Allow NEWLINE(s) between ')' and '{' of method body
|
// Allow NEWLINE(s) between ')' and '{' of method body
|
||||||
|
|||||||
@ -43,10 +43,10 @@ CODE="$(cat "$IN")"
|
|||||||
|
|
||||||
# 1) Stage‑B: Hako parser emits Program(JSON v0) to stdout
|
# 1) Stage‑B: Hako parser emits Program(JSON v0) to stdout
|
||||||
set +e
|
set +e
|
||||||
PROG_JSON_OUT=$(NYASH_DISABLE_NY_COMPILER=1 HAKO_DISABLE_NY_COMPILER=1 \
|
PROG_JSON_OUT=$(NYASH_JSON_ONLY=1 NYASH_DISABLE_NY_COMPILER=1 HAKO_DISABLE_NY_COMPILER=1 \
|
||||||
NYASH_PARSER_STAGE3=1 HAKO_PARSER_STAGE3=1 NYASH_PARSER_ALLOW_SEMICOLON=1 \
|
NYASH_PARSER_STAGE3=1 HAKO_PARSER_STAGE3=1 NYASH_PARSER_ALLOW_SEMICOLON=1 \
|
||||||
NYASH_ENABLE_USING=1 HAKO_ENABLE_USING=1 \
|
NYASH_ENABLE_USING=1 HAKO_ENABLE_USING=1 \
|
||||||
"$NYASH_BIN" --backend vm "$ROOT/lang/src/compiler/entry/compiler_stageb.hako" -- --source "$CODE" 2>/dev/null)
|
"$NYASH_BIN" --backend vm "$ROOT/lang/src/compiler/entry/compiler_stageb.hako" -- --source "$CODE" 2>/dev/null | awk '/^{/,/^}$/')
|
||||||
rc=$?
|
rc=$?
|
||||||
set -e
|
set -e
|
||||||
if [ $rc -ne 0 ] || [ -z "$PROG_JSON_OUT" ]; then
|
if [ $rc -ne 0 ] || [ -z "$PROG_JSON_OUT" ]; then
|
||||||
|
|||||||
Reference in New Issue
Block a user