jql_parser/
parser.rs

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