parser: support property fetches

This commit is contained in:
Ryan Chandler 2022-07-26 11:21:05 +01:00
parent 2654286ddb
commit 2d332f90e4
No known key found for this signature in database
GPG Key ID: F113BCADDB3B0CCA
4 changed files with 43 additions and 1 deletions

View File

@ -0,0 +1,3 @@
<?php
$foo->bar();

4
phpast/samples/prop.php Normal file
View File

@ -0,0 +1,4 @@
<?php
$foo->bar;
$foo->bar->baz;

View File

@ -29,6 +29,12 @@ impl From<&String> for Identifier {
}
}
impl From<&str> for Identifier {
fn from(name: &str) -> Self {
Self::from(name.to_string())
}
}
#[derive(Debug, PartialEq, Clone, Serialize)]
pub struct Param {
pub(crate) name: Expression,
@ -232,6 +238,7 @@ pub enum Expression {
ArrowFunction(Vec<Param>, Option<Type>, Box<Self>),
New(Box<Self>, Vec<Self>),
ConstantString(String),
PropertyFetch(Box<Self>, Identifier),
}
#[derive(Debug, Clone, PartialEq, Serialize)]

View File

@ -879,6 +879,16 @@ impl Parser {
Expression::Call(Box::new(lhs), args)
},
TokenKind::Arrow => {
// TODO: Add support for dynamic property fetch or method call here.
let property = expect!(self, TokenKind::Identifier(i), i, "expected identifier");
if self.current.kind == TokenKind::LeftParen {
todo!("parse method calls");
} else {
Expression::PropertyFetch(Box::new(lhs), property.into())
}
},
_ => todo!("postfix: {:?}", op),
})
}
@ -930,6 +940,7 @@ fn infix_binding_power(t: &TokenKind) -> Option<(u8, u8)> {
fn postfix_binding_power(t: &TokenKind) -> Option<u8> {
Some(match t {
TokenKind::LeftParen => 19,
TokenKind::Arrow => 18,
_ => return None
})
}
@ -964,7 +975,7 @@ impl Display for ParseError {
#[cfg(test)]
mod tests {
use trunk_lexer::Lexer;
use crate::{Statement, Param, Expression, ast::{InfixOp}, Type};
use crate::{Statement, Param, Expression, ast::{InfixOp}, Type, Identifier};
use super::Parser;
macro_rules! function {
@ -1062,6 +1073,23 @@ mod tests {
]);
}
#[test]
fn property_fetch() {
assert_ast("<?php $foo->bar; $foo->bar->baz;", &[
expr!(Expression::PropertyFetch(
Box::new(Expression::Variable("foo".into())),
Identifier::from("bar")
)),
expr!(Expression::PropertyFetch(
Box::new(Expression::PropertyFetch(
Box::new(Expression::Variable("foo".into())),
Identifier::from("bar")
)),
Identifier::from("baz")
))
]);
}
#[test]
fn concat() {
assert_ast("<?php 'foo' . 'bar' . 'baz';", &[