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