Get rid of left-recursion cached rule

This commit is contained in:
Greg Shuflin 2021-11-12 21:41:15 -08:00
parent 10ea99e95c
commit 13353f8801

View File

@ -6,6 +6,12 @@ fn rc_string(s: &str) -> Rc<String> {
Rc::new(s.to_string())
}
enum ExtendedPart<'a> {
Index(Vec<Expression>),
Accessor(&'a str),
Call(Vec<InvocationArgument>),
}
peg::parser! {
pub grammar schala_parser() for str {
@ -207,52 +213,33 @@ peg::parser! {
quiet!{$( ['+' | '-' | '*' | '/' | '%' | '<' | '>' | '=' | '!' | '$' | '&' | '|' | '?' | '^' | '`']+ )} /
expected!("operator")
rule extended_expr(struct_ok: bool) -> ExpressionKind =
item:extended_expr_ok_struct() {? if struct_ok { Ok(item) } else { Err("no-struct-allowed") } } /
item:extended_expr_no_struct() {? if !struct_ok { Ok(item) } else { Err("!no-struct-allowed") } }
primary:primary(struct_ok) parts:(extended_expr_part()*) {
let mut expression = Expression::new(Default::default(), primary);
for part in parts.into_iter() {
let kind = match part {
ExtendedPart::Index(indexers) => {
ExpressionKind::Index { indexee: Box::new(expression), indexers }
},
ExtendedPart::Accessor(name) => {
let name = rc_string(name);
ExpressionKind::Access { name, expr: Box::new(expression) }
},
ExtendedPart::Call(arguments) => {
ExpressionKind::Call { f: Box::new(expression), arguments }
}
};
#[cache_left_rec]
rule extended_expr_ok_struct() -> ExpressionKind =
indexee:extended_expr_ok_struct() indexers:index_part() {
ExpressionKind::Index {
indexee: Box::new(Expression::new(Default::default(), indexee)),
indexers,
}
} /
f:extended_expr_ok_struct() arguments:call_part() {
ExpressionKind::Call {
f: Box::new(Expression::new(Default::default(), f)),
arguments,
expression = Expression::new(Default::default(), kind);
}
} /
expr:extended_expr_ok_struct() "." name:identifier() { ExpressionKind::Access {
name: Rc::new(name.to_string()),
expr: Box::new(Expression::new(Default::default(),expr)),
} } /
primary(true)
expression.kind
}
#[cache_left_rec]
rule extended_expr_no_struct() -> ExpressionKind =
indexee:extended_expr_no_struct() indexers:index_part() {
ExpressionKind::Index {
indexee: Box::new(Expression::new(Default::default(), indexee)),
indexers,
}
} /
f:extended_expr_no_struct() arguments:call_part() {
ExpressionKind::Call {
f: Box::new(Expression::new(Default::default(), f)),
arguments,
}
} /
expr:extended_expr_no_struct() "." name:identifier() { ExpressionKind::Access {
name: Rc::new(name.to_string()),
expr: Box::new(Expression::new(Default::default(),expr)),
} } /
primary(false)
rule extended_expr_part() -> ExtendedPart<'input> =
indexers:index_part() { ExtendedPart::Index(indexers) } /
arguments:call_part() { ExtendedPart::Call(arguments) } /
"." name:identifier() { ExtendedPart::Accessor(name) }
rule index_part() -> Vec<Expression> =
"[" indexers:(expression() ++ ",") "]" { indexers }