From 8384183a4d369863ecfcf6612be20765c43a3c9d Mon Sep 17 00:00:00 2001 From: "Guillem L. Jara" <4lon3ly0@tutanota.com> Date: Thu, 30 Apr 2026 01:06:04 +0200 Subject: [PATCH] fix(parser): Rework function call parsing --- lexer/src/lib.rs | 5 +---- parser/src/lib.rs | 35 +++++++++++++++++++++++------------ 2 files changed, 24 insertions(+), 16 deletions(-) diff --git a/lexer/src/lib.rs b/lexer/src/lib.rs index 862ce2f..50f32e1 100644 --- a/lexer/src/lib.rs +++ b/lexer/src/lib.rs @@ -120,9 +120,6 @@ pub enum Token<'a> { #[regex("(?&identifier)", Identifier::without_namespace)] #[regex(r"(?&identifier)::(?&identifier)", Identifier::with_namespace)] Identifier(Identifier<'a>), - #[regex(r"(?&identifier)\(", Identifier::without_namespace)] - #[regex(r"(?&identifier)::(?&identifier)\(", Identifier::with_namespace)] - FunctionCall(Identifier<'a>), #[token("+", accept_expression)] Plus, #[token("-", accept_expression)] @@ -231,7 +228,7 @@ pub enum LexingError { UnexpectedEof, } -#[derive(Debug, PartialEq, Eq)] +#[derive(Debug, PartialEq, Eq, Clone, Copy)] pub struct Identifier<'a> { pub namespace: Option<&'a str>, pub literal: &'a str, diff --git a/parser/src/lib.rs b/parser/src/lib.rs index 17c5603..c645574 100644 --- a/parser/src/lib.rs +++ b/parser/src/lib.rs @@ -367,7 +367,8 @@ impl<'a> Parser<'a> { #[tracing::instrument] fn parse_case(&mut self, lex: &mut Lexer<'a>) -> Result> { lex.expect(&Token::Case)?; - let value = self.parse_atom(lex)?; + let next = lex.expect_next()?; + let value = self.parse_atom(lex, next)?; lex.expect(&Token::Colon)?; match value { Atom::Variable(_) => Err(ParsingError::UnexpectedToken), @@ -485,10 +486,16 @@ impl<'a> Parser<'a> { } else { return Err(ParsingError::UnexpectedToken); } - } else if lex.peek_with(|t| matches!(t, Token::FunctionCall(_))) { - self.parse_function_call(lex)? } else { - Expr::leaf(self.parse_atom(lex)?) + let next = lex.expect_next()?; + if let Token::Identifier(name) = next + && lex.peek_is(&Token::OpenParent) + { + // TODO: use spans to check there is no space between ident, (. + self.parse_function_call(lex, name.qualify(self.namespace))? + } else { + Expr::leaf(self.parse_atom(lex, next)?) + } }; while let Some(next) = lex.peek() { @@ -592,12 +599,14 @@ impl<'a> Parser<'a> { } #[tracing::instrument] - fn parse_function_call(&mut self, lex: &mut Lexer<'a>) -> Result> { - let Token::FunctionCall(ident) = lex.expect_next()? else { - return Err(ParsingError::UnexpectedToken); - }; + fn parse_function_call( + &mut self, + lex: &mut Lexer<'a>, + name: Identifier<'a>, + ) -> Result> { + lex.expect(&Token::OpenParent)?; let expr = ExprNode::FunctionCall( - ident.qualify(self.namespace), + name, self.parse_arguments(lex, |t| t == &Token::ClosedParent)?, ); lex.expect(&Token::ClosedParent)?; @@ -605,12 +614,14 @@ impl<'a> Parser<'a> { } #[tracing::instrument] - fn parse_atom(&self, lex: &mut Lexer<'a>) -> Result> { - match lex.expect_next()? { + fn parse_atom(&self, lex: &mut Lexer<'a>, token: Token<'a>) -> Result> { + match token { Token::Number(n) => Ok(Atom::Number(n)), Token::String(s) => Ok(Atom::String(s)), Token::Regex(r) => Ok(Atom::Regex(r)), - Token::Identifier(a) => Ok(Atom::Variable(a.qualify(self.namespace).into())), + Token::Identifier(a) if !lex.peek_is(&Token::OpenParent) => { + Ok(Atom::Variable(a.qualify(self.namespace).into())) + } Token::NrVariable => Ok(Variable::Nr.into()), Token::NfVariable => Ok(Variable::Nf.into()), Token::FsVariable => Ok(Variable::Fs.into()),