parser: support basic math ops

This commit is contained in:
Ryan Chandler 2022-07-25 20:16:18 +01:00
parent 53c7970f83
commit be40cd61c4
No known key found for this signature in database
GPG Key ID: F113BCADDB3B0CCA
3 changed files with 47 additions and 0 deletions

View File

@ -496,6 +496,17 @@ impl Lexer {
TokenKind::Comment(buffer) TokenKind::Comment(buffer)
} }
}, },
'*' => {
self.col += 1;
if let Some('*') = it.peek() {
self.col += 1;
it.next();
TokenKind::Pow
} else {
TokenKind::Asterisk
}
},
'|' => { '|' => {
self.col += 1; self.col += 1;
// TODO: Handle boolean or || tokens. // TODO: Handle boolean or || tokens.

View File

@ -243,6 +243,8 @@ pub struct ArrayItem {
pub enum InfixOp { pub enum InfixOp {
Add, Add,
Sub, Sub,
Div,
Mul,
LessThan, LessThan,
} }
@ -251,6 +253,8 @@ impl From<TokenKind> for InfixOp {
match k { match k {
TokenKind::Plus => Self::Add, TokenKind::Plus => Self::Add,
TokenKind::Minus => Self::Sub, TokenKind::Minus => Self::Sub,
TokenKind::Asterisk => Self::Mul,
TokenKind::Slash => Self::Div,
TokenKind::LessThan => Self::LessThan, TokenKind::LessThan => Self::LessThan,
_ => unreachable!() _ => unreachable!()
} }

View File

@ -911,6 +911,7 @@ fn infix(lhs: Expression, op: TokenKind, rhs: Expression) -> Expression {
fn infix_binding_power(t: &TokenKind) -> Option<(u8, u8)> { fn infix_binding_power(t: &TokenKind) -> Option<(u8, u8)> {
Some(match t { Some(match t {
TokenKind::Asterisk | TokenKind::Slash => (13, 14),
TokenKind::Plus | TokenKind::Minus => (11, 12), TokenKind::Plus | TokenKind::Minus => (11, 12),
TokenKind::LessThan => (9, 10), TokenKind::LessThan => (9, 10),
TokenKind::Equals => (2, 1), TokenKind::Equals => (2, 1),
@ -1011,6 +1012,14 @@ mod tests {
}; };
} }
macro_rules! expr {
($expr:expr) => {
Statement::Expression {
expr: $expr,
}
};
}
#[test] #[test]
fn paren_expression() { fn paren_expression() {
assert_ast("<?php (1 + 2);", &[ assert_ast("<?php (1 + 2);", &[
@ -1022,6 +1031,29 @@ mod tests {
]); ]);
} }
#[test]
fn math_precedence() {
assert_ast("<?php 1 + 2 * 3 / 4 - 5;", &[
expr!(Expression::Infix(
Box::new(Expression::Infix(
Box::new(Expression::Int(1)),
InfixOp::Add,
Box::new(Expression::Infix(
Box::new(Expression::Infix(
Box::new(Expression::Int(2)),
InfixOp::Mul,
Box::new(Expression::Int(3))
)),
InfixOp::Div,
Box::new(Expression::Int(4))
))
)),
InfixOp::Sub,
Box::new(Expression::Int(5))
))
]);
}
#[test] #[test]
fn empty_fn() { fn empty_fn() {
assert_ast("<?php function foo() {}", &[ assert_ast("<?php function foo() {}", &[