git.delta.rocks / jrsonnet / refs/commits / be9904ac0d57

difftreelog

fix(parser) use precedence climbing for suffixes

Лач2020-06-06parent: #e78129a.patch.diff
in: master

1 file changed

modifiedcrates/jsonnet-parser/src/lib.rsdiffbeforeafterboth
9pub use expr::*;9pub use expr::*;
10pub use peg;10pub use peg;
11
12enum Suffix {
13 String(String),
14 Slice(SliceDesc),
15 Expression(LocExpr),
16 Apply(expr::ArgsDesc),
17 Extend(expr::ObjBody),
18}
19struct LocSuffix(Suffix, ExprLocation);
2011
21pub struct ParserSettings {12pub struct ParserSettings {
22 pub loc_data: bool,13 pub loc_data: bool,
41 rule digit() -> char = d:$(['0'..='9']) {d.chars().next().unwrap()}32 rule digit() -> char = d:$(['0'..='9']) {d.chars().next().unwrap()}
42 rule end_of_ident() = !['0'..='9' | '_' | 'a'..='z' | 'A'..='Z']33 rule end_of_ident() = !['0'..='9' | '_' | 'a'..='z' | 'A'..='Z']
43 /// Sequence of digits34 /// Sequence of digits
44 rule uint() -> u32 = a:$(digit()+) { a.parse().unwrap() }35 rule uint() -> u64 = a:$(digit()+) { a.parse().unwrap() }
45 /// Number in scientific notation format36 /// Number in scientific notation format
46 rule number() -> f64 = quiet!{a:$(uint() ("." uint())? (['e'|'E'] (s:['+'|'-'])? uint())?) { a.parse().unwrap() }} / expected!("<number>")37 rule number() -> f64 = quiet!{a:$(uint() ("." uint())? (['e'|'E'] (s:['+'|'-'])? uint())?) { a.parse().unwrap() }} / expected!("<number>")
4738
184175
185 / l(s,<keyword("error") _ expr:expr(s) { Expr::Error(expr) }>)176 / l(s,<keyword("error") _ expr:expr(s) { Expr::Error(expr) }>)
186
187 rule expr_basic_with_suffix(s: &ParserSettings) -> LocExpr
188 = a:expr_basic(s) suffixes:(_ suffix:l_expr_suffix(s) {suffix})* {
189 let mut cur = a;
190 for suffix in suffixes {
191 let LocSuffix(suffix, location) = suffix;
192 cur = LocExpr(Rc::new(match suffix {
193 Suffix::String(index) => Expr::Index(cur, loc_expr!(Expr::Str(index), s.loc_data, (s.file_name.clone(), location.1, location.2))),
194 Suffix::Slice(desc) => Expr::Slice(cur, desc),
195 Suffix::Expression(index) => Expr::Index(cur, index),
196 Suffix::Apply(args) => Expr::Apply(cur, args),
197 Suffix::Extend(body) => Expr::ObjExtend(cur, body),
198 }), if s.loc_data { Some(Rc::new(location)) } else { None })
199 }
200 cur
201 }
202177
203 pub rule slice_desc(s: &ParserSettings) -> SliceDesc178 pub rule slice_desc(s: &ParserSettings) -> SliceDesc
204 = start:expr(s)? _ ":" _ pair:(end:expr(s)? _ step:(":" _ e:expr(s) {e})? {(end, step)})? {179 = start:expr(s)? _ ":" _ pair:(end:expr(s)? _ step:(":" _ e:expr(s) {e})? {(end, step)})? {
209 }184 }
210 }185 }
211186
212 rule expr_suffix(s: &ParserSettings) -> Suffix187 rule expr(s: &ParserSettings) -> LocExpr
213 = "." _ s:id() { Suffix::String(s) }
214 / "[" _ s:slice_desc(s) _ "]" { Suffix::Slice(s) }
215 / "[" _ s:expr(s) _ "]" { Suffix::Expression(s) }
216 / "(" _ args:args(s) _ ")" (_ keyword("tailstrict"))? { Suffix::Apply(args) }
217 / "{" _ body:objinside(s) _ "}" { Suffix::Extend(body) }
218 rule l_expr_suffix(s: &ParserSettings) -> LocSuffix
219 = start:position!() suffix:expr_suffix(s) end:position!() {LocSuffix(suffix, ExprLocation(s.file_name.clone(), start, end))}
220
221 rule expr(s: &ParserSettings) -> LocExpr
222 = start:position!() a:precedence! {188 = start:position!() a:precedence! {
223 a:(@) _ "||" _ b:@ {loc_expr_todo!(Expr::BinaryOp(a, BinaryOpType::Or, b))}189 a:(@) _ "||" _ b:@ {loc_expr_todo!(Expr::BinaryOp(a, BinaryOpType::Or, b))}
224 --190 --
267 "!" _ b:@ {loc_expr_todo!(Expr::UnaryOp(UnaryOpType::Not, b))}233 "!" _ b:@ {loc_expr_todo!(Expr::UnaryOp(UnaryOpType::Not, b))}
268 "~" _ b:@ { loc_expr_todo!(Expr::UnaryOp(UnaryOpType::BitNot, b)) }234 "~" _ b:@ { loc_expr_todo!(Expr::UnaryOp(UnaryOpType::BitNot, b)) }
269 --235 --
236 a:(@) _ "[" _ s:slice_desc(s) _ "]" {loc_expr_todo!(Expr::Slice(a, s))}
237 a:(@) _ "." _ s:id() {loc_expr_todo!(Expr::Index(a, el!(Expr::Str(s))))}
238 a:(@) _ "[" _ s:expr(s) _ "]" {loc_expr_todo!(Expr::Index(a, s))}
239 a:(@) _ "(" _ args:args(s) _ ")" (_ keyword("tailstrict"))? {loc_expr_todo!(Expr::Apply(a, args))}
240 a:(@) _ "{" _ body:objinside(s) _ "}" {loc_expr_todo!(Expr::ObjExtend(a, body))}
241 --
270 e:expr_basic_with_suffix(s) {e}242 e:expr_basic(s) {e}
271 "(" _ e:expr(s) _ ")" {loc_expr_todo!(Expr::Parened(e))}243 "(" _ e:expr(s) _ ")" {loc_expr_todo!(Expr::Parened(e))}
272 } end:position!() {244 } end:position!() {
273 let LocExpr(e, _) = a;245 let LocExpr(e, _) = a;
277 None249 None
278 })250 })
279 }251 }
280 / e:expr_basic_with_suffix(s) {e}252 / e:expr_basic(s) {e}
281253
282 pub rule jsonnet(s: &ParserSettings) -> LocExpr = _ e:expr(s) _ {e}254 pub rule jsonnet(s: &ParserSettings) -> LocExpr = _ e:expr(s) _ {e}
283 }255 }
398 );370 );
399 }371 }
372
373 #[test]
374 fn suffix() {
375 // assert_eq!(parse!("std.test"), el!(Expr::Num(2.2)));
376 // assert_eq!(parse!("std(2)"), el!(Expr::Num(2.2)));
377 // assert_eq!(parse!("std.test(2)"), el!(Expr::Num(2.2)));
378 // assert_eq!(parse!("a[b]"), el!(Expr::Num(2.2)))
379 }
400380
401 #[test]381 #[test]
402 fn array_comp() {382 fn array_comp() {