Parse submembers and function calls

This commit is contained in:
mars 2022-03-01 13:58:58 -07:00
parent 732d80dd9a
commit d15fd0c748
1 changed files with 27 additions and 25 deletions

View File

@ -242,9 +242,10 @@ pub enum Expr<'a> {
BinaryOp(BinaryOp, ExprPair<'a>),
Literal(Literal<'a>),
Local(&'a str),
Member(&'a str),
Member(&'a str, Box<Expr<'a>>),
SelfMember(&'a str),
Group(Box<Expr<'a>>),
FnCall(&'a str, Vec<Expr<'a>>),
FnCall(Box<Expr<'a>>, Vec<Expr<'a>>),
If {
test_expr: Box<Expr<'a>>,
then_body: BranchBody<'a>,
@ -254,22 +255,9 @@ pub enum Expr<'a> {
impl<'a> Expr<'a> {
pub fn build_start(tok: Token, lexer: &mut Lexer<'a>) -> (Option<Self>, Token) {
let mut next = None;
let lhs = match tok {
Token::Identifier => {
let local = lexer.slice();
let tok = lexer.next().unwrap();
next = Some(tok);
match tok {
Token::ParanOpen => {
next = None;
Self::FnCall(local, Self::eat_args(lexer))
}
_ => Self::Local(local),
}
}
Token::Dot => Self::Member(lexer.eat_expect_id()),
let mut lhs = match tok {
Token::Identifier => Self::Local(lexer.slice()),
Token::Dot => Self::SelfMember(lexer.eat_expect_id()),
Token::ParanOpen => {
let (inner, next) = Self::build(lexer);
if next != Token::ParanClose {
@ -305,15 +293,29 @@ impl<'a> Expr<'a> {
_ => lexer.panic_message("Unexpected token"),
};
let next = next.unwrap_or_else(|| lexer.next().unwrap());
loop {
let tok = lexer.next().unwrap();
if let Some(op) = BinaryOp::from_token(next) {
match Self::build(lexer) {
(Some(rhs), tail) => (Some(Self::BinaryOp(op, Box::new((lhs, rhs)))), tail),
_ => lexer.panic_message("Expected right-hand expression"),
match tok {
Token::Dot => {
let member = lexer.eat_expect_id();
let expr = Self::Member(member, Box::new(lhs));
lhs = expr;
}
Token::ParanOpen => lhs = Self::FnCall(Box::new(lhs), Self::eat_args(lexer)),
_ => {
if let Some(op) = BinaryOp::from_token(tok) {
match Self::build(lexer) {
(Some(rhs), tail) => {
break (Some(Self::BinaryOp(op, Box::new((lhs, rhs)))), tail)
}
_ => lexer.panic_message("Expected right-hand expression"),
}
} else {
break (Some(lhs), tok);
}
}
}
} else {
(Some(lhs), next)
}
}