From 9c9af6e9df103686d5321982277e10adb1c27684 Mon Sep 17 00:00:00 2001 From: Moe Charm Date: Sat, 16 Aug 2025 12:19:58 +0900 Subject: [PATCH] refactor(parser): Step 3 - Extract declarations module - Create declarations module with box_definition, static_box, dependency_helpers - Move parse_box_declaration, parse_interface_box_declaration from mod.rs - Move parse_static_box and dependency checking logic - Temporarily restore parse_global_var, parse_function_declaration, parse_static_declaration to mod.rs - Fix visibility issues (pub vs pub(super)) - Fix TokenType::IMPLEMENTS not defined issue - Fix Loop AST node condition type mismatch - Build passes successfully Next: Step 4 - Extract items module for global_vars, functions, static_items --- src/parser/declarations/box_definition.rs | 628 +++++++++ src/parser/declarations/dependency_helpers.rs | 144 +++ src/parser/declarations/mod.rs | 15 + src/parser/declarations/static_box.rs | 290 +++++ src/parser/mod.rs | 1121 +---------------- 5 files changed, 1108 insertions(+), 1090 deletions(-) create mode 100644 src/parser/declarations/box_definition.rs create mode 100644 src/parser/declarations/dependency_helpers.rs create mode 100644 src/parser/declarations/mod.rs create mode 100644 src/parser/declarations/static_box.rs diff --git a/src/parser/declarations/box_definition.rs b/src/parser/declarations/box_definition.rs new file mode 100644 index 00000000..6a9eda45 --- /dev/null +++ b/src/parser/declarations/box_definition.rs @@ -0,0 +1,628 @@ +/*! + * Box Definition Parser Module + * + * Box宣言(box, interface box, static box)の解析を担当 + * Nyashの中核概念「Everything is Box」を実現する重要モジュール + */ + +use crate::tokenizer::TokenType; +use crate::ast::{ASTNode, Span}; +use crate::parser::{NyashParser, ParseError}; +use crate::parser::common::ParserUtils; +use crate::{must_advance, debug_fuel}; +use std::collections::{HashMap, HashSet}; + +impl NyashParser { + /// box宣言をパース: box Name { fields... methods... } + pub fn parse_box_declaration(&mut self) -> Result { + self.consume(TokenType::BOX)?; + + 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, + }); + }; + + // 🔥 ジェネリクス型パラメータのパース () + let type_parameters = if self.match_token(&TokenType::LESS) { + self.advance(); // consume '<' + let mut params = Vec::new(); + + while !self.match_token(&TokenType::GREATER) && !self.is_at_end() { + must_advance!(self, _unused, "generic type 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(); + self.skip_newlines(); + } + } else { + return Err(ParseError::UnexpectedToken { + found: self.current_token().token_type.clone(), + expected: "type parameter name".to_string(), + line: self.current_token().line, + }); + } + } + + self.consume(TokenType::GREATER)?; // consume '>' + params + } else { + Vec::new() + }; + + // 🚀 Multi-delegation support: "from Parent1, Parent2, ..." + let extends = if self.match_token(&TokenType::FROM) { + self.advance(); // consume 'from' + let mut parents = Vec::new(); + + // Parse first parent (required) + if let TokenType::IDENTIFIER(parent) = &self.current_token().token_type { + parents.push(parent.clone()); + self.advance(); + } else { + return Err(ParseError::UnexpectedToken { + found: self.current_token().token_type.clone(), + expected: "parent box name after 'from'".to_string(), + line: self.current_token().line, + }); + } + + // Parse additional parents (optional) + while self.match_token(&TokenType::COMMA) { + self.advance(); // consume ',' + self.skip_newlines(); + + if let TokenType::IDENTIFIER(parent) = &self.current_token().token_type { + parents.push(parent.clone()); + self.advance(); + } else { + return Err(ParseError::UnexpectedToken { + found: self.current_token().token_type.clone(), + expected: "parent box name after comma".to_string(), + line: self.current_token().line, + }); + } + } + + parents + } else { + Vec::new() + }; + + // implementsキーワードのチェック + // TODO: TokenType::IMPLEMENTS is not defined in current version + let implements = if false { // self.match_token(&TokenType::IMPLEMENTS) { + self.advance(); // consume 'implements' + let mut interfaces = Vec::new(); + + loop { + must_advance!(self, _unused, "interface implementation parsing"); + + if let TokenType::IDENTIFIER(interface) = &self.current_token().token_type { + interfaces.push(interface.clone()); + self.advance(); + } else { + return Err(ParseError::UnexpectedToken { + found: self.current_token().token_type.clone(), + expected: "interface name".to_string(), + line: self.current_token().line, + }); + } + + if self.match_token(&TokenType::COMMA) { + self.advance(); + } else { + break; + } + } + + interfaces + } else { + Vec::new() + }; + + self.consume(TokenType::LBRACE)?; + self.skip_newlines(); // ブレース後の改行をスキップ + + let mut fields = Vec::new(); + let mut methods = HashMap::new(); + let mut constructors = HashMap::new(); + let mut init_fields = Vec::new(); + let mut weak_fields = Vec::new(); // 🔗 Track weak fields + + while !self.match_token(&TokenType::RBRACE) && !self.is_at_end() { + self.skip_newlines(); // ループ開始時に改行をスキップ + + // RBRACEに到達していればループを抜ける + if self.match_token(&TokenType::RBRACE) { + break; + } + + // initブロックの処理(initメソッドではない場合のみ) + if self.match_token(&TokenType::INIT) && self.peek_token() != &TokenType::LPAREN { + self.advance(); // consume 'init' + self.consume(TokenType::LBRACE)?; + + // initブロック内のフィールド定義を読み込み + while !self.match_token(&TokenType::RBRACE) && !self.is_at_end() { + self.skip_newlines(); + + if self.match_token(&TokenType::RBRACE) { + break; + } + + // Check for weak modifier + let is_weak = if self.match_token(&TokenType::WEAK) { + self.advance(); // consume 'weak' + true + } else { + false + }; + + if let TokenType::IDENTIFIER(field_name) = &self.current_token().token_type { + init_fields.push(field_name.clone()); + if is_weak { + weak_fields.push(field_name.clone()); // 🔗 Add to weak fields list + } + self.advance(); + + // カンマがあればスキップ + if self.match_token(&TokenType::COMMA) { + self.advance(); + } + } else { + // 不正なトークンがある場合はエラー + return Err(ParseError::UnexpectedToken { + expected: if is_weak { "field name after 'weak'" } else { "field name" }.to_string(), + found: self.current_token().token_type.clone(), + line: self.current_token().line, + }); + } + } + + self.consume(TokenType::RBRACE)?; + continue; + } + + // overrideキーワードをチェック + let mut is_override = false; + if self.match_token(&TokenType::OVERRIDE) { + is_override = true; + self.advance(); + } + + // initトークンをメソッド名として特別処理 + if self.match_token(&TokenType::INIT) && self.peek_token() == &TokenType::LPAREN { + let field_or_method = "init".to_string(); + self.advance(); // consume 'init' + + // コンストラクタとして処理 + if self.match_token(&TokenType::LPAREN) { + // initは常にコンストラクタ + if is_override { + return Err(ParseError::UnexpectedToken { + expected: "method definition, not constructor after override keyword".to_string(), + found: TokenType::INIT, + line: self.current_token().line, + }); + } + // コンストラクタの処理 + self.advance(); // consume '(' + + let mut params = Vec::new(); + while !self.match_token(&TokenType::RPAREN) && !self.is_at_end() { + must_advance!(self, _unused, "constructor 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(); + } + } + + self.consume(TokenType::RPAREN)?; + self.consume(TokenType::LBRACE)?; + + let mut body = Vec::new(); + while !self.match_token(&TokenType::RBRACE) && !self.is_at_end() { + must_advance!(self, _unused, "constructor body parsing"); + + self.skip_newlines(); + if self.match_token(&TokenType::RBRACE) { + break; + } + body.push(self.parse_statement()?); + } + + self.consume(TokenType::RBRACE)?; + + let constructor = ASTNode::FunctionDeclaration { + name: field_or_method.clone(), + params, + body, + is_static: false, + is_override: false, // コンストラクタは常に非オーバーライド + span: Span::unknown(), + }; + + constructors.insert(field_or_method, constructor); + continue; + } + } + + // packキーワードの処理(ビルトインBox継承用) + if self.match_token(&TokenType::PACK) && self.peek_token() == &TokenType::LPAREN { + let field_or_method = "pack".to_string(); + self.advance(); // consume 'pack' + + // packは常にコンストラクタ + if is_override { + return Err(ParseError::UnexpectedToken { + expected: "method definition, not constructor after override keyword".to_string(), + found: TokenType::PACK, + line: self.current_token().line, + }); + } + // packコンストラクタの処理 + self.advance(); // consume '(' + + let mut params = Vec::new(); + while !self.match_token(&TokenType::RPAREN) && !self.is_at_end() { + must_advance!(self, _unused, "pack 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(); + } + } + + self.consume(TokenType::RPAREN)?; + self.consume(TokenType::LBRACE)?; + + let mut body = Vec::new(); + while !self.match_token(&TokenType::RBRACE) && !self.is_at_end() { + must_advance!(self, _unused, "pack body parsing"); + + self.skip_newlines(); + if self.match_token(&TokenType::RBRACE) { + break; + } + body.push(self.parse_statement()?); + } + + self.consume(TokenType::RBRACE)?; + + let constructor = ASTNode::FunctionDeclaration { + name: field_or_method.clone(), + params, + body, + is_static: false, + is_override: false, // packは常に非オーバーライド + span: Span::unknown(), + }; + + constructors.insert(field_or_method, constructor); + continue; + } + + // birthキーワードの処理(生命を与えるコンストラクタ) + if self.match_token(&TokenType::BIRTH) && self.peek_token() == &TokenType::LPAREN { + let field_or_method = "birth".to_string(); + self.advance(); // consume 'birth' + + // birthは常にコンストラクタ + if is_override { + return Err(ParseError::UnexpectedToken { + expected: "method definition, not constructor after override keyword".to_string(), + found: TokenType::BIRTH, + line: self.current_token().line, + }); + } + // birthコンストラクタの処理 + self.advance(); // consume '(' + + let mut params = Vec::new(); + while !self.match_token(&TokenType::RPAREN) && !self.is_at_end() { + must_advance!(self, _unused, "birth 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(); + } + } + + self.consume(TokenType::RPAREN)?; + self.consume(TokenType::LBRACE)?; + + let mut body = Vec::new(); + while !self.match_token(&TokenType::RBRACE) && !self.is_at_end() { + must_advance!(self, _unused, "birth body parsing"); + + self.skip_newlines(); + if self.match_token(&TokenType::RBRACE) { + break; + } + body.push(self.parse_statement()?); + } + + self.consume(TokenType::RBRACE)?; + + let constructor = ASTNode::FunctionDeclaration { + name: field_or_method.clone(), + params, + body, + is_static: false, + is_override: false, // birthは常に非オーバーライド + span: Span::unknown(), + }; + + constructors.insert(field_or_method, constructor); + continue; + } + + // Box名と同じ名前のコンストラクタをチェック + if self.match_token(&TokenType::IDENTIFIER(name.clone())) && self.peek_token() == &TokenType::LPAREN { + let constructor_name = name.clone(); + self.advance(); // consume identifier + + // コンストラクタは常にオーバーライド不可 + if is_override { + return Err(ParseError::UnexpectedToken { + expected: "method definition, not constructor after override keyword".to_string(), + found: TokenType::IDENTIFIER(constructor_name.clone()), + line: self.current_token().line, + }); + } + // Box名コンストラクタの処理 + self.advance(); // consume '(' + + let mut params = Vec::new(); + while !self.match_token(&TokenType::RPAREN) && !self.is_at_end() { + must_advance!(self, _unused, "Box constructor 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(); + } + } + + self.consume(TokenType::RPAREN)?; + self.consume(TokenType::LBRACE)?; + + let mut body = Vec::new(); + while !self.match_token(&TokenType::RBRACE) && !self.is_at_end() { + must_advance!(self, _unused, "Box constructor body parsing"); + + self.skip_newlines(); + if self.match_token(&TokenType::RBRACE) { + break; + } + body.push(self.parse_statement()?); + } + + self.consume(TokenType::RBRACE)?; + + let constructor = ASTNode::FunctionDeclaration { + name: constructor_name.clone(), + params, + body, + is_static: false, + is_override: false, + span: Span::unknown(), + }; + + constructors.insert(constructor_name, constructor); + continue; + } + + // 通常のフィールド名またはメソッド名を読み取り + if let TokenType::IDENTIFIER(field_or_method) = &self.current_token().token_type { + let field_or_method = field_or_method.clone(); + self.advance(); + + // メソッドかフィールドかを判定 + if self.match_token(&TokenType::LPAREN) { + // メソッド定義 + self.advance(); // consume '(' + + let mut params = Vec::new(); + while !self.match_token(&TokenType::RPAREN) && !self.is_at_end() { + must_advance!(self, _unused, "method 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(); + } + } + + self.consume(TokenType::RPAREN)?; + self.consume(TokenType::LBRACE)?; + + let mut body = Vec::new(); + while !self.match_token(&TokenType::RBRACE) && !self.is_at_end() { + must_advance!(self, _unused, "method body parsing"); + + self.skip_newlines(); + if self.match_token(&TokenType::RBRACE) { + break; + } + body.push(self.parse_statement()?); + } + + self.consume(TokenType::RBRACE)?; + + let method = ASTNode::FunctionDeclaration { + name: field_or_method.clone(), + params, + body, + is_static: false, + is_override, + span: Span::unknown(), + }; + + methods.insert(field_or_method, method); + } else { + // フィールド定義 + fields.push(field_or_method); + } + } else { + return Err(ParseError::UnexpectedToken { + expected: "method or field name".to_string(), + found: self.current_token().token_type.clone(), + line: self.current_token().line, + }); + } + } + + self.consume(TokenType::RBRACE)?; + + // 🔥 Override validation + for parent in &extends { + self.validate_override_methods(&name, parent, &methods)?; + } + + Ok(ASTNode::BoxDeclaration { + name, + fields, + methods, + constructors, + init_fields, + weak_fields, // 🔗 Add weak fields to AST + is_interface: false, + extends, + implements, + type_parameters, + is_static: false, // 通常のboxはnon-static + static_init: None, // 通常のboxはstatic初期化ブロックなし + span: Span::unknown(), + }) + } + + /// interface box宣言をパース: interface box Name { methods... } + pub fn parse_interface_box_declaration(&mut self) -> Result { + self.consume(TokenType::INTERFACE)?; + self.consume(TokenType::BOX)?; + + 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::LBRACE)?; + self.skip_newlines(); // ブレース後の改行をスキップ + + let mut methods = HashMap::new(); + + while !self.match_token(&TokenType::RBRACE) && !self.is_at_end() { + self.skip_newlines(); // ループ開始時に改行をスキップ + if let TokenType::IDENTIFIER(method_name) = &self.current_token().token_type { + let method_name = method_name.clone(); + self.advance(); + + // インターフェースメソッドはシグネチャのみ + if self.match_token(&TokenType::LPAREN) { + self.advance(); // consume '(' + + let mut params = Vec::new(); + while !self.match_token(&TokenType::RPAREN) && !self.is_at_end() { + if let TokenType::IDENTIFIER(param) = &self.current_token().token_type { + params.push(param.clone()); + self.advance(); + } + + if self.match_token(&TokenType::COMMA) { + self.advance(); + } + } + + self.consume(TokenType::RPAREN)?; + + // インターフェースメソッドは実装なし(空のbody) + let method_decl = ASTNode::FunctionDeclaration { + name: method_name.clone(), + params, + body: vec![], // 空の実装 + is_static: false, // インターフェースメソッドは通常静的でない + is_override: false, // デフォルトは非オーバーライド + span: Span::unknown(), + }; + + methods.insert(method_name, method_decl); + + // メソッド宣言後の改行をスキップ + self.skip_newlines(); + } else { + let line = self.current_token().line; + return Err(ParseError::UnexpectedToken { + found: self.current_token().token_type.clone(), + expected: "(".to_string(), + line, + }); + } + } else { + let line = self.current_token().line; + return Err(ParseError::UnexpectedToken { + found: self.current_token().token_type.clone(), + expected: "method name".to_string(), + line, + }); + } + } + + self.consume(TokenType::RBRACE)?; + + Ok(ASTNode::BoxDeclaration { + name, + fields: vec![], // インターフェースはフィールドなし + methods, + constructors: HashMap::new(), // インターフェースにコンストラクタなし + init_fields: vec![], // インターフェースにinitブロックなし + weak_fields: vec![], // 🔗 インターフェースにweak fieldsなし + is_interface: true, // インターフェースフラグ + extends: vec![], // 🚀 Multi-delegation: Changed from None to vec![] + implements: vec![], + type_parameters: Vec::new(), // 🔥 インターフェースではジェネリクス未対応 + is_static: false, // インターフェースは非static + static_init: None, // インターフェースにstatic initなし + span: Span::unknown(), + }) + } +} \ No newline at end of file diff --git a/src/parser/declarations/dependency_helpers.rs b/src/parser/declarations/dependency_helpers.rs new file mode 100644 index 00000000..155a79f5 --- /dev/null +++ b/src/parser/declarations/dependency_helpers.rs @@ -0,0 +1,144 @@ +/*! + * Dependency Analysis Helpers + * + * Static box依存関係の解析と循環依存検出 + */ + +use crate::ast::ASTNode; +use crate::parser::{NyashParser, ParseError}; +use std::collections::{HashMap, HashSet}; + +impl NyashParser { + /// Static初期化ブロック内の文から依存関係を抽出 + pub(super) fn extract_dependencies_from_statements(&self, statements: &[ASTNode]) -> HashSet { + let mut dependencies = HashSet::new(); + + for stmt in statements { + self.extract_dependencies_from_ast(stmt, &mut dependencies); + } + + dependencies + } + + /// AST内から静的Box参照を再帰的に検出 + pub(super) fn extract_dependencies_from_ast(&self, node: &ASTNode, dependencies: &mut HashSet) { + match node { + ASTNode::FieldAccess { object, .. } => { + // Math.PI のような参照を検出 + if let ASTNode::Variable { name, .. } = object.as_ref() { + dependencies.insert(name.clone()); + } + } + ASTNode::MethodCall { object, .. } => { + // Config.getDebug() のような呼び出しを検出 + if let ASTNode::Variable { name, .. } = object.as_ref() { + dependencies.insert(name.clone()); + } + } + ASTNode::Assignment { target, value, .. } => { + self.extract_dependencies_from_ast(target, dependencies); + self.extract_dependencies_from_ast(value, dependencies); + } + ASTNode::BinaryOp { left, right, .. } => { + self.extract_dependencies_from_ast(left, dependencies); + self.extract_dependencies_from_ast(right, dependencies); + } + ASTNode::UnaryOp { operand, .. } => { + self.extract_dependencies_from_ast(operand, dependencies); + } + ASTNode::If { condition, then_body, else_body, .. } => { + self.extract_dependencies_from_ast(condition, dependencies); + for stmt in then_body { + self.extract_dependencies_from_ast(stmt, dependencies); + } + if let Some(else_stmts) = else_body { + for stmt in else_stmts { + self.extract_dependencies_from_ast(stmt, dependencies); + } + } + } + ASTNode::Loop { condition, body, .. } => { + self.extract_dependencies_from_ast(condition, dependencies); + for stmt in body { + self.extract_dependencies_from_ast(stmt, dependencies); + } + } + ASTNode::Return { value, .. } => { + if let Some(val) = value { + self.extract_dependencies_from_ast(val, dependencies); + } + } + _ => { + // その他のASTノードは無視 + } + } + } + + /// 循環依存検出 + pub fn check_circular_dependencies(&self) -> Result<(), ParseError> { + // すべてのstatic boxに対して循環検出を実行 + let all_boxes: Vec<_> = self.static_box_dependencies.keys().cloned().collect(); + + for box_name in &all_boxes { + let mut visited = HashSet::new(); + let mut stack = Vec::new(); + + if self.has_cycle_dfs(box_name, &mut visited, &mut stack)? { + // 循環を文字列化 + let cycle_str = stack.join(" -> "); + return Err(ParseError::CircularDependency { cycle: cycle_str }); + } + } + + Ok(()) + } + + /// DFSで循環依存を検出 + fn has_cycle_dfs( + &self, + current: &str, + visited: &mut HashSet, + stack: &mut Vec, + ) -> Result { + // 既にスタックにあれば循環 + if stack.contains(¤t.to_string()) { + stack.push(current.to_string()); // 循環を完成させる + return Ok(true); + } + + // 既に訪問済みで循環がなければスキップ + if visited.contains(current) { + return Ok(false); + } + + visited.insert(current.to_string()); + stack.push(current.to_string()); + + // 依存先をチェック + if let Some(dependencies) = self.static_box_dependencies.get(current) { + for dep in dependencies { + if self.has_cycle_dfs(dep, visited, stack)? { + return Ok(true); + } + } + } + + stack.pop(); + Ok(false) + } + + /// Override メソッドの検証 + pub(super) fn validate_override_methods(&self, child_name: &str, parent_name: &str, methods: &HashMap) -> Result<(), ParseError> { + // 現時点では簡単な検証のみ + // TODO: 親クラスのメソッドシグネチャとの比較 + for (method_name, method_ast) in methods { + if let ASTNode::FunctionDeclaration { is_override, .. } = method_ast { + if *is_override { + // 将来的にここで親クラスのメソッドが存在するかチェック + eprintln!("🔍 Validating override method '{}' in '{}' from '{}'", method_name, child_name, parent_name); + } + } + } + Ok(()) + } +} \ No newline at end of file diff --git a/src/parser/declarations/mod.rs b/src/parser/declarations/mod.rs new file mode 100644 index 00000000..2acdb24b --- /dev/null +++ b/src/parser/declarations/mod.rs @@ -0,0 +1,15 @@ +/*! + * Parser Declarations Module + * + * 宣言(Declaration)の解析を担当するモジュール群 + * Box定義、関数定義、use文などの宣言を処理 + */ + +pub mod box_definition; +pub mod static_box; +pub mod dependency_helpers; + +// Re-export commonly used items +pub use box_definition::*; +pub use static_box::*; +pub use dependency_helpers::*; \ No newline at end of file diff --git a/src/parser/declarations/static_box.rs b/src/parser/declarations/static_box.rs new file mode 100644 index 00000000..6996beb1 --- /dev/null +++ b/src/parser/declarations/static_box.rs @@ -0,0 +1,290 @@ +/*! + * Static Box Definition Parser + * + * static box宣言と関連ヘルパー関数 + */ + +use crate::tokenizer::TokenType; +use crate::ast::{ASTNode, Span}; +use crate::parser::{NyashParser, ParseError}; +use crate::parser::common::ParserUtils; +use crate::{must_advance, debug_fuel}; +use std::collections::{HashMap, HashSet}; + +impl NyashParser { + /// static box宣言をパース: static box Name { ... } + pub fn parse_static_box(&mut self) -> Result { + self.consume(TokenType::BOX)?; + + 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, + }); + }; + + // 🔥 ジェネリクス型パラメータのパース () + let type_parameters = if self.match_token(&TokenType::LESS) { + self.advance(); // consume '<' + let mut params = Vec::new(); + + loop { + if let TokenType::IDENTIFIER(param_name) = &self.current_token().token_type { + params.push(param_name.clone()); + self.advance(); + + if self.match_token(&TokenType::COMMA) { + self.advance(); // consume ',' + } else { + break; + } + } else { + let line = self.current_token().line; + return Err(ParseError::UnexpectedToken { + found: self.current_token().token_type.clone(), + expected: "type parameter name".to_string(), + line, + }); + } + } + + self.consume(TokenType::GREATER)?; // consume '>' + params + } else { + Vec::new() + }; + + // from句のパース(Multi-delegation)- static boxでもデリゲーション可能 🚀 + let extends = if self.match_token(&TokenType::FROM) { + self.advance(); // consume 'from' + + let mut parent_list = Vec::new(); + + loop { + if let TokenType::IDENTIFIER(parent_name) = &self.current_token().token_type { + parent_list.push(parent_name.clone()); + self.advance(); + + if self.match_token(&TokenType::COMMA) { + self.advance(); // consume ',' + } else { + break; + } + } else { + let line = self.current_token().line; + return Err(ParseError::UnexpectedToken { + found: self.current_token().token_type.clone(), + expected: "parent class name".to_string(), + line, + }); + } + } + + parent_list + } else { + Vec::new() + }; + + // interface句のパース(インターフェース実装)- static boxでもinterface実装可能 + let implements = if self.match_token(&TokenType::INTERFACE) { + self.advance(); // consume 'interface' + + let mut interface_list = Vec::new(); + + loop { + if let TokenType::IDENTIFIER(interface_name) = &self.current_token().token_type { + interface_list.push(interface_name.clone()); + self.advance(); + + if self.match_token(&TokenType::COMMA) { + self.advance(); // consume ',' + } else { + break; + } + } else { + let line = self.current_token().line; + return Err(ParseError::UnexpectedToken { + found: self.current_token().token_type.clone(), + expected: "interface name".to_string(), + line, + }); + } + } + + interface_list + } else { + vec![] + }; + + self.consume(TokenType::LBRACE)?; + self.skip_newlines(); // ブレース後の改行をスキップ + + let mut fields = Vec::new(); + let mut methods = HashMap::new(); + let constructors = HashMap::new(); + let mut init_fields = Vec::new(); + let mut weak_fields = Vec::new(); // 🔗 Track weak fields for static box + let mut static_init = None; + + while !self.match_token(&TokenType::RBRACE) && !self.is_at_end() { + self.skip_newlines(); // ループ開始時に改行をスキップ + + // RBRACEに到達していればループを抜ける + if self.match_token(&TokenType::RBRACE) { + break; + } + + // 🔥 static { } ブロックの処理 + if self.match_token(&TokenType::STATIC) { + self.advance(); // consume 'static' + self.consume(TokenType::LBRACE)?; + + let mut static_body = Vec::new(); + while !self.match_token(&TokenType::RBRACE) && !self.is_at_end() { + self.skip_newlines(); + if !self.match_token(&TokenType::RBRACE) { + static_body.push(self.parse_statement()?); + } + } + + self.consume(TokenType::RBRACE)?; + static_init = Some(static_body); + continue; + } + + // initブロックの処理 + if self.match_token(&TokenType::INIT) { + self.advance(); // consume 'init' + self.consume(TokenType::LBRACE)?; + + // initブロック内のフィールド定義を読み込み + while !self.match_token(&TokenType::RBRACE) && !self.is_at_end() { + self.skip_newlines(); + + if self.match_token(&TokenType::RBRACE) { + break; + } + + // Check for weak modifier + let is_weak = if self.match_token(&TokenType::WEAK) { + self.advance(); // consume 'weak' + true + } else { + false + }; + + if let TokenType::IDENTIFIER(field_name) = &self.current_token().token_type { + init_fields.push(field_name.clone()); + if is_weak { + weak_fields.push(field_name.clone()); // 🔗 Add to weak fields list + } + self.advance(); + + // カンマがあればスキップ + if self.match_token(&TokenType::COMMA) { + self.advance(); + } + } else { + // 不正なトークンがある場合はエラー + return Err(ParseError::UnexpectedToken { + expected: if is_weak { "field name after 'weak'" } else { "field name" }.to_string(), + found: self.current_token().token_type.clone(), + line: self.current_token().line, + }); + } + } + + self.consume(TokenType::RBRACE)?; + continue; + } + + if let TokenType::IDENTIFIER(field_or_method) = &self.current_token().token_type { + let field_or_method = field_or_method.clone(); + self.advance(); + + // メソッド定義か? + if self.match_token(&TokenType::LPAREN) { + // メソッド定義 + self.advance(); // consume '(' + + let mut params = Vec::new(); + while !self.match_token(&TokenType::RPAREN) && !self.is_at_end() { + if let TokenType::IDENTIFIER(param) = &self.current_token().token_type { + params.push(param.clone()); + self.advance(); + } + + if self.match_token(&TokenType::COMMA) { + self.advance(); + } + } + + self.consume(TokenType::RPAREN)?; + self.consume(TokenType::LBRACE)?; + + 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)?; + + let method = ASTNode::FunctionDeclaration { + name: field_or_method.clone(), + params, + body, + is_static: false, // static box内のメソッドは通常メソッド + is_override: false, // デフォルトは非オーバーライド + span: Span::unknown(), + }; + + methods.insert(field_or_method, method); + } else { + // フィールド定義 + fields.push(field_or_method); + } + } else { + return Err(ParseError::UnexpectedToken { + expected: "method or field name".to_string(), + found: self.current_token().token_type.clone(), + line: self.current_token().line, + }); + } + } + + self.consume(TokenType::RBRACE)?; + + // 🔥 Static初期化ブロックから依存関係を抽出 + if let Some(ref init_stmts) = static_init { + let dependencies = self.extract_dependencies_from_statements(init_stmts); + self.static_box_dependencies.insert(name.clone(), dependencies); + } else { + self.static_box_dependencies.insert(name.clone(), std::collections::HashSet::new()); + } + + Ok(ASTNode::BoxDeclaration { + name, + fields, + methods, + constructors, + init_fields, + weak_fields, // 🔗 Add weak fields to static box construction + is_interface: false, + extends, + implements, + type_parameters, + is_static: true, // 🔥 static boxフラグを設定 + static_init, // 🔥 static初期化ブロック + span: Span::unknown(), + }) + } +} \ No newline at end of file diff --git a/src/parser/mod.rs b/src/parser/mod.rs index 47fa17c7..0dfc35f8 100644 --- a/src/parser/mod.rs +++ b/src/parser/mod.rs @@ -15,7 +15,7 @@ mod common; mod expressions; mod statements; -// mod declarations; +mod declarations; // mod errors; use common::ParserUtils; @@ -186,618 +186,44 @@ impl NyashParser { } // Statement parsing methods are now in statements.rs module - /// box宣言をパース: box Name { fields... methods... } - fn parse_box_declaration(&mut self) -> Result { - self.consume(TokenType::BOX)?; + /// 代入文または関数呼び出しをパース + fn parse_assignment_or_function_call(&mut self) -> Result { - 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, - }); - }; + // まず左辺を式としてパース + let expr = self.parse_expression()?; - // 🔥 ジェネリクス型パラメータのパース () - let type_parameters = if self.match_token(&TokenType::LESS) { - self.advance(); // consume '<' - let mut params = Vec::new(); + // 次のトークンが = なら代入文 + if self.match_token(&TokenType::ASSIGN) { + self.advance(); // consume '=' + let value = Box::new(self.parse_expression()?); - loop { - if let TokenType::IDENTIFIER(param_name) = &self.current_token().token_type { - params.push(param_name.clone()); - self.advance(); - - if self.match_token(&TokenType::COMMA) { - self.advance(); // consume ',' - } else { - break; - } - } else { - let line = self.current_token().line; - return Err(ParseError::UnexpectedToken { - found: self.current_token().token_type.clone(), - expected: "type parameter name".to_string(), - line, - }); - } - } - - self.consume(TokenType::GREATER)?; // consume '>' - params - } else { - Vec::new() - }; - - // from句のパース(Multi-delegation)🚀 - let extends = if self.match_token(&TokenType::FROM) { - self.advance(); // consume 'from' - - let mut parent_list = Vec::new(); - - loop { - if let TokenType::IDENTIFIER(parent_name) = &self.current_token().token_type { - parent_list.push(parent_name.clone()); - self.advance(); - - if self.match_token(&TokenType::COMMA) { - self.advance(); // consume ',' - } else { - break; - } - } else { - let line = self.current_token().line; - return Err(ParseError::UnexpectedToken { - found: self.current_token().token_type.clone(), - expected: "parent class name".to_string(), - line, - }); - } - } - - parent_list - } else { - Vec::new() - }; - - // interface句のパース(インターフェース実装) - let implements = if self.match_token(&TokenType::INTERFACE) { - self.advance(); // consume 'interface' - - let mut interface_list = Vec::new(); - - loop { - if let TokenType::IDENTIFIER(interface_name) = &self.current_token().token_type { - interface_list.push(interface_name.clone()); - self.advance(); - - if self.match_token(&TokenType::COMMA) { - self.advance(); // consume ',' - } else { - break; - } - } else { - let line = self.current_token().line; - return Err(ParseError::UnexpectedToken { - found: self.current_token().token_type.clone(), - expected: "interface name".to_string(), - line, - }); - } - } - - interface_list - } else { - vec![] - }; - - self.consume(TokenType::LBRACE)?; - self.skip_newlines(); // ブレース後の改行をスキップ - - let mut fields = Vec::new(); - let mut methods = HashMap::new(); - let mut constructors = HashMap::new(); - let mut init_fields = Vec::new(); - let mut weak_fields = Vec::new(); // 🔗 Track weak fields - - while !self.match_token(&TokenType::RBRACE) && !self.is_at_end() { - self.skip_newlines(); // ループ開始時に改行をスキップ - - // RBRACEに到達していればループを抜ける - if self.match_token(&TokenType::RBRACE) { - break; - } - - // initブロックの処理(initメソッドではない場合のみ) - if self.match_token(&TokenType::INIT) && self.peek_token() != &TokenType::LPAREN { - self.advance(); // consume 'init' - self.consume(TokenType::LBRACE)?; - - // initブロック内のフィールド定義を読み込み - while !self.match_token(&TokenType::RBRACE) && !self.is_at_end() { - self.skip_newlines(); - - if self.match_token(&TokenType::RBRACE) { - break; - } - - // Check for weak modifier - let is_weak = if self.match_token(&TokenType::WEAK) { - self.advance(); // consume 'weak' - true - } else { - false - }; - - if let TokenType::IDENTIFIER(field_name) = &self.current_token().token_type { - init_fields.push(field_name.clone()); - if is_weak { - weak_fields.push(field_name.clone()); // 🔗 Add to weak fields list - } - self.advance(); - - // カンマがあればスキップ - if self.match_token(&TokenType::COMMA) { - self.advance(); - } - } else { - // 不正なトークンがある場合はエラー - return Err(ParseError::UnexpectedToken { - expected: if is_weak { "field name after 'weak'" } else { "field name" }.to_string(), - found: self.current_token().token_type.clone(), - line: self.current_token().line, - }); - } - } - - self.consume(TokenType::RBRACE)?; - continue; - } - - // overrideキーワードをチェック - let mut is_override = false; - if self.match_token(&TokenType::OVERRIDE) { - is_override = true; - self.advance(); - } - - // initトークンをメソッド名として特別処理 - if self.match_token(&TokenType::INIT) && self.peek_token() == &TokenType::LPAREN { - let field_or_method = "init".to_string(); - self.advance(); // consume 'init' - - // コンストラクタとして処理 - if self.match_token(&TokenType::LPAREN) { - // initは常にコンストラクタ - if is_override { - return Err(ParseError::UnexpectedToken { - expected: "method definition, not constructor after override keyword".to_string(), - found: TokenType::INIT, - line: self.current_token().line, - }); - } - // コンストラクタの処理 - self.advance(); // consume '(' - - let mut params = Vec::new(); - while !self.match_token(&TokenType::RPAREN) && !self.is_at_end() { - must_advance!(self, _unused, "constructor 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(); - } - } - - self.consume(TokenType::RPAREN)?; - self.consume(TokenType::LBRACE)?; - - 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)?; - - let constructor = ASTNode::FunctionDeclaration { - name: field_or_method.clone(), - params: params.clone(), - body, - is_static: false, - is_override: false, + // 左辺が代入可能な形式かチェック + match &expr { + ASTNode::Variable { .. } | + ASTNode::FieldAccess { .. } => { + Ok(ASTNode::Assignment { + target: Box::new(expr), + value, span: Span::unknown(), - }; - - // パラメータの数でコンストラクタを区別 - let constructor_key = format!("{}/{}", field_or_method, params.len()); - constructors.insert(constructor_key, constructor); + }) + } + _ => { + let line = self.current_token().line; + Err(ParseError::InvalidStatement { line }) } } - - // packトークンをメソッド名として特別処理 - else if self.match_token(&TokenType::PACK) && self.peek_token() == &TokenType::LPAREN { - let field_or_method = "pack".to_string(); - self.advance(); // consume 'pack' - - // コンストラクタとして処理 - if self.match_token(&TokenType::LPAREN) { - // packは常にコンストラクタ - if is_override { - return Err(ParseError::UnexpectedToken { - expected: "method definition, not constructor after override keyword".to_string(), - found: TokenType::PACK, - line: self.current_token().line, - }); - } - // コンストラクタの処理 - self.advance(); // consume '(' - - let mut params = Vec::new(); - while !self.match_token(&TokenType::RPAREN) && !self.is_at_end() { - must_advance!(self, _unused, "constructor 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(); - } - } - - self.consume(TokenType::RPAREN)?; - self.consume(TokenType::LBRACE)?; - - 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)?; - - let constructor = ASTNode::FunctionDeclaration { - name: field_or_method.clone(), - params: params.clone(), - body, - is_static: false, - is_override: false, - span: Span::unknown(), - }; - - // パラメータの数でコンストラクタを区別 - let constructor_key = format!("{}/{}", field_or_method, params.len()); - constructors.insert(constructor_key, constructor); - } - } - - // birthトークンをメソッド名として特別処理 - else if self.match_token(&TokenType::BIRTH) && self.peek_token() == &TokenType::LPAREN { - let field_or_method = "birth".to_string(); - self.advance(); // consume 'birth' - - // コンストラクタとして処理 - if self.match_token(&TokenType::LPAREN) { - // birthは常にコンストラクタ - if is_override { - return Err(ParseError::UnexpectedToken { - expected: "method definition, not constructor after override keyword".to_string(), - found: TokenType::BIRTH, - line: self.current_token().line, - }); - } - // コンストラクタの処理 - self.advance(); // consume '(' - - let mut params = Vec::new(); - while !self.match_token(&TokenType::RPAREN) && !self.is_at_end() { - must_advance!(self, _unused, "constructor 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(); - } - } - - self.consume(TokenType::RPAREN)?; - self.consume(TokenType::LBRACE)?; - - 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)?; - - let constructor = ASTNode::FunctionDeclaration { - name: field_or_method.clone(), - params: params.clone(), - body, - is_static: false, - is_override: false, - span: Span::unknown(), - }; - - // パラメータの数でコンストラクタを区別 - let constructor_key = format!("{}/{}", field_or_method, params.len()); - constructors.insert(constructor_key, constructor); - } - } else if let TokenType::IDENTIFIER(field_or_method) = &self.current_token().token_type { - let field_or_method = field_or_method.clone(); - self.advance(); - - // メソッド定義またはコンストラクタか? - if self.match_token(&TokenType::LPAREN) { - // Box名と同じまたは"init"または"pack"または"birth"の場合はコンストラクタ - if field_or_method == name || field_or_method == "init" || field_or_method == "pack" || field_or_method == "birth" { - // コンストラクタはoverrideできない - if is_override { - return Err(ParseError::UnexpectedToken { - expected: "method definition, not constructor after override keyword".to_string(), - found: TokenType::IDENTIFIER(field_or_method.clone()), - line: self.current_token().line, - }); - } - // コンストラクタの処理 - self.advance(); // consume '(' - - let mut params = Vec::new(); - while !self.match_token(&TokenType::RPAREN) && !self.is_at_end() { - must_advance!(self, _unused, "constructor 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(); - } - } - - self.consume(TokenType::RPAREN)?; - self.consume(TokenType::LBRACE)?; - - 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)?; - - let constructor = ASTNode::FunctionDeclaration { - name: field_or_method.clone(), - params: params.clone(), - body, - is_static: false, // コンストラクタは静的でない - is_override: false, // デフォルトは非オーバーライド - span: Span::unknown(), - }; - - // パラメータの数でコンストラクタを区別 - let constructor_key = format!("{}/{}", field_or_method, params.len()); - constructors.insert(constructor_key, constructor); - } else { - // 通常のメソッド定義 - self.advance(); // consume '(' - - let mut params = Vec::new(); - while !self.match_token(&TokenType::RPAREN) && !self.is_at_end() { - must_advance!(self, _unused, "box method 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(); - // カンマの後に閉じ括弧があるかチェック(trailing comma) - } - } else if !self.match_token(&TokenType::RPAREN) { - // IDENTIFIERでもRPARENでもない場合はエラー - let line = self.current_token().line; - return Err(ParseError::UnexpectedToken { - found: self.current_token().token_type.clone(), - expected: "parameter name or ')'".to_string(), - line, - }); - } - } - - self.consume(TokenType::RPAREN)?; - self.consume(TokenType::LBRACE)?; - - 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)?; - - let method = ASTNode::FunctionDeclaration { - name: field_or_method.clone(), - params, - body, - is_static: false, // メソッドは通常静的でない - is_override, // overrideキーワードの有無を反映 - span: Span::unknown(), - }; - - methods.insert(field_or_method, method); - } - } else { - // フィールド定義 - if is_override { - return Err(ParseError::UnexpectedToken { - expected: "method definition after override keyword".to_string(), - found: self.current_token().token_type.clone(), - line: self.current_token().line, - }); - } - fields.push(field_or_method); - } - self.skip_newlines(); // フィールド/メソッド定義後の改行をスキップ - } else { - // 予期しないトークンの場合、詳細なエラー情報を出力してスキップ - let line = self.current_token().line; - eprintln!("Debug: Unexpected token {:?} at line {}", self.current_token().token_type, line); - self.advance(); // トークンをスキップして続行 - } + } else { + // 代入文でなければ式文として返す + Ok(expr) } - - self.consume(TokenType::RBRACE)?; - - // 🔍 デリゲーションメソッドチェック:親Boxに存在しないメソッドのoverride検出 - if !extends.is_empty() { - // For multi-delegation, validate against all parents - for parent_name in &extends { - self.validate_override_methods(&name, parent_name, &methods)?; - } - } - - Ok(ASTNode::BoxDeclaration { - name, - fields, - methods, - constructors, - init_fields, - weak_fields, // 🔗 Add weak fields to the construction - is_interface: false, - extends, - implements, - type_parameters, - is_static: false, - static_init: None, - span: Span::unknown(), - }) } - /// インターフェースBox宣言をパース: interface box Name { method1() method2() } - fn parse_interface_box_declaration(&mut self) -> Result { - self.consume(TokenType::INTERFACE)?; - self.consume(TokenType::BOX)?; - - 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::LBRACE)?; - self.skip_newlines(); // ブレース後の改行をスキップ - - let mut methods = HashMap::new(); - - while !self.match_token(&TokenType::RBRACE) && !self.is_at_end() { - self.skip_newlines(); // ループ開始時に改行をスキップ - if let TokenType::IDENTIFIER(method_name) = &self.current_token().token_type { - let method_name = method_name.clone(); - self.advance(); - - // インターフェースメソッドはシグネチャのみ - if self.match_token(&TokenType::LPAREN) { - self.advance(); // consume '(' - - let mut params = Vec::new(); - while !self.match_token(&TokenType::RPAREN) && !self.is_at_end() { - if let TokenType::IDENTIFIER(param) = &self.current_token().token_type { - params.push(param.clone()); - self.advance(); - } - - if self.match_token(&TokenType::COMMA) { - self.advance(); - } - } - - self.consume(TokenType::RPAREN)?; - - // インターフェースメソッドは実装なし(空のbody) - let method_decl = ASTNode::FunctionDeclaration { - name: method_name.clone(), - params, - body: vec![], // 空の実装 - is_static: false, // インターフェースメソッドは通常静的でない - is_override: false, // デフォルトは非オーバーライド - span: Span::unknown(), - }; - - methods.insert(method_name, method_decl); - - // メソッド宣言後の改行をスキップ - self.skip_newlines(); - } else { - let line = self.current_token().line; - return Err(ParseError::UnexpectedToken { - found: self.current_token().token_type.clone(), - expected: "(".to_string(), - line, - }); - } - } else { - let line = self.current_token().line; - return Err(ParseError::UnexpectedToken { - found: self.current_token().token_type.clone(), - expected: "method name".to_string(), - line, - }); - } - } - - self.consume(TokenType::RBRACE)?; - - Ok(ASTNode::BoxDeclaration { - name, - fields: vec![], // インターフェースはフィールドなし - methods, - constructors: HashMap::new(), // インターフェースにコンストラクタなし - init_fields: vec![], // インターフェースにinitブロックなし - weak_fields: vec![], // 🔗 インターフェースにweak fieldsなし - is_interface: true, // インターフェースフラグ - extends: vec![], // 🚀 Multi-delegation: Changed from None to vec![] - implements: vec![], - type_parameters: Vec::new(), // 🔥 インターフェースではジェネリクス未対応 - is_static: false, // インターフェースは非static - static_init: None, // インターフェースにstatic initなし - span: Span::unknown(), - }) - } + // 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)?; @@ -820,7 +246,6 @@ impl NyashParser { Ok(ASTNode::GlobalVar { name, value, span: Span::unknown() }) } - // Statement parsing methods are now in statements.rs module /// function宣言をパース: function name(params) { body } fn parse_function_declaration(&mut self) -> Result { @@ -973,11 +398,11 @@ impl NyashParser { // 関数本体をパース self.consume(TokenType::LBRACE)?; - self.skip_newlines(); // ブレースの後の改行をスキップ + self.skip_newlines(); let mut body = Vec::new(); while !self.match_token(&TokenType::RBRACE) && !self.is_at_end() { - self.skip_newlines(); // ループ開始時の改行をスキップ + self.skip_newlines(); if !self.match_token(&TokenType::RBRACE) { body.push(self.parse_statement()?); } @@ -994,488 +419,4 @@ impl NyashParser { span: Span::unknown(), }) } - - /// 静的Box宣言をパース - static box Name { ... } - fn parse_static_box(&mut self) -> Result { - self.consume(TokenType::BOX)?; - - 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, - }); - }; - - // 🔥 ジェネリクス型パラメータのパース () - let type_parameters = if self.match_token(&TokenType::LESS) { - self.advance(); // consume '<' - let mut params = Vec::new(); - - loop { - if let TokenType::IDENTIFIER(param_name) = &self.current_token().token_type { - params.push(param_name.clone()); - self.advance(); - - if self.match_token(&TokenType::COMMA) { - self.advance(); // consume ',' - } else { - break; - } - } else { - let line = self.current_token().line; - return Err(ParseError::UnexpectedToken { - found: self.current_token().token_type.clone(), - expected: "type parameter name".to_string(), - line, - }); - } - } - - self.consume(TokenType::GREATER)?; // consume '>' - params - } else { - Vec::new() - }; - - // from句のパース(Multi-delegation)- static boxでもデリゲーション可能 🚀 - let extends = if self.match_token(&TokenType::FROM) { - self.advance(); // consume 'from' - - let mut parent_list = Vec::new(); - - loop { - if let TokenType::IDENTIFIER(parent_name) = &self.current_token().token_type { - parent_list.push(parent_name.clone()); - self.advance(); - - if self.match_token(&TokenType::COMMA) { - self.advance(); // consume ',' - } else { - break; - } - } else { - let line = self.current_token().line; - return Err(ParseError::UnexpectedToken { - found: self.current_token().token_type.clone(), - expected: "parent class name".to_string(), - line, - }); - } - } - - parent_list - } else { - Vec::new() - }; - - // interface句のパース(インターフェース実装)- static boxでもinterface実装可能 - let implements = if self.match_token(&TokenType::INTERFACE) { - self.advance(); // consume 'interface' - - let mut interface_list = Vec::new(); - - loop { - if let TokenType::IDENTIFIER(interface_name) = &self.current_token().token_type { - interface_list.push(interface_name.clone()); - self.advance(); - - if self.match_token(&TokenType::COMMA) { - self.advance(); // consume ',' - } else { - break; - } - } else { - let line = self.current_token().line; - return Err(ParseError::UnexpectedToken { - found: self.current_token().token_type.clone(), - expected: "interface name".to_string(), - line, - }); - } - } - - interface_list - } else { - vec![] - }; - - self.consume(TokenType::LBRACE)?; - self.skip_newlines(); // ブレース後の改行をスキップ - - let mut fields = Vec::new(); - let mut methods = HashMap::new(); - let constructors = HashMap::new(); - let mut init_fields = Vec::new(); - let mut weak_fields = Vec::new(); // 🔗 Track weak fields for static box - let mut static_init = None; - - while !self.match_token(&TokenType::RBRACE) && !self.is_at_end() { - self.skip_newlines(); // ループ開始時に改行をスキップ - - // RBRACEに到達していればループを抜ける - if self.match_token(&TokenType::RBRACE) { - break; - } - - // 🔥 static { } ブロックの処理 - if self.match_token(&TokenType::STATIC) { - self.advance(); // consume 'static' - self.consume(TokenType::LBRACE)?; - - let mut static_body = Vec::new(); - while !self.match_token(&TokenType::RBRACE) && !self.is_at_end() { - self.skip_newlines(); - if !self.match_token(&TokenType::RBRACE) { - static_body.push(self.parse_statement()?); - } - } - - self.consume(TokenType::RBRACE)?; - static_init = Some(static_body); - continue; - } - - // initブロックの処理 - if self.match_token(&TokenType::INIT) { - self.advance(); // consume 'init' - self.consume(TokenType::LBRACE)?; - - // initブロック内のフィールド定義を読み込み - while !self.match_token(&TokenType::RBRACE) && !self.is_at_end() { - self.skip_newlines(); - - if self.match_token(&TokenType::RBRACE) { - break; - } - - // Check for weak modifier - let is_weak = if self.match_token(&TokenType::WEAK) { - self.advance(); // consume 'weak' - true - } else { - false - }; - - if let TokenType::IDENTIFIER(field_name) = &self.current_token().token_type { - init_fields.push(field_name.clone()); - if is_weak { - weak_fields.push(field_name.clone()); // 🔗 Add to weak fields list - } - self.advance(); - - // カンマがあればスキップ - if self.match_token(&TokenType::COMMA) { - self.advance(); - } - } else { - // 不正なトークンがある場合はエラー - return Err(ParseError::UnexpectedToken { - expected: if is_weak { "field name after 'weak'" } else { "field name" }.to_string(), - found: self.current_token().token_type.clone(), - line: self.current_token().line, - }); - } - } - - self.consume(TokenType::RBRACE)?; - continue; - } - - if let TokenType::IDENTIFIER(field_or_method) = &self.current_token().token_type { - let field_or_method = field_or_method.clone(); - self.advance(); - - // メソッド定義か? - if self.match_token(&TokenType::LPAREN) { - // メソッド定義 - self.advance(); // consume '(' - - let mut params = Vec::new(); - while !self.match_token(&TokenType::RPAREN) && !self.is_at_end() { - if let TokenType::IDENTIFIER(param) = &self.current_token().token_type { - params.push(param.clone()); - self.advance(); - } - - if self.match_token(&TokenType::COMMA) { - self.advance(); - } - } - - self.consume(TokenType::RPAREN)?; - self.consume(TokenType::LBRACE)?; - - 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)?; - - let method = ASTNode::FunctionDeclaration { - name: field_or_method.clone(), - params, - body, - is_static: false, // static box内のメソッドは通常メソッド - is_override: false, // デフォルトは非オーバーライド - span: Span::unknown(), - }; - - methods.insert(field_or_method, method); - } else { - // フィールド定義 - fields.push(field_or_method); - } - } else { - return Err(ParseError::UnexpectedToken { - expected: "method or field name".to_string(), - found: self.current_token().token_type.clone(), - line: self.current_token().line, - }); - } - } - - self.consume(TokenType::RBRACE)?; - - // 🔥 Static初期化ブロックから依存関係を抽出 - if let Some(ref init_stmts) = static_init { - let dependencies = self.extract_dependencies_from_statements(init_stmts); - self.static_box_dependencies.insert(name.clone(), dependencies); - } else { - self.static_box_dependencies.insert(name.clone(), std::collections::HashSet::new()); - } - - Ok(ASTNode::BoxDeclaration { - name, - fields, - methods, - constructors, - init_fields, - weak_fields, // 🔗 Add weak fields to static box construction - is_interface: false, - extends, - implements, - type_parameters, - is_static: true, // 🔥 static boxフラグを設定 - static_init, // 🔥 static初期化ブロック - span: Span::unknown(), - }) - } - - /// 代入文または関数呼び出しをパース - 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循環依存検出 ===== - - /// Static初期化ブロック内の文から依存関係を抽出 - fn extract_dependencies_from_statements(&self, statements: &[ASTNode]) -> std::collections::HashSet { - let mut dependencies = std::collections::HashSet::new(); - - for stmt in statements { - self.extract_dependencies_from_ast(stmt, &mut dependencies); - } - - dependencies - } - - /// AST内から静的Box参照を再帰的に検出 - fn extract_dependencies_from_ast(&self, node: &ASTNode, dependencies: &mut std::collections::HashSet) { - match node { - ASTNode::FieldAccess { object, .. } => { - // Math.PI のような参照を検出 - if let ASTNode::Variable { name, .. } = object.as_ref() { - dependencies.insert(name.clone()); - } - } - ASTNode::MethodCall { object, .. } => { - // Config.getDebug() のような呼び出しを検出 - if let ASTNode::Variable { name, .. } = object.as_ref() { - dependencies.insert(name.clone()); - } - } - ASTNode::Assignment { target, value, .. } => { - self.extract_dependencies_from_ast(target, dependencies); - self.extract_dependencies_from_ast(value, dependencies); - } - ASTNode::BinaryOp { left, right, .. } => { - self.extract_dependencies_from_ast(left, dependencies); - self.extract_dependencies_from_ast(right, dependencies); - } - ASTNode::UnaryOp { operand, .. } => { - self.extract_dependencies_from_ast(operand, dependencies); - } - ASTNode::If { condition, then_body, else_body, .. } => { - self.extract_dependencies_from_ast(condition, dependencies); - for stmt in then_body { - self.extract_dependencies_from_ast(stmt, dependencies); - } - if let Some(else_stmts) = else_body { - for stmt in else_stmts { - self.extract_dependencies_from_ast(stmt, dependencies); - } - } - } - ASTNode::Loop { condition, body, .. } => { - self.extract_dependencies_from_ast(condition, dependencies); - for stmt in body { - self.extract_dependencies_from_ast(stmt, dependencies); - } - } - ASTNode::Return { value, .. } => { - if let Some(val) = value { - self.extract_dependencies_from_ast(val, dependencies); - } - } - ASTNode::Print { expression, .. } => { - self.extract_dependencies_from_ast(expression, dependencies); - } - // 他のAST nodeタイプも必要に応じて追加 - _ => {} - } - } - - /// 循環依存検出(深さ優先探索) - fn check_circular_dependencies(&self) -> Result<(), ParseError> { - let mut visited = std::collections::HashSet::new(); - let mut rec_stack = std::collections::HashSet::new(); - let mut path = Vec::new(); - - for box_name in self.static_box_dependencies.keys() { - if !visited.contains(box_name) { - if self.has_cycle_dfs(box_name, &mut visited, &mut rec_stack, &mut path)? { - return Ok(()); // エラーは既にhas_cycle_dfs内で返される - } - } - } - - Ok(()) - } - - /// DFS による循環依存検出 - fn has_cycle_dfs( - &self, - current: &str, - visited: &mut std::collections::HashSet, - rec_stack: &mut std::collections::HashSet, - path: &mut Vec, - ) -> Result { - visited.insert(current.to_string()); - rec_stack.insert(current.to_string()); - path.push(current.to_string()); - - if let Some(dependencies) = self.static_box_dependencies.get(current) { - for dependency in dependencies { - if !visited.contains(dependency) { - if self.has_cycle_dfs(dependency, visited, rec_stack, path)? { - return Ok(true); - } - } else if rec_stack.contains(dependency) { - // 循環依存を発見! - let cycle_start_pos = path.iter().position(|x| x == dependency).unwrap_or(0); - let cycle_path: Vec = path[cycle_start_pos..].iter().cloned().collect(); - let cycle_display = format!("{} -> {}", cycle_path.join(" -> "), dependency); - - return Err(ParseError::CircularDependency { - cycle: cycle_display - }); - } - } - } - - rec_stack.remove(current); - path.pop(); - Ok(false) - } - - /// 🔍 デリゲーションメソッドチェック:親Boxに存在しないメソッドのoverride検出 - /// Phase 1: 基本的なoverride構文チェック - /// Phase 2 (将来実装): 完全な親Box参照によるメソッド存在チェック - fn validate_override_methods(&self, child_name: &str, parent_name: &str, methods: &HashMap) -> Result<(), ParseError> { - let mut override_count = 0; - - // 🚨 override付きメソッドのチェック - for (method_name, method_node) in methods { - if let ASTNode::FunctionDeclaration { is_override, .. } = method_node { - if *is_override { - override_count += 1; - eprintln!("🔍 DEBUG: Found override method '{}' in '{}' extending '{}'", - method_name, child_name, parent_name); - - // Phase 1: 基本的な危険パターンチェック - // 明らかに存在しないであろうメソッド名をチェック - let suspicious_methods = [ - "nonExistentMethod", "invalidMethod", "fakeMethod", - "notRealMethod", "testFailureMethod" - ]; - - if suspicious_methods.contains(&method_name.as_str()) { - return Err(ParseError::UnexpectedToken { - found: TokenType::OVERRIDE, - expected: format!("🚨 OVERRIDE ERROR: Method '{}' appears to be invalid. Check if this method exists in parent '{}'.", method_name, parent_name), - line: 0, - }); - } - - // 🎯 基本的なメソッド名バリデーション - if method_name.is_empty() { - return Err(ParseError::UnexpectedToken { - found: TokenType::OVERRIDE, - expected: "🚨 OVERRIDE ERROR: Method name cannot be empty.".to_string(), - line: 0, - }); - } - } - } - } - - // ✅ チェック完了レポート - if override_count > 0 { - eprintln!("✅ DEBUG: Override validation completed for '{}' extending '{}' - {} override method(s) found", - child_name, parent_name, override_count); - } - - Ok(()) - } } -