git.delta.rocks / jrsonnet / refs/commits / 4d5d46c772ee

difftreelog

Add location info to all sub-expressions

Kohei Suzuki2021-09-22parent: #62c9d0d.patch.diff
in: master

2 files changed

modifiedcrates/jrsonnet-parser/src/expr.rsdiffbeforeafterboth
--- a/crates/jrsonnet-parser/src/expr.rs
+++ b/crates/jrsonnet-parser/src/expr.rs
@@ -403,11 +403,3 @@
 		)
 	};
 }
-
-/// Creates LocExpr without location info
-#[macro_export]
-macro_rules! loc_expr_todo {
-	($expr:expr) => {
-		LocExpr(Rc::new($expr), None)
-	};
-}
modifiedcrates/jrsonnet-parser/src/lib.rsdiffbeforeafterboth
1717
18macro_rules! expr_bin {18macro_rules! expr_bin {
19 ($a:ident $op:ident $b:ident) => {19 ($a:ident $op:ident $b:ident) => {
20 loc_expr_todo!(Expr::BinaryOp($a, $op, $b))20 Expr::BinaryOp($a, $op, $b)
21 };21 };
22}22}
23macro_rules! expr_un {23macro_rules! expr_un {
24 ($op:ident $a:ident) => {24 ($op:ident $a:ident) => {
25 loc_expr_todo!(Expr::UnaryOp($op, $a))25 Expr::UnaryOp($op, $a)
26 };26 };
27}27}
2828
5555
56 rule keyword(id: &'static str) -> ()56 rule keyword(id: &'static str) -> ()
57 = ##parse_string_literal(id) end_of_ident()57 = ##parse_string_literal(id) end_of_ident()
58 // Adds location data information to existing expression
59 rule l(s: &ParserSettings, x: rule<Expr>) -> LocExpr
60 = start:position!() v:x() end:position!() {loc_expr!(v, s.loc_data, (s.file_name.clone(), start, end))}
6158
62 pub rule param(s: &ParserSettings) -> expr::Param = name:$(id()) expr:(_ "=" _ expr:expr(s){expr})? { expr::Param(name.into(), expr) }59 pub rule param(s: &ParserSettings) -> expr::Param = name:$(id()) expr:(_ "=" _ expr:expr(s){expr})? { expr::Param(name.into(), expr) }
63 pub rule params(s: &ParserSettings) -> expr::ParamsDesc60 pub rule params(s: &ParserSettings) -> expr::ParamsDesc
166 = keyword("for") _ id:$(id()) _ keyword("in") _ cond:expr(s) {ForSpecData(id.into(), cond)}163 = keyword("for") _ id:$(id()) _ keyword("in") _ cond:expr(s) {ForSpecData(id.into(), cond)}
167 pub rule compspec(s: &ParserSettings) -> Vec<expr::CompSpec>164 pub rule compspec(s: &ParserSettings) -> Vec<expr::CompSpec>
168 = s:(i:ifspec(s) { expr::CompSpec::IfSpec(i) } / f:forspec(s) {expr::CompSpec::ForSpec(f)} ) ** _ {s}165 = s:(i:ifspec(s) { expr::CompSpec::IfSpec(i) } / f:forspec(s) {expr::CompSpec::ForSpec(f)} ) ** _ {s}
169 pub rule local_expr(s: &ParserSettings) -> LocExpr166 pub rule local_expr(s: &ParserSettings) -> Expr
170 = l(s,<keyword("local") _ binds:bind(s) ** comma() _ ";" _ expr:expr(s) { Expr::LocalExpr(binds, expr) }>)167 = keyword("local") _ binds:bind(s) ** comma() _ ";" _ expr:expr(s) { Expr::LocalExpr(binds, expr) }
171 pub rule string_expr(s: &ParserSettings) -> LocExpr168 pub rule string_expr(s: &ParserSettings) -> Expr
172 = l(s, <s:string() {Expr::Str(s.into())}>)169 = s:string() {Expr::Str(s.into())}
173 pub rule obj_expr(s: &ParserSettings) -> LocExpr170 pub rule obj_expr(s: &ParserSettings) -> Expr
174 = l(s,<"{" _ body:objinside(s) _ "}" {Expr::Obj(body)}>)171 = "{" _ body:objinside(s) _ "}" {Expr::Obj(body)}
175 pub rule array_expr(s: &ParserSettings) -> LocExpr172 pub rule array_expr(s: &ParserSettings) -> Expr
176 = l(s,<"[" _ elems:(expr(s) ** comma()) _ comma()? "]" {Expr::Arr(elems)}>)173 = "[" _ elems:(expr(s) ** comma()) _ comma()? "]" {Expr::Arr(elems)}
177 pub rule array_comp_expr(s: &ParserSettings) -> LocExpr174 pub rule array_comp_expr(s: &ParserSettings) -> Expr
178 = l(s,<"[" _ expr:expr(s) _ comma()? _ forspec:forspec(s) _ others:(others: compspec(s) _ {others})? "]" {175 = "[" _ expr:expr(s) _ comma()? _ forspec:forspec(s) _ others:(others: compspec(s) _ {others})? "]" {
179 let mut specs = vec![CompSpec::ForSpec(forspec)];176 let mut specs = vec![CompSpec::ForSpec(forspec)];
180 specs.extend(others.unwrap_or_default());177 specs.extend(others.unwrap_or_default());
181 Expr::ArrComp(expr, specs)178 Expr::ArrComp(expr, specs)
182 }>)179 }
183 pub rule number_expr(s: &ParserSettings) -> LocExpr180 pub rule number_expr(s: &ParserSettings) -> Expr
184 = l(s,<n:number() { expr::Expr::Num(n) }>)181 = n:number() { expr::Expr::Num(n) }
185 pub rule var_expr(s: &ParserSettings) -> LocExpr182 pub rule var_expr(s: &ParserSettings) -> Expr
186 = l(s,<n:$(id()) { expr::Expr::Var(n.into()) }>)183 = n:$(id()) { expr::Expr::Var(n.into()) }
187 pub rule if_then_else_expr(s: &ParserSettings) -> LocExpr184 pub rule if_then_else_expr(s: &ParserSettings) -> Expr
188 = l(s,<cond:ifspec(s) _ keyword("then") _ cond_then:expr(s) cond_else:(_ keyword("else") _ e:expr(s) {e})? {Expr::IfElse{185 = cond:ifspec(s) _ keyword("then") _ cond_then:expr(s) cond_else:(_ keyword("else") _ e:expr(s) {e})? {Expr::IfElse{
189 cond,186 cond,
190 cond_then,187 cond_then,
191 cond_else,188 cond_else,
192 }}>)189 }}
193190
194 pub rule literal(s: &ParserSettings) -> LocExpr191 pub rule literal(s: &ParserSettings) -> Expr
195 = l(s,<v:(192 = v:(
196 keyword("null") {LiteralType::Null}193 keyword("null") {LiteralType::Null}
197 / keyword("true") {LiteralType::True}194 / keyword("true") {LiteralType::True}
198 / keyword("false") {LiteralType::False}195 / keyword("false") {LiteralType::False}
199 / keyword("self") {LiteralType::This}196 / keyword("self") {LiteralType::This}
200 / keyword("$") {LiteralType::Dollar}197 / keyword("$") {LiteralType::Dollar}
201 / keyword("super") {LiteralType::Super}198 / keyword("super") {LiteralType::Super}
202 ) {Expr::Literal(v)}>)199 ) {Expr::Literal(v)}
203200
204 pub rule expr_basic(s: &ParserSettings) -> LocExpr201 pub rule expr_basic(s: &ParserSettings) -> Expr
205 = literal(s)202 = literal(s)
206203
207 / quiet!{l(s,<"$intrinsic(" name:$(id()) ")" {Expr::Intrinsic(name.into())}>)}204 / quiet!{"$intrinsic(" name:$(id()) ")" {Expr::Intrinsic(name.into())}}
208205
209 / string_expr(s) / number_expr(s)206 / string_expr(s) / number_expr(s)
210 / array_expr(s)207 / array_expr(s)
211 / obj_expr(s)208 / obj_expr(s)
212 / array_expr(s)209 / array_expr(s)
213 / array_comp_expr(s)210 / array_comp_expr(s)
214211
215 / l(s,<keyword("importstr") _ path:string() {Expr::ImportStr(PathBuf::from(path))}>)212 / keyword("importstr") _ path:string() {Expr::ImportStr(PathBuf::from(path))}
216 / l(s,<keyword("import") _ path:string() {Expr::Import(PathBuf::from(path))}>)213 / keyword("import") _ path:string() {Expr::Import(PathBuf::from(path))}
217214
218 / var_expr(s)215 / var_expr(s)
219 / local_expr(s)216 / local_expr(s)
220 / if_then_else_expr(s)217 / if_then_else_expr(s)
221218
222 / l(s,<keyword("function") _ "(" _ params:params(s) _ ")" _ expr:expr(s) {Expr::Function(params, expr)}>)219 / keyword("function") _ "(" _ params:params(s) _ ")" _ expr:expr(s) {Expr::Function(params, expr)}
223 / l(s,<assertion:assertion(s) _ ";" _ expr:expr(s) { Expr::AssertExpr(assertion, expr) }>)220 / assertion:assertion(s) _ ";" _ expr:expr(s) { Expr::AssertExpr(assertion, expr) }
224221
225 / l(s,<keyword("error") _ expr:expr(s) { Expr::ErrorStmt(expr) }>)222 / keyword("error") _ expr:expr(s) { Expr::ErrorStmt(expr) }
226223
227 rule slice_part(s: &ParserSettings) -> Option<LocExpr>224 rule slice_part(s: &ParserSettings) -> Option<LocExpr>
228 = e:(_ e:expr(s) _{e})? {e}225 = e:(_ e:expr(s) _{e})? {e}
246 use BinaryOpType::*;243 use BinaryOpType::*;
247 use UnaryOpType::*;244 use UnaryOpType::*;
248 rule expr(s: &ParserSettings) -> LocExpr245 rule expr(s: &ParserSettings) -> LocExpr
249 = start:position!() a:precedence! {246 = precedence! {
247 start:position!() v:@ end:position!() { loc_expr!(v, s.loc_data, (s.file_name.clone(), start, end)) }
248 --
250 a:(@) _ binop(<"||">) _ b:@ {expr_bin!(a Or b)}249 a:(@) _ binop(<"||">) _ b:@ {expr_bin!(a Or b)}
251 --250 --
252 a:(@) _ binop(<"&&">) _ b:@ {expr_bin!(a And b)}251 a:(@) _ binop(<"&&">) _ b:@ {expr_bin!(a And b)}
280 unaryop(<"!">) _ b:@ {expr_un!(Not b)}279 unaryop(<"!">) _ b:@ {expr_un!(Not b)}
281 unaryop(<"~">) _ b:@ {expr_un!(BitNot b)}280 unaryop(<"~">) _ b:@ {expr_un!(BitNot b)}
282 --281 --
283 a:(@) _ "[" _ s:slice_desc(s) _ "]" {loc_expr_todo!(Expr::Slice(a, s))}282 a:(@) _ "[" _ e:slice_desc(s) _ "]" {Expr::Slice(a, e)}
284 a:(@) _ "." _ s:$(id()) {loc_expr_todo!(Expr::Index(a, el!(Expr::Str(s.into()))))}283 a:(@) _ "." _ e:$(id()) {Expr::Index(a, el!(Expr::Str(e.into())))}
285 a:(@) _ "[" _ s:expr(s) _ "]" {loc_expr_todo!(Expr::Index(a, s))}284 a:(@) _ "[" _ e:expr(s) _ "]" {Expr::Index(a, e)}
286 a:(@) _ "(" _ args:args(s) _ ")" ts:(_ keyword("tailstrict"))? {loc_expr_todo!(Expr::Apply(a, args, ts.is_some()))}285 a:(@) _ "(" _ args:args(s) _ ")" ts:(_ keyword("tailstrict"))? {Expr::Apply(a, args, ts.is_some())}
287 a:(@) _ "{" _ body:objinside(s) _ "}" {loc_expr_todo!(Expr::ObjExtend(a, body))}286 a:(@) _ "{" _ body:objinside(s) _ "}" {Expr::ObjExtend(a, body)}
288 --287 --
289 e:expr_basic(s) {e}288 e:expr_basic(s) {e}
290 "(" _ e:expr(s) _ ")" {loc_expr_todo!(Expr::Parened(e))}289 "(" _ e:expr(s) _ ")" {Expr::Parened(e)}
291 } end:position!() {290 }
292 let LocExpr(e, _) = a;
293 LocExpr(e, if s.loc_data {
294 Some(ExprLocation(s.file_name.clone(), start, end))
295 } else {
296 None
297 })
298 }
299 / e:expr_basic(s) {e}
300291
301 pub rule jsonnet(s: &ParserSettings) -> LocExpr = _ e:expr(s) _ {e}292 pub rule jsonnet(s: &ParserSettings) -> LocExpr = _ e:expr(s) _ {e}
302 }293 }
334 };325 };
335 }326 }
327
328 macro_rules! el_loc {
329 ($expr:expr, $loc:expr$(,)?) => {
330 LocExpr(std::rc::Rc::new($expr), Some($loc))
331 };
332 }
336333
337 mod expressions {334 mod expressions {
338 use super::*;335 use super::*;
576 parse!(jrsonnet_stdlib::STDLIB_STR);573 parse!(jrsonnet_stdlib::STDLIB_STR);
577 }574 }
578575
576 #[test]
577 fn add_location_info_to_all_sub_expressions() {
578 use Expr::*;
579
580 let file_name: std::rc::Rc<std::path::Path> = PathBuf::from("/test.jsonnet").into();
581 let expr = parse(
582 "{} { local x = 1, x: x } + {}",
583 &ParserSettings {
584 loc_data: true,
585 file_name: file_name.clone(),
586 },
587 )
588 .unwrap();
589 assert_eq!(
590 expr,
591 el_loc!(
592 BinaryOp(
593 el_loc!(
594 ObjExtend(
595 el_loc!(
596 Obj(ObjBody::MemberList(vec![])),
597 ExprLocation(file_name.clone(), 0, 2)
598 ),
599 ObjBody::MemberList(vec![
600 Member::BindStmt(BindSpec {
601 name: "x".into(),
602 params: None,
603 value: el_loc!(
604 Num(1.0),
605 ExprLocation(file_name.clone(), 15, 16)
606 )
607 }),
608 Member::Field(FieldMember {
609 name: FieldName::Fixed("x".into()),
610 plus: false,
611 params: None,
612 visibility: Visibility::Normal,
613 value: el_loc!(
614 Var("x".into()),
615 ExprLocation(file_name.clone(), 21, 22)
616 ),
617 })
618 ])
619 ),
620 ExprLocation(file_name.clone(), 0, 24)
621 ),
622 BinaryOpType::Add,
623 el_loc!(
624 Obj(ObjBody::MemberList(vec![])),
625 ExprLocation(file_name.clone(), 27, 29)
626 ),
627 ),
628 ExprLocation(file_name.clone(), 0, 29),
629 ),
630 );
631 }
579 // From source code632 // From source code
580 /*633 /*
581 #[bench]634 #[bench]