parser: support short-hand ternaries

This commit is contained in:
Ryan Chandler 2022-08-09 12:00:35 +01:00
parent 0ae93c2ea1
commit 2fb879b763
No known key found for this signature in database
GPG Key ID: F113BCADDB3B0CCA
2 changed files with 11 additions and 17 deletions

View File

@ -412,7 +412,7 @@ pub enum Expression {
}, },
Ternary { Ternary {
condition: Box<Self>, condition: Box<Self>,
then: Box<Self>, then: Option<Box<Self>>,
r#else: Box<Self> r#else: Box<Self>
}, },
Coalesce { Coalesce {

View File

@ -1339,7 +1339,11 @@ impl Parser {
let then = self.expression(0)?; let then = self.expression(0)?;
expect!(self, TokenKind::Colon, "expected :"); expect!(self, TokenKind::Colon, "expected :");
let otherwise = self.expression(rbp)?; let otherwise = self.expression(rbp)?;
lhs = Expression::Ternary { condition: Box::new(lhs), then: Box::new(then), r#else: Box::new(otherwise) } lhs = Expression::Ternary { condition: Box::new(lhs), then: Some(Box::new(then)), r#else: Box::new(otherwise) }
},
TokenKind::QuestionColon => {
let r#else = self.expression(0)?;
lhs = Expression::Ternary { condition: Box::new(lhs), then: None, r#else: Box::new(r#else) }
}, },
_ => { _ => {
let rhs = self.expression(rbp)?; let rhs = self.expression(rbp)?;
@ -1388,16 +1392,6 @@ impl Parser {
Expression::ArrayIndex { array: Box::new(lhs), index: Some(Box::new(index)) } Expression::ArrayIndex { array: Box::new(lhs), index: Some(Box::new(index)) }
} }
}, },
TokenKind::Question => {
// TODO: Handle short-hand ternaries here too.
let then = self.expression(0)?;
expect!(self, TokenKind::Colon, "expected :");
let otherwise = self.expression(0)?;
Expression::Ternary { condition: Box::new(lhs), then: Box::new(then), r#else: Box::new(otherwise) }
},
TokenKind::DoubleColon => { TokenKind::DoubleColon => {
match self.current.kind.clone() { match self.current.kind.clone() {
TokenKind::Variable(_) => { TokenKind::Variable(_) => {
@ -1517,7 +1511,7 @@ fn infix_binding_power(t: &TokenKind) -> Option<(u8, u8)> {
TokenKind::Dot => (12, 12), TokenKind::Dot => (12, 12),
TokenKind::LessThan | TokenKind::GreaterThan | TokenKind::LessThanEquals | TokenKind::GreaterThanEquals => (10, 11), TokenKind::LessThan | TokenKind::GreaterThan | TokenKind::LessThanEquals | TokenKind::GreaterThanEquals => (10, 11),
TokenKind::DoubleEquals | TokenKind::TripleEquals | TokenKind::BangEquals | TokenKind::BangDoubleEquals => (8, 9), TokenKind::DoubleEquals | TokenKind::TripleEquals | TokenKind::BangEquals | TokenKind::BangDoubleEquals => (8, 9),
TokenKind::Question => (6, 7), TokenKind::Question | TokenKind::QuestionColon => (6, 7),
TokenKind::BooleanAnd => (4, 5), TokenKind::BooleanAnd => (4, 5),
TokenKind::BooleanOr => (2, 3), TokenKind::BooleanOr => (2, 3),
TokenKind::Equals | TokenKind::PlusEquals | TokenKind::DotEquals => (0, 1), TokenKind::Equals | TokenKind::PlusEquals | TokenKind::DotEquals => (0, 1),
@ -1676,7 +1670,7 @@ mod tests {
assert_ast("<?php 1 ? 2 : 3;", &[ assert_ast("<?php 1 ? 2 : 3;", &[
expr!(Expression::Ternary { expr!(Expression::Ternary {
condition: Box::new(Expression::Int { i: 1 }), condition: Box::new(Expression::Int { i: 1 }),
then: Box::new(Expression::Int { i: 2 }), then: Some(Box::new(Expression::Int { i: 2 })),
r#else: Box::new(Expression::Int { i: 3 }), r#else: Box::new(Expression::Int { i: 3 }),
}) })
]); ]);
@ -1684,11 +1678,11 @@ mod tests {
assert_ast("<?php 1 ? 2 ? 3 : 4 : 5;", &[ assert_ast("<?php 1 ? 2 ? 3 : 4 : 5;", &[
expr!(Expression::Ternary { expr!(Expression::Ternary {
condition: Box::new(Expression::Int { i: 1 }), condition: Box::new(Expression::Int { i: 1 }),
then: Box::new(Expression::Ternary { then: Some(Box::new(Expression::Ternary {
condition: Box::new(Expression::Int { i: 2 }), condition: Box::new(Expression::Int { i: 2 }),
then: Box::new(Expression::Int { i: 3 }), then: Some(Box::new(Expression::Int { i: 3 })),
r#else: Box::new(Expression::Int { i: 4 }), r#else: Box::new(Expression::Int { i: 4 }),
}), })),
r#else: Box::new(Expression::Int { i: 5 }), r#else: Box::new(Expression::Int { i: 5 }),
}) })
]); ]);