1use serde_json::Number;
2use std::collections::HashMap;
3use winnow::combinator::opt;
4
5use winnow::ascii;
6use winnow::error::{ContextError, ParseError};
7use winnow::prelude::*;
8use winnow::{
9 combinator::alt,
10 combinator::cut_err,
11 combinator::{delimited, preceded, separated_pair, terminated},
12 combinator::{repeat, separated},
13 error::ParserError,
14 token::{any, none_of, take, take_while},
15};
16
17pub(crate) fn expr<'a>(
18 input: &'a mut &str,
19) -> Result<Expression, ParseError<&'a str, ContextError>> {
20 delimited(ws, expression, ws).parse(input)
21}
22
23#[derive(Debug, PartialEq, Clone)]
24pub(crate) enum Expression {
25 Indexed(Box<(Expression, Expression)>),
26 BinaryOperation(Box<(Expression, BinaryOperator, Expression)>),
27 FunctionCall(Box<(String, Expression)>),
28 UnaryOperation(Box<(UnaryOperator, Expression)>),
29 Conditional(Box<(Expression, Expression, Expression)>),
30 Null,
31 Boolean(bool),
32 Str(String),
33 Num(Number),
34 Array(Vec<Expression>),
35 Object(HashMap<String, Expression>),
36 Identifier(String),
37}
38
39#[derive(Debug, PartialEq, Clone)]
40pub(crate) enum BinaryOperator {
41 Add,
42 Subtract,
43 Multiply,
44 Divide,
45 Modulo,
46 EqualTo,
47 NotEqualTo,
48 GreaterThan,
49 GreterThanOrEqualTo,
50 LessThan,
51 LessThanOrEqualTo,
52 Or,
53 And,
54}
55
56#[derive(Debug, PartialEq, Clone)]
57pub(crate) enum UnaryOperator {
58 Not,
59}
60
61pub(crate) fn expression(input: &mut &str) -> PResult<Expression> {
62 conditional_expression.parse_next(input)
63}
64
65fn conditional_expression(input: &mut &str) -> PResult<Expression> {
66 let cond = or_expression.parse_next(input)?;
67 if let Ok(Some((x, y))) = opt((
68 preceded((ws, '?', ws), expression),
69 preceded((ws, ':', ws), conditional_expression),
70 ))
71 .parse_next(input)
72 {
73 Ok(Expression::Conditional(Box::new((cond, x, y))))
74 } else {
75 Ok(cond)
76 }
77}
78
79fn or_expression(input: &mut &str) -> PResult<Expression> {
80 let x = and_expression.parse_next(input)?;
81 if let Ok(op) = delimited(ws, "||".value(BinaryOperator::Or), ws).parse_next(input) {
82 let y = or_expression(input)?;
83 return Ok(Expression::BinaryOperation(Box::new((x, op, y))));
84 } else {
85 return Ok(x);
86 }
87}
88
89fn and_expression(input: &mut &str) -> PResult<Expression> {
90 let x = equality_operation.parse_next(input)?;
91 if let Ok(op) = delimited(ws, "&&".value(BinaryOperator::And), ws).parse_next(input) {
92 let y = and_expression(input)?;
93 return Ok(Expression::BinaryOperation(Box::new((x, op, y))));
94 } else {
95 return Ok(x);
96 }
97}
98
99fn equality_operation(input: &mut &str) -> PResult<Expression> {
100 let x = comparison_expression.parse_next(input)?;
101 if let Ok(op) = delimited(
102 ws,
103 alt((
104 "==".value(BinaryOperator::EqualTo),
105 "!=".value(BinaryOperator::NotEqualTo),
106 )),
107 ws,
108 )
109 .parse_next(input)
110 {
111 let y = equality_operation(input)?;
112 return Ok(Expression::BinaryOperation(Box::new((x, op, y))));
113 } else {
114 return Ok(x);
115 }
116}
117
118fn comparison_expression(input: &mut &str) -> PResult<Expression> {
119 let x = modulo_expression.parse_next(input)?;
120 if let Ok(op) = delimited(
121 ws,
122 alt((
123 ">=".value(BinaryOperator::GreterThanOrEqualTo),
124 ">".value(BinaryOperator::GreaterThan),
125 "<=".value(BinaryOperator::LessThanOrEqualTo),
126 "<".value(BinaryOperator::LessThan),
127 )),
128 ws,
129 )
130 .parse_next(input)
131 {
132 let y = comparison_expression(input)?;
133 return Ok(Expression::BinaryOperation(Box::new((x, op, y))));
134 } else {
135 return Ok(x);
136 }
137}
138
139fn modulo_expression(input: &mut &str) -> PResult<Expression> {
140 let x = additive_expression.parse_next(input)?;
141 if let Ok(op) = delimited(ws, "%".value(BinaryOperator::Modulo), ws).parse_next(input) {
142 let y = modulo_expression(input)?;
143 return Ok(Expression::BinaryOperation(Box::new((x, op, y))));
144 } else {
145 return Ok(x);
146 }
147}
148
149fn additive_expression(input: &mut &str) -> PResult<Expression> {
150 let x = multiplicative_expression.parse_next(input)?;
151 if let Ok(op) = delimited(
152 ws,
153 alt((
154 "+".value(BinaryOperator::Add),
155 "-".value(BinaryOperator::Subtract),
156 )),
157 ws,
158 )
159 .parse_next(input)
160 {
161 let y = additive_expression(input)?;
162 return Ok(Expression::BinaryOperation(Box::new((x, op, y))));
163 } else {
164 return Ok(x);
165 }
166}
167
168fn multiplicative_expression(input: &mut &str) -> PResult<Expression> {
169 let x = unary_expression.parse_next(input)?;
170 if let Ok(op) = delimited(
171 ws,
172 alt((
173 "*".value(BinaryOperator::Multiply),
174 "/".value(BinaryOperator::Divide),
175 )),
176 ws,
177 )
178 .parse_next(input)
179 {
180 let y = multiplicative_expression(input)?;
181 return Ok(Expression::BinaryOperation(Box::new((x, op, y))));
182 } else {
183 return Ok(x);
184 }
185}
186
187fn unary_expression(input: &mut &str) -> PResult<Expression> {
188 if let Ok(exp) = preceded(('!', ws), indexed_expression).parse_next(input) {
189 return Ok(Expression::UnaryOperation(Box::new((
190 UnaryOperator::Not,
191 exp,
192 ))));
193 } else {
194 return indexed_expression.parse_next(input);
195 }
196}
197
198fn indexed_expression(input: &mut &str) -> PResult<Expression> {
199 let mut exp = primary_expression.parse_next(input)?;
200 while let Ok(index) = preceded(
201 ws,
202 alt((
203 delimited('[', delimited(ws, expression, ws), ']'),
204 preceded(('.', ws), identifier.map(Expression::Str)),
205 )),
206 )
207 .parse_next(input)
208 {
209 exp = Expression::Indexed(Box::new((exp, index)));
210 }
211 return Ok(exp);
212}
213
214fn primary_expression(input: &mut &str) -> PResult<Expression> {
215 alt((
216 delimited('(', delimited(ws, expression, ws), ')'),
217 null.value(Expression::Null),
218 boolean.map(Expression::Boolean),
219 string.map(Expression::Str),
220 number.map(Expression::Num),
221 array.map(Expression::Array),
222 object.map(Expression::Object),
223 function_call.map(Expression::FunctionCall),
224 identifier.map(Expression::Identifier),
225 ))
226 .parse_next(input)
227}
228
229fn function_call(input: &mut &str) -> PResult<Box<(String, Expression)>> {
230 separated_pair(identifier, ws, delimited(('(', ws), expression, (ws, ')')))
231 .map(|(id, arg)| Box::new((id, arg)))
232 .parse_next(input)
233}
234
235pub(crate) fn number(input: &mut &str) -> PResult<Number> {
236 (|input: &mut &str| {
237 let s = recognize_float(input)?;
238 categorize_num(s).ok_or_else(|| {
239 winnow::error::ErrMode::from_error_kind(input, winnow::error::ErrorKind::Verify)
240 })
241 })
242 .parse_next(input)
243}
244
245fn categorize_num(s: &str) -> Option<Number> {
246 if s.contains('.') || s.contains('e') || s.contains('E') {
247 return s.parse().map(|x: f64| Number::from_f64(x).unwrap()).ok();
248 } else if s.starts_with('-') {
249 return s.parse::<i32>().map(|x| Number::from(x)).ok();
250 } else {
251 return s.parse::<u32>().map(|x| Number::from(x)).ok();
252 }
253}
254
255fn recognize_float<'a>(input: &mut &'a str) -> PResult<&'a str> {
256 (
257 opt(winnow::token::one_of(['+', '-'])),
258 alt((
259 (ascii::digit1, opt(('.', opt(ascii::digit1)))).void(),
260 ('.', ascii::digit1).void(),
261 )),
262 opt((
263 winnow::token::one_of(['e', 'E']),
264 opt(winnow::token::one_of(['+', '-'])),
265 cut_err(ascii::digit1),
266 )),
267 )
268 .recognize()
269 .parse_next(input)
270}
271
272fn null<'s>(input: &mut &'s str) -> PResult<&'s str> {
273 "null".parse_next(input)
274}
275
276fn boolean(input: &mut &str) -> PResult<bool> {
277 alt(("true".value(true), "false".value(false))).parse_next(input)
278}
279fn string(input: &mut &str) -> PResult<String> {
280 alt((single_string, double_string)).parse_next(input)
281}
282
283fn double_string(input: &mut &str) -> PResult<String> {
284 preceded(
285 '\"',
286 cut_err(terminated(
287 repeat(0.., character).fold(String::new, |mut string, c| {
288 string.push(c);
289 string
290 }),
291 '\"',
292 )),
293 )
294 .parse_next(input)
295}
296
297fn single_string(input: &mut &str) -> PResult<String> {
298 preceded(
299 '\'',
300 cut_err(terminated(
301 repeat(0.., character).fold(String::new, |mut string, c| {
302 string.push(c);
303 string
304 }),
305 '\'',
306 )),
307 )
308 .parse_next(input)
309}
310
311pub(crate) fn identifier<'s>(input: &'s mut &str) -> PResult<String> {
312 take_while(1.., ('a'..='z', 'A'..='Z', '_'))
313 .parse_next(input)
314 .map(|s| s.to_string())
315}
316
317fn character(input: &mut &str) -> PResult<char> {
320 let c = none_of(['\"', '\'']).parse_next(input)?;
321 if c == '\\' {
322 alt((
323 any.verify_map(|c| {
324 Some(match c {
325 '"' | '\\' | '/' => c,
326 'b' => '\x08',
327 'f' => '\x0C',
328 'n' => '\n',
329 'r' => '\r',
330 't' => '\t',
331 _ => return None,
332 })
333 }),
334 preceded('u', unicode_escape),
335 ))
336 .parse_next(input)
337 } else {
338 Ok(c)
339 }
340}
341
342fn unicode_escape<'s>(input: &mut &'s str) -> PResult<char> {
343 alt((
344 u16_hex
346 .verify(|cp| !(0xD800..0xE000).contains(cp))
347 .map(|cp| cp as u32),
348 separated_pair(u16_hex, "\\u", u16_hex)
350 .verify(|(high, low)| (0xD800..0xDC00).contains(high) && (0xDC00..0xE000).contains(low))
351 .map(|(high, low)| {
352 let high_ten = (high as u32) - 0xD800;
353 let low_ten = (low as u32) - 0xDC00;
354 (high_ten << 10) + low_ten + 0x10000
355 }),
356 ))
357 .verify_map(
358 std::char::from_u32,
360 )
361 .parse_next(input)
362}
363
364fn u16_hex(input: &mut &str) -> PResult<u16> {
365 take(4usize)
366 .verify_map(|s| u16::from_str_radix(s, 16).ok())
367 .parse_next(input)
368}
369
370fn array(input: &mut &str) -> PResult<Vec<Expression>> {
375 preceded(
376 ('[', ws),
377 cut_err(terminated(
378 separated(0.., expression, (ws, ',', ws)),
379 (ws, ']'),
380 )),
381 )
382 .parse_next(input)
383}
384
385fn object(input: &mut &str) -> PResult<HashMap<String, Expression>> {
386 preceded(
387 ('{', ws),
388 cut_err(terminated(
389 separated(0.., key_value, (ws, ',', ws)),
390 (ws, '}'),
391 )),
392 )
393 .parse_next(input)
394}
395
396fn key_value(input: &mut &str) -> PResult<(String, Expression)> {
397 separated_pair(string, cut_err((ws, ':', ws)), expression).parse_next(input)
398}
399
400pub(crate) fn ws<'s>(input: &mut &'s str) -> PResult<&'s str> {
401 take_while(0.., WS).parse_next(input)
402}
403
404const WS: &[char] = &[' ', '\t', '\r', '\n'];
405
406#[cfg(test)]
407mod test {
408 use super::*;
409
410 #[test]
411 fn json_string() {
412 assert_eq!(string.parse_peek("\"\""), Ok(("", "".to_owned())));
413 assert_eq!(string.parse_peek("\"abc\""), Ok(("", "abc".to_owned())));
414 assert_eq!(
415 string.parse_peek("\"abc\\\"\\\\\\/\\b\\f\\n\\r\\t\\u0001\\u2014\u{2014}def\""),
416 Ok(("", "abc\"\\/\x08\x0C\n\r\t\x01ββdef".to_owned())),
417 );
418 assert_eq!(
419 string.parse_peek("\"\\uD83D\\uDE10\""),
420 Ok(("", "π".to_owned()))
421 );
422
423 assert!(string.parse_peek("\"").is_err());
424 assert!(string.parse_peek("\"abc").is_err());
425 assert!(string.parse_peek("\"\\\"").is_err());
426 assert!(string.parse_peek("\"\\u123\"").is_err());
427 assert!(string.parse_peek("\"\\uD800\"").is_err());
428 assert!(string.parse_peek("\"\\uD800\\uD800\"").is_err());
429 assert!(string.parse_peek("\"\\uDC00\"").is_err());
430 }
431
432 #[test]
433 fn json_object() {
434 use Expression::{Num, Str};
435
436 let input = r#"{"a":42,"b":"x"}"#;
437
438 let expected = Expression::Object(
439 vec![
440 ("a".to_owned(), Num(42.into())),
441 ("b".to_owned(), Str("x".to_owned())),
442 ]
443 .into_iter()
444 .collect(),
445 );
446
447 assert_eq!(expression.parse_peek(input), Ok(("", expected)));
448 }
449
450 #[test]
451 fn json_array() {
452 use Expression::{Num, Str};
453
454 let input = r#"[42,"x"]"#;
455
456 let expected = Expression::Array(vec![Num(42.into()), Str("x".to_owned())]);
457
458 assert_eq!(expression.parse_peek(input), Ok(("", expected)));
459 }
460
461 #[test]
462 fn json_whitespace() {
463 use Expression::{Array, Boolean, Null, Num, Object, Str};
464
465 let input = r#"{
466 "null" : null,
467 "true" :true ,
468 "false": false ,
469 "number" : 123e4 ,
470 "string" : " abc 123 " ,
471 "array" : [ false , 1 , "two" ] ,
472 "object" : { "a" : 1.0 , "b" : "c" } ,
473 "empty_array" : [ ] ,
474 "empty_object" : { }
475 }"#;
476
477 assert_eq!(
478 expression.parse_peek(input),
479 Ok((
480 "",
481 Expression::Object(
482 vec![
483 ("null".to_owned(), Null),
484 ("true".to_owned(), Boolean(true)),
485 ("false".to_owned(), Boolean(false)),
486 ("number".to_owned(), Num(Number::from_f64(123e4).unwrap())),
487 ("string".to_owned(), Str(" abc 123 ".to_owned())),
488 (
489 "array".to_owned(),
490 Array(vec![Boolean(false), Num(1.into()), Str("two".to_owned())])
491 ),
492 (
493 "object".to_owned(),
494 Object(
495 vec![
496 ("a".to_owned(), Num(Number::from_f64(1.0).unwrap())),
497 ("b".to_owned(), Str("c".to_owned())),
498 ]
499 .into_iter()
500 .collect()
501 )
502 ),
503 ("empty_array".to_owned(), Array(vec![]),),
504 ("empty_object".to_owned(), Object(HashMap::new()),),
505 ]
506 .into_iter()
507 .collect()
508 )
509 ))
510 );
511 }
512
513 #[test]
514 fn indexed_expressions() {
515 use Expression::{Num, Object};
516
517 let input = r#"{ "z": 1 }[0]"#;
518
519 assert_eq!(
520 expression.parse_peek(input),
521 Ok((
522 "",
523 Expression::Indexed(Box::new((
524 Object(vec![("z".to_owned(), Num(1.into()))].into_iter().collect()),
525 Num(0.into())
526 )))
527 ))
528 )
529 }
530
531 #[test]
532 fn indexed_expressions_2() {
533 use Expression::{Num, Object};
534
535 let input = r#"{ "z": 1 } [ 0 ]"#;
536
537 assert_eq!(
538 expression.parse_peek(input),
539 Ok((
540 "",
541 Expression::Indexed(Box::new((
542 Object(vec![("z".to_owned(), Num(1.into()))].into_iter().collect()),
543 Num(0.into())
544 )))
545 ))
546 )
547 }
548
549 #[test]
550 fn multi_identifiers_0() {
551 let input = r#"window"#;
552
553 assert_eq!(identifier.parse_peek(input), Ok(("", "window".to_owned())))
554 }
555
556 #[test]
557 fn expression_multi_identifier() {
558 let input = r#"props.user.name"#;
559
560 assert_eq!(
561 expression.parse_peek(input),
562 Ok((
563 "",
564 Expression::Indexed(Box::new((
565 Expression::Indexed(Box::new((
566 Expression::Identifier("props".to_owned()),
567 Expression::Str("user".to_owned())
568 ))),
569 Expression::Str("name".to_owned())
570 ))),
571 ))
572 )
573 }
574
575 #[test]
576 fn expression_or() {
577 use Expression::{BinaryOperation, Num};
578 let input = r#"props.user.name || 1.0"#;
579
580 assert_eq!(
581 expression.parse_peek(input),
582 Ok((
583 "",
584 BinaryOperation(Box::new((
585 Expression::Indexed(Box::new((
586 Expression::Indexed(Box::new((
587 Expression::Identifier("props".to_owned()),
588 Expression::Str("user".to_owned())
589 ))),
590 Expression::Str("name".to_owned())
591 ))),
592 BinaryOperator::Or,
593 Num(Number::from_f64(1.0).unwrap())
594 )))
595 ))
596 )
597 }
598
599 #[test]
600 fn expression_and() {
601 use Expression::{Array, BinaryOperation, Indexed, Num, Object};
602 let input = r#"[1] && {}[3]"#;
603
604 assert_eq!(
605 expression.parse_peek(input),
606 Ok((
607 "",
608 BinaryOperation(Box::new((
609 Array(vec![Num(1.into())]),
610 BinaryOperator::And,
611 Indexed(Box::new((Object(HashMap::new()), Num(3.into()))))
612 )))
613 ))
614 )
615 }
616
617 #[test]
618 fn expression_add() {
619 use Expression::{BinaryOperation, Identifier, Num};
620 let input = r#"name + 1.0"#;
621
622 assert_eq!(
623 expression.parse_peek(input),
624 Ok((
625 "",
626 BinaryOperation(Box::new((
627 Identifier("name".to_owned()),
628 BinaryOperator::Add,
629 Num(Number::from_f64(1.0).unwrap())
630 )))
631 ))
632 )
633 }
634
635 #[test]
636 fn expression_eq() {
637 use Expression::{BinaryOperation, Identifier, Str};
638 let input = r#"props == """#;
639
640 assert_eq!(
641 expression.parse_peek(input),
642 Ok((
643 "",
644 BinaryOperation(Box::new((
645 Identifier("props".to_owned()),
646 BinaryOperator::EqualTo,
647 Str("".to_owned())
648 )))
649 ))
650 )
651 }
652
653 #[test]
654 fn expression_indexed() {
655 use Expression::{BinaryOperation, Indexed, Object, Str};
656 let input = r#"{ "hello": "world" }["hell" + "o"]"#;
657
658 assert_eq!(
659 expression.parse_peek(input),
660 Ok((
661 "",
662 Indexed(Box::new((
663 Object(HashMap::from([(
664 "hello".to_owned(),
665 Str("world".to_owned())
666 )])),
667 BinaryOperation(Box::new((
668 Str("hell".to_owned()),
669 BinaryOperator::Add,
670 Str("o".to_owned())
671 )))
672 )))
673 ))
674 )
675 }
676
677 #[test]
678 fn expression_iif() {
679 use Expression::{BinaryOperation, Conditional, Num};
680 let input = r#"1 > 2 ? 1 : 2"#;
681
682 assert_eq!(
683 expression.parse_peek(input),
684 Ok((
685 "",
686 Conditional(Box::new((
687 BinaryOperation(Box::new((
688 Num(1.into()),
689 BinaryOperator::GreaterThan,
690 Num(2.into())
691 ))),
692 Num(1.into()),
693 Num(2.into())
694 )))
695 ))
696 )
697 }
698
699 #[test]
700 fn expression_bidmas() {
701 use Expression::{BinaryOperation, Num};
702 let input = r#"(9 + 3) / 2 == 6"#;
703
704 assert_eq!(
705 expression.parse_peek(input),
706 Ok((
707 "",
708 BinaryOperation(Box::new((
709 BinaryOperation(Box::new((
710 BinaryOperation(Box::new((
711 Num(9.into()),
712 BinaryOperator::Add,
713 Num(3.into())
714 ))),
715 BinaryOperator::Divide,
716 Num(2.into())
717 ))),
718 BinaryOperator::EqualTo,
719 Num(6.into())
720 )))
721 ))
722 )
723 }
724
725 #[test]
726 fn unary_not() {
727 let input = r#"!this"#;
728
729 assert_eq!(
730 expression.parse_peek(input),
731 Ok((
732 "",
733 Expression::UnaryOperation(Box::new((
734 UnaryOperator::Not,
735 Expression::Identifier("this".to_owned())
736 )))
737 ))
738 )
739 }
740
741 #[test]
742 fn expression_mod() {
743 let input = r#"1%3"#;
744
745 assert_eq!(
746 expression.parse_peek(input),
747 Ok((
748 "",
749 Expression::BinaryOperation(Box::new((
750 Expression::Num(1.into()),
751 BinaryOperator::Modulo,
752 Expression::Num(3.into())
753 )))
754 ))
755 )
756 }
757
758 #[test]
759 fn expression_conditional_order_of_ops() {
760 let input = r#"1 < 2 == true"#;
761
762 assert_eq!(
763 expression.parse_peek(input),
764 Ok((
765 "",
766 Expression::BinaryOperation(Box::new((
767 Expression::BinaryOperation(Box::new((
768 Expression::Num(1.into()),
769 BinaryOperator::LessThan,
770 Expression::Num(2.into())
771 ))),
772 BinaryOperator::EqualTo,
773 Expression::Boolean(true.into())
774 )))
775 ))
776 )
777 }
778
779 #[test]
780 fn expression_in_object() {
781 let input = r#"{"hello": [ 1 * 2 ] }"#;
782 assert_eq!(
783 expression.parse_peek(input),
784 Ok((
785 "",
786 Expression::Object(HashMap::from([(
787 "hello".to_owned(),
788 Expression::Array(vec![Expression::BinaryOperation(Box::new((
789 Expression::Num(1.into()),
790 BinaryOperator::Multiply,
791 Expression::Num(2.into())
792 )))])
793 )]))
794 ))
795 )
796 }
797
798 #[test]
799 fn single_quote_strings() {
800 let input = r#"{'hello': 'worl' + "d"}"#;
801 assert_eq!(
802 expression.parse_peek(input),
803 Ok((
804 "",
805 Expression::Object(HashMap::from([(
806 "hello".to_owned(),
807 Expression::BinaryOperation(Box::new((
808 Expression::Str("worl".into()),
809 BinaryOperator::Add,
810 Expression::Str("d".into()),
811 )))
812 )]))
813 ))
814 )
815 }
816
817 #[test]
818 fn indexed_exp() {
819 let input = r#"data.people[0].age"#;
820 assert_eq!(
821 expression.parse_peek(input),
822 Ok((
823 "",
824 Expression::Indexed(Box::new((
825 (Expression::Indexed(Box::new((
826 Expression::Indexed(Box::new((
827 Expression::Identifier("data".to_owned()),
828 Expression::Str("people".to_owned())
829 ))),
830 Expression::Num(0.into())
831 )))),
832 Expression::Str("age".to_owned())
833 )))
834 ))
835 )
836 }
837
838 #[test]
839 fn indexed_exp_no_dots() {
840 let input = r#"data["people"][0]["age"]"#;
841 assert_eq!(
842 expression.parse_peek(input),
843 Ok((
844 "",
845 Expression::Indexed(Box::new((
846 (Expression::Indexed(Box::new((
847 Expression::Indexed(Box::new((
848 Expression::Identifier("data".to_owned()),
849 Expression::Str("people".to_owned())
850 ))),
851 Expression::Num(0.into())
852 )))),
853 Expression::Str("age".to_owned())
854 )))
855 ))
856 )
857 }
858
859 #[test]
860 fn function_call() {
861 let input = r#"format_money({"currency": "gbp", "value": 100})"#;
862 assert_eq!(
863 expression.parse_peek(input),
864 Ok((
865 "",
866 Expression::FunctionCall(Box::new((
867 "format_money".into(),
868 Expression::Object(HashMap::from([
869 ("currency".into(), Expression::Str("gbp".into())),
870 ("value".into(), Expression::Num(100.into()))
871 ]))
872 )))
873 ))
874 )
875 }
876
877 #[test]
878 fn wtf() {
879 let input = r#"false ? true"#;
880 assert_eq!(
881 expression.parse_peek(input),
882 Ok(("? true", Expression::Boolean(false)))
883 )
884 }
885}