/*! * Nyash Parser - Rust Implementation * * Python版nyashc_v4.pyのNyashParserをRustで完全再実装 * Token列をAST (Abstract Syntax Tree) に変換 * * TODO: リファクタリング計画 * - expressions.rs: 式パーサー (parse_expression, parse_or, parse_and等) * - statements.rs: 文パーサー (parse_statement, parse_if, parse_loop等) * - declarations.rs: 宣言パーサー (parse_box_declaration, parse_function_declaration等) * - errors.rs: エラー型定義とハンドリング */ // サブモジュール宣言 mod common; mod expressions; mod statements; mod declarations; // mod errors; use common::ParserUtils; use crate::tokenizer::{Token, TokenType, TokenizeError}; use crate::ast::{ASTNode, Span}; use std::collections::HashMap; use thiserror::Error; // ===== 🔥 Debug Macros ===== /// Infinite loop detection macro - must be called in every loop that advances tokens /// Prevents parser from hanging due to token consumption bugs /// Uses parser's debug_fuel field for centralized fuel management #[macro_export] macro_rules! must_advance { ($parser:expr, $fuel:expr, $location:literal) => { // デバッグ燃料がSomeの場合のみ制限チェック if let Some(ref mut limit) = $parser.debug_fuel { if *limit == 0 { eprintln!("🚨 PARSER INFINITE LOOP DETECTED at {}", $location); eprintln!("🔍 Current token: {:?} at line {}", $parser.current_token().token_type, $parser.current_token().line); eprintln!("🔍 Parser position: {}/{}", $parser.current, $parser.tokens.len()); return Err($crate::parser::ParseError::InfiniteLoop { location: $location.to_string(), token: $parser.current_token().token_type.clone(), line: $parser.current_token().line, }); } *limit -= 1; } // None の場合は無制限なのでチェックしない }; } /// Initialize debug fuel for loop monitoring #[macro_export] macro_rules! debug_fuel { () => { 100_000 // Default: 100k iterations should be enough for any reasonable program }; } // Two-phase parser structures are no longer needed - simplified to direct parsing /// パースエラー #[derive(Error, Debug)] pub enum ParseError { #[error("Unexpected token {found:?}, expected {expected} at line {line}")] UnexpectedToken { found: TokenType, expected: String, line: usize }, #[error("Unexpected end of file")] UnexpectedEOF, #[error("Invalid expression at line {line}")] InvalidExpression { line: usize }, #[error("Invalid statement at line {line}")] InvalidStatement { line: usize }, #[error("Circular dependency detected between static boxes: {cycle}")] CircularDependency { cycle: String }, #[error("🚨 Infinite loop detected in parser at {location} - token: {token:?} at line {line}")] InfiniteLoop { location: String, token: TokenType, line: usize }, #[error("🔥 Transparency system removed: {suggestion} at line {line}")] TransparencySystemRemoved { suggestion: String, line: usize }, #[error("Unsupported namespace '{name}' at line {line}. Only 'nyashstd' is supported in Phase 0.")] UnsupportedNamespace { name: String, line: usize }, #[error("Expected identifier at line {line}")] ExpectedIdentifier { line: usize }, #[error("Tokenize error: {0}")] TokenizeError(#[from] TokenizeError), } /// Nyashパーサー - トークン列をASTに変換 pub struct NyashParser { pub(super) tokens: Vec, pub(super) current: usize, /// 🔥 Static box依存関係追跡(循環依存検出用) pub(super) static_box_dependencies: std::collections::HashMap>, /// 🔥 デバッグ燃料:無限ループ検出用制限値 (None = 無制限) pub(super) debug_fuel: Option, } // Implement ParserUtils trait impl ParserUtils for NyashParser { fn tokens(&self) -> &Vec { &self.tokens } fn current(&self) -> usize { self.current } fn current_mut(&mut self) -> &mut usize { &mut self.current } } impl NyashParser { /// 新しいパーサーを作成 pub fn new(tokens: Vec) -> Self { Self { tokens, current: 0, static_box_dependencies: std::collections::HashMap::new(), debug_fuel: Some(100_000), // デフォルト値 } } /// 文字列からパース (トークナイズ + パース) pub fn parse_from_string(input: impl Into) -> Result { Self::parse_from_string_with_fuel(input, Some(100_000)) } /// 文字列からパース (デバッグ燃料指定版) /// fuel: Some(n) = n回まで、None = 無制限 pub fn parse_from_string_with_fuel(input: impl Into, fuel: Option) -> Result { let mut tokenizer = crate::tokenizer::NyashTokenizer::new(input); let tokens = tokenizer.tokenize()?; let mut parser = Self::new(tokens); parser.debug_fuel = fuel; let result = parser.parse(); result } /// パース実行 - Program ASTを返す pub fn parse(&mut self) -> Result { self.parse_program() } // ===== パース関数群 ===== /// プログラム全体をパース fn parse_program(&mut self) -> Result { let mut statements = Vec::new(); let mut statement_count = 0; while !self.is_at_end() { // EOF tokenはスキップ if matches!(self.current_token().token_type, TokenType::EOF) { break; } // NEWLINE tokenはスキップ(文の区切りとして使用) if matches!(self.current_token().token_type, TokenType::NEWLINE) { self.advance(); continue; } let statement = self.parse_statement()?; statements.push(statement); statement_count += 1; } // 🔥 すべてのstatic box解析後に循環依存検出 self.check_circular_dependencies()?; Ok(ASTNode::Program { statements, span: Span::unknown() }) } // Statement parsing methods are now in statements.rs module /// 代入文または関数呼び出しをパース fn parse_assignment_or_function_call(&mut self) -> Result { // まず左辺を式としてパース let expr = self.parse_expression()?; // 次のトークンが = なら代入文 if self.match_token(&TokenType::ASSIGN) { self.advance(); // consume '=' let value = Box::new(self.parse_expression()?); // 左辺が代入可能な形式かチェック match &expr { ASTNode::Variable { .. } | ASTNode::FieldAccess { .. } => { Ok(ASTNode::Assignment { target: Box::new(expr), value, span: Span::unknown(), }) } _ => { let line = self.current_token().line; Err(ParseError::InvalidStatement { line }) } } } else { // 代入文でなければ式文として返す Ok(expr) } } // Expression parsing methods are now in expressions.rs module // Utility methods are now in common.rs module via ParserUtils trait // ===== 🔥 Static Box循環依存検出 ===== // TODO: Move these to items module in Step 4 /// グローバル変数をパース: global name = value fn parse_global_var(&mut self) -> Result { self.consume(TokenType::GLOBAL)?; let name = if let TokenType::IDENTIFIER(name) = &self.current_token().token_type { let name = name.clone(); self.advance(); name } else { let line = self.current_token().line; return Err(ParseError::UnexpectedToken { found: self.current_token().token_type.clone(), expected: "identifier".to_string(), line, }); }; self.consume(TokenType::ASSIGN)?; let value = Box::new(self.parse_expression()?); Ok(ASTNode::GlobalVar { name, value, span: Span::unknown() }) } /// function宣言をパース: function name(params) { body } fn parse_function_declaration(&mut self) -> Result { self.consume(TokenType::FUNCTION)?; // 関数名を取得 let name = if let TokenType::IDENTIFIER(name) = &self.current_token().token_type { let name = name.clone(); self.advance(); name } else { let line = self.current_token().line; return Err(ParseError::UnexpectedToken { found: self.current_token().token_type.clone(), expected: "function name".to_string(), line, }); }; // パラメータリストをパース self.consume(TokenType::LPAREN)?; let mut params = Vec::new(); while !self.match_token(&TokenType::RPAREN) && !self.is_at_end() { must_advance!(self, _unused, "function declaration parameter parsing"); if let TokenType::IDENTIFIER(param) = &self.current_token().token_type { params.push(param.clone()); self.advance(); if self.match_token(&TokenType::COMMA) { self.advance(); } } else if !self.match_token(&TokenType::RPAREN) { let line = self.current_token().line; return Err(ParseError::UnexpectedToken { found: self.current_token().token_type.clone(), expected: "parameter name".to_string(), line, }); } } self.consume(TokenType::RPAREN)?; // 関数本体をパース self.consume(TokenType::LBRACE)?; self.skip_newlines(); let mut body = Vec::new(); while !self.match_token(&TokenType::RBRACE) && !self.is_at_end() { self.skip_newlines(); if !self.match_token(&TokenType::RBRACE) { body.push(self.parse_statement()?); } } self.consume(TokenType::RBRACE)?; Ok(ASTNode::FunctionDeclaration { name, params, body, is_static: false, // 通常の関数は静的でない is_override: false, // デフォルトは非オーバーライド span: Span::unknown(), }) } /// 静的宣言をパース - 🔥 static function / static box 記法 fn parse_static_declaration(&mut self) -> Result { self.consume(TokenType::STATIC)?; // 次のトークンで分岐: function か box か match &self.current_token().token_type { TokenType::FUNCTION => self.parse_static_function(), TokenType::BOX => self.parse_static_box(), _ => { let line = self.current_token().line; Err(ParseError::UnexpectedToken { found: self.current_token().token_type.clone(), expected: "function or box after static".to_string(), line, }) } } } /// 静的関数宣言をパース - static function Name() { ... } fn parse_static_function(&mut self) -> Result { self.consume(TokenType::FUNCTION)?; // 関数名を取得(Box名.関数名の形式をサポート) let name = if let TokenType::IDENTIFIER(first_part) = &self.current_token().token_type { let mut full_name = first_part.clone(); self.advance(); // ドット記法をチェック(例:Math.min) if self.match_token(&TokenType::DOT) { self.advance(); // DOTを消費 if let TokenType::IDENTIFIER(method_name) = &self.current_token().token_type { full_name = format!("{}.{}", full_name, method_name); self.advance(); } else { let line = self.current_token().line; return Err(ParseError::UnexpectedToken { found: self.current_token().token_type.clone(), expected: "method name after dot".to_string(), line, }); } } full_name } else { let line = self.current_token().line; return Err(ParseError::UnexpectedToken { found: self.current_token().token_type.clone(), expected: "static function name".to_string(), line, }); }; // パラメータリストをパース self.consume(TokenType::LPAREN)?; let mut params = Vec::new(); while !self.match_token(&TokenType::RPAREN) && !self.is_at_end() { must_advance!(self, _unused, "static function parameter parsing"); if let TokenType::IDENTIFIER(param) = &self.current_token().token_type { params.push(param.clone()); self.advance(); if self.match_token(&TokenType::COMMA) { self.advance(); } } else if !self.match_token(&TokenType::RPAREN) { let line = self.current_token().line; return Err(ParseError::UnexpectedToken { found: self.current_token().token_type.clone(), expected: "parameter name".to_string(), line, }); } } self.consume(TokenType::RPAREN)?; // 関数本体をパース self.consume(TokenType::LBRACE)?; self.skip_newlines(); let mut body = Vec::new(); while !self.match_token(&TokenType::RBRACE) && !self.is_at_end() { self.skip_newlines(); if !self.match_token(&TokenType::RBRACE) { body.push(self.parse_statement()?); } } self.consume(TokenType::RBRACE)?; Ok(ASTNode::FunctionDeclaration { name, params, body, is_static: true, // 🔥 静的関数フラグを設定 is_override: false, // デフォルトは非オーバーライド span: Span::unknown(), }) } }