From e6440123eeb234ccb02e419816623f34f927759a Mon Sep 17 00:00:00 2001 From: "Guillem L. Jara" <4lon3ly0@tutanota.com> Date: Mon, 4 May 2026 18:46:24 +0200 Subject: [PATCH] Revert "parser, lexer: solve function call ambiguity" This reverts commit 5213c1e6fba7428b6c4eb823a3537ede46492650. --- lexer/src/lib.rs | 15 ++++++--------- parser/src/lex.rs | 6 ++---- parser/src/lib.rs | 28 +++++++++++++++------------- 3 files changed, 23 insertions(+), 26 deletions(-) diff --git a/lexer/src/lib.rs b/lexer/src/lib.rs index c5ae782..cc8de2d 100644 --- a/lexer/src/lib.rs +++ b/lexer/src/lib.rs @@ -126,12 +126,9 @@ pub enum Token<'a> { RlengthVariable, #[token("ENVIRON", accept_expression)] EnvironVariable, - #[regex("(?&identifier)", |lex| Identifier::without_namespace::<0>(lex))] - #[regex(r"(?&identifier)::(?&identifier)", |lex| Identifier::with_namespace::<0>(lex))] + #[regex("(?&identifier)", Identifier::without_namespace)] + #[regex(r"(?&identifier)::(?&identifier)", Identifier::with_namespace)] Identifier(Identifier<'a>), - #[regex(r"(?&identifier)\(", |lex| Identifier::without_namespace::<1>(lex))] - #[regex(r"(?&identifier)::(?&identifier)\(", |lex| Identifier::with_namespace::<1>(lex))] - FunctionCall(Identifier<'a>), #[token("+", accept_expression)] Plus, #[token("-", accept_expression)] @@ -379,19 +376,19 @@ fn parse_float(lex: &mut Lexer<'_>) -> f64 { } impl<'a> Identifier<'a> { - fn without_namespace(lex: &mut Lexer<'a>) -> Self { + fn without_namespace(lex: &mut Lexer<'a>) -> Self { Self { namespace: None, - literal: parse_ident(lex, ..lex.slice().len() - TRIM), + literal: parse_ident(lex, ..), } } - fn with_namespace(lex: &mut Lexer<'a>) -> Self { + fn with_namespace(lex: &mut Lexer<'a>) -> Self { // SAFETY: The regex matching ensures it is present and well-formed. let separator = unsafe { memchr(b':', lex.slice()).unwrap_unchecked() }; Self { namespace: Some(parse_ident(lex, ..separator)), - literal: parse_ident(lex, separator + 2..lex.slice().len() - TRIM), + literal: parse_ident(lex, separator + 2..), } } } diff --git a/parser/src/lex.rs b/parser/src/lex.rs index c7c991b..94eecda 100644 --- a/parser/src/lex.rs +++ b/parser/src/lex.rs @@ -190,10 +190,8 @@ impl TokenExt for Token<'_> { fn is_expr_start(&self) -> bool { self.is_atom() || self.is_prefix_op() - || matches!( - self, - Token::OpenParent | Token::FunctionCall(_) | Token::Getline - ) + || self == &Token::OpenParent + || self == &Token::Getline } fn is_place(&self) -> bool { matches!( diff --git a/parser/src/lib.rs b/parser/src/lib.rs index 688e371..6c89920 100644 --- a/parser/src/lib.rs +++ b/parser/src/lib.rs @@ -465,17 +465,7 @@ impl<'a> Parser<'a> { #[tracing::instrument] fn parse_function(&mut self, lex: &mut Lexer<'a>) -> Result<()> { - let name = match lex.expect_next()? { - Token::FunctionCall(ident) => ident, - Token::Identifier(ident) => { - lex.expect(&Token::OpenParent, |span| { - ParsingError::NoFunctionSignature(span, ident.literal.to_string()) - })?; - ident - } - _ => return Err(ParsingError::ExpectedIdentifier(lex.span())), - } - .qualify(self.namespace); + let name = lex.expect_identifier()?.qualify(self.namespace); let args = self.parse_signature(lex, &name)?; lex.consume(&Token::Newline); let body = self.parse_body(lex)?; @@ -491,6 +481,9 @@ impl<'a> Parser<'a> { name: &Identifier<'a>, ) -> Result>> { let mut args = Vec::new_in(self.arena); + lex.expect(&Token::OpenParent, |s| { + ParsingError::NoFunctionSignature(s, name.to_string()) + })?; if lex.consume(&Token::ClosedParent) { return Ok(args); @@ -574,7 +567,10 @@ impl<'a> Parser<'a> { } } else { let next = lex.expect_next()?; - if let Token::FunctionCall(name) = 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), lex.span())? } else { Expr::leaf(self.parse_atom(lex, next)?) @@ -695,6 +691,10 @@ impl<'a> Parser<'a> { name: Identifier<'a>, span: Span, ) -> Result> { + lex.expect(&Token::OpenParent, ParsingError::ExpectedOpeningParenthesis)?; + if lex.span().start != span.end { + return Err(ParsingError::FunctionCallSeparatedIdent(span)); + } let expr = ExprNode::FunctionCall( name, self.parse_arguments(lex, |t| t == &Token::ClosedParent)?, @@ -724,7 +724,9 @@ impl<'a> Parser<'a> { #[tracing::instrument] fn get_place(&self, lex: &mut Lexer<'a>, token: Token<'a>) -> Option> { match token { - Token::Identifier(a) => Some(a.qualify(self.namespace).into()), + Token::Identifier(a) if !lex.peek_is(&Token::OpenParent) => { + Some(a.qualify(self.namespace).into()) + } Token::NrVariable => Some(Variable::Nr), Token::NfVariable => Some(Variable::Nf), Token::FsVariable => Some(Variable::Fs),