From f6fcc64074cbf2595b1570622efde1a7a833242d Mon Sep 17 00:00:00 2001 From: Selfhosting Dev Date: Thu, 25 Sep 2025 06:33:40 +0900 Subject: [PATCH] =?UTF-8?q?parser(cursor):=20Step=E2=80=912=20cont.=20?= =?UTF-8?q?=E2=80=93=20unary=20(-/not)=20and=20postfix=20chain=20in=20Toke?= =?UTF-8?q?nCursor=20path;=20parity=20tests=20for=20precedence=20and=20una?= =?UTF-8?q?ry;=20quick/core=20remains=20green=20under=20env=20toggle?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/parser/expr_cursor.rs | 32 +++++++++++++++++-- .../parity/vm_llvm_precedence_arith.sh | 16 ++++++++++ .../integration/parity/vm_llvm_unary_not.sh | 16 ++++++++++ 3 files changed, 62 insertions(+), 2 deletions(-) create mode 100644 tools/smokes/v2/profiles/integration/parity/vm_llvm_precedence_arith.sh create mode 100644 tools/smokes/v2/profiles/integration/parity/vm_llvm_unary_not.sh diff --git a/src/parser/expr_cursor.rs b/src/parser/expr_cursor.rs index ce2006a7..b6cf8aa4 100644 --- a/src/parser/expr_cursor.rs +++ b/src/parser/expr_cursor.rs @@ -116,12 +116,12 @@ impl ExprParserWithCursor { /// 乗算式をパース fn parse_multiplicative_expr(cursor: &mut TokenCursor) -> Result { - 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 { + // 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 { let mut expr = Self::parse_primary_expr(cursor)?; diff --git a/tools/smokes/v2/profiles/integration/parity/vm_llvm_precedence_arith.sh b/tools/smokes/v2/profiles/integration/parity/vm_llvm_precedence_arith.sh new file mode 100644 index 00000000..771f3a77 --- /dev/null +++ b/tools/smokes/v2/profiles/integration/parity/vm_llvm_precedence_arith.sh @@ -0,0 +1,16 @@ +#!/bin/bash +# vm_llvm_precedence_arith.sh - arithmetic precedence parity (1 + 2 * 3 == 7, (1+2)*3==9) + +source "$(dirname "$0")/../../../lib/test_runner.sh" +source "$(dirname "$0")/../../../lib/result_checker.sh" + +require_env || exit 2 +preflight_plugins || exit 2 + +test_vm_llvm_precedence_arith() { + local code='print(1 + 2 * 3)\nprint((1 + 2) * 3)' + check_parity -c "$code" "vm_llvm_precedence_arith" +} + +run_test "vm_llvm_precedence_arith" test_vm_llvm_precedence_arith + diff --git a/tools/smokes/v2/profiles/integration/parity/vm_llvm_unary_not.sh b/tools/smokes/v2/profiles/integration/parity/vm_llvm_unary_not.sh new file mode 100644 index 00000000..aa223a14 --- /dev/null +++ b/tools/smokes/v2/profiles/integration/parity/vm_llvm_unary_not.sh @@ -0,0 +1,16 @@ +#!/bin/bash +# vm_llvm_unary_not.sh - unary 'not' parity + +source "$(dirname "$0")/../../../lib/test_runner.sh" +source "$(dirname "$0")/../../../lib/result_checker.sh" + +require_env || exit 2 +preflight_plugins || exit 2 + +test_vm_llvm_unary_not() { + local code='print(not false)' + check_parity -c "$code" "vm_llvm_unary_not" +} + +run_test "vm_llvm_unary_not" test_vm_llvm_unary_not +