parser(cursor): Step‑2 cont. – unary (-/not) and postfix chain in TokenCursor path; parity tests for precedence and unary; quick/core remains green under env toggle

This commit is contained in:
Selfhosting Dev
2025-09-25 06:33:40 +09:00
parent b66fafde62
commit f6fcc64074
3 changed files with 62 additions and 2 deletions

View File

@ -116,12 +116,12 @@ impl ExprParserWithCursor {
/// 乗算式をパース
fn parse_multiplicative_expr(cursor: &mut TokenCursor) -> Result<ASTNode, ParseError> {
let mut left = Self::parse_postfix_expr(cursor)?;
let mut left = Self::parse_unary_expr(cursor)?;
while let Some(op) = Self::match_multiplicative_op(cursor) {
let op_line = cursor.current().line;
cursor.advance();
let right = Self::parse_postfix_expr(cursor)?;
let right = Self::parse_unary_expr(cursor)?;
left = ASTNode::BinaryOp {
operator: op,
left: Box::new(left),
@ -133,6 +133,34 @@ impl ExprParserWithCursor {
Ok(left)
}
/// 単項演算子(- / not
fn parse_unary_expr(cursor: &mut TokenCursor) -> Result<ASTNode, ParseError> {
// match式は旧系にあるが、ここでは単項の最小対応に限定
match &cursor.current().token_type {
TokenType::MINUS => {
let op_line = cursor.current().line;
cursor.advance();
let operand = Self::parse_unary_expr(cursor)?;
Ok(ASTNode::UnaryOp {
operator: crate::ast::UnaryOperator::Minus,
operand: Box::new(operand),
span: Span::new(op_line, 0, op_line, 0),
})
}
TokenType::NOT => {
let op_line = cursor.current().line;
cursor.advance();
let operand = Self::parse_unary_expr(cursor)?;
Ok(ASTNode::UnaryOp {
operator: crate::ast::UnaryOperator::Not,
operand: Box::new(operand),
span: Span::new(op_line, 0, op_line, 0),
})
}
_ => Self::parse_postfix_expr(cursor),
}
}
/// 後置(フィールドアクセス・関数/メソッド呼び出し)をパース
fn parse_postfix_expr(cursor: &mut TokenCursor) -> Result<ASTNode, ParseError> {
let mut expr = Self::parse_primary_expr(cursor)?;