Mutual recursion with `#[cache_left_rec]` fails
kevinmehall opened this issue · 0 comments
kevinmehall commented
Discussed in #358
Originally posted by stqcky July 30, 2023
Hi, I'm having some issues using the #[cache_left_rec]
attribute.
Here's my code:
#[derive(Clone, PartialEq, Debug)]
pub enum TestExpression {
FunctionCall {
callee: Box<TestExpression>,
arguments: Vec<TestExpression>
},
Identifier(String)
}
peg::parser! {
grammar test() for str {
pub rule identifier() -> TestExpression = i:$(['a'..='z']+) {
TestExpression::Identifier(i.to_string())
}
#[cache_left_rec]
pub rule expression() -> TestExpression = exp:(function_call() / identifier()) {
exp
}
rule lparen() = "("
rule rparen() = ")"
#[cache_left_rec]
pub rule function_call() -> TestExpression = callee:expression() lparen() arg:(expression() ** ",") rparen() {
TestExpression::FunctionCall { callee: Box::new(callee), arguments: arg }
}
}
}
pub fn parse() {
let input = "abc()";
let a = test::expression(&input);
println!("{:?}", a);
}
When I try to match the string abc()
with the rule function_call
it works fine, returning Ok(FunctionCall { callee: Identifier("abc"), arguments: [] })
.
But when I try to match the same string with the expression
rule it doesn't work.
Here's the trace:
[PEG_TRACE] Attempting to match rule `expression` at 1:1
[PEG_TRACE] Attempting to match rule `function_call` at 1:1
[PEG_TRACE] Cached fail of rule expression at 1:1
[PEG_TRACE] Failed to match rule `function_call` at 1:1
[PEG_TRACE] Attempting to match rule `identifier` at 1:1
[PEG_TRACE] Matched rule `identifier` at 1:1 to 1:4
[PEG_TRACE] Matched rule `expression` at 1:1 to 1:4
[PEG_TRACE] Attempting to match rule `expression` at 1:1
[PEG_TRACE] Cached fail of rule function_call at 1:1
[PEG_TRACE] Attempting to match rule `identifier` at 1:1
[PEG_TRACE] Matched rule `identifier` at 1:1 to 1:4
[PEG_TRACE] Matched rule `expression` at 1:1 to 1:4
[PEG_TRACE] Attempting to match rule `expression` at 1:1
[PEG_TRACE] Attempting to match rule `function_call` at 1:1
[PEG_TRACE] Cached fail of rule expression at 1:1
[PEG_TRACE] Failed to match rule `function_call` at 1:1
[PEG_TRACE] Attempting to match rule `identifier` at 1:1
[PEG_TRACE] Matched rule `identifier` at 1:1 to 1:4
[PEG_TRACE] Matched rule `expression` at 1:1 to 1:4
[PEG_TRACE] Attempting to match rule `expression` at 1:1
[PEG_TRACE] Cached fail of rule function_call at 1:1
[PEG_TRACE] Attempting to match rule `identifier` at 1:1
[PEG_TRACE] Matched rule `identifier` at 1:1 to 1:4
[PEG_TRACE] Matched rule `expression` at 1:1 to 1:4
Err(ParseError { location: LineCol { line: 1, column: 4, offset: 3 }, expected: ExpectedSet { expected: {"['a' ..= 'z']", "EOF"} } })
It looks as if it just discards the possibility of the expression
being a function_call
at the very beginning and just matches abc
as an identifier
, leaving ()
which then causes the error.
I would really appreciate some help, as I have banged my head against this for like 2 days.