feat: 添加三元运算符支持,更新解析器和解释器以处理条件表达式
This commit is contained in:
+55
-1
@@ -208,8 +208,24 @@ impl Parser {
|
||||
self.assignment()
|
||||
}
|
||||
|
||||
fn assignment(&mut self) -> Result<Expr, RuntimeError> {
|
||||
fn ternary(&mut self) -> Result<Expr, RuntimeError> {
|
||||
let expr = self.logical_or()?;
|
||||
if self.match_kind(&[TokenKind::Question]) {
|
||||
let then_branch = self.assignment()?;
|
||||
self.consume(TokenKind::Colon, "Expected ':' after then branch of ternary.")?;
|
||||
let else_branch = self.assignment()?;
|
||||
Ok(Expr::Ternary {
|
||||
condition: Box::new(expr),
|
||||
then_branch: Box::new(then_branch),
|
||||
else_branch: Box::new(else_branch),
|
||||
})
|
||||
} else {
|
||||
Ok(expr)
|
||||
}
|
||||
}
|
||||
|
||||
fn assignment(&mut self) -> Result<Expr, RuntimeError> {
|
||||
let expr = self.ternary()?;
|
||||
|
||||
let op = if self.match_kind(&[TokenKind::Equal]) {
|
||||
Some(AssignOp::Equal)
|
||||
@@ -814,6 +830,44 @@ mod tests {
|
||||
}
|
||||
}
|
||||
|
||||
// ----- ternary -----
|
||||
|
||||
#[test]
|
||||
fn parse_ternary_simple() {
|
||||
match parse_expr("a ? 1 : 2") {
|
||||
Expr::Ternary { condition, then_branch, else_branch } => {
|
||||
assert!(matches!(*condition, Expr::Variable(_)));
|
||||
assert!(matches!(*then_branch, Expr::Literal(Literal::Number(1.0))));
|
||||
assert!(matches!(*else_branch, Expr::Literal(Literal::Number(2.0))));
|
||||
}
|
||||
e => panic!("Expected Ternary, got {:?}", e),
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn parse_ternary_nested_right_assoc() {
|
||||
// a ? b : c ? d : e → a ? b : (c ? d : e)
|
||||
match parse_expr("a ? b : c ? d : e") {
|
||||
Expr::Ternary { condition, then_branch, else_branch } => {
|
||||
assert!(matches!(*condition, Expr::Variable(_)));
|
||||
assert!(matches!(*then_branch, Expr::Variable(_)));
|
||||
assert!(matches!(*else_branch, Expr::Ternary { .. }));
|
||||
}
|
||||
e => panic!("Expected Ternary with nested Ternary else, got {:?}", e),
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn parse_ternary_with_assignment_in_else() {
|
||||
// a ? b : c = d → a ? b : (c = d)
|
||||
match parse_expr("a ? b : c = 5") {
|
||||
Expr::Ternary { else_branch, .. } => {
|
||||
assert!(matches!(*else_branch, Expr::Assign { .. }));
|
||||
}
|
||||
e => panic!("Expected Ternary with Assign else, got {:?}", e),
|
||||
}
|
||||
}
|
||||
|
||||
// ----- assignment -----
|
||||
|
||||
#[test]
|
||||
|
||||
Reference in New Issue
Block a user