forked from besok/jsonpath-rust
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathjson_path_9535.pest
More file actions
152 lines (133 loc) · 7.45 KB
/
Copy pathjson_path_9535.pest
File metadata and controls
152 lines (133 loc) · 7.45 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
main = ${ SOI ~ jp_query ~ EOI }
jp_query = {root ~ segments}
segments = !{(S ~ segment)*}
segment = { child_segment | descendant_segment }
child_segment = { bracketed_selection | ("." ~ (wildcard_selector | member_name_shorthand)) }
bracketed_selection = { "[" ~ S ~ selector ~ (S ~ "," ~ S ~ selector)* ~ S ~ "]" }
descendant_segment = { ".." ~ (bracketed_selection | wildcard_selector | member_name_shorthand)}
selector = {name_selector | wildcard_selector | slice_selector| index_selector | filter_selector}
root = _{"$"}
name_selector = {string}
wildcard_selector = {"*"}
index_selector = {int}
int = { "0" | ("-"? ~ safe_int) }
step = {":" ~ S ~ int?}
start = {int}
end = {int}
slice_selector = { start? ~ S ~ ":" ~ S ~ end? ~ S ~ step? }
filter_selector = {"?" ~ S ~ logical_expr}
logical_expr = {logical_expr_and ~ S ~ ("||" ~ S ~ logical_expr_and)*}
logical_expr_and = {atom_expr ~ S ~ ("&&" ~ S ~ atom_expr)*}
atom_expr = {paren_expr | comp_expr| test_expr}
paren_expr = {not_op? ~ S ~ "(" ~ S ~ logical_expr ~ S ~ ")"}
comp_expr = { comparable ~ S ~ comp_op ~ S ~ comparable }
test_expr = {not_op? ~ S ~ test}
test = {
filter_query // existence/non-existence
// Per RFC: [function expressions may be used] As a test-expr in a logical expression:
// The function's declared result type is LogicalType or (giving rise to conversion as per Section 2.4.2) NodesType.
| ( &( returns_logical_type | returns_nodes_type ) ~ function_expr ) // LogicalType or NodesType
}
filter_query = _{ rel_query | jp_query }
rel_query = {curr ~ segments}
function_expr = { length_func_call | search_func_call | match_func_call | in_func_call | nin_func_call | none_of_func_call | any_of_func_call | subset_of_func_call }
// https://github.com/pest-parser/pest/issues/333 would be awesome for this but it doesn't exist yet and it's been 7 years
// Lookahead to peek the names and then homogenize them into the same rule till we refine the parser code
length_func_call = _{ &"length" ~ function_name ~ "(" ~ S ~ value_type ~ S ~ ")" }
value_func_call = _{ &"value" ~ function_name ~ "(" ~ S ~ nodes_type ~ S ~ ")" }
count_func_call = _{ &"count" ~ function_name ~ "(" ~ S ~ nodes_type ~ S ~ ")" }
search_func_call = _{ &"search" ~ function_name ~ "(" ~ S ~ value_type ~ S ~ "," ~ S ~ value_type ~ S ~ ")" }
match_func_call = _{ &"match" ~ function_name ~ "(" ~ S ~ value_type ~ S ~ "," ~ S ~ value_type ~ S ~ ")" }
in_func_call = _{ &"in" ~ function_name ~ "(" ~ S ~ value_type ~ S ~ "," ~ S ~ value_type ~ S ~ ")" }
nin_func_call = _{ &"nin" ~ function_name ~ "(" ~ S ~ value_type ~ S ~ "," ~ S ~ value_type ~ S ~ ")" }
none_of_func_call = _{ &"none_of" ~ function_name ~ "(" ~ S ~ value_type ~ S ~ "," ~ S ~ value_type ~ S ~ ")" }
any_of_func_call = _{ &"any_of" ~ function_name ~ "(" ~ S ~ value_type ~ S ~ "," ~ S ~ value_type ~ S ~ ")" }
subset_of_func_call = _{ &"subset_of" ~ function_name ~ "(" ~ S ~ value_type ~ S ~ "," ~ S ~ value_type ~ S ~ ")" }
// When the declared type of the parameter is ValueType and the argument is one of the following:
// - A value expressed as a literal.
// - A singular query. In this case:
// - If the query results in a nodelist consisting of a single node, the argument is the value of the node.
// - If the query results in an empty nodelist, the argument is the special result Nothing.
value_type = { literal | singular_query | returns_value_type }
// When the declared type of the parameter is LogicalType and the argument is one of the following:
// - A function expression with declared result type NodesType. In this case, the argument is converted to LogicalType as per Section 2.4.2.
// - A logical-expr that is not a function expression.
logical_type = {
logical_expr // TODO why is this not allowed to be a function_expr? we guarantee it's return is a logical type
// | returns_logical_type // this case is actually covered as a subset of logical_expr
| nodes_type
}
// When the declared type of the parameter is NodesType and the argument is a query (which includes singular query).
nodes_type = { jp_query | returns_nodes_type }
returns_value_type = _{ length_func_call | value_func_call | count_func_call }
returns_logical_type = _{ search_func_call | match_func_call | in_func_call | nin_func_call | none_of_func_call | any_of_func_call | subset_of_func_call }
// Currently no functions return this, so never match for now. To add a node which returns NodesType, replace !ANY
returns_nodes_type = _{ !ANY }
function_name = { "length" | "value" | "count" | "search" | "match" | "in" | "nin" | "none_of" | "any_of" | "subset_of" }
// Removed, a literal is a ValueType, and a logical_expr is just a test with more rules around it, both are LogicalType
// function_argument = { literal | test | logical_expr }
// Per RFC: As a comparable in a comparison:
// The function's declared result type is ValueType.
comparable = { literal | singular_query | ( &returns_value_type ~ function_expr ) }
literal = { number | string | bool | null }
bool = {"true" | "false"}
null = {"null"}
singular_query = { rel_singular_query | abs_singular_query }
rel_singular_query = { curr ~ singular_query_segments }
abs_singular_query = { root ~ singular_query_segments }
singular_query_segments = { (S ~ (name_segment | index_segment))* }
name_segment = { ("[" ~ name_selector ~ "]") | ("." ~ member_name_shorthand) }
index_segment = { "[" ~ index_selector ~ "]" }
comp_op = { "==" | "!=" | "<=" | ">=" | "<" | ">" }
LCALPHA = { 'a'..'z' }
string = { "\"" ~ double_quoted* ~ "\"" | "\'" ~ single_quoted* ~ "\'" }
double_quoted = _{ unescaped | "\'" | ESC ~ "\"" | ESC ~ escapable }
single_quoted = _{ unescaped | "\"" | ESC ~ "\'" | ESC ~ escapable }
escapable = _{
"b" | "f" | "n" | "r" | "t" | "/" | "\\" | ("u" ~ hexchar)
}
member_name_shorthand = { name_first ~ name_char* }
name_first = { ALPHA | "_" | '\u{0080}'..'\u{D7FF}' | '\u{E000}'..'\u{10FFFF}' }
name_char = { name_first | DIGIT }
not_op = {"!"}
curr = _{"@"}
ESC = _{ "\\" }
unescaped = _{
'\u{0020}'..'\u{0021}' |
'\u{0023}'..'\u{0026}' |
'\u{0028}'..'\u{005B}' |
'\u{005D}'..'\u{D7FF}' |
'\u{E000}'..'\u{10FFFF}'
}
S = _{ WHITESPACE* }
hexchar = _{ non_surrogate | (high_surrogate ~ "\\" ~ "u" ~ low_surrogate) }
number = { (int | "-0") ~ frac? ~ exp? }
frac = { "." ~ DIGIT+ }
exp = { ("e" | "E") ~ ("-" | "+")? ~ DIGIT+ }
non_surrogate = _{ (DIGIT | "A" | "B" | "C" | "E" | "F") ~ HEXDIG{3} | ("D" ~ ('0'..'7') ~ HEXDIG{2}) }
high_surrogate = _{ "D" ~ ("8" | "9" | "A" | "B") ~ HEXDIG{2} }
low_surrogate = _{ "D" ~ ("C" | "D" | "E" | "F") ~ HEXDIG{2} }
HEXDIG = _{ DIGIT | "A" | "B" | "C" | "D" | "E" | "F" }
DIGIT = _{ ASCII_DIGIT }
DIGIT1 = _{ ASCII_NONZERO_DIGIT}
ALPHA = { ASCII_ALPHA }
WHITESPACE = _{ " " | "\t" | "\r\n" | "\n" | "\r"}
// Matches any number less than 9007199254740991 early escape for any number <= 999999999999999
safe_int = _{
(
DIGIT1 ~ DIGIT{0,14} ~ !ASCII_DIGIT // 1 to 15 digits (well below the max)
| '1'..'8' ~ ASCII_DIGIT{15}
| "900" ~ '0'..'6' ~ ASCII_DIGIT{12}
| "90070" ~ ASCII_DIGIT{11}
| "90071" ~ '0'..'8' ~ ASCII_DIGIT{10}
| "900719" ~ '0'..'8' ~ ASCII_DIGIT{9}
| "9007199" ~ '0'..'1' ~ ASCII_DIGIT{8}
| "90071992" ~ '0'..'4' ~ ASCII_DIGIT{7}
| "900719925" ~ '0'..'3' ~ ASCII_DIGIT{6}
| "9007199254" ~ '0'..'6' ~ ASCII_DIGIT{5}
| "90071992547" ~ '0'..'3' ~ ASCII_DIGIT{4}
| "9007199254740" ~ '0'..'8' ~ ASCII_DIGIT{2}
| "90071992547409" ~ '0'..'8' ~ ASCII_DIGIT
| "900719925474099" ~ '0'..'1'
) ~ !ASCII_DIGIT
}