1use winnow::{
2 Parser,
3 Result,
4 combinator::{
5 alt,
6 dispatch,
7 fail,
8 iterator,
9 peek,
10 },
11 token::any,
12};
13
14use crate::{
15 combinators::{
16 parse_flatten_operator,
17 parse_group_separator,
18 parse_keys_operator,
19 parse_lenses,
20 parse_pipe_in_operator,
21 parse_pipe_out_operator,
22 parse_selector,
23 parse_truncate_operator,
24 trim,
25 },
26 errors::JqlParserError,
27 tokens::{
28 Lens,
29 Token,
30 View,
31 },
32};
33
34fn parse_fragment<'a>(input: &mut &'a str) -> Result<Token<'a>> {
36 trim(dispatch! {peek(any);
37 '[' | '"' | '{' => parse_selector,
38 '|' => {
39 alt((
40 parse_lenses.map(|lenses| {
41 Token::LensSelector(
42 lenses
43 .into_iter()
44 .map(|(tokens, value)| Lens(tokens, value))
45 .collect(),
46 )
47 }),
48 parse_pipe_in_operator.value(Token::PipeInOperator),
49 ))
50 },
51 '@' => parse_keys_operator.value(Token::KeyOperator),
52 '.' => parse_flatten_operator.value(Token::FlattenOperator),
53 '<' => parse_pipe_out_operator.value(Token::PipeOutOperator),
54 ',' => parse_group_separator.value(Token::GroupSeparator),
55 '!' => parse_truncate_operator.value(Token::TruncateOperator),
56 _ => fail
57 })
58 .parse_next(input)
59}
60
61pub fn parse(input: &str) -> Result<Vec<Token<'_>>, JqlParserError> {
67 let mut input = input;
68 let mut parser_iterator = iterator(&mut input, parse_fragment);
69 let tokens = parser_iterator.collect::<Vec<Token>>();
70 let result: Result<_, _> = parser_iterator.finish();
71
72 match result {
73 Ok(()) => {
74 if !input.is_empty() {
75 return Err(JqlParserError::ParsingError {
76 tokens: tokens.stringify(),
77 unparsed: input.to_string(),
78 });
79 }
80
81 let truncate_count = tokens
82 .iter()
83 .filter(|&token| *token == Token::TruncateOperator)
84 .count();
85
86 if truncate_count > 1
87 || (truncate_count == 1 && tokens.last() != Some(&Token::TruncateOperator))
88 {
89 return Err(JqlParserError::TruncateError(tokens.stringify()));
90 }
91
92 Ok(tokens)
93 }
94 Err(_) => Err(JqlParserError::UnknownError),
95 }
96}
97
98#[cfg(test)]
99mod tests {
100 use super::{
101 parse,
102 parse_fragment,
103 };
104 use crate::{
105 errors::JqlParserError,
106 tokens::{
107 Index,
108 Lens,
109 LensValue,
110 Range,
111 Token,
112 View,
113 },
114 };
115
116 #[test]
117 fn check_array_index_selector() {
118 assert_eq!(
119 parse_fragment(&mut "[0,1,2]"),
120 Ok(Token::ArrayIndexSelector(vec![
121 Index(0),
122 Index(1),
123 Index(2)
124 ]))
125 );
126 assert_eq!(
127 parse_fragment(&mut " [ 0 , 1 , 2 ] "),
128 Ok(Token::ArrayIndexSelector(vec![
129 Index(0),
130 Index(1),
131 Index(2)
132 ]))
133 );
134 }
135
136 #[test]
137 fn check_array_range_selector() {
138 assert_eq!(
139 parse_fragment(&mut "[0:2]"),
140 Ok(Token::ArrayRangeSelector(Range(
141 Some(Index(0)),
142 Some(Index(2))
143 )))
144 );
145 assert_eq!(
146 parse_fragment(&mut "[:2]"),
147 Ok(Token::ArrayRangeSelector(Range(None, Some(Index(2)))))
148 );
149 assert_eq!(
150 parse_fragment(&mut "[0:]"),
151 Ok(Token::ArrayRangeSelector(Range(Some(Index(0)), None)))
152 );
153 assert_eq!(
154 parse_fragment(&mut "[:]"),
155 Ok(Token::ArrayRangeSelector(Range(None, None)))
156 );
157 }
158
159 #[test]
160 fn check_key_selector() {
161 assert_eq!(
162 parse_fragment(&mut r#""one""#),
163 Ok(Token::KeySelector("one".into()))
164 );
165 assert_eq!(
166 parse_fragment(&mut r#" "one" "#),
167 Ok(Token::KeySelector("one".into()))
168 );
169 }
170
171 #[test]
172 fn check_multi_key_selector() {
173 assert_eq!(
174 parse_fragment(&mut r#"{"one","two","three"}"#),
175 Ok(Token::MultiKeySelector(vec![
176 "one".into(),
177 "two".into(),
178 "three".into()
179 ]))
180 );
181 assert_eq!(
182 parse_fragment(&mut r#" { "one", "two" , "three" } "#),
183 Ok(Token::MultiKeySelector(vec![
184 "one".into(),
185 "two".into(),
186 "three".into()
187 ]))
188 );
189 }
190
191 #[test]
192 fn check_object_index_selector() {
193 assert_eq!(
194 parse_fragment(&mut "{0,1,2}"),
195 Ok(Token::ObjectIndexSelector(vec![
196 Index(0),
197 Index(1),
198 Index(2)
199 ]))
200 );
201 assert_eq!(
202 parse_fragment(&mut " { 0 , 1 , 2 } "),
203 Ok(Token::ObjectIndexSelector(vec![
204 Index(0),
205 Index(1),
206 Index(2)
207 ]))
208 );
209 }
210
211 #[test]
212 fn check_object_range_selector() {
213 assert_eq!(
214 parse_fragment(&mut "{0:2}"),
215 Ok(Token::ObjectRangeSelector(Range(
216 Some(Index(0)),
217 Some(Index(2))
218 )))
219 );
220 assert_eq!(
221 parse_fragment(&mut "{:2}"),
222 Ok(Token::ObjectRangeSelector(Range(None, Some(Index(2)))))
223 );
224 assert_eq!(
225 parse_fragment(&mut "{0:}"),
226 Ok(Token::ObjectRangeSelector(Range(Some(Index(0)), None)))
227 );
228 assert_eq!(
229 parse_fragment(&mut "{:}"),
230 Ok(Token::ObjectRangeSelector(Range(None, None)))
231 );
232 }
233
234 #[test]
235 fn check_lens_selector() {
236 assert_eq!(
237 parse_fragment(&mut r#"|={"abc""c","bcd""d"=123,"efg"=null,"hij"="test"}"#),
238 Ok(Token::LensSelector(vec![
239 Lens(
240 vec![
241 Token::KeySelector("abc".into()),
242 Token::KeySelector("c".into())
243 ],
244 None
245 ),
246 Lens(
247 vec![
248 Token::KeySelector("bcd".into()),
249 Token::KeySelector("d".into())
250 ],
251 Some(LensValue::Number(123))
252 ),
253 Lens(
254 vec![Token::KeySelector("efg".into())],
255 Some(LensValue::Null)
256 ),
257 Lens(
258 vec![Token::KeySelector("hij".into())],
259 Some(LensValue::String("test".into()))
260 ),
261 ]))
262 );
263 }
264
265 #[test]
266 fn check_flatten_operator() {
267 assert_eq!(parse_fragment(&mut ".."), Ok(Token::FlattenOperator));
268 assert_eq!(parse_fragment(&mut " .. "), Ok(Token::FlattenOperator));
269 }
270
271 #[test]
272 fn check_pipe_in_operator() {
273 assert_eq!(parse_fragment(&mut "|>"), Ok(Token::PipeInOperator));
274 assert_eq!(parse_fragment(&mut " |> "), Ok(Token::PipeInOperator));
275 }
276
277 #[test]
278 fn check_pipe_out_operator() {
279 assert_eq!(parse_fragment(&mut "<|"), Ok(Token::PipeOutOperator));
280 assert_eq!(parse_fragment(&mut " <| "), Ok(Token::PipeOutOperator));
281 }
282
283 #[test]
284 fn check_truncate_operator() {
285 assert_eq!(parse_fragment(&mut "!"), Ok(Token::TruncateOperator));
286 assert_eq!(parse_fragment(&mut " ! "), Ok(Token::TruncateOperator));
287 }
288
289 #[test]
290 fn check_group_separator() {
291 assert_eq!(parse_fragment(&mut ","), Ok(Token::GroupSeparator));
292 assert_eq!(parse_fragment(&mut " , "), Ok(Token::GroupSeparator));
293 }
294
295 #[test]
296 fn check_full_parser() {
297 assert_eq!(
298 parse(r#""this"[9,0]"#),
299 Ok(vec![
300 Token::KeySelector("this".into()),
301 Token::ArrayIndexSelector(vec![Index(9), Index(0)])
302 ]),
303 );
304 assert_eq!(
305 parse("[9,0]nope"),
306 Err(JqlParserError::ParsingError {
307 tokens: [Token::ArrayIndexSelector(vec![Index(9), Index(0)])].stringify(),
308 unparsed: "nope".to_string(),
309 })
310 );
311 assert_eq!(
312 parse(r#""this"[9,0]|>"some"<|"ok"..!"#),
313 Ok(vec![
314 Token::KeySelector("this".into()),
315 Token::ArrayIndexSelector(vec![Index(9), Index(0)]),
316 Token::PipeInOperator,
317 Token::KeySelector("some".into()),
318 Token::PipeOutOperator,
319 Token::KeySelector("ok".into()),
320 Token::FlattenOperator,
321 Token::TruncateOperator
322 ]),
323 );
324 assert_eq!(
325 parse(r#""a"!"b""#),
326 Err(JqlParserError::TruncateError(
327 [
328 Token::KeySelector("a".into()),
329 Token::TruncateOperator,
330 Token::KeySelector("b".into())
331 ]
332 .stringify()
333 ))
334 );
335 }
336}