feat: nyash.toml SSOT + using AST統合完了(12時間の戦い)
- nyash.tomlを唯一の真実(SSOT)として依存管理確立 - dev/ci/prodプロファイルによる段階的厳格化実装 - AST結合で宣言/式の曖昧性を根本解決 - Fail-Fast原則をCLAUDE.md/AGENTS.mdに明文化 - VM fallbackでもASTベース using有効化(NYASH_USING_AST=1) - 静的メソッドの is_static=true 修正で解決安定化 - STATICブレークハック既定OFF化で堅牢性向上 🎉 usingシステム完全体への道筋確立!JSONライブラリ・Nyash VM開発が可能に Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@ -29,6 +29,15 @@ impl NyashParser {
|
||||
// Track last inserted method name to allow postfix catch/cleanup fallback parsing
|
||||
let mut last_method_name: Option<String> = None;
|
||||
while !self.match_token(&TokenType::RBRACE) && !self.is_at_end() {
|
||||
// Tolerate blank lines between members
|
||||
while self.match_token(&TokenType::NEWLINE) { self.advance(); }
|
||||
let trace = std::env::var("NYASH_PARSER_TRACE_STATIC").ok().as_deref() == Some("1");
|
||||
if trace {
|
||||
eprintln!(
|
||||
"[parser][static-box] loop token={:?}",
|
||||
self.current_token().token_type
|
||||
);
|
||||
}
|
||||
|
||||
// Fallback: method-level postfix catch/cleanup immediately following a method
|
||||
if crate::parser::declarations::box_def::members::postfix::try_parse_method_postfix_after_last_method(
|
||||
@ -45,8 +54,14 @@ impl NyashParser {
|
||||
static_init = Some(body);
|
||||
continue;
|
||||
} else if self.match_token(&TokenType::STATIC) {
|
||||
// STRICT で top-level seam を検出した場合は while を抜ける
|
||||
break;
|
||||
// 互換用の暫定ガード(既定OFF): using テキスト結合の継ぎ目で誤って 'static' が入った場合に
|
||||
// ループを抜けて外側の '}' 消費に委ねる。既定では無効化し、文脈エラーとして扱う。
|
||||
if std::env::var("NYASH_PARSER_SEAM_BREAK_ON_STATIC").ok().as_deref() == Some("1") {
|
||||
if std::env::var("NYASH_CLI_VERBOSE").ok().as_deref() == Some("1") {
|
||||
eprintln!("[parser][static-box][seam] encountered 'static' inside static box; breaking (compat shim)");
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// initブロックの処理(共通ヘルパに委譲)
|
||||
@ -69,6 +84,12 @@ impl NyashParser {
|
||||
}
|
||||
}
|
||||
|
||||
if std::env::var("NYASH_PARSER_TRACE_STATIC").ok().as_deref() == Some("1") {
|
||||
eprintln!(
|
||||
"[parser][static-box] closing '}}' at token={:?}",
|
||||
self.current_token().token_type
|
||||
);
|
||||
}
|
||||
self.consume(TokenType::RBRACE)?;
|
||||
|
||||
// 🔥 Static初期化ブロックから依存関係を抽出
|
||||
|
||||
@ -56,6 +56,7 @@ pub(crate) fn try_parse_method_or_field(
|
||||
fields: &mut Vec<String>,
|
||||
last_method_name: &mut Option<String>,
|
||||
) -> Result<bool, ParseError> {
|
||||
let trace = std::env::var("NYASH_PARSER_TRACE_STATIC").ok().as_deref() == Some("1");
|
||||
// Allow NEWLINE(s) between identifier and '('
|
||||
if !p.match_token(&TokenType::LPAREN) {
|
||||
// Lookahead skipping NEWLINE to see if a '(' follows → treat as method head
|
||||
@ -65,11 +66,13 @@ pub(crate) fn try_parse_method_or_field(
|
||||
// Consume intervening NEWLINEs so current becomes '('
|
||||
while p.match_token(&TokenType::NEWLINE) { p.advance(); }
|
||||
} else {
|
||||
if trace { eprintln!("[parser][static-box] field detected: {}", name); }
|
||||
// Field
|
||||
fields.push(name);
|
||||
return Ok(true);
|
||||
}
|
||||
}
|
||||
if trace { eprintln!("[parser][static-box] method head detected: {}(..)", name); }
|
||||
// Method
|
||||
p.advance(); // consume '('
|
||||
let mut params = Vec::new();
|
||||
@ -84,14 +87,20 @@ pub(crate) fn try_parse_method_or_field(
|
||||
p.consume(TokenType::RPAREN)?;
|
||||
// Allow NEWLINE(s) between ')' and '{' of method body
|
||||
while p.match_token(&TokenType::NEWLINE) { p.advance(); }
|
||||
let body = p.parse_block_statements()?;
|
||||
// Parse method body; optionally use strict method-body guard when enabled
|
||||
let body = if std::env::var("NYASH_PARSER_METHOD_BODY_STRICT").ok().as_deref() == Some("1") {
|
||||
p.parse_method_body_statements()?
|
||||
} else {
|
||||
p.parse_block_statements()?
|
||||
};
|
||||
let body = wrap_method_body_with_postfix_if_any(p, body)?;
|
||||
// Construct method node
|
||||
let method = ASTNode::FunctionDeclaration {
|
||||
name: name.clone(),
|
||||
params,
|
||||
body,
|
||||
is_static: false,
|
||||
// Methods inside a static box are semantically static
|
||||
is_static: true,
|
||||
is_override: false,
|
||||
span: crate::ast::Span::unknown(),
|
||||
};
|
||||
|
||||
@ -83,13 +83,96 @@ impl NyashParser {
|
||||
|
||||
/// Parse block statements: { statement* }
|
||||
pub(super) fn parse_block_statements(&mut self) -> Result<Vec<ASTNode>, ParseError> {
|
||||
let trace_blocks = std::env::var("NYASH_PARSER_TRACE_BLOCKS").ok().as_deref() == Some("1");
|
||||
if trace_blocks {
|
||||
eprintln!(
|
||||
"[parser][block] enter '{{' at line {}",
|
||||
self.current_token().line
|
||||
);
|
||||
}
|
||||
self.consume(TokenType::LBRACE)?;
|
||||
let mut statements = Vec::new();
|
||||
|
||||
while !self.is_at_end() && !self.match_token(&TokenType::RBRACE) {
|
||||
statements.push(self.parse_statement()?);
|
||||
}
|
||||
if trace_blocks {
|
||||
eprintln!(
|
||||
"[parser][block] exit '}}' at line {}",
|
||||
self.current_token().line
|
||||
);
|
||||
}
|
||||
self.consume(TokenType::RBRACE)?;
|
||||
Ok(statements)
|
||||
}
|
||||
|
||||
/// Parse method body statements: { statement* }
|
||||
/// Optional seam-guard (env-gated via NYASH_PARSER_METHOD_BODY_STRICT=1) is applied
|
||||
/// conservatively at top-level only, and only right after a nested block '}' was
|
||||
/// just consumed, to avoid false positives inside method bodies.
|
||||
pub(super) fn parse_method_body_statements(&mut self) -> Result<Vec<ASTNode>, ParseError> {
|
||||
// Reuse block entry tracing
|
||||
let trace_blocks = std::env::var("NYASH_PARSER_TRACE_BLOCKS").ok().as_deref() == Some("1");
|
||||
if trace_blocks {
|
||||
eprintln!(
|
||||
"[parser][block] enter '{{' (method) at line {}",
|
||||
self.current_token().line
|
||||
);
|
||||
}
|
||||
self.consume(TokenType::LBRACE)?;
|
||||
let mut statements = Vec::new();
|
||||
|
||||
// Helper: lookahead for `ident '(' ... ')' [NEWLINE*] '{'`
|
||||
let mut looks_like_method_head = |this: &Self| -> bool {
|
||||
// Only meaningful when starting at a new statement head
|
||||
match &this.current_token().token_type {
|
||||
TokenType::IDENTIFIER(_) => {
|
||||
// Expect '(' after optional NEWLINE
|
||||
let mut k = 1usize;
|
||||
while matches!(this.peek_nth_token(k), TokenType::NEWLINE) { k += 1; }
|
||||
if !matches!(this.peek_nth_token(k), TokenType::LPAREN) { return false; }
|
||||
// Walk to matching ')'
|
||||
k += 1; // after '('
|
||||
let mut depth: i32 = 1;
|
||||
while !matches!(this.peek_nth_token(k), TokenType::EOF) {
|
||||
match this.peek_nth_token(k) {
|
||||
TokenType::LPAREN => depth += 1,
|
||||
TokenType::RPAREN => { depth -= 1; if depth == 0 { k += 1; break; } },
|
||||
_ => {}
|
||||
}
|
||||
k += 1;
|
||||
}
|
||||
// Allow NEWLINE(s) between ')' and '{'
|
||||
while matches!(this.peek_nth_token(k), TokenType::NEWLINE) { k += 1; }
|
||||
matches!(this.peek_nth_token(k), TokenType::LBRACE)
|
||||
}
|
||||
_ => false,
|
||||
}
|
||||
};
|
||||
|
||||
while !self.is_at_end() && !self.match_token(&TokenType::RBRACE) {
|
||||
statements.push(self.parse_statement()?);
|
||||
// Conservative seam guard: apply only when env is ON, we just consumed a '}'
|
||||
// (end of a nested block), and the next tokens at the top-level look like a
|
||||
// method head. This limits the guard to real seams between members.
|
||||
if std::env::var("NYASH_PARSER_METHOD_BODY_STRICT").ok().as_deref() == Some("1") {
|
||||
// If the next token would close the current method, do not guard here
|
||||
if self.match_token(&TokenType::RBRACE) { break; }
|
||||
// Check if we just consumed a '}' token from inner content
|
||||
let just_saw_rbrace = if self.current > 0 {
|
||||
matches!(self.tokens[self.current - 1].token_type, TokenType::RBRACE)
|
||||
} else { false };
|
||||
if just_saw_rbrace && looks_like_method_head(self) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if trace_blocks {
|
||||
eprintln!(
|
||||
"[parser][block] exit '}}' (method) at line {}",
|
||||
self.current_token().line
|
||||
);
|
||||
}
|
||||
self.consume(TokenType::RBRACE)?;
|
||||
Ok(statements)
|
||||
}
|
||||
@ -158,4 +241,4 @@ impl NyashParser {
|
||||
|
||||
result
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user