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}