Skip to content

Commit ba5874b

Browse files
committed
chore: experimenting
1 parent 3731d0e commit ba5874b

24 files changed

+4931
-118
lines changed

README.md

Lines changed: 212 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,212 @@
1+
# jsonpath
2+
3+
This is a full implementation of [RFC 9535](https://datatracker.ietf.org/doc/rfc9535/)
4+
5+
It is build to be webasm compatible. A playground application is also included.
6+
7+
Everything within RFC9535 is in scope. Grammars outside RFC 9535 are not in scope. For using `=~` to dynamically represent a matched regex is not in scope.
8+
9+
## Installation
10+
11+
This application is included in the [speakeasy](https://github.com/speakeasy-api/speakeasy) CLI, but available as a stand-alone library.
12+
13+
## ABNF grammar
14+
15+
```
16+
jsonpath-query = root-identifier segments
17+
segments = *(S segment)
18+
19+
B = %x20 / ; Space
20+
%x09 / ; Horizontal tab
21+
%x0A / ; Line feed or New line
22+
%x0D ; Carriage return
23+
S = *B ; optional blank space
24+
root-identifier = "$"
25+
selector = name-selector /
26+
wildcard-selector /
27+
slice-selector /
28+
index-selector /
29+
filter-selector
30+
name-selector = string-literal
31+
32+
string-literal = %x22 *double-quoted %x22 / ; "string"
33+
%x27 *single-quoted %x27 ; 'string'
34+
35+
double-quoted = unescaped /
36+
%x27 / ; '
37+
ESC %x22 / ; \"
38+
ESC escapable
39+
40+
single-quoted = unescaped /
41+
%x22 / ; "
42+
ESC %x27 / ; \'
43+
ESC escapable
44+
45+
ESC = %x5C ; \ backslash
46+
47+
unescaped = %x20-21 / ; see RFC 8259
48+
; omit 0x22 "
49+
%x23-26 /
50+
; omit 0x27 '
51+
%x28-5B /
52+
; omit 0x5C \
53+
%x5D-D7FF /
54+
; skip surrogate code points
55+
%xE000-10FFFF
56+
57+
escapable = %x62 / ; b BS backspace U+0008
58+
%x66 / ; f FF form feed U+000C
59+
%x6E / ; n LF line feed U+000A
60+
%x72 / ; r CR carriage return U+000D
61+
%x74 / ; t HT horizontal tab U+0009
62+
"/" / ; / slash (solidus) U+002F
63+
"\" / ; \ backslash (reverse solidus) U+005C
64+
(%x75 hexchar) ; uXXXX U+XXXX
65+
66+
hexchar = non-surrogate /
67+
(high-surrogate "\" %x75 low-surrogate)
68+
non-surrogate = ((DIGIT / "A"/"B"/"C" / "E"/"F") 3HEXDIG) /
69+
("D" %x30-37 2HEXDIG )
70+
high-surrogate = "D" ("8"/"9"/"A"/"B") 2HEXDIG
71+
low-surrogate = "D" ("C"/"D"/"E"/"F") 2HEXDIG
72+
73+
HEXDIG = DIGIT / "A" / "B" / "C" / "D" / "E" / "F"
74+
wildcard-selector = "*"
75+
index-selector = int ; decimal integer
76+
77+
int = "0" /
78+
(["-"] DIGIT1 *DIGIT) ; - optional
79+
DIGIT1 = %x31-39 ; 1-9 non-zero digit
80+
slice-selector = [start S] ":" S [end S] [":" [S step ]]
81+
82+
start = int ; included in selection
83+
end = int ; not included in selection
84+
step = int ; default: 1
85+
filter-selector = "?" S logical-expr
86+
logical-expr = logical-or-expr
87+
logical-or-expr = logical-and-expr *(S "||" S logical-and-expr)
88+
; disjunction
89+
; binds less tightly than conjunction
90+
logical-and-expr = basic-expr *(S "&&" S basic-expr)
91+
; conjunction
92+
; binds more tightly than disjunction
93+
94+
basic-expr = paren-expr /
95+
comparison-expr /
96+
test-expr
97+
98+
paren-expr = [logical-not-op S] "(" S logical-expr S ")"
99+
; parenthesized expression
100+
logical-not-op = "!" ; logical NOT operator
101+
test-expr = [logical-not-op S]
102+
(filter-query / ; existence/non-existence
103+
function-expr) ; LogicalType or NodesType
104+
filter-query = rel-query / jsonpath-query
105+
rel-query = current-node-identifier segments
106+
current-node-identifier = "@"
107+
comparison-expr = comparable S comparison-op S comparable
108+
literal = number / string-literal /
109+
true / false / null
110+
comparable = literal /
111+
singular-query / ; singular query value
112+
function-expr ; ValueType
113+
comparison-op = "==" / "!=" /
114+
"<=" / ">=" /
115+
"<" / ">"
116+
117+
singular-query = rel-singular-query / abs-singular-query
118+
rel-singular-query = current-node-identifier singular-query-segments
119+
abs-singular-query = root-identifier singular-query-segments
120+
singular-query-segments = *(S (name-segment / index-segment))
121+
name-segment = ("[" name-selector "]") /
122+
("." member-name-shorthand)
123+
index-segment = "[" index-selector "]"
124+
number = (int / "-0") [ frac ] [ exp ] ; decimal number
125+
frac = "." 1*DIGIT ; decimal fraction
126+
exp = "e" [ "-" / "+" ] 1*DIGIT ; decimal exponent
127+
true = %x74.72.75.65 ; true
128+
false = %x66.61.6c.73.65 ; false
129+
null = %x6e.75.6c.6c ; null
130+
function-name = function-name-first *function-name-char
131+
function-name-first = LCALPHA
132+
function-name-char = function-name-first / "_" / DIGIT
133+
LCALPHA = %x61-7A ; "a".."z"
134+
135+
function-expr = function-name "(" S [function-argument
136+
*(S "," S function-argument)] S ")"
137+
function-argument = literal /
138+
filter-query / ; (includes singular-query)
139+
logical-expr /
140+
function-expr
141+
segment = child-segment / descendant-segment
142+
child-segment = bracketed-selection /
143+
("."
144+
(wildcard-selector /
145+
member-name-shorthand))
146+
147+
bracketed-selection = "[" S selector *(S "," S selector) S "]"
148+
149+
member-name-shorthand = name-first *name-char
150+
name-first = ALPHA /
151+
"_" /
152+
%x80-D7FF /
153+
; skip surrogate code points
154+
%xE000-10FFFF
155+
name-char = name-first / DIGIT
156+
157+
DIGIT = %x30-39 ; 0-9
158+
ALPHA = %x41-5A / %x61-7A ; A-Z / a-z
159+
descendant-segment = ".." (bracketed-selection /
160+
wildcard-selector /
161+
member-name-shorthand)
162+
163+
Figure 2: Collected ABNF of JSONPath Queries
164+
165+
Figure 3 contains the collected ABNF grammar that defines the syntax
166+
of a JSONPath Normalized Path while also using the rules root-
167+
identifier, ESC, DIGIT, and DIGIT1 from Figure 2.
168+
169+
normalized-path = root-identifier *(normal-index-segment)
170+
normal-index-segment = "[" normal-selector "]"
171+
normal-selector = normal-name-selector / normal-index-selector
172+
normal-name-selector = %x27 *normal-single-quoted %x27 ; 'string'
173+
normal-single-quoted = normal-unescaped /
174+
ESC normal-escapable
175+
normal-unescaped = ; omit %x0-1F control codes
176+
%x20-26 /
177+
; omit 0x27 '
178+
%x28-5B /
179+
; omit 0x5C \
180+
%x5D-D7FF /
181+
; skip surrogate code points
182+
%xE000-10FFFF
183+
184+
normal-escapable = %x62 / ; b BS backspace U+0008
185+
%x66 / ; f FF form feed U+000C
186+
%x6E / ; n LF line feed U+000A
187+
%x72 / ; r CR carriage return U+000D
188+
%x74 / ; t HT horizontal tab U+0009
189+
"'" / ; ' apostrophe U+0027
190+
"\" / ; \ backslash (reverse solidus) U+005C
191+
(%x75 normal-hexchar)
192+
; certain values u00xx U+00XX
193+
normal-hexchar = "0" "0"
194+
(
195+
("0" %x30-37) / ; "00"-"07"
196+
; omit U+0008-U+000A BS HT LF
197+
("0" %x62) / ; "0b"
198+
; omit U+000C-U+000D FF CR
199+
("0" %x65-66) / ; "0e"-"0f"
200+
("1" normal-HEXDIG)
201+
)
202+
normal-HEXDIG = DIGIT / %x61-66 ; "0"-"9", "a"-"f"
203+
normal-index-selector = "0" / (DIGIT1 *DIGIT)
204+
; non-negative decimal integer
205+
```
206+
207+
## Functions
208+
209+
210+
211+
## Contributing
212+

0 commit comments

Comments
 (0)