From be9904ac0d57fd543612e99582af9e845e44265b Mon Sep 17 00:00:00 2001 From: Лач Date: Sat, 06 Jun 2020 09:32:25 +0000 Subject: [PATCH] fix(parser): use precedence climbing for suffixes --- --- a/crates/jsonnet-parser/src/lib.rs +++ b/crates/jsonnet-parser/src/lib.rs @@ -9,15 +9,6 @@ pub use expr::*; pub use peg; -enum Suffix { - String(String), - Slice(SliceDesc), - Expression(LocExpr), - Apply(expr::ArgsDesc), - Extend(expr::ObjBody), -} -struct LocSuffix(Suffix, ExprLocation); - pub struct ParserSettings { pub loc_data: bool, pub file_name: PathBuf, @@ -41,7 +32,7 @@ rule digit() -> char = d:$(['0'..='9']) {d.chars().next().unwrap()} rule end_of_ident() = !['0'..='9' | '_' | 'a'..='z' | 'A'..='Z'] /// Sequence of digits - rule uint() -> u32 = a:$(digit()+) { a.parse().unwrap() } + rule uint() -> u64 = a:$(digit()+) { a.parse().unwrap() } /// Number in scientific notation format rule number() -> f64 = quiet!{a:$(uint() ("." uint())? (['e'|'E'] (s:['+'|'-'])? uint())?) { a.parse().unwrap() }} / expected!("") @@ -183,22 +174,6 @@ / l(s,) / l(s,) - - rule expr_basic_with_suffix(s: &ParserSettings) -> LocExpr - = a:expr_basic(s) suffixes:(_ suffix:l_expr_suffix(s) {suffix})* { - let mut cur = a; - for suffix in suffixes { - let LocSuffix(suffix, location) = suffix; - cur = LocExpr(Rc::new(match suffix { - Suffix::String(index) => Expr::Index(cur, loc_expr!(Expr::Str(index), s.loc_data, (s.file_name.clone(), location.1, location.2))), - Suffix::Slice(desc) => Expr::Slice(cur, desc), - Suffix::Expression(index) => Expr::Index(cur, index), - Suffix::Apply(args) => Expr::Apply(cur, args), - Suffix::Extend(body) => Expr::ObjExtend(cur, body), - }), if s.loc_data { Some(Rc::new(location)) } else { None }) - } - cur - } pub rule slice_desc(s: &ParserSettings) -> SliceDesc = start:expr(s)? _ ":" _ pair:(end:expr(s)? _ step:(":" _ e:expr(s) {e})? {(end, step)})? { @@ -209,15 +184,6 @@ } } - rule expr_suffix(s: &ParserSettings) -> Suffix - = "." _ s:id() { Suffix::String(s) } - / "[" _ s:slice_desc(s) _ "]" { Suffix::Slice(s) } - / "[" _ s:expr(s) _ "]" { Suffix::Expression(s) } - / "(" _ args:args(s) _ ")" (_ keyword("tailstrict"))? { Suffix::Apply(args) } - / "{" _ body:objinside(s) _ "}" { Suffix::Extend(body) } - rule l_expr_suffix(s: &ParserSettings) -> LocSuffix - = start:position!() suffix:expr_suffix(s) end:position!() {LocSuffix(suffix, ExprLocation(s.file_name.clone(), start, end))} - rule expr(s: &ParserSettings) -> LocExpr = start:position!() a:precedence! { a:(@) _ "||" _ b:@ {loc_expr_todo!(Expr::BinaryOp(a, BinaryOpType::Or, b))} @@ -267,7 +233,13 @@ "!" _ b:@ {loc_expr_todo!(Expr::UnaryOp(UnaryOpType::Not, b))} "~" _ b:@ { loc_expr_todo!(Expr::UnaryOp(UnaryOpType::BitNot, b)) } -- - e:expr_basic_with_suffix(s) {e} + a:(@) _ "[" _ s:slice_desc(s) _ "]" {loc_expr_todo!(Expr::Slice(a, s))} + a:(@) _ "." _ s:id() {loc_expr_todo!(Expr::Index(a, el!(Expr::Str(s))))} + a:(@) _ "[" _ s:expr(s) _ "]" {loc_expr_todo!(Expr::Index(a, s))} + a:(@) _ "(" _ args:args(s) _ ")" (_ keyword("tailstrict"))? {loc_expr_todo!(Expr::Apply(a, args))} + a:(@) _ "{" _ body:objinside(s) _ "}" {loc_expr_todo!(Expr::ObjExtend(a, body))} + -- + e:expr_basic(s) {e} "(" _ e:expr(s) _ ")" {loc_expr_todo!(Expr::Parened(e))} } end:position!() { let LocExpr(e, _) = a; @@ -277,7 +249,7 @@ None }) } - / e:expr_basic_with_suffix(s) {e} + / e:expr_basic(s) {e} pub rule jsonnet(s: &ParserSettings) -> LocExpr = _ e:expr(s) _ {e} } @@ -399,6 +371,14 @@ } #[test] + fn suffix() { + // assert_eq!(parse!("std.test"), el!(Expr::Num(2.2))); + // assert_eq!(parse!("std(2)"), el!(Expr::Num(2.2))); + // assert_eq!(parse!("std.test(2)"), el!(Expr::Num(2.2))); + // assert_eq!(parse!("a[b]"), el!(Expr::Num(2.2))) + } + + #[test] fn array_comp() { use Expr::*; assert_eq!( -- gitstuff