1use nom::{
2 branch::alt,
3 bytes::complete::tag,
4 character::complete::{none_of, one_of},
5 combinator::{cut, map, opt},
6 multi::{count, many0, many1, many_m_n},
7 sequence::{delimited, pair, preceded, terminated},
8 IResult, Parser,
9};
10use std::fmt;
11
12use super::{ws0, ParseResult, SyntaxError, SyntaxErrorKind};
13
14#[derive(Debug, Eq, PartialEq, Clone)]
15pub enum Expression {
16 Number(String),
17 BigInt(String),
18 String(StringLiteral),
19 Identifier(String),
20 UnaryOperation {
21 operator: UnaryOperator,
22 operand: Box<Expression>,
23 },
24 BinaryOperation {
25 operator: BinaryOperator,
26 left: Box<Expression>,
27 right: Box<Expression>,
28 },
29}
30
31impl fmt::Display for Expression {
32 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
33 match self {
34 Self::Number(number) => write!(f, "{}", number),
35 Self::BigInt(bigint) => write!(f, "{}n", bigint),
36 Self::String(string) => write!(f, "\"{}\"", string.value),
37 Self::Identifier(name) => write!(f, "{}", name),
38 Self::UnaryOperation { operator, operand } => match operator {
39 UnaryOperator::Try => write!(f, "({}?)", operand),
40 _ => write!(f, "({}{})", operator, operand),
41 },
42 Self::BinaryOperation {
43 operator,
44 left,
45 right,
46 } => write!(f, "({} {} {})", left, operator, right),
47 }
48 }
49}
50
51#[derive(Debug, Eq, PartialEq, Clone)]
56pub struct StringLiteral {
57 pub value: String,
59 pub interpolations: Vec<(usize, Box<Expression>)>,
61}
62
63#[derive(Debug, PartialEq, Clone)]
64enum StringPart {
65 Literal(String),
66 Interpolation(Box<Expression>),
67}
68
69#[derive(Debug, Eq, PartialEq, Clone, Copy)]
70pub enum UnaryOperator {
71 Negate,
72 LogicalNot,
73 BitwiseNot,
74 UnaryPlus,
75 UnaryMinus,
76 Try,
77}
78
79impl fmt::Display for UnaryOperator {
80 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
81 match self {
82 Self::Negate => write!(f, "!"),
83 Self::LogicalNot => write!(f, "!"),
84 Self::BitwiseNot => write!(f, "~"),
85 Self::UnaryPlus => write!(f, "+"),
86 Self::UnaryMinus => write!(f, "-"),
87 Self::Try => write!(f, "?"),
88 }
89 }
90}
91
92impl std::str::FromStr for UnaryOperator {
93 type Err = ();
94
95 fn from_str(s: &str) -> Result<Self, Self::Err> {
96 match s {
97 "!" => Ok(Self::Negate),
98 "~" => Ok(Self::BitwiseNot),
99 "+" => Ok(Self::UnaryPlus),
100 "-" => Ok(Self::UnaryMinus),
101 "?" => Ok(Self::Try),
102 _ => Err(()),
103 }
104 }
105}
106
107#[derive(Debug, Eq, PartialEq, Clone, Copy)]
108pub enum Associativity {
109 LeftToRight,
110 RightToLeft,
111}
112
113#[derive(Debug, Eq, PartialEq, Clone, Copy)]
114pub enum BinaryOperator {
115 Exponent,
117 Multiply,
119 Divide,
121 Modulo,
123 Add,
125 Subtract,
127 LeftShift,
129 RightShift,
131 LessThan,
133 LessThanOrEqual,
135 GreaterThan,
137 GreaterThanOrEqual,
139 Equal,
141 NotEqual,
143 BitwiseAnd,
145 BitwiseXor,
147 BitwiseOr,
149 LogicalAnd,
151 LogicalOr,
153 Pipe,
155}
156
157impl BinaryOperator {
158 pub fn precedence(&self) -> u8 {
159 match self {
160 Self::Exponent => 13,
161 Self::Multiply | Self::Divide | Self::Modulo => 12,
162 Self::Add | Self::Subtract => 11,
163 Self::LeftShift | Self::RightShift => 10,
164 Self::LessThan
165 | Self::LessThanOrEqual
166 | Self::GreaterThan
167 | Self::GreaterThanOrEqual => 9,
168 Self::Equal | Self::NotEqual => 8,
169 Self::BitwiseAnd => 7,
170 Self::BitwiseXor => 6,
171 Self::BitwiseOr => 5,
172 Self::LogicalAnd => 4,
173 Self::LogicalOr => 3,
174 Self::Pipe => 2,
175 }
176 }
177
178 pub fn associativity(&self) -> Associativity {
179 match self {
180 Self::Exponent => Associativity::RightToLeft,
181 Self::Multiply
182 | Self::Divide
183 | Self::Modulo
184 | Self::Add
185 | Self::Subtract
186 | Self::LeftShift
187 | Self::RightShift
188 | Self::LessThan
189 | Self::LessThanOrEqual
190 | Self::GreaterThan
191 | Self::GreaterThanOrEqual
192 | Self::Equal
193 | Self::NotEqual
194 | Self::BitwiseAnd
195 | Self::BitwiseXor
196 | Self::BitwiseOr
197 | Self::LogicalAnd
198 | Self::LogicalOr
199 | Self::Pipe => Associativity::LeftToRight,
200 }
201 }
202}
203
204impl std::str::FromStr for BinaryOperator {
205 type Err = ();
206
207 fn from_str(s: &str) -> Result<Self, Self::Err> {
208 match s {
209 "**" => Ok(Self::Exponent),
210 "*" => Ok(Self::Multiply),
211 "/" => Ok(Self::Divide),
212 "%" => Ok(Self::Modulo),
213 "+" => Ok(Self::Add),
214 "-" => Ok(Self::Subtract),
215 "<<" => Ok(Self::LeftShift),
216 ">>" => Ok(Self::RightShift),
217 "<" => Ok(Self::LessThan),
218 "<=" => Ok(Self::LessThanOrEqual),
219 ">" => Ok(Self::GreaterThan),
220 ">=" => Ok(Self::GreaterThanOrEqual),
221 "==" => Ok(Self::Equal),
222 "!=" => Ok(Self::NotEqual),
223 "&" => Ok(Self::BitwiseAnd),
224 "^" => Ok(Self::BitwiseXor),
225 "|" => Ok(Self::BitwiseOr),
226 "&&" => Ok(Self::LogicalAnd),
227 "||" => Ok(Self::LogicalOr),
228 "|>" => Ok(Self::Pipe),
229 _ => Err(()),
230 }
231 }
232}
233
234impl fmt::Display for BinaryOperator {
235 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
236 match self {
237 Self::Exponent => write!(f, "**"),
238 Self::Multiply => write!(f, "*"),
239 Self::Divide => write!(f, "/"),
240 Self::Modulo => write!(f, "%"),
241 Self::Add => write!(f, "+"),
242 Self::Subtract => write!(f, "-"),
243 Self::LeftShift => write!(f, "<<"),
244 Self::RightShift => write!(f, ">>"),
245 Self::LessThan => write!(f, "<"),
246 Self::LessThanOrEqual => write!(f, "<="),
247 Self::GreaterThan => write!(f, ">"),
248 Self::GreaterThanOrEqual => write!(f, ">="),
249 Self::Equal => write!(f, "=="),
250 Self::NotEqual => write!(f, "!="),
251 Self::BitwiseAnd => write!(f, "&"),
252 Self::BitwiseXor => write!(f, "^"),
253 Self::BitwiseOr => write!(f, "|"),
254 Self::LogicalAnd => write!(f, "&&"),
255 Self::LogicalOr => write!(f, "||"),
256 Self::Pipe => write!(f, "|>"),
257 }
258 }
259}
260
261fn non_zero_digit(input: &str) -> ParseResult<char> {
262 one_of("123456789")(input)
263}
264
265fn digit(input: &str) -> ParseResult<char> {
266 one_of("0123456789")(input)
267}
268
269fn hex_digit(input: &str) -> ParseResult<char> {
270 let result: IResult<&str, char> = one_of("0123456789abcdefABCDEF").parse(input);
271 match result {
272 Ok((input, c)) => Ok((input, c)),
273 Err(_) => Err(nom::Err::Error(SyntaxError {
274 input,
275 error: SyntaxErrorKind::InvalidHexDigit,
276 })),
277 }
278}
279
280fn delimited_digit(input: &str) -> ParseResult<char> {
281 if input.starts_with("__") {
282 return Err(nom::Err::Failure(SyntaxError {
283 input,
284 error: SyntaxErrorKind::ConsecutiveUnderscoreInNumericLiteral,
285 }));
286 }
287 alt((digit, preceded(tag("_"), digit))).parse(input)
288}
289
290fn whole_number(input: &str) -> ParseResult<String> {
291 if input.starts_with('_') {
292 return Err(nom::Err::Failure(SyntaxError {
293 input,
294 error: SyntaxErrorKind::NumericLiteralStartsWithUnderscore,
295 }));
296 } else if input.is_empty() {
297 return Err(nom::Err::Failure(SyntaxError {
298 input,
299 error: SyntaxErrorKind::EmptyInput,
300 }));
301 }
302 let (input, start) = non_zero_digit(input)?;
304 let (input, digits) = many0(delimited_digit).parse(input)?;
307 let number = std::iter::once(start).chain(digits).collect::<String>();
309 Ok((input, number))
310}
311
312fn decimal_number(input: &str) -> ParseResult<String> {
313 let (input, mut number) = whole_number(input)?;
314 let (input, decimal) = opt(preceded(tag("."), many1(delimited_digit))).parse(input)?;
316 if input.starts_with('_') {
317 return Err(nom::Err::Failure(SyntaxError {
318 input,
319 error: SyntaxErrorKind::NumericLiteralEndsWithUnderscore,
320 }));
321 }
322 if let Some(decimal) = decimal {
324 number.extend(std::iter::once('.').chain(decimal));
325 }
326 Ok((input, number))
327}
328
329fn scientific_notation(input: &str) -> ParseResult<String> {
330 let (input, mut number) = decimal_number(input)?;
331 let (input, sign) = preceded(alt((tag("e"), tag("E"))), opt(one_of("+-"))).parse(input)?;
332 let (input, exponent) = many1(delimited_digit).parse(input)?;
333 if input.starts_with('_') {
334 return Err(nom::Err::Failure(SyntaxError {
335 input,
336 error: SyntaxErrorKind::NumericLiteralEndsWithUnderscore,
337 }));
338 }
339 match sign {
340 Some('-') => number.push_str("e-"),
341 Some('+') => number.push('e'),
342 None => number.push('e'),
343 _ => unreachable!(),
344 };
345 number.extend(exponent);
346
347 Ok((input, number))
348}
349
350fn parse_number(input: &str) -> ParseResult<Expression> {
351 map(alt((scientific_notation, decimal_number)), |number| {
352 Expression::Number(number)
353 })
354 .parse(input)
355}
356
357fn parse_bigint(input: &str) -> ParseResult<Expression> {
358 if input.starts_with('n') {
359 return Err(nom::Err::Failure(SyntaxError {
360 input,
361 error: SyntaxErrorKind::EmptyBigIntLiteral,
362 }));
363 }
364 map(
365 terminated(alt((scientific_notation, whole_number)), tag("n")),
366 Expression::BigInt,
367 )
368 .parse(input)
369}
370
371fn parse_escaped_char(input: &str) -> ParseResult<char> {
372 let (input, result) = alt((
373 tag("\\\\"), tag("\\\""), tag("\\n"), tag("\\r"), tag("\\t"), tag("\\0"), tag("{{"), tag("}}"), ))
382 .parse(input)?;
383 match result {
384 "\\\\" => Ok((input, '\\')),
385 "\\\"" => Ok((input, '"')),
386 "\\n" => Ok((input, '\n')),
387 "\\r" => Ok((input, '\r')),
388 "\\t" => Ok((input, '\t')),
389 "\\0" => Ok((input, '\0')),
390 "{{" => Ok((input, '{')),
391 "}}" => Ok((input, '}')),
392 _ => unreachable!(),
393 }
394}
395
396fn parse_escaped_code_point(input: &str) -> ParseResult<char> {
408 let (input, value) = alt((
409 preceded(
410 tag("\\u"),
411 cut(delimited(tag("{"), many_m_n(2, 6, hex_digit), tag("}"))),
412 ),
413 preceded(tag("\\x"), cut(count(hex_digit, 2))),
414 ))
415 .parse(input)?;
416 let value = value.iter().collect::<String>();
417 let code_point = u32::from_str_radix(&value, 16).unwrap();
418 match std::char::from_u32(code_point) {
419 Some(c) => Ok((input, c)),
420 None => Err(nom::Err::Failure(SyntaxError {
421 input,
422 error: SyntaxErrorKind::InvalidUnicodeCodePoint(code_point),
423 })),
424 }
425}
426
427fn parse_regular_char(input: &str) -> ParseResult<char> {
428 none_of("\\\"{}").parse(input)
429}
430
431fn parse_interpolation(input: &str) -> ParseResult<StringPart> {
432 map(
433 delimited(tag("{"), alt((parse_number, parse_bigint)), tag("}")),
434 |inter| StringPart::Interpolation(inter.into()),
435 )
436 .parse(input)
437}
438
439fn parse_string(input: &str) -> ParseResult<Expression> {
440 let (input, parsed) = delimited(
441 tag("\""),
442 many0(alt((
443 map(
444 many1(alt((
445 parse_regular_char,
446 parse_escaped_char,
447 parse_escaped_code_point,
448 ))),
449 |f| StringPart::Literal(f.iter().collect()),
450 ),
451 parse_interpolation,
452 ))),
453 tag("\""),
454 )
455 .parse(input)?;
456 let mut string = StringLiteral {
457 value: String::new(),
458 interpolations: vec![],
459 };
460 for part in parsed {
461 match part {
462 StringPart::Literal(literal) => string.value.push_str(&literal),
463 StringPart::Interpolation(interpolation) => {
464 string
465 .interpolations
466 .push((string.value.len(), interpolation));
467 }
468 }
469 }
470 Ok((input, Expression::String(string)))
471}
472
473const ALPHA_WITH_UNDERSCORE: &str = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_";
474const ALPHANUMERIC_WITH_UNDERSCORE: &str =
475 "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_0123456789";
476
477pub(crate) fn parse_identifier(input: &str) -> ParseResult<String> {
478 map(
479 pair(
480 one_of(ALPHA_WITH_UNDERSCORE),
481 many0(one_of(ALPHANUMERIC_WITH_UNDERSCORE)),
482 ),
483 |(first, rest)| std::iter::once(first).chain(rest).collect(),
484 )
485 .parse(input)
486}
487
488pub(crate) fn parse_binary_operator(input: &str) -> ParseResult<BinaryOperator> {
489 map(
490 ws0(alt((
491 tag("|>"),
492 tag("**"),
493 tag("*"),
494 tag("/"),
495 tag("%"),
496 tag("+"),
497 tag("-"),
498 tag("<<"),
499 tag(">>"),
500 tag("<="),
501 tag("<"),
502 tag(">="),
503 tag(">"),
504 tag("=="),
505 tag("!="),
506 tag("&&"),
507 tag("||"),
508 tag("&"),
509 tag("^"),
510 tag("|"),
511 ))),
512 |op| op.parse().unwrap(),
513 )
514 .parse(input)
515}
516
517pub(crate) fn parse_unary_operator(input: &str) -> ParseResult<UnaryOperator> {
518 map(ws0(alt((tag("!"), tag("~"), tag("+"), tag("-")))), |op| {
519 op.parse().unwrap()
520 })
521 .parse(input)
522}
523
524pub(crate) fn parse_term(input: &str) -> ParseResult<Expression> {
525 map(
526 (
527 opt(parse_unary_operator),
528 alt((
529 map(parse_identifier, Expression::Identifier),
530 parse_string,
531 parse_bigint,
532 parse_number,
533 )),
534 opt(tag("?")),
535 ),
536 |(prefix, expr, postfix)| {
537 let mut expression = expr;
538 if postfix.is_some() {
539 expression = Expression::UnaryOperation {
540 operator: UnaryOperator::Try,
541 operand: Box::new(expression),
542 };
543 }
544 if let Some(op) = prefix {
545 expression = Expression::UnaryOperation {
546 operator: op,
547 operand: Box::new(expression),
548 };
549 }
550 expression
551 },
552 )
553 .parse(input)
554}
555
556pub(crate) fn parse_expression(input: &str) -> ParseResult<Expression> {
576 let (input, left) = parse_term(input)?;
577 let mut output: Vec<Expression> = vec![left];
578 let mut operators = Vec::<BinaryOperator>::new();
579 let mut remaining = input;
580 loop {
581 let (input, opt_right) =
582 opt(pair(ws0(parse_binary_operator), ws0(parse_term))).parse(remaining)?;
583 remaining = input;
584 let (op, right) = match opt_right {
585 Some((op, right)) => (op, right),
587 None => break,
589 };
590 while let Some(&top) = operators.last() {
591 if top.precedence() > op.precedence()
596 || (top.precedence() == op.precedence()
597 && op.associativity() == Associativity::LeftToRight)
598 {
599 let right = output.pop().unwrap();
600 let left = output.pop().unwrap();
601 output.push(Expression::BinaryOperation {
602 operator: operators.pop().unwrap(),
603 left: Box::new(left),
604 right: Box::new(right),
605 });
606 } else {
607 break;
608 }
609 }
610 output.push(right);
611 operators.push(op);
612 }
613 while let Some(op) = operators.pop() {
614 let right = output.pop().unwrap();
615 let left = output.pop().unwrap();
616 output.push(Expression::BinaryOperation {
617 operator: op,
618 left: Box::new(left),
619 right: Box::new(right),
620 });
621 }
622 Ok((remaining, output.pop().unwrap()))
623}
624
625#[cfg(test)]
626mod tests {
627 use super::*;
628
629 macro_rules! test_expression {
630 ($name:ident, $input:expr, $expected:expr) => {
631 #[test]
632 fn $name() {
633 let (rest, result) = parse_expression($input).unwrap();
634 assert_eq!(rest, "");
635 assert_eq!(result, $expected);
636 }
637 };
638 }
639
640 macro_rules! test_error_kind {
641 ($parser:ident, $name:ident, $input:expr, $kind:pat) => {
642 #[test]
643 fn $name() {
644 let result = $parser($input);
645 assert!(result.is_err());
646 let err = result.unwrap_err();
647 match err {
648 nom::Err::Failure(SyntaxError { error, .. }) => assert!(matches!(error, $kind)),
649 _ => panic!("Unexpected error: {:?}", err),
650 }
651 }
652 };
653 ($name:ident, $input:expr, $kind:pat) => {
654 test_error_kind!(parse_expression, $name, $input, $kind);
655 };
656 }
657
658 test_expression!(number_simple, "42", Expression::Number("42".into()));
659 test_expression!(number_pi, "3.14159", Expression::Number("3.14159".into()));
660 test_expression!(
661 number_pi_underscore,
662 "3.141_59",
663 Expression::Number("3.14159".into())
664 );
665 test_expression!(
666 number_billion,
667 "1000000000",
668 Expression::Number("1000000000".into())
669 );
670 test_expression!(
671 number_billion_with_underline,
672 "1_000_000_000",
673 Expression::Number("1000000000".into())
674 );
675 test_error_kind!(parse_number, number_empty, "", SyntaxErrorKind::EmptyInput);
676 test_error_kind!(
677 parse_number,
678 number_underscore_at_start,
679 "_42",
680 SyntaxErrorKind::NumericLiteralStartsWithUnderscore
681 );
682 test_error_kind!(
683 parse_number,
684 number_underscore_at_end,
685 "42_",
686 SyntaxErrorKind::NumericLiteralEndsWithUnderscore
687 );
688 test_error_kind!(
689 parse_number,
690 number_decimal_underscore_at_end,
691 "42.0_",
692 SyntaxErrorKind::NumericLiteralEndsWithUnderscore
693 );
694 test_error_kind!(
695 parse_number,
696 number_exponent_underscore_at_end,
697 "42e10_",
698 SyntaxErrorKind::NumericLiteralEndsWithUnderscore
699 );
700 test_error_kind!(
701 parse_number,
702 number_consecutive_underscores,
703 "1__000",
704 SyntaxErrorKind::ConsecutiveUnderscoreInNumericLiteral
705 );
706 test_expression!(
707 number_scientific_notation,
708 "1e6",
709 Expression::Number("1e6".into())
710 );
711 test_expression!(
712 number_scientific_notation_uppercase,
713 "1E6",
714 Expression::Number("1e6".into())
715 );
716 test_expression!(
717 number_scientific_notation_positive,
718 "1e+6",
719 Expression::Number("1e6".into())
720 );
721 test_expression!(
722 number_scientific_notation_negative,
723 "1e-6",
724 Expression::Number("1e-6".into())
725 );
726 test_expression!(
727 number_scientific_notation_decimal,
728 "1.23e4",
729 Expression::Number("1.23e4".into())
730 );
731 test_expression!(
732 number_scientific_notation_decimal_positive,
733 "1.23e+4",
734 Expression::Number("1.23e4".into())
735 );
736 test_expression!(
737 number_scientific_notation_decimal_negative,
738 "1.23e-4",
739 Expression::Number("1.23e-4".into())
740 );
741
742 test_expression!(bigint_simple, "42n", Expression::BigInt("42".into()));
743 test_expression!(
744 bigint_billion,
745 "1000000000n",
746 Expression::BigInt("1000000000".into())
747 );
748 test_expression!(
749 bigint_billion_with_underline,
750 "1_000_000_000n",
751 Expression::BigInt("1000000000".into())
752 );
753 test_expression!(
754 bigint_scientific_notation,
755 "1e6n",
756 Expression::BigInt("1e6".into())
757 );
758 test_expression!(
759 bigint_scientific_notation_uppercase,
760 "1E6n",
761 Expression::BigInt("1e6".into())
762 );
763 test_expression!(
764 bigint_scientific_notation_positive,
765 "1e+6n",
766 Expression::BigInt("1e6".into())
767 );
768 test_expression!(
769 bigint_scientific_notation_negative,
770 "100e-2n",
771 Expression::BigInt("100e-2".into())
772 );
773 test_expression!(
774 bigint_scientific_notation_decimal,
775 "1.23e4n",
776 Expression::BigInt("1.23e4".into())
777 );
778 test_error_kind!(
779 parse_bigint,
780 bigint_empty,
781 "n",
782 SyntaxErrorKind::EmptyBigIntLiteral
783 );
784 test_error_kind!(
785 parse_bigint,
786 bigint_underscore_at_end,
787 "42_n",
788 SyntaxErrorKind::NumericLiteralEndsWithUnderscore
789 );
790 test_error_kind!(
791 parse_bigint,
792 bigint_consecutive_underscores,
793 "1__000n",
794 SyntaxErrorKind::ConsecutiveUnderscoreInNumericLiteral
795 );
796
797 test_expression!(
798 string_empty,
799 r#""""#,
800 Expression::String(StringLiteral {
801 value: "".into(),
802 interpolations: vec![]
803 })
804 );
805 test_expression!(
806 string_simple,
807 r#""Hello, World!""#,
808 Expression::String(StringLiteral {
809 value: "Hello, World!".into(),
810 interpolations: vec![]
811 })
812 );
813 test_expression!(
814 string_escaped_chars,
815 r#""\\\"\n\r\t{{}}""#,
816 Expression::String(StringLiteral {
817 value: "\\\"\n\r\t{}".into(),
818 interpolations: vec![]
819 })
820 );
821 test_expression!(
822 string_unicode_code,
823 r#""\x41\u{41}\u{0041}\u{000041}""#,
824 Expression::String(StringLiteral {
825 value: "AAAA".into(),
826 interpolations: vec![]
827 })
828 );
829 test_expression!(
830 string_unicode_code_emoji,
831 r#""\u{2603}\u{1F600}""#,
832 Expression::String(StringLiteral {
833 value: "☃😀".into(),
834 interpolations: vec![]
835 })
836 );
837 test_error_kind!(
838 string_invalid_unicode_code_point,
839 r#""\u{110000}""#,
840 SyntaxErrorKind::InvalidUnicodeCodePoint(0x110000)
841 );
842 test_error_kind!(
843 string_missing_unicode_code_point_opening_brace,
844 r#""\u41}""#,
845 SyntaxErrorKind::NomError(nom::error::ErrorKind::Tag)
846 );
847 test_error_kind!(
848 string_missing_unicode_code_point_closing_brace,
849 r#""\u{41""#,
850 SyntaxErrorKind::NomError(nom::error::ErrorKind::Tag)
851 );
852 test_error_kind!(
853 string_invalid_hex_digit,
854 r#""\xGG""#,
855 SyntaxErrorKind::InvalidHexDigit
856 );
857 test_error_kind!(
858 string_invalid_unicode_code_point_hex,
859 r#""\u{GG}""#,
860 SyntaxErrorKind::InvalidHexDigit
861 );
862 test_expression!(
863 string_interpolation,
864 r#""{42}""#,
865 Expression::String(StringLiteral {
866 value: "".into(),
867 interpolations: vec![(0, Box::new(Expression::Number("42".into())))]
868 })
869 );
870 test_expression!(
871 string_interpolation_with_text,
872 r#""Hello, {42}!""#,
873 Expression::String(StringLiteral {
874 value: "Hello, !".into(),
875 interpolations: vec![(7, Box::new(Expression::Number("42".into())))]
876 })
877 );
878 test_expression!(
879 string_newline,
880 r#""
881""#,
882 Expression::String(StringLiteral {
883 value: "\n".into(),
884 interpolations: vec![]
885 })
886 );
887 test_expression!(
888 identifier_simple,
889 "foo",
890 Expression::Identifier("foo".into())
891 );
892 test_expression!(
893 identifier_with_underscore,
894 "_foo",
895 Expression::Identifier("_foo".into())
896 );
897 test_expression!(
898 identifier_with_numbers,
899 "foo123",
900 Expression::Identifier("foo123".into())
901 );
902 test_expression!(
903 identifier_with_underscore_and_numbers,
904 "_foo_123",
905 Expression::Identifier("_foo_123".into())
906 );
907 test_expression!(
908 identifier_all_uppercase,
909 "FOO",
910 Expression::Identifier("FOO".into())
911 );
912 test_expression!(
913 identifier_mixed_case,
914 "FooBar",
915 Expression::Identifier("FooBar".into())
916 );
917 test_expression!(
918 identifier_single_character,
919 "f",
920 Expression::Identifier("f".into())
921 );
922 test_expression!(
923 identifier_with_multiple_underscores,
924 "foo_bar_baz",
925 Expression::Identifier("foo_bar_baz".into())
926 );
927 test_expression!(
928 identifier_with_leading_underscore_and_numbers,
929 "_123foo",
930 Expression::Identifier("_123foo".into())
931 );
932 test_expression!(
933 identifier_underscore_number,
934 "_42",
935 Expression::Identifier("_42".into())
936 );
937 test_expression!(
938 bigint_underscore_number_n,
939 "_42n",
940 Expression::Identifier("_42n".into())
941 );
942
943 macro_rules! test_binary_expression {
944 ($input:expr, $expected:expr) => {
945 let (input, result) = parse_expression($input).unwrap();
946 assert_eq!(input, "");
947 assert_eq!(dbg!(result).to_string(), $expected);
948 };
949 }
950
951 #[test]
952 fn test_binary_expression() {
953 test_binary_expression!("1 + 2 * 3", "(1 + (2 * 3))");
954 test_binary_expression!("2 * 3 + 4", "((2 * 3) + 4)");
955 test_binary_expression!("2 ** 3 * 4", "((2 ** 3) * 4)");
956 test_binary_expression!("2 * 3 ** 4", "(2 * (3 ** 4))");
957
958 test_binary_expression!("1 + 2 + 3", "((1 + 2) + 3)"); test_binary_expression!("2 ** 3 ** 2", "(2 ** (3 ** 2))"); test_binary_expression!("10 / 5 / 2", "((10 / 5) / 2)"); test_binary_expression!("-2 * 3", "((-2) * 3)");
965 test_binary_expression!("!1 && 2", "((!1) && 2)");
966 test_binary_expression!("~1 & 2", "((~1) & 2)");
967
968 test_binary_expression!("1 | 2 & 3", "(1 | (2 & 3))");
970 test_binary_expression!("1 & 2 ^ 3", "((1 & 2) ^ 3)");
971 test_binary_expression!("1 | 2 | 3", "((1 | 2) | 3)");
972
973 test_binary_expression!("1 || 2 && 3", "(1 || (2 && 3))");
975 test_binary_expression!("1 && 2 || 3 && 4", "((1 && 2) || (3 && 4))");
976
977 test_binary_expression!("1 < 2 == 3 > 4", "((1 < 2) == (3 > 4))");
979 test_binary_expression!("1 == 2 != 3 == 4", "(((1 == 2) != 3) == 4)");
980
981 test_binary_expression!("1 << 2 + 3", "(1 << (2 + 3))");
983 test_binary_expression!("1 + 2 >> 3", "((1 + 2) >> 3)");
984
985 test_binary_expression!("1 |> 2 |> 3", "((1 |> 2) |> 3)");
987
988 test_binary_expression!("1 + 2 * 3 ** 4", "(1 + (2 * (3 ** 4)))");
990 test_binary_expression!(
991 "1 || 2 && 3 | 4 ^ 5 & 6",
992 "(1 || (2 && (3 | (4 ^ (5 & 6)))))"
993 );
994 test_binary_expression!(
995 "1 + 2 * 3 < 4 && 5 == 6",
996 "(((1 + (2 * 3)) < 4) && (5 == 6))"
997 );
998 }
999}