Get rid of left-recursion cached rule
This commit is contained in:
parent
10ea99e95c
commit
13353f8801
@ -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 }
|
||||||
|
Loading…
Reference in New Issue
Block a user