Skip to main content

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 input = input;
89    let mut parser_iterator = iterator(&mut input, parse_fragment);
90    let tokens = parser_iterator.collect::<Vec<Token>>();
91    let result: Result<_, _> = parser_iterator.finish();
92
93    match result {
94        Ok(()) => {
95            if !input.is_empty() {
96                return Err(JqlParserError::ParsingError {
97                    tokens: tokens.stringify(),
98                    unparsed: input.to_string(),
99                });
100            }
101
102            let truncate_count = tokens
103                .iter()
104                .filter(|&token| *token == Token::TruncateOperator)
105                .count();
106
107            if truncate_count > 1
108                || (truncate_count == 1 && tokens.last() != Some(&Token::TruncateOperator))
109            {
110                return Err(JqlParserError::TruncateError(tokens.stringify()));
111            }
112
113            Ok(tokens)
114        }
115        Err(_) => Err(JqlParserError::UnknownError),
116    }
117}
118
119#[cfg(test)]
120mod tests {
121    use super::{
122        parse,
123        parse_fragment,
124    };
125    use crate::{
126        errors::JqlParserError,
127        tokens::{
128            Index,
129            Lens,
130            LensValue,
131            Range,
132            Token,
133            View,
134        },
135    };
136
137    #[test]
138    fn check_array_index_selector() {
139        assert_eq!(
140            parse_fragment(&mut "[0,1,2]"),
141            Ok(Token::ArrayIndexSelector(vec![
142                Index(0),
143                Index(1),
144                Index(2)
145            ]))
146        );
147        assert_eq!(
148            parse_fragment(&mut " [ 0 , 1 , 2 ] "),
149            Ok(Token::ArrayIndexSelector(vec![
150                Index(0),
151                Index(1),
152                Index(2)
153            ]))
154        );
155    }
156
157    #[test]
158    fn check_array_range_selector() {
159        assert_eq!(
160            parse_fragment(&mut "[0:2]"),
161            Ok(Token::ArrayRangeSelector(Range(
162                Some(Index(0)),
163                Some(Index(2))
164            )))
165        );
166        assert_eq!(
167            parse_fragment(&mut "[:2]"),
168            Ok(Token::ArrayRangeSelector(Range(None, Some(Index(2)))))
169        );
170        assert_eq!(
171            parse_fragment(&mut "[0:]"),
172            Ok(Token::ArrayRangeSelector(Range(Some(Index(0)), None)))
173        );
174        assert_eq!(
175            parse_fragment(&mut "[:]"),
176            Ok(Token::ArrayRangeSelector(Range(None, None)))
177        );
178    }
179
180    #[test]
181    fn check_key_selector() {
182        assert_eq!(
183            parse_fragment(&mut r#""one""#),
184            Ok(Token::KeySelector("one"))
185        );
186        assert_eq!(
187            parse_fragment(&mut r#" "one" "#),
188            Ok(Token::KeySelector("one"))
189        );
190    }
191
192    #[test]
193    fn check_multi_key_selector() {
194        assert_eq!(
195            parse_fragment(&mut r#"{"one","two","three"}"#),
196            Ok(Token::MultiKeySelector(vec!["one", "two", "three"]))
197        );
198        assert_eq!(
199            parse_fragment(&mut r#" { "one", "two" , "three" } "#),
200            Ok(Token::MultiKeySelector(vec!["one", "two", "three"]))
201        );
202    }
203
204    #[test]
205    fn check_object_index_selector() {
206        assert_eq!(
207            parse_fragment(&mut "{0,1,2}"),
208            Ok(Token::ObjectIndexSelector(vec![
209                Index(0),
210                Index(1),
211                Index(2)
212            ]))
213        );
214        assert_eq!(
215            parse_fragment(&mut " { 0 , 1 , 2 } "),
216            Ok(Token::ObjectIndexSelector(vec![
217                Index(0),
218                Index(1),
219                Index(2)
220            ]))
221        );
222    }
223
224    #[test]
225    fn check_object_range_selector() {
226        assert_eq!(
227            parse_fragment(&mut "{0:2}"),
228            Ok(Token::ObjectRangeSelector(Range(
229                Some(Index(0)),
230                Some(Index(2))
231            )))
232        );
233        assert_eq!(
234            parse_fragment(&mut "{:2}"),
235            Ok(Token::ObjectRangeSelector(Range(None, Some(Index(2)))))
236        );
237        assert_eq!(
238            parse_fragment(&mut "{0:}"),
239            Ok(Token::ObjectRangeSelector(Range(Some(Index(0)), None)))
240        );
241        assert_eq!(
242            parse_fragment(&mut "{:}"),
243            Ok(Token::ObjectRangeSelector(Range(None, None)))
244        );
245    }
246
247    #[test]
248    fn check_lens_selector() {
249        assert_eq!(
250            parse_fragment(&mut r#"|={"abc""c","bcd""d"=123,"efg"=null,"hij"="test"}"#),
251            Ok(Token::LensSelector(vec![
252                Lens(
253                    vec![Token::KeySelector("abc"), Token::KeySelector("c")],
254                    None
255                ),
256                Lens(
257                    vec![Token::KeySelector("bcd"), Token::KeySelector("d")],
258                    Some(LensValue::Number(123))
259                ),
260                Lens(vec![Token::KeySelector("efg")], Some(LensValue::Null)),
261                Lens(
262                    vec![Token::KeySelector("hij")],
263                    Some(LensValue::String("test"))
264                ),
265            ]))
266        );
267    }
268
269    #[test]
270    fn check_flatten_operator() {
271        assert_eq!(parse_fragment(&mut ".."), Ok(Token::FlattenOperator));
272        assert_eq!(parse_fragment(&mut " .. "), Ok(Token::FlattenOperator));
273    }
274
275    #[test]
276    fn check_pipe_in_operator() {
277        assert_eq!(parse_fragment(&mut "|>"), Ok(Token::PipeInOperator));
278        assert_eq!(parse_fragment(&mut " |> "), Ok(Token::PipeInOperator));
279    }
280
281    #[test]
282    fn check_pipe_out_operator() {
283        assert_eq!(parse_fragment(&mut "<|"), Ok(Token::PipeOutOperator));
284        assert_eq!(parse_fragment(&mut " <| "), Ok(Token::PipeOutOperator));
285    }
286
287    #[test]
288    fn check_truncate_operator() {
289        assert_eq!(parse_fragment(&mut "!"), Ok(Token::TruncateOperator));
290        assert_eq!(parse_fragment(&mut " ! "), Ok(Token::TruncateOperator));
291    }
292
293    #[test]
294    fn check_group_separator() {
295        assert_eq!(parse_fragment(&mut ","), Ok(Token::GroupSeparator));
296        assert_eq!(parse_fragment(&mut " , "), Ok(Token::GroupSeparator));
297    }
298
299    #[test]
300    fn check_full_parser() {
301        assert_eq!(
302            parse(r#""this"[9,0]"#),
303            Ok(vec![
304                Token::KeySelector("this"),
305                Token::ArrayIndexSelector(vec![Index(9), Index(0)])
306            ]),
307        );
308        assert_eq!(
309            parse("[9,0]nope"),
310            Err(JqlParserError::ParsingError {
311                tokens: [Token::ArrayIndexSelector(vec![Index(9), Index(0)])].stringify(),
312                unparsed: "nope".to_string(),
313            })
314        );
315        assert_eq!(
316            parse(r#""this"[9,0]|>"some"<|"ok"..!"#),
317            Ok(vec![
318                Token::KeySelector("this"),
319                Token::ArrayIndexSelector(vec![Index(9), Index(0)]),
320                Token::PipeInOperator,
321                Token::KeySelector("some"),
322                Token::PipeOutOperator,
323                Token::KeySelector("ok"),
324                Token::FlattenOperator,
325                Token::TruncateOperator
326            ]),
327        );
328        assert_eq!(
329            parse(r#""a"!"b""#),
330            Err(JqlParserError::TruncateError(
331                [
332                    Token::KeySelector("a"),
333                    Token::TruncateOperator,
334                    Token::KeySelector("b")
335                ]
336                .stringify()
337            ))
338        );
339    }
340}