fix(parser): Stage-B NEWLINE handling and test file corrections
**Stage-B Parser Improvements:**
- Add NEWLINE skipping before/after LOCAL keyword (variables.rs)
- Add NEWLINE skipping after '{' in block statements (mod.rs)
- Add safety valve for statement keywords in static_box.rs
**Test File Fixes:**
- Fix collect_empty_args_smoke.hako: static box → box (allow instantiation)
- Fix method calls: index_of_from() → me.index_of_from() (explicit receiver)
**Context:**
These changes support the PHI UseBeforeDef bug investigation and improve
Stage-B parser robustness for NEWLINE handling in method bodies.
**Test Results:**
✅ collect_prints() loop break handling verified
✅ ArrayBox.length() working correctly (after user fix)
✅ All existing loop smoke tests passing (loop_min_while, nested_loop_inner_break, etc.)
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@ -91,6 +91,11 @@ impl NyashParser {
|
||||
);
|
||||
}
|
||||
self.consume(TokenType::LBRACE)?;
|
||||
|
||||
// Critical: Skip any leading NEWLINE tokens immediately after '{'
|
||||
// This ensures the first statement starts at the correct position
|
||||
while self.match_token(&TokenType::NEWLINE) { self.advance(); }
|
||||
|
||||
let mut statements = Vec::new();
|
||||
|
||||
// Be tolerant to blank lines within blocks: skip NEWLINE tokens between statements
|
||||
|
||||
@ -29,6 +29,17 @@ impl NyashParser {
|
||||
|
||||
/// Parse local variable declaration: local var1, var2, var3 or local x = 10
|
||||
pub(super) fn parse_local(&mut self) -> Result<ASTNode, ParseError> {
|
||||
let debug_parse_local = std::env::var("NYASH_DEBUG_PARSE_LOCAL").ok().as_deref() == Some("1");
|
||||
if debug_parse_local {
|
||||
eprintln!("[parse_local] entry: current_token={:?} at line {}",
|
||||
self.current_token().token_type, self.current_token().line);
|
||||
}
|
||||
|
||||
// Always skip leading NEWLINEs before consuming 'local' keyword
|
||||
while self.match_token(&TokenType::NEWLINE) {
|
||||
self.advance();
|
||||
}
|
||||
|
||||
if super::helpers::cursor_enabled() {
|
||||
let mut cursor = TokenCursor::new(&self.tokens);
|
||||
cursor.set_position(self.current);
|
||||
@ -37,6 +48,16 @@ impl NyashParser {
|
||||
}
|
||||
self.advance(); // consume 'local'
|
||||
|
||||
// Skip any NEWLINE tokens after 'local' keyword
|
||||
while self.match_token(&TokenType::NEWLINE) {
|
||||
self.advance();
|
||||
}
|
||||
|
||||
if debug_parse_local {
|
||||
eprintln!("[parse_local] after advance: current_token={:?} at line {}",
|
||||
self.current_token().token_type, self.current_token().line);
|
||||
}
|
||||
|
||||
let mut names = Vec::new();
|
||||
let mut initial_values = Vec::new();
|
||||
|
||||
@ -84,6 +105,20 @@ impl NyashParser {
|
||||
})
|
||||
}
|
||||
} else {
|
||||
// Enhanced error message for debugging
|
||||
if debug_parse_local {
|
||||
eprintln!("[parse_local] ERROR: Expected IDENTIFIER, found {:?} at line {}",
|
||||
self.current_token().token_type, self.current_token().line);
|
||||
eprintln!("[parse_local] ERROR: Previous 3 tokens:");
|
||||
for i in 1..=3 {
|
||||
if self.current >= i {
|
||||
let idx = self.current - i;
|
||||
if idx < self.tokens.len() {
|
||||
eprintln!(" [-{}] {:?}", i, self.tokens[idx].token_type);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Err(ParseError::UnexpectedToken {
|
||||
found: self.current_token().token_type.clone(),
|
||||
expected: "identifier".to_string(),
|
||||
|
||||
Reference in New Issue
Block a user