Files
hakorune/src/parser/expressions.rs
Moe Charm c13d9c045e 📚 Phase 12: Nyashスクリプトプラグインシステム設計と埋め込みVM構想
## 主な成果
- Nyashスクリプトでプラグイン作成可能という革命的発見
- C ABI制約の分析と埋め込みVMによる解決策
- MIR/VM/JIT層での箱引数サポートの詳細分析

## ドキュメント作成
- Phase 12基本構想(README.md)
- Gemini/Codex先生の技術分析
- C ABIとの整合性問題と解決策
- 埋め込みVM実装ロードマップ
- 箱引数サポートの技術詳細

## 重要な洞察
- 制約は「リンク時にC ABI必要」のみ
- 埋め込みVMでMIRバイトコード実行により解決可能
- Nyashスクリプト→C ABIプラグイン変換が実現可能

Everything is Box → Everything is Plugin → Everything is Possible!
2025-08-30 22:52:16 +09:00

563 lines
21 KiB
Rust
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*!
* Nyash Parser - Expression Parsing Module
*
*Expressionの解析を担当するモジュール
* 演算子の優先順位に従った再帰下降パーサー実装
*/
use crate::tokenizer::TokenType;
use crate::ast::{ASTNode, BinaryOperator, LiteralValue, UnaryOperator, Span};
use super::{NyashParser, ParseError};
use super::common::ParserUtils;
// Debug macros are now imported from the parent module via #[macro_export]
use crate::must_advance;
impl NyashParser {
/// 式をパース (演算子優先順位あり)
pub(super) fn parse_expression(&mut self) -> Result<ASTNode, ParseError> {
self.parse_or()
}
/// OR演算子をパース: ||
fn parse_or(&mut self) -> Result<ASTNode, ParseError> {
let mut expr = self.parse_and()?;
while self.match_token(&TokenType::OR) {
let operator = BinaryOperator::Or;
self.advance();
let right = self.parse_and()?;
expr = ASTNode::BinaryOp {
operator,
left: Box::new(expr),
right: Box::new(right),
span: Span::unknown(),
};
}
Ok(expr)
}
/// AND演算子をパース: &&
fn parse_and(&mut self) -> Result<ASTNode, ParseError> {
let mut expr = self.parse_equality()?;
while self.match_token(&TokenType::AND) {
let operator = BinaryOperator::And;
self.advance();
let right = self.parse_equality()?;
expr = ASTNode::BinaryOp {
operator,
left: Box::new(expr),
right: Box::new(right),
span: Span::unknown(),
};
}
Ok(expr)
}
/// 等値演算子をパース: == !=
fn parse_equality(&mut self) -> Result<ASTNode, ParseError> {
let mut expr = self.parse_comparison()?;
while self.match_token(&TokenType::EQUALS) || self.match_token(&TokenType::NotEquals) {
let operator = match &self.current_token().token_type {
TokenType::EQUALS => BinaryOperator::Equal,
TokenType::NotEquals => BinaryOperator::NotEqual,
_ => unreachable!(),
};
self.advance();
let right = self.parse_comparison()?;
expr = ASTNode::BinaryOp {
operator,
left: Box::new(expr),
right: Box::new(right),
span: Span::unknown(),
};
}
Ok(expr)
}
/// 比較演算子をパース: < <= > >=
fn parse_comparison(&mut self) -> Result<ASTNode, ParseError> {
let mut expr = self.parse_term()?;
while self.match_token(&TokenType::LESS) ||
self.match_token(&TokenType::LessEquals) ||
self.match_token(&TokenType::GREATER) ||
self.match_token(&TokenType::GreaterEquals) {
let operator = match &self.current_token().token_type {
TokenType::LESS => BinaryOperator::Less,
TokenType::LessEquals => BinaryOperator::LessEqual,
TokenType::GREATER => BinaryOperator::Greater,
TokenType::GreaterEquals => BinaryOperator::GreaterEqual,
_ => unreachable!(),
};
self.advance();
let right = self.parse_term()?;
expr = ASTNode::BinaryOp {
operator,
left: Box::new(expr),
right: Box::new(right),
span: Span::unknown(),
};
}
Ok(expr)
}
/// 項をパース: + - >>
fn parse_term(&mut self) -> Result<ASTNode, ParseError> {
let mut expr = self.parse_factor()?;
while self.match_token(&TokenType::PLUS) || self.match_token(&TokenType::MINUS) || self.match_token(&TokenType::ARROW) {
if self.match_token(&TokenType::ARROW) {
// >> Arrow演算子
self.advance();
let right = self.parse_factor()?;
expr = ASTNode::Arrow {
sender: Box::new(expr),
receiver: Box::new(right),
span: Span::unknown(),
};
} else {
let operator = match &self.current_token().token_type {
TokenType::PLUS => BinaryOperator::Add,
TokenType::MINUS => BinaryOperator::Subtract,
_ => unreachable!(),
};
self.advance();
let right = self.parse_factor()?;
expr = ASTNode::BinaryOp {
operator,
left: Box::new(expr),
right: Box::new(right),
span: Span::unknown(),
};
}
}
Ok(expr)
}
/// 因子をパース: * /
fn parse_factor(&mut self) -> Result<ASTNode, ParseError> {
let mut expr = self.parse_unary()?;
while self.match_token(&TokenType::MULTIPLY) || self.match_token(&TokenType::DIVIDE) || self.match_token(&TokenType::MODULO) {
let operator = match &self.current_token().token_type {
TokenType::MULTIPLY => BinaryOperator::Multiply,
TokenType::DIVIDE => BinaryOperator::Divide,
TokenType::MODULO => BinaryOperator::Modulo,
_ => unreachable!(),
};
self.advance();
let right = self.parse_unary()?;
expr = ASTNode::BinaryOp {
operator,
left: Box::new(expr),
right: Box::new(right),
span: Span::unknown(),
};
}
Ok(expr)
}
/// 単項演算子をパース
fn parse_unary(&mut self) -> Result<ASTNode, ParseError> {
if self.match_token(&TokenType::MINUS) {
self.advance(); // consume '-'
let operand = self.parse_unary()?; // 再帰的に単項演算をパース
return Ok(ASTNode::UnaryOp {
operator: UnaryOperator::Minus,
operand: Box::new(operand),
span: Span::unknown(),
});
}
if self.match_token(&TokenType::NOT) {
self.advance(); // consume 'not'
let operand = self.parse_unary()?; // 再帰的に単項演算をパース
return Ok(ASTNode::UnaryOp {
operator: UnaryOperator::Not,
operand: Box::new(operand),
span: Span::unknown(),
});
}
if self.match_token(&TokenType::AWAIT) {
self.advance(); // consume 'await'
let expression = self.parse_unary()?; // 再帰的にパース
return Ok(ASTNode::AwaitExpression {
expression: Box::new(expression),
span: Span::unknown(),
});
}
self.parse_call()
}
/// 関数・メソッド呼び出しをパース
fn parse_call(&mut self) -> Result<ASTNode, ParseError> {
let mut expr = self.parse_primary()?;
loop {
if self.match_token(&TokenType::DOT) {
self.advance(); // consume '.'
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) {
// メソッド呼び出し: obj.method(args)
self.advance(); // consume '('
let mut arguments = Vec::new();
let mut _arg_count = 0;
while !self.match_token(&TokenType::RPAREN) && !self.is_at_end() {
must_advance!(self, _unused, "method call argument parsing");
arguments.push(self.parse_expression()?);
_arg_count += 1;
if self.match_token(&TokenType::COMMA) {
self.advance();
// カンマの後の trailing comma をチェック
}
}
self.consume(TokenType::RPAREN)?;
expr = ASTNode::MethodCall {
object: Box::new(expr),
method: method_name,
arguments,
span: Span::unknown(),
};
} else {
// フィールドアクセス: obj.field
expr = ASTNode::FieldAccess {
object: Box::new(expr),
field: method_name,
span: Span::unknown(),
};
}
} else {
let line = self.current_token().line;
return Err(ParseError::UnexpectedToken {
found: self.current_token().token_type.clone(),
expected: "identifier".to_string(),
line,
});
}
} else if self.match_token(&TokenType::LPAREN) {
// 関数呼び出し: function(args)
if let ASTNode::Variable { name, .. } = expr {
self.advance(); // consume '('
let mut arguments = Vec::new();
while !self.match_token(&TokenType::RPAREN) && !self.is_at_end() {
must_advance!(self, _unused, "function call argument parsing");
arguments.push(self.parse_expression()?);
if self.match_token(&TokenType::COMMA) {
self.advance();
}
}
self.consume(TokenType::RPAREN)?;
expr = ASTNode::FunctionCall { name, arguments, span: Span::unknown() };
} else {
break;
}
} else {
break;
}
}
Ok(expr)
}
/// 基本式をパース: リテラル、変数、括弧、this、new
fn parse_primary(&mut self) -> Result<ASTNode, ParseError> {
match &self.current_token().token_type {
TokenType::INCLUDE => {
// Allow include as an expression: include "path"
self.parse_include()
}
TokenType::STRING(s) => {
let value = s.clone();
self.advance();
// 🌟 文字列リテラル自動変換: "text" → new StringBox("text")
Ok(ASTNode::New {
class: "StringBox".to_string(),
arguments: vec![ASTNode::Literal {
value: LiteralValue::String(value),
span: Span::unknown(),
}],
type_arguments: vec![],
span: Span::unknown(),
})
}
TokenType::NUMBER(n) => {
let value = *n;
self.advance();
// 🌟 整数リテラル自動変換: 42 → new IntegerBox(42)
Ok(ASTNode::New {
class: "IntegerBox".to_string(),
arguments: vec![ASTNode::Literal {
value: LiteralValue::Integer(value),
span: Span::unknown(),
}],
type_arguments: vec![],
span: Span::unknown(),
})
}
TokenType::FLOAT(f) => {
let value = *f;
self.advance();
// 🌟 浮動小数点リテラル自動変換: 3.14 → new FloatBox(3.14)
Ok(ASTNode::New {
class: "FloatBox".to_string(),
arguments: vec![ASTNode::Literal {
value: LiteralValue::Float(value),
span: Span::unknown(),
}],
type_arguments: vec![],
span: Span::unknown(),
})
}
TokenType::TRUE => {
self.advance();
// 🌟 真偽値リテラル自動変換: true → new BoolBox(true)
Ok(ASTNode::New {
class: "BoolBox".to_string(),
arguments: vec![ASTNode::Literal {
value: LiteralValue::Bool(true),
span: Span::unknown(),
}],
type_arguments: vec![],
span: Span::unknown(),
})
}
TokenType::FALSE => {
self.advance();
// 🌟 真偽値リテラル自動変換: false → new BoolBox(false)
Ok(ASTNode::New {
class: "BoolBox".to_string(),
arguments: vec![ASTNode::Literal {
value: LiteralValue::Bool(false),
span: Span::unknown(),
}],
type_arguments: vec![],
span: Span::unknown(),
})
}
TokenType::NULL => {
self.advance();
Ok(ASTNode::Literal {
value: LiteralValue::Null,
span: Span::unknown(),
})
}
TokenType::THIS => {
self.advance();
Ok(ASTNode::This { span: Span::unknown() })
}
TokenType::ME => {
self.advance();
Ok(ASTNode::Me { span: Span::unknown() })
}
TokenType::NEW => {
self.advance();
if let TokenType::IDENTIFIER(class_name) = &self.current_token().token_type {
let class_name = class_name.clone();
self.advance();
// 🔥 ジェネリクス型引数のパース (<IntegerBox, StringBox>)
let type_arguments = if self.match_token(&TokenType::LESS) {
self.advance(); // consume '<'
let mut args = Vec::new();
loop {
if let TokenType::IDENTIFIER(type_name) = &self.current_token().token_type {
args.push(type_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 argument".to_string(),
line,
});
}
}
self.consume(TokenType::GREATER)?; // consume '>'
args
} else {
Vec::new()
};
self.consume(TokenType::LPAREN)?;
let mut arguments = Vec::new();
while !self.match_token(&TokenType::RPAREN) && !self.is_at_end() {
must_advance!(self, _unused, "new expression argument parsing");
arguments.push(self.parse_expression()?);
if self.match_token(&TokenType::COMMA) {
self.advance();
}
}
self.consume(TokenType::RPAREN)?;
Ok(ASTNode::New {
class: class_name,
arguments,
type_arguments,
span: Span::unknown(),
})
} else {
let line = self.current_token().line;
Err(ParseError::UnexpectedToken {
found: self.current_token().token_type.clone(),
expected: "class name".to_string(),
line,
})
}
}
TokenType::FROM => {
// from構文をパース: from Parent.method(arguments)
self.parse_from_call()
}
TokenType::IDENTIFIER(name) => {
let name = name.clone();
self.advance();
Ok(ASTNode::Variable { name, span: Span::unknown() })
}
TokenType::LPAREN => {
self.advance(); // consume '('
let expr = self.parse_expression()?;
self.consume(TokenType::RPAREN)?;
Ok(expr)
}
_ => {
let line = self.current_token().line;
Err(ParseError::InvalidExpression { line })
}
}
}
/// from構文をパース: from Parent.method(arguments)
pub(super) fn parse_from_call(&mut self) -> Result<ASTNode, ParseError> {
self.advance(); // consume 'from'
// Parent名を取得
let parent = 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: "parent class name".to_string(),
line,
});
};
// DOT とmethod名は任意pack透明化対応
let method = if self.match_token(&TokenType::DOT) {
// DOTがある場合: from Parent.method() 形式
self.advance(); // consume DOT
// method名を取得 (IDENTIFIERまたはINITを受け入れ)
match &self.current_token().token_type {
TokenType::IDENTIFIER(name) => {
let name = name.clone();
self.advance();
name
}
TokenType::INIT => {
self.advance();
"init".to_string()
}
TokenType::PACK => {
self.advance();
"pack".to_string()
}
TokenType::BIRTH => {
self.advance();
"birth".to_string()
}
_ => {
let line = self.current_token().line;
return Err(ParseError::UnexpectedToken {
found: self.current_token().token_type.clone(),
expected: "method name".to_string(),
line,
});
}
}
} else {
// DOTがない場合: from Parent() 形式 - 透明化システム廃止
// Phase 8.9: 明示的birth()構文を強制
let line = self.current_token().line;
return Err(ParseError::TransparencySystemRemoved {
suggestion: format!("Use 'from {}.birth()' instead of 'from {}()'", parent, parent),
line,
});
};
// 引数リストをパース
self.consume(TokenType::LPAREN)?;
let mut arguments = Vec::new();
while !self.match_token(&TokenType::RPAREN) && !self.is_at_end() {
must_advance!(self, _unused, "from call argument parsing");
arguments.push(self.parse_expression()?);
if self.match_token(&TokenType::COMMA) {
self.advance();
// カンマの後の trailing comma をチェック
}
}
self.consume(TokenType::RPAREN)?;
Ok(ASTNode::FromCall {
parent,
method,
arguments,
span: Span::unknown(),
})
}
}