git.delta.rocks / jrsonnet / refs/commits / 45767d31ad1f

difftreelog

refactor(parser) make parser parse stdlib successfully

Лач2020-05-29parent: #aee104d.patch.diff
in: master

4 files changed

modifiedcrates/jsonnet-parser/Cargo.tomldiffbeforeafterboth
12[dependencies]12[dependencies]
13peg = "0.6.2"13peg = "0.6.2"
14
15[dev-dependencies]
16jsonnet-stdlib = { version = "0.1.0", path = "../jsonnet-stdlib" }
1417
addedcrates/jsonnet-parser/README.mddiffbeforeafterboth

no changes

modifiedcrates/jsonnet-parser/src/expr.rsdiffbeforeafterboth
1use std::fmt::Display;
2
1#[derive(Debug, Clone, PartialEq)]3#[derive(Debug, Clone, PartialEq)]
2pub enum FieldName {4pub enum FieldName {
20pub struct AssertStmt(pub Box<Expr>, pub Option<Box<Expr>>);22pub struct AssertStmt(pub Box<Expr>, pub Option<Box<Expr>>);
2123
22#[derive(Debug, Clone, PartialEq)]24#[derive(Debug, Clone, PartialEq)]
23pub enum FieldMember {25pub struct FieldMember {
24 Value {
25 name: FieldName,26 pub name: FieldName,
26 plus: bool,27 pub plus: bool,
27 visibility: Visibility,
28 value: Expr,
29 },
30 Function {
31 name: FieldName,
32 params: ParamsDesc,28 pub params: Option<ParamsDesc>,
33 visibility: Visibility,29 pub visibility: Visibility,
34 value: Expr,30 pub value: Expr,
35 },
36}31}
3732
38#[derive(Debug, Clone, PartialEq)]33#[derive(Debug, Clone, PartialEq)]
39pub enum Member {34pub enum Member {
40 Field(FieldMember),35 Field(FieldMember),
41 BindStmt(Bind),36 BindStmt(BindSpec),
42 AssertStmt(AssertStmt),37 AssertStmt(AssertStmt),
43}38}
4439
50 Not,45 Not,
51}46}
5247
53#[derive(Debug, Clone, PartialEq)]48#[derive(Debug, Clone, Copy, PartialEq)]
54pub enum BinaryOpType {49pub enum BinaryOpType {
55 Mul,50 Mul,
56 Div,51 Div,
80 Or,75 Or,
81}76}
8277
78/// name, default value
83#[derive(Debug, Clone, PartialEq)]79#[derive(Debug, Clone, PartialEq)]
84pub enum Param {80pub struct Param(pub String, pub Option<Box<Expr>>);
85 Positional(String),81/// Defined function parameters
86 Named(String, Box<Expr>),
87}
88
89#[derive(Debug, Clone, PartialEq)]82#[derive(Debug, Clone, PartialEq)]
90pub struct ParamsDesc(pub Vec<Param>);83pub struct ParamsDesc(pub Vec<Param>);
84impl ParamsDesc {
85 pub fn with_defaults(&self) -> Vec<Param> {
86 self.0
87 .iter()
88 .filter(|e| e.1.is_some())
89 .map(|e| e.clone())
90 .collect()
91 }
92}
9193
92#[derive(Debug, Clone, PartialEq)]94#[derive(Debug, Clone, PartialEq)]
93pub enum Arg {95pub struct Arg(pub Option<String>, pub Box<Expr>);
94 Positional(Box<Expr>),
95 Named(String, Box<Expr>),
96}
97
98#[derive(Debug, Clone, PartialEq)]96#[derive(Debug, Clone, PartialEq)]
99pub struct ArgsDesc(pub Vec<Arg>);97pub struct ArgsDesc(pub Vec<Arg>);
10098
101#[derive(Debug, Clone, PartialEq)]99#[derive(Debug, Clone, PartialEq)]
102pub enum Bind {100pub struct BindSpec {
101 pub name: String,
103 Value(String, Box<Expr>),102 pub params: Option<ParamsDesc>,
104 Function(String, ParamsDesc, Box<Expr>),103 pub value: Box<Expr>,
105}104}
106105
107#[derive(Debug, Clone, PartialEq)]106#[derive(Debug, Clone, PartialEq)]
108pub struct IfSpec(pub Box<Expr>);107pub struct IfSpecData(pub Box<Expr>);
109#[derive(Debug, Clone, PartialEq)]108#[derive(Debug, Clone, PartialEq)]
110pub struct ForSpec(pub String, pub Vec<IfSpec>);109pub struct ForSpecData(pub String, pub Box<Expr>);
111110
112#[derive(Debug, Clone, PartialEq)]111#[derive(Debug, Clone, PartialEq)]
113pub enum CompSpec {112pub enum CompSpec {
114 IfSpec(IfSpec),113 IfSpec(IfSpecData),
115 ForSpec(ForSpec),114 ForSpec(ForSpecData),
116}115}
117116
118#[derive(Debug, Clone, PartialEq)]117#[derive(Debug, Clone, PartialEq)]
119pub enum ObjBody {118pub enum ObjBody {
120 MemberList(Vec<Member>),119 MemberList(Vec<Member>),
121 ObjComp {120 ObjComp {
122 pre_locals: Vec<Bind>,121 pre_locals: Vec<BindSpec>,
123 key: Box<Expr>,122 key: Box<Expr>,
124 value: Box<Expr>,123 value: Box<Expr>,
125 post_locals: Vec<Bind>,124 post_locals: Vec<BindSpec>,
126 first: ForSpec,125 first: ForSpecData,
127 rest: Vec<CompSpec>,126 rest: Vec<CompSpec>,
128 },127 },
129}128}
130129
131#[derive(Debug, Clone, PartialEq)]130#[derive(Debug, Clone, PartialEq)]
132pub enum ValueType {131pub enum LiteralType {
132 This,
133 Super,
134 Dollar,
133 Null,135 Null,
134 True,136 True,
135 False,137 False,
136}138}
139impl Display for LiteralType {
140 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
141 use LiteralType::*;
142 match self {
143 This => write!(f, "this"),
144 Null => write!(f, "null"),
145 True => write!(f, "true"),
146 False => write!(f, "false"),
147 _ => panic!("non printable item"),
148 }
149 }
150}
137151
138#[derive(Debug, Clone, PartialEq)]152#[derive(Debug, Clone, PartialEq)]
139pub enum LiteralType {153pub struct SliceDesc {
140 This,154 pub start: Option<Box<Expr>>,
141 Super,155 pub end: Option<Box<Expr>>,
142 Dollar,156 pub step: Option<Box<Expr>>,
143}157}
144158
145/// Syntax base159/// Syntax base
146#[derive(Debug, Clone, PartialEq)]160#[derive(Debug, Clone, PartialEq)]
147pub enum Expr {161pub enum Expr {
148 Value(ValueType),
149 /// Plain value: null/true/false
150 Literal(LiteralType),162 Literal(LiteralType),
151163
152 /// String value: "hello"164 /// String value: "hello"
169 /// ]181 /// ]
170 /// ],182 /// ],
171 /// ```183 /// ```
172 ArrComp(Box<Expr>, Vec<ForSpec>),184 ArrComp(Box<Expr>, ForSpecData, Vec<CompSpec>),
173185
174 /// Object: {a: 2}186 /// Object: {a: 2}
175 Obj(ObjBody),187 Obj(ObjBody),
179 /// (obj)191 /// (obj)
180 Parened(Box<Expr>),192 Parened(Box<Expr>),
181193
194 /// Params in function definition
195 /// hello, world, test = 2
182 Params(ParamsDesc),196 Params(ParamsDesc),
197 /// Args in function call
198 /// 2 + 2, 3, named = 6
183 Args(ArgsDesc),199 Args(ArgsDesc),
184200
201 /// -2
185 UnaryOp(UnaryOpType, Box<Expr>),202 UnaryOp(UnaryOpType, Box<Expr>),
203 /// 2 - 2
186 BinaryOp(Box<Expr>, BinaryOpType, Box<Expr>),204 BinaryOp(Box<Expr>, BinaryOpType, Box<Expr>),
205 /// assert 2 == 2 : "Math is broken"
187 AssertExpr(AssertStmt, Box<Expr>),206 AssertExpr(AssertStmt, Box<Expr>),
207 /// local a = 2; { b: a }
188 LocalExpr(Vec<Bind>, Box<Expr>),208 LocalExpr(Vec<BindSpec>, Box<Expr>),
189209
210 /// a = 3
190 Bind(Bind),211 Bind(BindSpec),
212 /// import "hello"
191 Import(String),213 Import(String),
214 /// importStr "file.txt"
192 ImportStr(String),215 ImportStr(String),
216 /// error "I'm broken"
193 Error(Box<Expr>),217 Error(Box<Expr>),
218 /// a(b, c)
194 Apply(Box<Expr>, ArgsDesc),219 Apply(Box<Expr>, ArgsDesc),
220 ///
195 Select(Box<Expr>, String),221 Select(Box<Expr>, String),
222 /// a[b]
196 Index(Box<Expr>, Box<Expr>),223 Index(Box<Expr>, Box<Expr>),
224 /// a[1::2]
197 Slice {225 Slice(Box<Expr>, SliceDesc),
198 value: Box<Expr>,226 /// function(x) x
199 start: Option<Box<Expr>>,
200 end: Option<Box<Expr>>,
201 step: Option<Box<Expr>>,
202 },
203 Function(ParamsDesc, Box<Expr>),227 Function(ParamsDesc, Box<Expr>),
228 /// if true == false then 1 else 2
204 IfElse {229 IfElse {
205 cond: IfSpec,230 cond: IfSpecData,
206 cond_then: Box<Expr>,231 cond_then: Box<Expr>,
207 cond_else: Option<Box<Expr>>,232 cond_else: Option<Box<Expr>>,
208 },233 },
234 /// if 2 = 3
209 IfSpec(IfSpec),235 IfSpec(IfSpecData),
236 /// for elem in array
210 ForSpec(ForSpec),237 ForSpec(ForSpecData),
211}238}
212239
modifiedcrates/jsonnet-parser/src/lib.rsdiffbeforeafterboth
77
8enum Suffix {8enum Suffix {
9 String(String),9 String(String),
10 Slice(SliceDesc),
10 Expression(Expr),11 Expression(Expr),
11 Apply(expr::ArgsDesc),12 Apply(expr::ArgsDesc),
13 Extend(expr::ObjBody),
12}14}
1315
14parser! {16parser! {
15 grammar jsonnet_parser() for str {17 grammar jsonnet_parser() for str {
18 use peg::ParseLiteral;
19
20 /// Standard C-like comments
16 rule delimiter() = quiet!{__() "," __()} / expected!("<elements delimiter>")21 rule comment() = "//" (!['\n'][_])* "\n" / "/*" ((!("*/")[_][_])/("\\" "*/"))* "*/"
17 rule _() = quiet!{[' ' | '\n' | '\t']+} / expected!("<whitespace>")22 rule _() = ([' ' | '\n' | '\t'] / comment())*
23
24 /// For comma-delimited elements
18 rule __() = quiet!{[' ' | '\n' | '\t']*}25 rule comma() = quiet!{_ "," _} / expected!("<comma>")
19 rule alpha() -> char = c:$(['_' | 'a'..='z' | 'A'..='Z']) {c.chars().nth(0).unwrap()}26 rule alpha() -> char = c:$(['_' | 'a'..='z' | 'A'..='Z']) {c.chars().nth(0).unwrap()}
20 rule digit() -> char = d:$(['0'..='9']) {d.chars().nth(0).unwrap()}27 rule digit() -> char = d:$(['0'..='9']) {d.chars().nth(0).unwrap()}
21 rule int() -> u32 = a:$(digit()+) { a.parse().unwrap() }28 rule end_of_ident() = !['0'..='9' | '_' | 'a'..='z' | 'A'..='Z']
29 /// Sequence of digits
30 rule uint() -> u32 = a:$(digit()+) { a.parse().unwrap() }
31 /// Number in scientific notation format
22 rule number() -> f64 = quiet!{a:$((['-'|'+'])? int() ("." int())? (['e'|'E'] (s:['+'|'-'])? int())?) { a.parse().unwrap() }} / expected!("<number>")32 rule number() -> f64 = quiet!{a:$(uint() ("." uint())? (['e'|'E'] (s:['+'|'-'])? uint())?) { a.parse().unwrap() }} / expected!("<number>")
33
34 /// Reserved word followed by any non-alphanumberic
23 rule id() -> String = quiet!{ !("local" / "super" / "self" / "true" / "false" / "null" / "$" / "if" / "then" / "else" / "function") s:$(alpha() (alpha() / digit())*) {s.to_owned()}} / expected!("<identifier>")35 rule reserved() = ("assert" / "else" / "error" / "false" / "for" / "function" / "if" / "import" / "importstr" / "in" / "local" / "null" / "tailstrict" / "then" / "self" / "super" / "true") end_of_ident()
2436 rule id() -> String = quiet!{ !reserved() s:$(alpha() (alpha() / digit())*) {s.to_owned()}} / expected!("<identifier>")
25 pub rule positional_param() -> expr::Param = name:id() {expr::Param::Positional(name)}37 rule keyword(id: &'static str) = ##parse_string_literal(id) end_of_ident()
38
26 pub rule named_param() -> expr::Param = name:id() __() "=" __() expr:boxed_expr() {expr::Param::Named(name, expr)}39 pub rule param() -> expr::Param = name:id() expr:(_ "=" _ expr:boxed_expr(){expr})? { expr::Param(name, expr) }
27 pub rule params() -> expr::ParamsDesc40 pub rule params() -> expr::ParamsDesc
28 = positionals:(positional_param() ** delimiter()) named: (delimiter() named:(named_param() ** delimiter()) {named})? {41 = params:(param() ** comma()) {
42 let mut defaults_started = false;
43 for param in &params {
29 if named.is_some() {44 defaults_started = defaults_started || param.1.is_some();
30 expr::ParamsDesc([&positionals[..], &named.unwrap()[..]].concat())45 assert_eq!(defaults_started, param.1.is_some(), "defauld parameters should be used after all positionals");
31 } else {
32 expr::ParamsDesc(positionals)
33 }
34 }46 }
35 / named:(named_param() ** delimiter()) {expr::ParamsDesc(named)}47 expr::ParamsDesc(params)
48 }
36 / {expr::ParamsDesc(Vec::new())}49 / { expr::ParamsDesc(Vec::new()) }
3750
38 pub rule positional_arg() -> expr::Arg = quiet!{name:boxed_expr() {expr::Arg::Positional(name)}}/expected!("<positional arg>")51 pub rule arg() -> expr::Arg
52 = name:id() _ "=" _ expr:boxed_expr() {expr::Arg(Some(name), expr)}
39 pub rule named_arg() -> expr::Arg = quiet!{name:id() __() "=" __() expr:boxed_expr() {expr::Arg::Named(name, expr)}}/expected!("<named arg>")53 / expr:boxed_expr() {expr::Arg(None, expr)}
40 pub rule args() -> expr::ArgsDesc54 pub rule args() -> expr::ArgsDesc
41 = positionals:(positional_arg() ** delimiter()) named: (delimiter() named:(named_arg() ** delimiter()) {named})? {55 = args:arg() ** comma() comma()? {
56 let mut named_started = false;
57 for arg in &args {
42 if named.is_some() {58 named_started = named_started || arg.0.is_some();
43 expr::ArgsDesc([&positionals[..], &named.unwrap()[..]].concat())59 assert_eq!(named_started, arg.0.is_some(), "named args should be used after all positionals");
44 } else {
45 expr::ArgsDesc(positionals)
46 }
47 }60 }
48 / named:(named_arg() ** delimiter()) {expr::ArgsDesc(named)}61 expr::ArgsDesc(args)
62 }
49 / {expr::ArgsDesc(Vec::new())}63 / { expr::ArgsDesc(Vec::new()) }
5064
51 pub rule bind() -> expr::Bind65 pub rule bind() -> expr::BindSpec
52 = name:id() __() "=" __() expr:boxed_expr() {expr::Bind::Value(name, expr)}66 = name:id() _ "=" _ expr:boxed_expr() {expr::BindSpec{name, params: None, value: expr}}
53 / name:id() __() "(" __() params:params() __() ")" __() "=" __() expr:boxed_expr() {expr::Bind::Function(name, params, expr)}67 / name:id() _ "(" _ params:params() _ ")" _ "=" _ expr:boxed_expr() {expr::BindSpec{name, params: Some(params), value: expr}}
54 pub rule assertion() -> expr::AssertStmt = "assert" _() cond:boxed_expr() msg:(__() ":" __() e:boxed_expr() {e})? { expr::AssertStmt(cond, msg) }68 pub rule assertion() -> expr::AssertStmt = keyword("assert") _ cond:boxed_expr() msg:(_ ":" _ e:boxed_expr() {e})? { expr::AssertStmt(cond, msg) }
55 pub rule string() -> String69 pub rule string() -> String
56 = "\"" str:$((!['"'][_])*) "\"" {str.to_owned()}70 = "\"" str:$(("\\\"" / !['"'][_])*) "\"" {str.to_owned()}
57 / "'" str:$((!['\''][_])*) "'" {str.to_owned()}71 / "'" str:$((!['\''][_])*) "'" {str.to_owned()}
58 pub rule field_name() -> expr::FieldName72 pub rule field_name() -> expr::FieldName
59 = name:id() {expr::FieldName::Fixed(name)}73 = name:id() {expr::FieldName::Fixed(name)}
60 / name:string() {expr::FieldName::Fixed(name)}74 / name:string() {expr::FieldName::Fixed(name)}
61 / "[" __() expr:boxed_expr() __() "]" {expr::FieldName::Dyn(expr)}75 / "[" _ expr:boxed_expr() _ "]" {expr::FieldName::Dyn(expr)}
62 pub rule visibility() -> expr::Visibility76 pub rule visibility() -> expr::Visibility
63 = ":::" {expr::Visibility::Unhide}77 = ":::" {expr::Visibility::Unhide}
64 / "::" {expr::Visibility::Hidden}78 / "::" {expr::Visibility::Hidden}
65 / ":" {expr::Visibility::Normal}79 / ":" {expr::Visibility::Normal}
66 pub rule field() -> expr::FieldMember80 pub rule field() -> expr::FieldMember
67 = name:field_name() __() plus:"+"? __() visibility:visibility() __() value:expr() {expr::FieldMember::Value{81 = name:field_name() _ plus:"+"? _ visibility:visibility() _ value:expr() {expr::FieldMember{
68 name,82 name,
69 plus: plus.is_some(),83 plus: plus.is_some(),
84 params: None,
70 visibility,85 visibility,
71 value,86 value,
72 }}87 }}
73 / name:field_name() __() "(" __() params:params() __() ")" __() visibility:visibility() __() value:expr() {expr::FieldMember::Function{88 / name:field_name() _ "(" _ params:params() _ ")" _ visibility:visibility() _ value:expr() {expr::FieldMember{
74 name,89 name,
90 plus: false,
75 params,91 params: Some(params),
76 visibility,92 visibility,
77 value,93 value,
78 }}94 }}
95 pub rule obj_local() -> BindSpec
96 = keyword("local") _ bind:bind() {bind}
79 pub rule member() -> expr::Member97 pub rule member() -> expr::Member
80 = "local" _() bind:bind() {expr::Member::BindStmt(bind)}98 = bind:obj_local() {expr::Member::BindStmt(bind)}
81 / assertion:assertion() {expr::Member::AssertStmt(assertion)}99 / assertion:assertion() {expr::Member::AssertStmt(assertion)}
82 / field:field() {expr::Member::Field(field)}100 / field:field() {expr::Member::Field(field)}
83 pub rule obj_body() -> expr::ObjBody = members:(member() ** delimiter()) delimiter()? {expr::ObjBody::MemberList(members)}101 pub rule objinside() -> expr::ObjBody
102 = pre_locals:(b: obj_local() comma() {b})* "[" _ key:boxed_expr() _ "]" _ ":" _ value:boxed_expr() post_locals:(comma() b:obj_local() {b})* _ first:forspec() rest:(_ rest:compspec() {rest})? {
103 expr::ObjBody::ObjComp {
104 pre_locals,
105 key,
106 value,
107 post_locals,
108 first,
109 rest: rest.unwrap_or(Vec::new()),
110 }
111 }
112 / members:(member() ** comma()) comma()? {expr::ObjBody::MemberList(members)}
84 pub rule ifspec() -> expr::IfSpec = "if" _() expr:boxed_expr() {expr::IfSpec(expr)}113 pub rule ifspec() -> IfSpecData = keyword("if") _ expr:boxed_expr() {IfSpecData(expr)}
85 pub rule forspec() -> expr::ForSpec = "for" _() id:id() _() "in" _() ifs:ifspec()* {expr::ForSpec(id, ifs)}114 pub rule forspec() -> ForSpecData = keyword("for") _ id:id() _ keyword("in") _ cond:boxed_expr() {ForSpecData(id, cond)}
115 pub rule compspec() -> Vec<expr::CompSpec> = s:(i:ifspec() { expr::CompSpec::IfSpec(i) } / f:forspec() {expr::CompSpec::ForSpec(f)} )+ {s}
86 pub rule bind_expr() -> Expr = bind:bind() {Expr::Bind(bind)}116 pub rule bind_expr() -> Expr = bind:bind() {Expr::Bind(bind)}
87 pub rule local_expr() -> Expr = "local" _() binds:(bind() ** delimiter()) __() ";" __() expr:boxed_expr() { Expr::LocalExpr(binds, expr) }117 pub rule local_expr() -> Expr = keyword("local") _ binds:bind() ** comma() _ ";" _ expr:boxed_expr() { Expr::LocalExpr(binds, expr) }
88 pub rule string_expr() -> Expr = s:string() {Expr::Str(s)}118 pub rule string_expr() -> Expr = s:string() {Expr::Str(s)}
89 pub rule parened_expr() -> Expr = "(" e:boxed_expr() ")" {Expr::Parened(e)}119 pub rule parened_expr() -> Expr = "(" e:boxed_expr() ")" {Expr::Parened(e)}
90 pub rule obj_expr() -> Expr = "{" __() body:obj_body() __() "}" {Expr::Obj(body)}120 pub rule obj_expr() -> Expr = "{" _ body:objinside() _ "}" {Expr::Obj(body)}
91 pub rule array_expr() -> Expr = "[" __() elems:(expr() ** delimiter()) __() delimiter()? "]" {Expr::Arr(elems)}121 pub rule array_expr() -> Expr = "[" _ elems:(expr() ** comma()) _ comma()? "]" {Expr::Arr(elems)}
92 pub rule array_comp_expr() -> Expr = "[" __() expr:boxed_expr() delimiter()? fors:forspec()+ __() "]" {Expr::ArrComp(expr, fors)}122 pub rule array_comp_expr() -> Expr = "[" _ expr:boxed_expr() _ comma()? _ forspec:forspec() _ others:(others: compspec() _ {others})? "]" {Expr::ArrComp(expr, forspec, others.unwrap_or(vec![]))}
93 pub rule index_expr() -> Expr123 pub rule index_expr() -> Expr
94 = val:boxed_expr() "." idx:id() {Expr::Index(val, Box::new(Expr::Str(idx)))}124 = val:boxed_expr() "." idx:id() {Expr::Index(val, Box::new(Expr::Str(idx)))}
95 / val:boxed_expr() "[" key:boxed_expr() "]" {Expr::Index(val, key)}125 / val:boxed_expr() "[" key:boxed_expr() "]" {Expr::Index(val, key)}
96 pub rule slice_expr() -> Expr
97 = value:boxed_expr() "[" start:boxed_expr()? ":" pair:(end:boxed_expr()? step:(":" e:boxed_expr() {e})? {(end, step)})? "]" {
98 if let Some((end, step)) = pair {
99 Expr::Slice { value, start, end, step }
100 }else{
101 Expr::Slice{ value, start, end: None, step: None }
102 }
103 }
104 pub rule number_expr() -> Expr = n:number() { expr::Expr::Num(n) }126 pub rule number_expr() -> Expr = n:number() { expr::Expr::Num(n) }
105 pub rule var_expr() -> Expr = n:id() { expr::Expr::Var(n) }127 pub rule var_expr() -> Expr = n:id() { expr::Expr::Var(n) }
106 pub rule if_then_else_expr() -> Expr = cond:ifspec() _() "then" _() cond_then:boxed_expr() cond_else:(_() "else" _() e:boxed_expr() {e})? {Expr::IfElse{128 pub rule if_then_else_expr() -> Expr = cond:ifspec() _ keyword("then") _ cond_then:boxed_expr() cond_else:(_ keyword("else") _ e:boxed_expr() {e})? {Expr::IfElse{
107 cond,129 cond,
108 cond_then,130 cond_then,
109 cond_else,131 cond_else,
110 }}132 }}
133
111 pub rule expr_basic() -> Expr134 pub rule literal() -> Expr
112 = "null" {Expr::Value(ValueType::Null)}135 = v:(
136 keyword("null") {LiteralType::Null}
113 / "true" {Expr::Value(ValueType::True)} / "false" {Expr::Value(ValueType::False)}137 / keyword("true") {LiteralType::True}
114138 / keyword("false") {LiteralType::False}
115 / "self" {Expr::Literal(LiteralType::This)} / "$" {Expr::Literal(LiteralType::Dollar)}139 / keyword("self") {LiteralType::This}
140 / keyword("$") {LiteralType::Dollar}
116 / "super" {Expr::Literal(LiteralType::Super)}141 / keyword("super") {LiteralType::Super}
142 ) {Expr::Literal(v)}
143
144 pub rule expr_basic() -> Expr
145 = literal()
117146
118 / string_expr() / number_expr()147 / string_expr() / number_expr()
119 / array_expr()148 / array_expr()
120 / array_comp_expr()
121 / obj_expr()149 / obj_expr()
122 / array_expr()150 / array_expr()
123 / array_comp_expr()151 / array_comp_expr()
124152
125 / var_expr()153 / var_expr()
154 / local_expr()
126 / if_then_else_expr()155 / if_then_else_expr()
127 / local_expr()156 / "-" _ expr:boxed_expr() { Expr::UnaryOp(UnaryOpType::Minus, expr) }
128
129 / "function" __() "(" __() params:params() __() ")" __() expr:boxed_expr() {Expr::Function(params, expr)}157 / "!" _ expr:boxed_expr() { Expr::UnaryOp(UnaryOpType::Not, expr) }
158
159 / keyword("function") _ "(" _ params:params() _ ")" _ expr:boxed_expr() {Expr::Function(params, expr)}
160 / assertion:assertion() _ ";" _ expr:boxed_expr() { Expr::AssertExpr(assertion, expr) }
161
162 / keyword("error") _ expr:boxed_expr() { Expr::Error(expr) }
130163
131 rule expr_basic_with_suffix() -> Expr164 rule expr_basic_with_suffix() -> Expr
132 = a:expr_basic() suffixes:(__() suffix:expr_suffix() {suffix})* {165 = a:expr_basic() suffixes:(_ suffix:expr_suffix() {suffix})* {
133 let mut cur = a;166 let mut cur = a;
134 for suffix in suffixes {167 for suffix in suffixes {
135 match suffix {168 cur = match suffix {
136 Suffix::String(index) => {169 Suffix::String(index) => Expr::Index(Box::new(cur), Box::new(Expr::Str(index))),
137 cur = Expr::Index(Box::new(cur), Box::new(Expr::Str(index)))170 Suffix::Slice(desc) => Expr::Slice(Box::new(cur), desc),
138 },
139 Suffix::Expression(index) => {171 Suffix::Expression(index) => Expr::Index(Box::new(cur), Box::new(index)),
140 cur = Expr::Index(Box::new(cur), Box::new(index))
141 },
142 Suffix::Apply(args) => {172 Suffix::Apply(args) => Expr::Apply(Box::new(cur), args),
143 cur = Expr::Apply(Box::new(cur), args)173 Suffix::Extend(body) => Expr::ObjExtend(box cur, body),
144 }
145 }174 }
146 }175 }
147 cur176 cur
148 }177 }
178
179 pub rule slice_desc() -> SliceDesc
180 = start:boxed_expr()? _ ":" _ pair:(end:boxed_expr()? _ step:(":" _ e:boxed_expr() {e})? {(end, step)})? {
181 if let Some((end, step)) = pair {
182 SliceDesc { start, end, step }
183 }else{
184 SliceDesc { start, end: None, step: None }
185 }
186 }
149187
150 rule expr_suffix() -> Suffix188 rule expr_suffix() -> Suffix
151 = "." __() s:id() { Suffix::String(s) }189 = "." _ s:id() { Suffix::String(s) }
152 / "[" __() s:expr() __() "]" { Suffix::Expression(s) }190 / "[" _ s:slice_desc() _ "]" { Suffix::Slice(s) }
191 / "[" _ s:expr() _ "]" { Suffix::Expression(s) }
153 / "(" __() args:args() __() ")" { Suffix::Apply(args) }192 / "(" _ args:args() _ ")" (_ keyword("tailstrict"))? { Suffix::Apply(args) }
193 / "{" _ body:objinside() _ "}" { Suffix::Extend(body) }
154194
155 rule expr() -> Expr195 rule expr() -> Expr
156 = a:precedence! {196 = a:precedence! {
157 a:(@) __() "||" __() b:@ {Expr::BinaryOp(Box::new(a), expr::BinaryOpType::Or, Box::new(b))}197 a:(@) _ "||" _ b:@ {Expr::BinaryOp(Box::new(a), BinaryOpType::Or, Box::new(b))}
158 --198 --
159 a:(@) __() "&&" __() b:@ {Expr::BinaryOp(Box::new(a), expr::BinaryOpType::And, Box::new(b))}199 a:(@) _ "&&" _ b:@ {Expr::BinaryOp(Box::new(a), BinaryOpType::And, Box::new(b))}
160 --200 --
161 a:(@) __() "|" __() b:@ {Expr::BinaryOp(Box::new(a), expr::BinaryOpType::BitOr, Box::new(b))}201 a:(@) _ "|" _ b:@ {Expr::BinaryOp(Box::new(a), BinaryOpType::BitOr, Box::new(b))}
162 --202 --
163 a:@ __() "^" __() b:(@) {Expr::BinaryOp(Box::new(a), expr::BinaryOpType::BitXor, Box::new(b))}203 a:@ _ "^" _ b:(@) {Expr::BinaryOp(Box::new(a), BinaryOpType::BitXor, Box::new(b))}
164 --204 --
165 a:(@) __() "&" __() b:@ {Expr::BinaryOp(Box::new(a), expr::BinaryOpType::BitAnd, Box::new(b))}205 a:(@) _ "&" _ b:@ {Expr::BinaryOp(Box::new(a), BinaryOpType::BitAnd, Box::new(b))}
166 --206 --
167 a:(@) __() "==" __() b:@ {Expr::BinaryOp(Box::new(a), expr::BinaryOpType::Eq, Box::new(b))}207 a:(@) _ "==" _ b:@ {Expr::BinaryOp(Box::new(a), BinaryOpType::Eq, Box::new(b))}
168 a:(@) __() "!=" __() b:@ {Expr::BinaryOp(Box::new(a), expr::BinaryOpType::Ne, Box::new(b))}208 a:(@) _ "!=" _ b:@ {Expr::BinaryOp(Box::new(a), BinaryOpType::Ne, Box::new(b))}
169 --209 --
170 a:(@) __() "<" __() b:@ {Expr::BinaryOp(Box::new(a), expr::BinaryOpType::Lt, Box::new(b))}210 a:(@) _ "<" _ b:@ {Expr::BinaryOp(Box::new(a), BinaryOpType::Lt, Box::new(b))}
171 a:(@) __() ">" __() b:@ {Expr::BinaryOp(Box::new(a), expr::BinaryOpType::Gt, Box::new(b))}211 a:(@) _ ">" _ b:@ {Expr::BinaryOp(Box::new(a), BinaryOpType::Gt, Box::new(b))}
172 a:(@) __() "<=" __() b:@ {Expr::BinaryOp(Box::new(a), expr::BinaryOpType::Lte, Box::new(b))}212 a:(@) _ "<=" _ b:@ {Expr::BinaryOp(Box::new(a), BinaryOpType::Lte, Box::new(b))}
173 a:(@) __() ">=" __() b:@ {Expr::BinaryOp(Box::new(a), expr::BinaryOpType::Gte, Box::new(b))}213 a:(@) _ ">=" _ b:@ {Expr::BinaryOp(Box::new(a), BinaryOpType::Gte, Box::new(b))}
174 --214 --
175 a:(@) __() "<<" __() b:@ {Expr::BinaryOp(Box::new(a), expr::BinaryOpType::Lhs, Box::new(b))}215 a:(@) _ "<<" _ b:@ {Expr::BinaryOp(Box::new(a), BinaryOpType::Lhs, Box::new(b))}
176 a:(@) __() ">>" __() b:@ {Expr::BinaryOp(Box::new(a), expr::BinaryOpType::Rhs, Box::new(b))}216 a:(@) _ ">>" _ b:@ {Expr::BinaryOp(Box::new(a), BinaryOpType::Rhs, Box::new(b))}
177 --217 --
178 a:(@) __() "+" __() b:@ {Expr::BinaryOp(Box::new(a), expr::BinaryOpType::Add, Box::new(b))}218 a:(@) _ "+" _ b:@ {Expr::BinaryOp(Box::new(a), BinaryOpType::Add, Box::new(b))}
179 a:(@) __() "-" __() b:@ {Expr::BinaryOp(Box::new(a), expr::BinaryOpType::Sub, Box::new(b))}219 a:(@) _ "-" _ b:@ {Expr::BinaryOp(Box::new(a), BinaryOpType::Sub, Box::new(b))}
180 --220 --
181 a:(@) __() "*" __() b:@ {Expr::BinaryOp(Box::new(a), expr::BinaryOpType::Mul, Box::new(b))}221 a:(@) _ "*" _ b:@ {Expr::BinaryOp(Box::new(a), BinaryOpType::Mul, Box::new(b))}
182 a:(@) __() "/" __() b:@ {Expr::BinaryOp(Box::new(a), expr::BinaryOpType::Div, Box::new(b))}222 a:(@) _ "/" _ b:@ {Expr::BinaryOp(Box::new(a), BinaryOpType::Div, Box::new(b))}
183 a:(@) __() "%" __() b:@ {Expr::BinaryOp(Box::new(a), expr::BinaryOpType::Mod, Box::new(b))}223 a:(@) _ "%" _ b:@ {Expr::BinaryOp(Box::new(a), BinaryOpType::Mod, Box::new(b))}
184 --224 --
185 e:expr_basic_with_suffix() {e}225 e:expr_basic_with_suffix() {e}
186 "(" __() e:boxed_expr() __() ")" {Expr::Parened(e)}226 "(" _ e:boxed_expr() _ ")" {Expr::Parened(e)}
187 }227 }
188 / e:expr_basic_with_suffix() {e}228 / e:expr_basic_with_suffix() {e}
189229
190 pub rule boxed_expr() -> Box<Expr> = e:expr() {Box::new(e)}230 pub rule boxed_expr() -> Box<Expr> = e:expr() {Box::new(e)}
191 pub rule jsonnet() -> Expr = __() e:expr() __() {e}231 pub rule jsonnet() -> Expr = _ e:expr() _ {e}
192 }232 }
193}233}
194234
220 );260 );
221 }261 }
262
263 /// Comments should not affect parsing
264 #[test]
265 fn comments() {
266 assert_eq!(
267 parse("2//comment\n+//comment\n3/*test*/*/*test*/4").unwrap(),
268 Expr::BinaryOp(
269 box Expr::Num(2.0),
270 BinaryOpType::Add,
271 box Expr::BinaryOp(box Expr::Num(3.0), BinaryOpType::Mul, box Expr::Num(4.0))
272 )
273 );
274 }
275
276 /// Comments should be able to be escaped
277 #[test]
278 fn comment_escaping() {
279 assert_eq!(
280 parse("2/*\\*/+*/ - 22").unwrap(),
281 Expr::BinaryOp(box Expr::Num(2.0), BinaryOpType::Sub, box Expr::Num(22.0))
282 );
283 }
222284
223 #[test]285 #[test]
224 fn suffix_comparsion() {286 fn suffix_comparsion() {
228 BinaryOp(290 BinaryOp(
229 box Apply(291 box Apply(
230 box Index(box Var("std".to_owned()), box Str("type".to_owned())),292 box Index(box Var("std".to_owned()), box Str("type".to_owned())),
231 ArgsDesc(vec![Arg::Positional(box Var("a".to_owned()))])293 ArgsDesc(vec![Arg(None, box Var("a".to_owned()))])
232 ),294 ),
233 BinaryOpType::Eq,295 BinaryOpType::Eq,
234 box Str("string".to_owned())296 box Str("string".to_owned())
235 )297 )
236 );298 );
237 }299 }
300
301 #[test]
302 fn array_comp() {
303 use Expr::*;
304 assert_eq!(
305 parse("[std.deepJoin(x) for x in arr]").unwrap(),
306 ArrComp(
307 box Apply(
308 box Index(box Var("std".to_owned()), box Str("deepJoin".to_owned())),
309 ArgsDesc(vec![Arg(None, box Var("x".to_owned()))])
310 ),
311 ForSpecData("x".to_owned(), box Var("arr".to_owned())),
312 vec![]
313 ),
314 )
315 }
316
317 #[test]
318 fn array_comp_with_ifs() {
319 use Expr::*;
320 assert_eq!(
321 parse("[k for k in std.objectFields(patch) if patch[k] == null]").unwrap(),
322 ArrComp(
323 box Var("k".to_owned()),
324 ForSpecData(
325 "k".to_owned(),
326 box Apply(
327 box Index(
328 box Var("std".to_owned()),
329 box Str("objectFields".to_owned())
330 ),
331 ArgsDesc(vec![Arg(None, box Var("patch".to_owned()))])
332 )
333 ),
334 vec![CompSpec::IfSpec(IfSpecData(box BinaryOp(
335 box Index(box Var("patch".to_owned()), box Var("k".to_owned())),
336 BinaryOpType::Eq,
337 box Literal(LiteralType::Null)
338 )))]
339 ),
340 );
341 }
342
343 #[test]
344 fn reserved() {
345 use Expr::*;
346 assert_eq!(parse("null").unwrap(), Literal(LiteralType::Null));
347 assert_eq!(parse("nulla").unwrap(), Var("nulla".to_owned()));
348 }
349
350 #[test]
351 fn multiple_args_buf() {
352 parse("a(b, null_fields)").unwrap();
353 }
354
355 #[test]
356 fn can_parse_stdlib() {
357 parse(jsonnet_stdlib::STDLIB_STR).unwrap();
358 }
238}359}
239360