Skip to content

Commit da6d47e

Browse files
committed
parser, lexer: solve function call ambiguity
I really wanted not to do it this way, but it causes an ambiguity with `getline foo(x)` and GNU seems to have bailed on this too.
1 parent d55ad9a commit da6d47e

3 files changed

Lines changed: 26 additions & 23 deletions

File tree

lexer/src/lib.rs

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -126,9 +126,12 @@ pub enum Token<'a> {
126126
RlengthVariable,
127127
#[token("ENVIRON", accept_expression)]
128128
EnvironVariable,
129-
#[regex("(?&identifier)", Identifier::without_namespace)]
130-
#[regex(r"(?&identifier)::(?&identifier)", Identifier::with_namespace)]
129+
#[regex("(?&identifier)", |lex| Identifier::without_namespace::<0>(lex))]
130+
#[regex(r"(?&identifier)::(?&identifier)", |lex| Identifier::with_namespace::<0>(lex))]
131131
Identifier(Identifier<'a>),
132+
#[regex(r"(?&identifier)\(", |lex| Identifier::without_namespace::<1>(lex))]
133+
#[regex(r"(?&identifier)::(?&identifier)\(", |lex| Identifier::with_namespace::<1>(lex))]
134+
FunctionCall(Identifier<'a>),
132135
#[token("+", accept_expression)]
133136
Plus,
134137
#[token("-", accept_expression)]
@@ -376,19 +379,19 @@ fn parse_float(lex: &mut Lexer<'_>) -> f64 {
376379
}
377380

378381
impl<'a> Identifier<'a> {
379-
fn without_namespace(lex: &mut Lexer<'a>) -> Self {
382+
fn without_namespace<const TRIM: usize>(lex: &mut Lexer<'a>) -> Self {
380383
Self {
381384
namespace: None,
382-
literal: parse_ident(lex, ..),
385+
literal: parse_ident(lex, ..lex.slice().len() - TRIM),
383386
}
384387
}
385388

386-
fn with_namespace(lex: &mut Lexer<'a>) -> Self {
389+
fn with_namespace<const TRIM: usize>(lex: &mut Lexer<'a>) -> Self {
387390
// SAFETY: The regex matching ensures it is present and well-formed.
388391
let separator = unsafe { memchr(b':', lex.slice()).unwrap_unchecked() };
389392
Self {
390393
namespace: Some(parse_ident(lex, ..separator)),
391-
literal: parse_ident(lex, separator + 2..),
394+
literal: parse_ident(lex, separator + 2..lex.slice().len() - TRIM),
392395
}
393396
}
394397
}

parser/src/lex.rs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -190,8 +190,10 @@ impl TokenExt for Token<'_> {
190190
fn is_expr_start(&self) -> bool {
191191
self.is_atom()
192192
|| self.is_prefix_op()
193-
|| self == &Token::OpenParent
194-
|| self == &Token::Getline
193+
|| matches!(
194+
self,
195+
Token::OpenParent | Token::FunctionCall(_) | Token::Getline
196+
)
195197
}
196198
fn is_place(&self) -> bool {
197199
matches!(

parser/src/lib.rs

Lines changed: 13 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -465,7 +465,17 @@ impl<'a> Parser<'a> {
465465

466466
#[tracing::instrument]
467467
fn parse_function(&mut self, lex: &mut Lexer<'a>) -> Result<()> {
468-
let name = lex.expect_identifier()?.qualify(self.namespace);
468+
let name = match lex.expect_next()? {
469+
Token::FunctionCall(ident) => ident,
470+
Token::Identifier(ident) => {
471+
lex.expect(&Token::OpenParent, |span| {
472+
ParsingError::NoFunctionSignature(span, ident.literal.to_string())
473+
})?;
474+
ident
475+
}
476+
_ => return Err(ParsingError::ExpectedIdentifier(lex.span())),
477+
}
478+
.qualify(self.namespace);
469479
let args = self.parse_signature(lex, &name)?;
470480
lex.consume(&Token::Newline);
471481
let body = self.parse_body(lex)?;
@@ -481,9 +491,6 @@ impl<'a> Parser<'a> {
481491
name: &Identifier<'a>,
482492
) -> Result<Vec<'a, Identifier<'a>>> {
483493
let mut args = Vec::new_in(self.arena);
484-
lex.expect(&Token::OpenParent, |s| {
485-
ParsingError::NoFunctionSignature(s, name.to_string())
486-
})?;
487494

488495
if lex.consume(&Token::ClosedParent) {
489496
return Ok(args);
@@ -567,10 +574,7 @@ impl<'a> Parser<'a> {
567574
}
568575
} else {
569576
let next = lex.expect_next()?;
570-
if let Token::Identifier(name) = next
571-
&& lex.peek_is(&Token::OpenParent)
572-
{
573-
// TODO: use spans to check there is no space between ident, (.
577+
if let Token::FunctionCall(name) = next {
574578
self.parse_function_call(lex, name.qualify(self.namespace), lex.span())?
575579
} else {
576580
Expr::leaf(self.parse_atom(lex, next)?)
@@ -691,10 +695,6 @@ impl<'a> Parser<'a> {
691695
name: Identifier<'a>,
692696
span: Span,
693697
) -> Result<Expr<'a>> {
694-
lex.expect(&Token::OpenParent, ParsingError::ExpectedOpeningParenthesis)?;
695-
if lex.span().start != span.end {
696-
return Err(ParsingError::FunctionCallSeparatedIdent(span));
697-
}
698698
let expr = ExprNode::FunctionCall(
699699
name,
700700
self.parse_arguments(lex, |t| t == &Token::ClosedParent)?,
@@ -724,9 +724,7 @@ impl<'a> Parser<'a> {
724724
#[tracing::instrument]
725725
fn get_place(&self, lex: &mut Lexer<'a>, token: Token<'a>) -> Option<Variable<'a>> {
726726
match token {
727-
Token::Identifier(a) if !lex.peek_is(&Token::OpenParent) => {
728-
Some(a.qualify(self.namespace).into())
729-
}
727+
Token::Identifier(a) => Some(a.qualify(self.namespace).into()),
730728
Token::NrVariable => Some(Variable::Nr),
731729
Token::NfVariable => Some(Variable::Nf),
732730
Token::FsVariable => Some(Variable::Fs),

0 commit comments

Comments
 (0)