cas_parser/parser/
mod.rs

1pub mod ast;
2pub mod error;
3pub mod fmt;
4pub mod garbage;
5pub mod iter;
6pub mod keyword;
7pub mod token;
8
9use cas_error::{ErrorKind, Error};
10use error::{ExpectedEof, UnexpectedEoExpr, UnexpectedEof};
11use super::tokenizer::{tokenize_complete, Token};
12use std::{ops::Range, sync::Arc};
13
14/// State that can be used to determine if certain parse trees are valid (e.g. if a checking if a
15/// `break` expression is inside a loop).
16///
17/// The state cannot be mutated directly; it can only be changed when parsing using the [`Parser::try_parse_with_state`] method.
18#[derive(Debug, Clone, Default)]
19pub struct ParserState {
20    /// Whether a `then` expression is allowed in the current context.
21    ///
22    /// `then` expressions are only allowed after the conditions of `if`, `while` and `loop`
23    /// expressions.
24    pub allow_then: bool,
25
26    /// Whether an `of` expression is allowed in the current context.
27    ///
28    /// `of` expressions are only allowed after the range of `sum` and `product` expressions.
29    pub allow_of: bool,
30
31    /// Whether loop control expressions are allowed in the current context.
32    ///
33    /// Loop control expressions are `break` and `continue` expressions. They are only allowed
34    /// inside loop expressions, such as `while`, `loop`, and `for`.
35    pub allow_loop_control: bool,
36
37    /// Whether a `return` expression is allowed in the current context.
38    ///
39    /// `return` expressions are only allowed inside function assignments.
40    pub allow_return: bool,
41
42    /// Whether to require the current expression to end at the end of the line.
43    ///
44    /// This is enabled on when parsing the expression of a `return` or `break` expression. The
45    /// expression returned by the `return` / `break` expression must lie on the same line as the
46    /// `return` / `break` keyword to prevent confusion in cases like:
47    ///
48    /// ```text
49    /// if k > n return
50    ///
51    /// sub = n - k
52    /// ```
53    ///
54    /// Without this requirement, the `return` expression would eagerly consume the assignment
55    /// `sub = n - k`, resulting in the above code being treated as:
56    ///
57    /// ```text
58    /// if k > n {
59    ///    return sub = n - k
60    /// }
61    /// ```
62    ///
63    /// Which is almost certainly not what the user intended.
64    pub expr_end_at_eol: bool,
65}
66
67/// A high-level parser for the language. This is the type to use to parse an arbitrary piece of
68/// code into an abstract syntax tree.
69///
70/// The parser contains an [`Arc`] to the tokens representing the source code to be parsed, and
71/// thus is relatively cheap to clone.
72#[derive(Debug, Clone)]
73pub struct Parser<'source> {
74    /// The tokens that this parser is currently parsing.
75    tokens: Arc<[Token<'source>]>,
76
77    /// The index of the **next** token to be parsed.
78    cursor: usize,
79
80    /// Holds state that can be used to determine if certain parse trees are valid (e.g. if a
81    /// checking if a `break` expression is inside a loop).
82    ///
83    /// The state cannot be mutated directly; it can only be changed when parsing using the [`Parser::try_parse_with_state`] method.
84    state: ParserState,
85}
86
87impl<'source> Parser<'source> {
88    /// Create a new parser for the given source.
89    pub fn new(source: &'source str) -> Self {
90        Self {
91            tokens: tokenize_complete(source).into(),
92            cursor: 0,
93            state: ParserState::default(),
94        }
95    }
96
97    /// Returns an immutable reference to the parser's state.
98    pub fn state(&self) -> &ParserState {
99        &self.state
100    }
101
102    /// Sets the parser to point to the same token as the given parser. It is assumed that both
103    /// parsers point to the same source code.
104    pub fn set_cursor(&mut self, other: &Self) {
105        self.cursor = other.cursor;
106    }
107
108    /// Creates an error that points at the current token, or the end of the source code if the
109    /// cursor is at the end of the stream.
110    pub fn error(&self, kind: impl ErrorKind + 'static) -> Error {
111        Error::new(vec![self.span()], kind)
112    }
113
114    /// Returns a span pointing at the end of the source code.
115    pub fn eof_span(&self) -> Range<usize> {
116        self.tokens.last().map_or(0..0, |token| token.span.end..token.span.end)
117    }
118
119    /// Returns the span of the current token, or the end of the source code if the cursor is at
120    /// the end of the stream.
121    pub fn span(&self) -> Range<usize> {
122        self.tokens
123            .get(self.cursor)
124            .map_or(self.eof_span(), |token| token.span.clone())
125    }
126
127    /// Move the cursor to the previous token. This function is a no-op if the cursor is at the
128    /// beginning of the stream.
129    pub fn prev(&mut self) {
130        if self.cursor > 0 {
131            self.cursor -= 1;
132        }
133    }
134
135    /// Returns the previous token. The cursor is not moved. Returns [`None`] if the cursor is at
136    /// the beginning of the stream.
137    pub fn prev_token(&self) -> Option<&Token<'source>> {
138        self.tokens.get(self.cursor.checked_sub(1)?)
139    }
140
141    /// Returns the current token. The cursor is not moved. Returns [`None`] if the cursor is at
142    /// the end of the stream.
143    pub fn current_token(&self) -> Option<&Token<'source>> {
144        self.tokens.get(self.cursor)
145    }
146
147    /// Advances the cursor past whitespace tokens to the next non-whitespace token. The cursor is
148    /// not guaranteed to point to a valid token (might be out of bounds), but if the token is
149    /// valid, it is guaranteed to be non-whitespace.
150    pub fn advance_past_whitespace(&mut self) {
151        while let Some(token) = self.tokens.get(self.cursor) {
152            if token.is_ignore() {
153                self.cursor += 1;
154                continue;
155            } else {
156                break;
157            }
158        }
159    }
160
161    /// Advances the cursor past non-significant whitespace tokens to the next token. **This next
162    /// token can be a newline.**
163    ///
164    /// The cursor is not guaranteed to point to a valid token (might be out of bounds), but if the
165    /// token is valid, it is guaranteed to be a newline, or otherwise, non-whitespace.
166    ///
167    /// Newlines are significant in the context of implicit multiplication. Allowing implicit
168    /// multiplication to span multiple lines has shown to be confusing and error-prone; for
169    /// example, consider how this reasonably-looking file would be parsed (before implicit
170    /// multiplication was restricted to the same line):
171    ///
172    /// ```text
173    /// fact(n) = {
174    ///     out = n;
175    ///     while n > 1 {
176    ///         n -= 1;
177    ///         out *= n;
178    ///     };
179    ///     out
180    /// }
181    ///
182    /// fact(14) == 14!
183    /// ```
184    ///
185    /// You would expect this code to behave like so:
186    ///
187    /// 1. Define the `fact` function.
188    /// 2. Call the `fact` function with the argument `14` and compare the result to `14!`.
189    ///
190    /// It certainly seems that way. However, in the past, parsing this example would actually
191    /// insert timplicit multiplication between the "end" of the function definition `}`, and
192    /// `fact(14)`, resulting in:
193    ///
194    /// ```text
195    /// fact(n) = {
196    ///     out = n;
197    ///     while n > 1 {
198    ///         n -= 1;
199    ///         out *= n;
200    ///     };
201    ///     out
202    /// }
203    /// * // <-- implicit multiplication!!
204    /// fact(14) == 14!
205    /// ```
206    ///
207    /// The comparison `fact(14) == 14!` actually ends up being a part of the `fact` function
208    /// definition, and no comparison is made! This function is used to prevent such confusion
209    /// during parsing.
210    pub fn advance_past_non_significant_whitespace(&mut self) {
211        while let Some(token) = self.tokens.get(self.cursor) {
212            if token.is_ignore() && !token.is_significant_whitespace() {
213                self.cursor += 1;
214                continue;
215            } else {
216                break;
217            }
218        }
219    }
220
221    /// Returns the current token, then advances the cursor. Whitespace tokens are skipped.
222    ///
223    /// Returns an EOF error if there are no more tokens.
224    pub fn next_token(&mut self) -> Result<Token<'source>, Error> {
225        self.advance_past_whitespace();
226        self.next_token_raw()
227    }
228
229    /// Returns the current token, then advances the cursor. Whitespace tokens **are not** skipped.
230    ///
231    /// Returns an EOF error if there are no more tokens.
232    pub fn next_token_raw(&mut self) -> Result<Token<'source>, Error> {
233        let result = self.current_token()
234            .cloned() // cloning is cheap; only Range<_> is cloned
235            .ok_or_else(|| self.error(UnexpectedEof));
236        self.cursor += 1;
237        result
238    }
239
240    /// Returns an [`UnexpectedEoExpr`] error if the state field `expr_end_at_eol` is set to `true`
241    /// and the cursor is on a newline token. This state would indicate that an expression has been
242    /// broken up to span multiple lines, which is not allowed in the context of `return` and
243    /// `break` expressions.
244    fn check_eol(&mut self) -> Result<(), Error> {
245        if self.state.expr_end_at_eol {
246            if let Some(token) = self.current_token() {
247                if token.is_significant_whitespace() {
248                    return Err(self.error(UnexpectedEoExpr));
249                }
250            }
251        }
252
253        Ok(())
254    }
255
256    /// Speculatively parses a value from the given stream of tokens. This function can be used
257    /// in the [`Parse::parse`] implementation of a type with the given [`Parser`], as it will
258    /// automatically backtrack the cursor position if parsing fails.
259    ///
260    /// If parsing is successful, the stream is advanced past the consumed tokens and the parsed
261    /// value is returned. Otherwise, the stream is left unchanged and an error is returned.
262    pub fn try_parse<T: Parse<'source>>(&mut self) -> ParseResult<T> {
263        self.try_parse_with_fn(T::parse)
264    }
265
266    /// Speculatively parses a value from the given stream of tokens. Before parsing, a copy of the
267    /// parser is created with the state mutated using the given function. The original parser's
268    /// state will not change, but the cursor position can be advanced if the new parser was
269    /// successful.
270    ///
271    /// This function can be used in the [`Parse::parse`] implementation of a type with the given
272    /// [`Parser`], as it will automatically backtrack the cursor position if parsing fails.
273    ///
274    /// If parsing is successful, the stream is advanced past the consumed tokens and the parsed
275    /// value is returned. Otherwise, the stream is left unchanged and an error is returned.
276    pub fn try_parse_with_state<F, T>(&mut self, modify_state: F) -> ParseResult<T>
277    where
278        F: FnOnce(&mut ParserState),
279        T: Parse<'source>,
280    {
281        let mut state = self.state.clone();
282        modify_state(&mut state);
283
284        let mut new_parser = Self {
285            tokens: self.tokens.clone(),
286            cursor: self.cursor,
287            state,
288        };
289
290        let t = new_parser.try_parse();
291        self.set_cursor(&new_parser);
292        t
293    }
294
295    /// Speculatively parses a value from the given stream of tokens, using a custom parsing
296    /// function to parse the value. This function can be used in the [`Parse::parse`]
297    /// implementation of a type with the given [`Parser`], as it will automatically backtrack the
298    /// cursor position if parsing fails.
299    ///
300    /// If parsing is successful, the stream is advanced past the consumed tokens and the parsed
301    /// value is returned. Otherwise, the stream is left unchanged and an error is returned.
302    pub fn try_parse_with_fn<T, F>(&mut self, f: F) -> ParseResult<T>
303    where
304        F: FnOnce(&mut Parser<'source>) -> ParseResult<T>,
305    {
306        let start = self.cursor;
307        let out = if let Err(err) = self.check_eol() {
308            ParseResult::Unrecoverable(vec![err])
309        } else {
310            f(self)
311        };
312        out.inspect_unrecoverable(|_| self.cursor = start)
313    }
314
315    /// Speculatively parses a value from the given stream of tokens, with a validation predicate.
316    /// The value must parse successfully, **and** the predicate must return [`Ok`] for this
317    /// function to return successfully.
318    ///
319    /// If parsing is successful, the stream is advanced past the consumed tokens and the parsed
320    /// value is returned. Otherwise, the stream is left unchanged and an error is returned.
321    pub fn try_parse_then<T: Parse<'source>, F>(&mut self, predicate: F) -> ParseResult<T>
322    where
323        F: FnOnce(&T, &Parser) -> ParseResult<()>,
324    {
325        let start = self.cursor;
326        let mut errors = Vec::new();
327
328        let inner = || {
329            self.check_eol().map_err(|err| vec![err])?;
330            let value = T::parse(self).forward_errors(&mut errors)?;
331            predicate(&value, self).forward_errors(&mut errors)?;
332            Ok(value)
333        };
334
335        inner()
336            .map(|value| (value, errors))
337            .inspect_err(|_unrecoverable| {
338                self.cursor = start;
339            })
340            .into()
341    }
342
343    /// Attempts to parse a value from the given stream of tokens. All the tokens must be consumed
344    /// by the parser; if not, an error is returned.
345    pub fn try_parse_full<T: Parse<'source>>(&mut self) -> Result<T, Vec<Error>> {
346        let mut errors = Vec::new();
347        let value = T::parse(self).forward_errors(&mut errors)?;
348
349        // consume whitespace
350        self.advance_past_whitespace();
351
352        if self.cursor < self.tokens.len() {
353            errors.push(self.error(ExpectedEof));
354        }
355
356        if errors.is_empty() {
357            Ok(value)
358        } else {
359            Err(errors)
360        }
361    }
362
363    /// Attempts to parse multiple values from the given stream of tokens. All the tokens must be
364    /// consumed by the parser; if not, an error is returned.
365    pub fn try_parse_full_many<T: std::fmt::Debug + Parse<'source>>(&mut self) -> Result<Vec<T>, Vec<Error>> {
366        let mut errors = Vec::new();
367        let mut values = Vec::new();
368
369        while self.cursor < self.tokens.len() {
370            let Ok(value) = T::parse(self).forward_errors(&mut errors) else {
371                break;
372            };
373            values.push(value);
374        }
375
376        // consume whitespace
377        self.advance_past_whitespace();
378
379        if self.cursor < self.tokens.len() {
380            errors.push(self.error(ExpectedEof));
381        }
382
383        if errors.is_empty() {
384            Ok(values)
385        } else {
386            Err(errors)
387        }
388    }
389}
390
391/// Any type that can be parsed from a source of tokens.
392pub trait Parse<'source>: Sized {
393    /// Parses a value from the given stream of tokens, advancing the stream past the consumed
394    /// tokens if parsing is successful.
395    ///
396    /// If any recoverable errors are encountered, they should be appended to the given [`Vec`],
397    /// and parsing should continue as normal. If an unrecoverable error is encountered, parsing
398    /// should abort with said error.
399    ///
400    /// This function should be used by private functions in the library.
401    fn std_parse(
402        input: &mut Parser<'source>,
403        recoverable_errors: &mut Vec<Error>
404    ) -> Result<Self, Vec<Error>>;
405
406    /// Parses a value from the given stream of tokens, advancing the stream past the consumed
407    /// tokens if parsing is successful.
408    ///
409    /// This function should be used by users of this parser.
410    fn parse(input: &mut Parser<'source>) -> ParseResult<Self> {
411        let mut recoverable_errors = Vec::new();
412        Self::std_parse(input, &mut recoverable_errors)
413            .map(|value| (value, recoverable_errors))
414            .into()
415    }
416}
417
418/// The result of a parsing operation.
419#[derive(Debug)]
420pub enum ParseResult<T> {
421    /// Parsing was successful.
422    Ok(T),
423
424    /// An error occurred while parsing, however the parser attempted to recover and has tried to
425    /// continue parsing in order to find more errors. The recovered value is returned in addition
426    /// to all the errors that were found.
427    ///
428    /// There are **no** guarantees on whether the recovered value is valid or not. Thus, it should
429    /// only be used to allow the parser to continue parsing, and should not be shown to the user.
430    Recoverable(T, Vec<Error>),
431
432    /// An error occurred while parsing, and the parser was unable to recover. Parsing is aborted
433    /// and the error are returned.
434    Unrecoverable(Vec<Error>),
435}
436
437impl<T> From<Result<(T, Vec<Error>), Vec<Error>>> for ParseResult<T> {
438    fn from(result: Result<(T, Vec<Error>), Vec<Error>>) -> Self {
439        match result {
440            Ok((value, errors)) => (value, errors).into(),
441            Err(unrecoverable_errors) => Self::Unrecoverable(unrecoverable_errors),
442        }
443    }
444}
445
446impl<T> From<(T, Vec<Error>)> for ParseResult<T> {
447    fn from((value, errors): (T, Vec<Error>)) -> Self {
448        if errors.is_empty() {
449            Self::Ok(value)
450        } else {
451            Self::Recoverable(value, errors)
452        }
453    }
454}
455
456impl<T> From<Vec<Error>> for ParseResult<T> {
457    fn from(errors: Vec<Error>) -> Self {
458        Self::Unrecoverable(errors)
459    }
460}
461
462impl<T> ParseResult<T> {
463    /// Converts the [`ParseResult<T>`] to a [`Result<T, Vec<Error>>`], using these rules:
464    ///
465    /// - [`ParseResult::Ok`] is converted to [`Ok`].
466    /// - [`ParseResult::Recoverable`] is converted to [`Ok`]. The errors are appended to the given
467    ///   mutable [`Vec`].
468    /// - [`ParseResult::Unrecoverable`] is converted to [`Err`].
469    ///
470    /// This can be a convenient way to allow utilizing the [`?`] operator in a parsing function,
471    /// while still holding onto errors that were found for later reporting.
472    pub fn forward_errors(self, errors: &mut Vec<Error>) -> Result<T, Vec<Error>> {
473        match self {
474            Self::Ok(value) => Ok(value),
475            Self::Recoverable(value, mut errs) => {
476                errors.append(&mut errs);
477                Ok(value)
478            },
479            Self::Unrecoverable(errs) => Err(errs),
480        }
481    }
482
483    /// Returns `true` if the result is [`ParseResult::Ok`].
484    pub fn is_ok(&self) -> bool {
485        matches!(self, ParseResult::Ok(_))
486    }
487
488    /// Calls the provided closure with a reference to the contained unrecoverable error.
489    ///
490    /// This is equivalent to [`Result::inspect_err`].
491    pub fn inspect_unrecoverable<F>(self, f: F) -> Self
492    where
493        F: FnOnce(&Vec<Error>),
494    {
495        if let Self::Unrecoverable(errs) = &self {
496            f(errs);
497        }
498
499        self
500    }
501
502    /// Maps a `ParseResult<T>` to `ParseResult<U>` by applying a function to a contained
503    /// [`ParseResult::Ok`] or [`ParseResult::Recoverable`] value, leaving an
504    /// [`ParseResult::Unrecoverable`] value untouched.
505    ///
506    /// This is equivalent to [`Result::map`].
507    pub fn map<U, F>(self, f: F) -> ParseResult<U>
508    where
509        F: FnOnce(T) -> U,
510    {
511        match self {
512            ParseResult::Ok(value) => ParseResult::Ok(f(value)),
513            ParseResult::Recoverable(value, errors) => ParseResult::Recoverable(f(value), errors),
514
515            // this line cannot be simplified to `err => err`, because then both the left hand side
516            // and right hand side are type `ParseResult<T>`!
517            ParseResult::Unrecoverable(errors) => ParseResult::Unrecoverable(errors),
518        }
519    }
520
521    /// Calls `op` if the result is an error, otherwise returns the `Ok` value of `self`.
522    ///
523    /// This is similar to [`Result::or_else`], but no error value is given to the closure.
524    pub fn or_else<F>(self, op: F) -> Self
525    where
526        F: FnOnce() -> Self,
527    {
528        match self {
529            ParseResult::Recoverable(..) | ParseResult::Unrecoverable(_) => op(),
530            ok => ok,
531        }
532    }
533}
534
535/// Convenience macro to short-circuit from a parsing function if the given [`Result`] is [`Ok`],
536/// or return the contained error if the result is [`Err`].
537///
538/// This is essentially the opposite of the [`try!`] macro.
539#[macro_export]
540macro_rules! return_if_ok {
541    ($result:expr) => {
542        match $result {
543            Ok(value) => return Ok(value),
544            Err(errors) => errors,
545        }
546    };
547}
548
549#[cfg(test)]
550mod tests {
551    use pretty_assertions::assert_eq;
552    use super::*;
553
554    use ast::*;
555    use token::op::{AssignOp, AssignOpKind, BinOp, BinOpKind, UnaryOp, UnaryOpKind};
556
557    #[test]
558    fn literal_int() {
559        let mut parser = Parser::new("16");
560        let expr = parser.try_parse_full::<Expr>().unwrap();
561
562        assert_eq!(expr, Expr::Literal(Literal::Integer(LitInt {
563            value: "16".to_string(),
564            span: 0..2,
565        })));
566    }
567
568    #[test]
569    fn literal_float() {
570        let mut parser = Parser::new("3.14");
571        let expr = parser.try_parse_full::<Expr>().unwrap();
572
573        assert_eq!(expr, Expr::Literal(Literal::Float(LitFloat {
574            value: "3.14".to_string(),
575            span: 0..4,
576        })));
577    }
578
579    #[test]
580    fn literal_float_2() {
581        let mut parser = Parser::new(".75");
582        let expr = parser.try_parse_full::<Expr>().unwrap();
583
584        assert_eq!(expr, Expr::Literal(Literal::Float(LitFloat {
585            value: ".75".to_string(),
586            span: 0..3,
587        })));
588    }
589
590    #[test]
591    fn wrong_float() {
592        let mut parser = Parser::new("1 .");
593        parser.try_parse_full::<Expr>().unwrap_err();
594    }
595
596    #[test]
597    fn wrong_float_2() {
598        let mut parser = Parser::new("1..");
599        parser.try_parse_full::<Expr>().unwrap_err();
600    }
601
602    #[test]
603    fn literal_radix_base_2() {
604        let mut parser = Parser::new("2'10000110000");
605        let expr = parser.try_parse_full::<Expr>().unwrap();
606
607        assert_eq!(expr, Expr::Literal(Literal::Radix(LitRadix {
608            base: 2,
609            value: "10000110000".to_string(),
610            span: 0..13,
611        })));
612    }
613
614    #[test]
615    fn literal_radix_base_8() {
616        let mut parser = Parser::new("8'2060");
617        let expr = parser.try_parse_full::<Expr>().unwrap();
618
619        assert_eq!(expr, Expr::Literal(Literal::Radix(LitRadix {
620            base: 8,
621            value: "2060".to_string(),
622            span: 0..6,
623        })));
624    }
625
626    #[test]
627    fn literal_radix_base_25() {
628        let mut parser = Parser::new("25'1hm");
629        let expr = parser.try_parse_full::<Expr>().unwrap();
630
631        assert_eq!(expr, Expr::Literal(Literal::Radix(LitRadix {
632            base: 25,
633            value: "1hm".to_string(),
634            span: 0..6,
635        })));
636    }
637
638    #[test]
639    fn literal_radix_base_32() {
640        let mut parser = Parser::new("32'11g");
641        let expr = parser.try_parse_full::<Expr>().unwrap();
642
643        assert_eq!(expr, Expr::Literal(Literal::Radix(LitRadix {
644            base: 32,
645            value: "11g".to_string(),
646            span: 0..6,
647        })));
648    }
649
650    #[test]
651    fn literal_radix_base_47() {
652        let mut parser = Parser::new("47'mC");
653        let expr = parser.try_parse_full::<Expr>().unwrap();
654
655        assert_eq!(expr, Expr::Literal(Literal::Radix(LitRadix {
656            base: 47,
657            value: "mC".to_string(),
658            span: 0..5,
659        })));
660    }
661
662    #[test]
663    fn literal_radix_with_nonword_tokens() {
664        let mut parser = Parser::new("64'++/+//");
665        let expr = parser.try_parse_full::<Expr>().unwrap();
666
667        assert_eq!(expr, Expr::Literal(Literal::Radix(LitRadix {
668            base: 64,
669            value: "++/+//".to_string(),
670            span: 0..9,
671        })));
672    }
673
674    #[test]
675    fn literal_symbol() {
676        let mut parser = Parser::new("pi");
677        let expr = parser.try_parse_full::<Expr>().unwrap();
678
679        assert_eq!(expr, Expr::Literal(Literal::Symbol(LitSym {
680            name: "pi".to_string(),
681            span: 0..2,
682        })));
683    }
684
685    #[test]
686    fn literal_list() {
687        let mut parser = Parser::new("[1, 2,i, 4, e]");
688        let expr = parser.try_parse_full::<Expr>().unwrap();
689
690        assert_eq!(expr, Expr::Literal(Literal::List(LitList {
691            values: vec![
692                Expr::Literal(Literal::Integer(LitInt {
693                    value: "1".to_string(),
694                    span: 1..2,
695                })),
696                Expr::Literal(Literal::Integer(LitInt {
697                    value: "2".to_string(),
698                    span: 4..5,
699                })),
700                Expr::Literal(Literal::Symbol(LitSym {
701                    name: "i".to_string(),
702                    span: 6..7,
703                })),
704                Expr::Literal(Literal::Integer(LitInt {
705                    value: "4".to_string(),
706                    span: 9..10,
707                })),
708                Expr::Literal(Literal::Symbol(LitSym {
709                    name: "e".to_string(),
710                    span: 12..13,
711                })),
712            ],
713            span: 0..14,
714        })));
715    }
716
717    #[test]
718    fn literal_list_repeat() {
719        let mut parser = Parser::new("[1; 5]");
720        let expr = parser.try_parse_full::<Expr>().unwrap();
721
722        assert_eq!(expr, Expr::Literal(Literal::ListRepeat(LitListRepeat {
723            value: Box::new(Expr::Literal(Literal::Integer(LitInt {
724                value: "1".to_string(),
725                span: 1..2,
726            }))),
727            count: Box::new(Expr::Literal(Literal::Integer(LitInt {
728                value: "5".to_string(),
729                span: 4..5,
730            }))),
731            span: 0..6,
732        })));
733    }
734
735    #[test]
736    fn list_indexing() {
737        let mut parser = Parser::new("(list[x + 2] + list[x + 5])[1][2]");
738        let expr = parser.try_parse_full::<Expr>().unwrap();
739
740        assert_eq!(expr, Expr::Index(Index {
741            target: Box::new(Expr::Index(Index {
742                target: Box::new(Expr::Paren(Paren {
743                    expr: Box::new(Expr::Binary(Binary {
744                        lhs: Box::new(Expr::Index(Index {
745                            target: Box::new(Expr::Literal(Literal::Symbol(LitSym {
746                                name: "list".to_string(),
747                                span: 1..5,
748                            }))),
749                            index: Box::new(Expr::Binary(Binary {
750                                lhs: Box::new(Expr::Literal(Literal::Symbol(LitSym {
751                                    name: "x".to_string(),
752                                    span: 6..7,
753                                }))),
754                                op: BinOp {
755                                    kind: BinOpKind::Add,
756                                    implicit: false,
757                                    span: 8..9,
758                                },
759                                rhs: Box::new(Expr::Literal(Literal::Integer(LitInt {
760                                    value: "2".to_string(),
761                                    span: 10..11,
762                                }))),
763                                span: 6..11,
764                            })),
765                            span: 1..12,
766                            bracket_span: 5..12,
767                        })),
768                        op: BinOp {
769                            kind: BinOpKind::Add,
770                            implicit: false,
771                            span: 13..14,
772                        },
773                        rhs: Box::new(Expr::Index(Index {
774                            target: Box::new(Expr::Literal(Literal::Symbol(LitSym {
775                                name: "list".to_string(),
776                                span: 15..19,
777                            }))),
778                            index: Box::new(Expr::Binary(Binary {
779                                lhs: Box::new(Expr::Literal(Literal::Symbol(LitSym {
780                                    name: "x".to_string(),
781                                    span: 20..21,
782                                }))),
783                                op: BinOp {
784                                    kind: BinOpKind::Add,
785                                    implicit: false,
786                                    span: 22..23,
787                                },
788                                rhs: Box::new(Expr::Literal(Literal::Integer(LitInt {
789                                    value: "5".to_string(),
790                                    span: 24..25,
791                                }))),
792                                span: 20..25,
793                            })),
794                            span: 15..26,
795                            bracket_span: 19..26,
796                        })),
797                        span: 1..26,
798                    })),
799                    span: 0..27,
800                })),
801                index: Box::new(Expr::Literal(Literal::Integer(LitInt {
802                    value: "1".to_string(),
803                    span: 28..29,
804                }))),
805                span: 0..30,
806                bracket_span: 27..30,
807            })),
808            index: Box::new(Expr::Literal(Literal::Integer(LitInt {
809                value: "2".to_string(),
810                span: 31..32,
811            }))),
812            span: 0..33,
813            bracket_span: 30..33,
814        }));
815    }
816
817    #[test]
818    fn not_indexing() {
819        let mut parser = Parser::new("abs(4) [8, 16]");
820        assert!(parser.try_parse_full::<Expr>().is_err());
821    }
822
823    #[test]
824    fn unary_left_associativity() {
825        let mut parser = Parser::new("3!!");
826        let expr = parser.try_parse_full::<Expr>().unwrap();
827
828        assert_eq!(expr, Expr::Unary(Unary {
829            operand: Box::new(Expr::Unary(Unary {
830                operand: Box::new(Expr::Literal(Literal::Integer(LitInt {
831                    value: "3".to_string(),
832                    span: 0..1,
833                }))),
834                op: UnaryOp {
835                    kind: UnaryOpKind::Factorial,
836                    span: 1..2,
837                },
838                span: 0..2,
839            })),
840            op: UnaryOp {
841                kind: UnaryOpKind::Factorial,
842                span: 2..3,
843            },
844            span: 0..3,
845        }));
846    }
847
848    #[test]
849    fn unary_right_associativity() {
850        let mut parser = Parser::new("not not --3");
851        let expr = parser.try_parse_full::<Expr>().unwrap();
852
853        assert_eq!(expr, Expr::Unary(Unary {
854            operand: Box::new(Expr::Unary(Unary {
855                operand: Box::new(Expr::Unary(Unary {
856                    operand: Box::new(Expr::Unary(Unary {
857                        operand: Box::new(Expr::Literal(Literal::Integer(LitInt {
858                            value: "3".to_string(),
859                            span: 10..11,
860                        }))),
861                        op: UnaryOp {
862                            kind: UnaryOpKind::Neg,
863                            span: 9..10,
864                        },
865                        span: 9..11,
866                    })),
867                    op: UnaryOp {
868                        kind: UnaryOpKind::Neg,
869                        span: 8..9,
870                    },
871                    span: 8..11,
872                })),
873                op: UnaryOp {
874                    kind: UnaryOpKind::Not,
875                    span: 4..7,
876                },
877                span: 4..11,
878            })),
879            op: UnaryOp {
880                kind: UnaryOpKind::Not,
881                span: 0..3,
882            },
883            span: 0..11,
884        }));
885    }
886
887    #[test]
888    fn wrong_unary() {
889        let mut parser = Parser::new("!3");
890        assert!(parser.try_parse_full::<Expr>().is_err());
891    }
892
893    #[test]
894    fn unary_complicated() {
895        let mut parser = Parser::new("not 3!! + -4");
896        let expr = parser.try_parse_full::<Expr>().unwrap();
897
898        assert_eq!(expr, Expr::Binary(Binary {
899            lhs: Box::new(Expr::Unary(Unary {
900                operand: Box::new(Expr::Unary(Unary {
901                    operand: Box::new(Expr::Unary(Unary {
902                        operand: Box::new(Expr::Literal(Literal::Integer(LitInt {
903                            value: "3".to_string(),
904                            span: 4..5,
905                        }))),
906                        op: UnaryOp {
907                            kind: UnaryOpKind::Factorial,
908                            span: 5..6,
909                        },
910                        span: 4..6,
911                    })),
912                    op: UnaryOp {
913                        kind: UnaryOpKind::Factorial,
914                        span: 6..7,
915                    },
916                    span: 4..7,
917                })),
918                op: UnaryOp {
919                    kind: UnaryOpKind::Not,
920                    span: 0..3,
921                },
922                span: 0..7,
923            })),
924            op: BinOp {
925                kind: BinOpKind::Add,
926                implicit: false,
927                span: 8..9,
928            },
929            rhs: Box::new(Expr::Unary(Unary {
930                operand: Box::new(Expr::Literal(Literal::Integer(LitInt {
931                    value: "4".to_string(),
932                    span: 11..12,
933                }))),
934                op: UnaryOp {
935                    kind: UnaryOpKind::Neg,
936                    span: 10..11,
937                },
938                span: 10..12,
939            })),
940            span: 0..12,
941        }));
942    }
943
944    #[test]
945    fn binary_left_associativity() {
946        let mut parser = Parser::new("3 * x * 5");
947        let expr = parser.try_parse_full::<Expr>().unwrap();
948
949        assert_eq!(expr, Expr::Binary(Binary {
950            lhs: Box::new(Expr::Binary(Binary {
951                lhs: Box::new(Expr::Literal(Literal::Integer(LitInt {
952                    value: "3".to_string(),
953                    span: 0..1,
954                }))),
955                op: BinOp {
956                    kind: BinOpKind::Mul,
957                    implicit: false,
958                    span: 2..3,
959                },
960                rhs: Box::new(Expr::Literal(Literal::Symbol(LitSym {
961                    name: "x".to_string(),
962                    span: 4..5,
963                }))),
964                span: 0..5,
965            })),
966            op: BinOp {
967                kind: BinOpKind::Mul,
968                implicit: false,
969                span: 6..7,
970            },
971            rhs: Box::new(Expr::Literal(Literal::Integer(LitInt {
972                value: "5".to_string(),
973                span: 8..9,
974            }))),
975            span: 0..9,
976        }));
977    }
978
979    #[test]
980    fn binary_left_associativity_mix_precedence() {
981        let mut parser = Parser::new("3 + 4 * a + b");
982        let expr = parser.try_parse_full::<Expr>().unwrap();
983
984        assert_eq!(expr, Expr::Binary(Binary {
985            lhs: Box::new(Expr::Binary(Binary {
986                lhs: Box::new(Expr::Literal(Literal::Integer(LitInt {
987                    value: "3".to_string(),
988                    span: 0..1,
989                }))),
990                op: BinOp {
991                    kind: BinOpKind::Add,
992                    implicit: false,
993                    span: 2..3,
994                },
995                rhs: Box::new(Expr::Binary(Binary {
996                    lhs: Box::new(Expr::Literal(Literal::Integer(LitInt {
997                        value: "4".to_string(),
998                        span: 4..5,
999                    }))),
1000                    op: BinOp {
1001                        kind: BinOpKind::Mul,
1002                        implicit: false,
1003                        span: 6..7,
1004                    },
1005                    rhs: Box::new(Expr::Literal(Literal::Symbol(LitSym {
1006                        name: "a".to_string(),
1007                        span: 8..9,
1008                    }))),
1009                    span: 4..9,
1010                })),
1011                span: 0..9,
1012            })),
1013            op: BinOp {
1014                kind: BinOpKind::Add,
1015                implicit: false,
1016                span: 10..11,
1017            },
1018            rhs: Box::new(Expr::Literal(Literal::Symbol(LitSym {
1019                name: "b".to_string(),
1020                span: 12..13,
1021            }))),
1022            span: 0..13,
1023        }));
1024    }
1025
1026    #[test]
1027    fn binary_right_associativity() {
1028        let mut parser = Parser::new("1 ^ 2 ^ 3");
1029        let expr = parser.try_parse_full::<Expr>().unwrap();
1030
1031        assert_eq!(expr, Expr::Binary(Binary {
1032            lhs: Box::new(Expr::Literal(Literal::Integer(LitInt {
1033                value: "1".to_string(),
1034                span: 0..1,
1035            }))),
1036            op: BinOp {
1037                kind: BinOpKind::Exp,
1038                implicit: false,
1039                span: 2..3,
1040            },
1041            rhs: Box::new(Expr::Binary(Binary {
1042                lhs: Box::new(Expr::Literal(Literal::Integer(LitInt {
1043                    value: "2".to_string(),
1044                    span: 4..5,
1045                }))),
1046                op: BinOp {
1047                    kind: BinOpKind::Exp,
1048                    implicit: false,
1049                    span: 6..7,
1050                },
1051                rhs: Box::new(Expr::Literal(Literal::Integer(LitInt {
1052                    value: "3".to_string(),
1053                    span: 8..9,
1054                }))),
1055                span: 4..9,
1056            })),
1057            span: 0..9,
1058        }));
1059    }
1060
1061    #[test]
1062    fn binary_complicated() {
1063        let mut parser = Parser::new("1 + 2 * 3 - 4 / 5 ^ 6");
1064        let expr = parser.try_parse_full::<Expr>().unwrap();
1065
1066        // 2 * 3
1067        let mul = Expr::Binary(Binary {
1068            lhs: Box::new(Expr::Literal(Literal::Integer(LitInt {
1069                value: "2".to_string(),
1070                span: 4..5,
1071            }))),
1072            op: BinOp {
1073                kind: BinOpKind::Mul,
1074                implicit: false,
1075                span: 6..7,
1076            },
1077            rhs: Box::new(Expr::Literal(Literal::Integer(LitInt {
1078                value: "3".to_string(),
1079                span: 8..9,
1080            }))),
1081            span: 4..9,
1082        });
1083
1084        // 1 + 2 * 3
1085        let add = Expr::Binary(Binary {
1086            lhs: Box::new(Expr::Literal(Literal::Integer(LitInt {
1087                value: "1".to_string(),
1088                span: 0..1,
1089            }))),
1090            op: BinOp {
1091                kind: BinOpKind::Add,
1092                implicit: false,
1093                span: 2..3,
1094            },
1095            rhs: Box::new(mul),
1096            span: 0..9,
1097        });
1098
1099        // 5 ^ 6
1100        let exp = Expr::Binary(Binary {
1101            lhs: Box::new(Expr::Literal(Literal::Integer(LitInt {
1102                value: "5".to_string(),
1103                span: 16..17,
1104            }))),
1105            op: BinOp {
1106                kind: BinOpKind::Exp,
1107                implicit: false,
1108                span: 18..19,
1109            },
1110            rhs: Box::new(Expr::Literal(Literal::Integer(LitInt {
1111                value: "6".to_string(),
1112                span: 20..21,
1113            }))),
1114            span: 16..21,
1115        });
1116
1117        // 4 / 5 ^ 6
1118        let div = Expr::Binary(Binary {
1119            lhs: Box::new(Expr::Literal(Literal::Integer(LitInt {
1120                value: "4".to_string(),
1121                span: 12..13,
1122            }))),
1123            op: BinOp {
1124                kind: BinOpKind::Div,
1125                implicit: false,
1126                span: 14..15,
1127            },
1128            rhs: Box::new(exp),
1129            span: 12..21,
1130        });
1131
1132        // 1 + 2 * 3 - 4 / 5 ^ 6
1133        let sub = Expr::Binary(Binary {
1134            lhs: Box::new(add),
1135            op: BinOp {
1136                kind: BinOpKind::Sub,
1137                implicit: false,
1138                span: 10..11,
1139            },
1140            rhs: Box::new(div),
1141            span: 0..21,
1142        });
1143
1144        assert_eq!(expr, sub);
1145    }
1146
1147    #[test]
1148    fn binary_and_unary() {
1149        let mut parser = Parser::new("-1 ^ -2 * 3");
1150        let expr = parser.try_parse_full::<Expr>().unwrap();
1151
1152        assert_eq!(expr, Expr::Binary(Binary {
1153            lhs: Box::new(Expr::Unary(Unary {
1154                operand: Box::new(Expr::Binary(Binary {
1155                    lhs: Box::new(Expr::Literal(Literal::Integer(LitInt {
1156                        value: "1".to_string(),
1157                        span: 1..2,
1158                    }))),
1159                    op: BinOp {
1160                        kind: BinOpKind::Exp,
1161                        implicit: false,
1162                        span: 3..4,
1163                    },
1164                    rhs: Box::new(Expr::Unary(Unary {
1165                        operand: Box::new(Expr::Literal(Literal::Integer(LitInt {
1166                            value: "2".to_string(),
1167                            span: 6..7,
1168                        }))),
1169                        op: UnaryOp {
1170                            kind: UnaryOpKind::Neg,
1171                            span: 5..6,
1172                        },
1173                        span: 5..7,
1174                    })),
1175                    span: 1..7,
1176                })),
1177                op: UnaryOp {
1178                    kind: UnaryOpKind::Neg,
1179                    span: 0..1,
1180                },
1181                span: 0..7,
1182            })),
1183            op: BinOp {
1184                kind: BinOpKind::Mul,
1185                implicit: false,
1186                span: 8..9,
1187            },
1188            rhs: Box::new(Expr::Literal(Literal::Integer(LitInt {
1189                value: "3".to_string(),
1190                span: 10..11,
1191            }))),
1192            span: 0..11,
1193        }));
1194    }
1195
1196    #[test]
1197    fn complicated_binary_and_unary() {
1198        let mut parser = Parser::new("pi^2 * 17! / -4.9 + e");
1199        let expr = parser.try_parse_full::<Expr>().unwrap();
1200
1201        assert_eq!(expr, Expr::Binary(Binary {
1202            lhs: Box::new(Expr::Binary(Binary {
1203                lhs: Box::new(Expr::Binary(Binary {
1204                    lhs: Box::new(Expr::Binary(Binary {
1205                        lhs: Box::new(Expr::Literal(Literal::Symbol(LitSym {
1206                            name: "pi".to_string(),
1207                            span: 0..2,
1208                        }))),
1209                        op: BinOp {
1210                            kind: BinOpKind::Exp,
1211                            implicit: false,
1212                            span: 2..3,
1213                        },
1214                        rhs: Box::new(Expr::Literal(Literal::Integer(LitInt {
1215                            value: "2".to_string(),
1216                            span: 3..4,
1217                        }))),
1218                        span: 0..4,
1219                    })),
1220                    op: BinOp {
1221                        kind: BinOpKind::Mul,
1222                        implicit: false,
1223                        span: 5..6,
1224                    },
1225                    rhs: Box::new(Expr::Unary(Unary {
1226                        operand: Box::new(Expr::Literal(Literal::Integer(LitInt {
1227                            value: "17".to_string(),
1228                            span: 7..9,
1229                        }))),
1230                        op: UnaryOp {
1231                            kind: UnaryOpKind::Factorial,
1232                            span: 9..10,
1233                        },
1234                        span: 7..10,
1235                    })),
1236                    span: 0..10,
1237                })),
1238                op: BinOp {
1239                    kind: BinOpKind::Div,
1240                    implicit: false,
1241                    span: 11..12,
1242                },
1243                rhs: Box::new(Expr::Unary(Unary {
1244                    operand: Box::new(Expr::Literal(Literal::Float(LitFloat {
1245                        value: "4.9".to_string(),
1246                        span: 14..17,
1247                    }))),
1248                    op: UnaryOp {
1249                        kind: UnaryOpKind::Neg,
1250                        span: 13..14,
1251                    },
1252                    span: 13..17,
1253                })),
1254                span: 0..17,
1255            })),
1256            op: BinOp {
1257                kind: BinOpKind::Add,
1258                implicit: false,
1259                span: 18..19,
1260            },
1261            rhs: Box::new(Expr::Literal(Literal::Symbol(LitSym {
1262                name: "e".to_string(),
1263                span: 20..21,
1264            }))),
1265            span: 0..21,
1266        }));
1267    }
1268
1269    #[test]
1270    fn implicit_multiplication() {
1271        let mut parser = Parser::new("2(3 + 4)");
1272        let expr = parser.try_parse_full::<Expr>().unwrap();
1273
1274        assert_eq!(expr, Expr::Binary(Binary {
1275            lhs: Box::new(Expr::Literal(Literal::Integer(LitInt {
1276                value: "2".to_string(),
1277                span: 0..1,
1278            }))),
1279            op: BinOp {
1280                kind: BinOpKind::Mul,
1281                implicit: true,
1282                span: 1..1,
1283            },
1284            rhs: Box::new(Expr::Paren(Paren {
1285                expr: Box::new(Expr::Binary(Binary {
1286                    lhs: Box::new(Expr::Literal(Literal::Integer(LitInt {
1287                        value: "3".to_string(),
1288                        span: 2..3,
1289                    }))),
1290                    op: BinOp {
1291                        kind: BinOpKind::Add,
1292                        implicit: false,
1293                        span: 4..5,
1294                    },
1295                    rhs: Box::new(Expr::Literal(Literal::Integer(LitInt {
1296                        value: "4".to_string(),
1297                        span: 6..7,
1298                    }))),
1299                    span: 2..7,
1300                })),
1301                span: 1..8,
1302            })),
1303            span: 0..8,
1304        }));
1305    }
1306
1307    #[test]
1308    fn implicit_multiplication_2() {
1309        let mut parser = Parser::new("1 + 2x");
1310        let expr = parser.try_parse_full::<Expr>().unwrap();
1311
1312        assert_eq!(expr, Expr::Binary(Binary {
1313            lhs: Box::new(Expr::Literal(Literal::Integer(LitInt {
1314                value: "1".to_string(),
1315                span: 0..1,
1316            }))),
1317            op: BinOp {
1318                kind: BinOpKind::Add,
1319                implicit: false,
1320                span: 2..3,
1321            },
1322            rhs: Box::new(Expr::Binary(Binary {
1323                lhs: Box::new(Expr::Literal(Literal::Integer(LitInt {
1324                    value: "2".to_string(),
1325                    span: 4..5,
1326                }))),
1327                op: BinOp {
1328                    kind: BinOpKind::Mul,
1329                    implicit: true,
1330                    span: 5..5,
1331                },
1332                rhs: Box::new(Expr::Literal(Literal::Symbol(LitSym {
1333                    name: "x".to_string(),
1334                    span: 5..6,
1335                }))),
1336                span: 4..6,
1337            })),
1338            span: 0..6,
1339        }));
1340    }
1341
1342    #[test]
1343    fn implicit_multiplication_3() {
1344        let mut parser = Parser::new("(1 - x)(1 + x)");
1345        let expr = parser.try_parse_full::<Expr>().unwrap();
1346
1347        assert_eq!(expr, Expr::Binary(Binary {
1348            lhs: Box::new(Expr::Paren(Paren {
1349                expr: Box::new(Expr::Binary(Binary {
1350                    lhs: Box::new(Expr::Literal(Literal::Integer(LitInt {
1351                        value: "1".to_string(),
1352                        span: 1..2,
1353                    }))),
1354                    op: BinOp {
1355                        kind: BinOpKind::Sub,
1356                        implicit: false,
1357                        span: 3..4,
1358                    },
1359                    rhs: Box::new(Expr::Literal(Literal::Symbol(LitSym {
1360                        name: "x".to_string(),
1361                        span: 5..6,
1362                    }))),
1363                    span: 1..6,
1364                })),
1365                span: 0..7,
1366            })),
1367            op: BinOp {
1368                kind: BinOpKind::Mul,
1369                implicit: true,
1370                span: 7..7,
1371            },
1372            rhs: Box::new(Expr::Paren(Paren {
1373                expr: Box::new(Expr::Binary(Binary {
1374                    lhs: Box::new(Expr::Literal(Literal::Integer(LitInt {
1375                        value: "1".to_string(),
1376                        span: 8..9,
1377                    }))),
1378                    op: BinOp {
1379                        kind: BinOpKind::Add,
1380                        implicit: false,
1381                        span: 10..11,
1382                    },
1383                    rhs: Box::new(Expr::Literal(Literal::Symbol(LitSym {
1384                        name: "x".to_string(),
1385                        span: 12..13,
1386                    }))),
1387                    span: 8..13,
1388                })),
1389                span: 7..14,
1390            })),
1391            span: 0..14,
1392        }));
1393    }
1394
1395    #[test]
1396    fn implicit_multiplication_4() {
1397        let mut parser = Parser::new("im(2sqrt(-1))");
1398        let expr = parser.try_parse_full::<Expr>().unwrap();
1399
1400        assert_eq!(expr, Expr::Call(Call {
1401            name: LitSym {
1402                name: "im".to_string(),
1403                span: 0..2,
1404            },
1405            derivatives: 0,
1406            args: vec![Expr::Binary(Binary {
1407                lhs: Box::new(Expr::Literal(Literal::Integer(LitInt {
1408                    value: "2".to_string(),
1409                    span: 3..4,
1410                }))),
1411                op: BinOp {
1412                    kind: BinOpKind::Mul,
1413                    implicit: true,
1414                    span: 4..4,
1415                },
1416                rhs: Box::new(Expr::Call(Call {
1417                    name: LitSym {
1418                        name: "sqrt".to_string(),
1419                        span: 4..8,
1420                    },
1421                    derivatives: 0,
1422                    args: vec![Expr::Unary(Unary {
1423                        operand: Box::new(Expr::Literal(Literal::Integer(LitInt {
1424                            value: "1".to_string(),
1425                            span: 10..11,
1426                        }))),
1427                        op: UnaryOp {
1428                            kind: UnaryOpKind::Neg,
1429                            span: 9..10,
1430                        },
1431                        span: 9..11,
1432                    })],
1433                    span: 4..12,
1434                    paren_span: 8..12,
1435                })),
1436                span: 3..12,
1437            })],
1438            span: 0..13,
1439            paren_span: 2..13,
1440        }));
1441    }
1442
1443    #[test]
1444    fn implicit_multiplication_extra() {
1445        let mut parser = Parser::new("4x^2 + 5x + 1");
1446        let expr = parser.try_parse_full::<Expr>().unwrap();
1447
1448        assert_eq!(expr, Expr::Binary(Binary {
1449            lhs: Box::new(Expr::Binary(Binary {
1450                lhs: Box::new(Expr::Binary(Binary {
1451                    lhs: Box::new(Expr::Literal(Literal::Integer(LitInt {
1452                        value: "4".to_string(),
1453                        span: 0..1,
1454                    }))),
1455                    op: BinOp {
1456                        kind: BinOpKind::Mul,
1457                        implicit: true,
1458                        span: 1..1,
1459                    },
1460                    rhs: Box::new(Expr::Binary(Binary {
1461                        lhs: Box::new(Expr::Literal(Literal::Symbol(LitSym {
1462                            name: "x".to_string(),
1463                            span: 1..2,
1464                        }))),
1465                        op: BinOp {
1466                            kind: BinOpKind::Exp,
1467                            implicit: false,
1468                            span: 2..3,
1469                        },
1470                        rhs: Box::new(Expr::Literal(Literal::Integer(LitInt {
1471                            value: "2".to_string(),
1472                            span: 3..4,
1473                        }))),
1474                        span: 1..4,
1475                    })),
1476                    span: 0..4,
1477                })),
1478                op: BinOp {
1479                    kind: BinOpKind::Add,
1480                    implicit: false,
1481                    span: 5..6,
1482                },
1483                rhs: Box::new(Expr::Binary(Binary {
1484                    lhs: Box::new(Expr::Literal(Literal::Integer(LitInt {
1485                        value: "5".to_string(),
1486                        span: 7..8,
1487                    }))),
1488                    op: BinOp {
1489                        kind: BinOpKind::Mul,
1490                        implicit: true,
1491                        span: 8..8,
1492                    },
1493                    rhs: Box::new(Expr::Literal(Literal::Symbol(LitSym {
1494                        name: "x".to_string(),
1495                        span: 8..9,
1496                    }))),
1497                    span: 7..9,
1498                })),
1499                span: 0..9,
1500            })),
1501            op: BinOp {
1502                kind: BinOpKind::Add,
1503                implicit: false,
1504                span: 10..11,
1505            },
1506            rhs: Box::new(Expr::Literal(Literal::Integer(LitInt {
1507                value: "1".to_string(),
1508                span: 12..13,
1509            }))),
1510            span: 0..13,
1511        }));
1512    }
1513
1514    #[test]
1515    fn implicit_multiplication_extra_2() {
1516        let mut parser = Parser::new("3^42.9i");
1517        let expr = parser.try_parse_full::<Expr>().unwrap();
1518
1519        assert_eq!(expr, Expr::Binary(Binary {
1520            lhs: Box::new(Expr::Binary(Binary {
1521                lhs: Box::new(Expr::Literal(Literal::Integer(LitInt {
1522                    value: "3".to_string(),
1523                    span: 0..1,
1524                }))),
1525                op: BinOp {
1526                    kind: BinOpKind::Exp,
1527                    implicit: false,
1528                    span: 1..2,
1529                },
1530                rhs: Box::new(Expr::Literal(Literal::Float(LitFloat {
1531                    value: "42.9".to_string(),
1532                    span: 2..6,
1533                }))),
1534                span: 0..6,
1535            })),
1536            op: BinOp {
1537                kind: BinOpKind::Mul,
1538                implicit: true,
1539                span: 6..6,
1540            },
1541            rhs: Box::new(Expr::Literal(Literal::Symbol(LitSym {
1542                name: "i".to_string(),
1543                span: 6..7,
1544            }))),
1545            span: 0..7,
1546        }));
1547    }
1548
1549    #[test]
1550    fn implicit_multiplication_nonsensical() {
1551        let mut parser = Parser::new("2!! 3!!");
1552        let expr = parser.try_parse_full::<Expr>().unwrap();
1553
1554        assert_eq!(expr, Expr::Binary(Binary {
1555            lhs: Box::new(Expr::Unary(Unary {
1556                operand: Box::new(Expr::Unary(Unary {
1557                    operand: Box::new(Expr::Literal(Literal::Integer(LitInt {
1558                        value: "2".to_string(),
1559                        span: 0..1,
1560                    }))),
1561                    op: UnaryOp {
1562                        kind: UnaryOpKind::Factorial,
1563                        span: 1..2,
1564                    },
1565                    span: 0..2,
1566                })),
1567                op: UnaryOp {
1568                    kind: UnaryOpKind::Factorial,
1569                    span: 2..3,
1570                },
1571                span: 0..3,
1572            })),
1573            op: BinOp {
1574                kind: BinOpKind::Mul,
1575                implicit: true,
1576                span: 3..4,
1577            },
1578            rhs: Box::new(Expr::Unary(Unary {
1579                operand: Box::new(Expr::Unary(Unary {
1580                    operand: Box::new(Expr::Literal(Literal::Integer(LitInt {
1581                        value: "3".to_string(),
1582                        span: 4..5,
1583                    }))),
1584                    op: UnaryOp {
1585                        kind: UnaryOpKind::Factorial,
1586                        span: 5..6,
1587                    },
1588                    span: 4..6,
1589                })),
1590                op: UnaryOp {
1591                    kind: UnaryOpKind::Factorial,
1592                    span: 6..7,
1593                },
1594                span: 4..7,
1595            })),
1596            span: 0..7,
1597        }));
1598    }
1599
1600    #[test]
1601    fn implicit_multiplication_ambiguous() {
1602        let mut parser = Parser::new("1 / 2a");
1603        let expr = parser.try_parse_full::<Expr>().unwrap();
1604
1605        assert_eq!(expr, Expr::Binary(Binary {
1606            lhs: Box::new(Expr::Binary(Binary {
1607                lhs: Box::new(Expr::Literal(Literal::Integer(LitInt {
1608                    value: "1".to_string(),
1609                    span: 0..1,
1610                }))),
1611                op: BinOp {
1612                    kind: BinOpKind::Div,
1613                    implicit: false,
1614                    span: 2..3,
1615                },
1616                rhs: Box::new(Expr::Literal(Literal::Integer(LitInt {
1617                    value: "2".to_string(),
1618                    span: 4..5,
1619                }))),
1620                span: 0..5,
1621            })),
1622            op: BinOp {
1623                kind: BinOpKind::Mul,
1624                implicit: true,
1625                span: 5..5,
1626            },
1627            rhs: Box::new(Expr::Literal(Literal::Symbol(LitSym {
1628                name: "a".to_string(),
1629                span: 5..6,
1630            }))),
1631            span: 0..6,
1632        }));
1633    }
1634
1635    #[test]
1636    fn implicit_multiplication_terms_with_power() {
1637        let mut parser = Parser::new("-16x y + 2x^2y");
1638        let expr = parser.try_parse_full::<Expr>().unwrap();
1639
1640        // -16xy
1641        let lhs = Expr::Binary(Binary {
1642            lhs: Box::new(Expr::Binary(Binary {
1643                lhs: Box::new(Expr::Unary(Unary {
1644                    operand: Box::new(Expr::Literal(Literal::Integer(LitInt {
1645                        value: "16".to_string(),
1646                        span: 1..3,
1647                    }))),
1648                    op: UnaryOp {
1649                        kind: UnaryOpKind::Neg,
1650                        span: 0..1,
1651                    },
1652                    span: 0..3,
1653                })),
1654                op: BinOp {
1655                    kind: BinOpKind::Mul,
1656                    implicit: true,
1657                    span: 3..3,
1658                },
1659                rhs: Box::new(Expr::Literal(Literal::Symbol(LitSym {
1660                    name: "x".to_string(),
1661                    span: 3..4,
1662                }))),
1663                span: 0..4,
1664            })),
1665            op: BinOp {
1666                kind: BinOpKind::Mul,
1667                implicit: true,
1668                span: 4..5,
1669            },
1670            rhs: Box::new(Expr::Literal(Literal::Symbol(LitSym {
1671                name: "y".to_string(),
1672                span: 5..6,
1673            }))),
1674            span: 0..6,
1675        });
1676
1677        // 2x^2y
1678        let rhs = Expr::Binary(Binary {
1679            lhs: Box::new(Expr::Binary(Binary {
1680                lhs: Box::new(Expr::Literal(Literal::Integer(LitInt {
1681                    value: "2".to_string(),
1682                    span: 9..10,
1683                }))),
1684                op: BinOp {
1685                    kind: BinOpKind::Mul,
1686                    implicit: true,
1687                    span: 10..10,
1688                },
1689                rhs: Box::new(Expr::Binary(Binary {
1690                    lhs: Box::new(Expr::Literal(Literal::Symbol(LitSym {
1691                        name: "x".to_string(),
1692                        span: 10..11,
1693                    }))),
1694                    op: BinOp {
1695                        kind: BinOpKind::Exp,
1696                        implicit: false,
1697                        span: 11..12,
1698                    },
1699                    rhs: Box::new(Expr::Literal(Literal::Integer(LitInt {
1700                        value: "2".to_string(),
1701                        span: 12..13,
1702                    }))),
1703                    span: 10..13,
1704                })),
1705                span: 9..13,
1706            })),
1707            op: BinOp {
1708                kind: BinOpKind::Mul,
1709                implicit: true,
1710                span: 13..13,
1711            },
1712            rhs: Box::new(Expr::Literal(Literal::Symbol(LitSym {
1713                name: "y".to_string(),
1714                span: 13..14,
1715            }))),
1716            span: 9..14,
1717        });
1718
1719        // -16xy + 2x^2y
1720        let add = Expr::Binary(Binary {
1721            lhs: Box::new(lhs),
1722            op: BinOp {
1723                kind: BinOpKind::Add,
1724                implicit: false,
1725                span: 7..8,
1726            },
1727            rhs: Box::new(rhs),
1728            span: 0..14,
1729        });
1730
1731        assert_eq!(expr, add);
1732    }
1733
1734    #[test]
1735    fn parenthesized() {
1736        let mut parser = Parser::new("(1 + 2) * __");
1737        let expr = parser.try_parse_full::<Expr>().unwrap();
1738
1739        assert_eq!(expr, Expr::Binary(Binary {
1740            lhs: Box::new(Expr::Paren(Paren {
1741                expr: Box::new(Expr::Binary(Binary {
1742                    lhs: Box::new(Expr::Literal(Literal::Integer(LitInt {
1743                        value: "1".to_string(),
1744                        span: 1..2,
1745                    }))),
1746                    op: BinOp {
1747                        kind: BinOpKind::Add,
1748                        implicit: false,
1749                        span: 3..4,
1750                    },
1751                    rhs: Box::new(Expr::Literal(Literal::Integer(LitInt {
1752                        value: "2".to_string(),
1753                        span: 5..6,
1754                    }))),
1755                    span: 1..6,
1756                })),
1757                span: 0..7,
1758            })),
1759            op: BinOp {
1760                kind: BinOpKind::Mul,
1761                implicit: false,
1762                span: 8..9,
1763            },
1764            rhs: Box::new(Expr::Literal(Literal::Symbol(LitSym {
1765                name: "__".to_string(),
1766                span: 10..12,
1767            }))),
1768            span: 0..12,
1769        }));
1770    }
1771
1772    #[test]
1773    fn parenthesized_complicated() {
1774        let mut parser = Parser::new("(3 * 9 + 4.0 / 11.9 % (6 - 3))");
1775        let expr = parser.try_parse_full::<Expr>().unwrap();
1776
1777        assert_eq!(expr, Expr::Paren(Paren {
1778            expr: Box::new(Expr::Binary(Binary {
1779                lhs: Box::new(Expr::Binary(Binary {
1780                    lhs: Box::new(Expr::Literal(Literal::Integer(LitInt {
1781                        value: "3".to_string(),
1782                        span: 1..2,
1783                    }))),
1784                    op: BinOp {
1785                        kind: BinOpKind::Mul,
1786                        implicit: false,
1787                        span: 3..4,
1788                    },
1789                    rhs: Box::new(Expr::Literal(Literal::Integer(LitInt {
1790                        value: "9".to_string(),
1791                        span: 5..6,
1792                    }))),
1793                    span: 1..6,
1794                })),
1795                op: BinOp {
1796                    kind: BinOpKind::Add,
1797                    implicit: false,
1798                    span: 7..8,
1799                },
1800                rhs: Box::new(Expr::Binary(Binary {
1801                    lhs: Box::new(Expr::Binary(Binary {
1802                        lhs: Box::new(Expr::Literal(Literal::Float(LitFloat {
1803                            value: "4.0".to_string(),
1804                            span: 9..12,
1805                        }))),
1806                        op: BinOp {
1807                            kind: BinOpKind::Div,
1808                            implicit: false,
1809                            span: 13..14,
1810                        },
1811                        rhs: Box::new(Expr::Literal(Literal::Float(LitFloat {
1812                            value: "11.9".to_string(),
1813                            span: 15..19,
1814                        }))),
1815                        span: 9..19,
1816                    })),
1817                    op: BinOp {
1818                        kind: BinOpKind::Mod,
1819                        implicit: false,
1820                        span: 20..21,
1821                    },
1822                    rhs: Box::new(Expr::Paren(Paren {
1823                        expr: Box::new(Expr::Binary(Binary {
1824                            lhs: Box::new(Expr::Literal(Literal::Integer(LitInt {
1825                                value: "6".to_string(),
1826                                span: 23..24,
1827                            }))),
1828                            op: BinOp {
1829                                kind: BinOpKind::Sub,
1830                                implicit: false,
1831                                span: 25..26,
1832                            },
1833                            rhs: Box::new(Expr::Literal(Literal::Integer(LitInt {
1834                                value: "3".to_string(),
1835                                span: 27..28,
1836                            }))),
1837                            span: 23..28,
1838                        })),
1839                        span: 22..29,
1840                    })),
1841                    span: 9..29,
1842                })),
1843                span: 1..29,
1844            })),
1845            span: 0..30,
1846        }));
1847    }
1848
1849    #[test]
1850    fn block_code() {
1851        let mut parser = Parser::new("{ x = 5; y = 6; x + y }");
1852        let expr = parser.try_parse_full::<Expr>().unwrap();
1853
1854        assert_eq!(expr, Expr::Block(Block {
1855            stmts: vec![
1856                Stmt {
1857                    expr: Expr::Assign(Assign {
1858                        target: AssignTarget::Symbol(LitSym {
1859                            name: "x".to_string(),
1860                            span: 2..3,
1861                        }),
1862                        op: AssignOp {
1863                            kind: AssignOpKind::Assign,
1864                            span: 4..5,
1865                        },
1866                        value: Box::new(Expr::Literal(Literal::Integer(LitInt {
1867                            value: "5".to_string(),
1868                            span: 6..7,
1869                        }))),
1870                        span: 2..7,
1871                    }),
1872                    semicolon: Some(7..8),
1873                    span: 2..8,
1874                },
1875                Stmt {
1876                    expr: Expr::Assign(Assign {
1877                        target: AssignTarget::Symbol(LitSym {
1878                            name: "y".to_string(),
1879                            span: 9..10,
1880                        }),
1881                        op: AssignOp {
1882                            kind: AssignOpKind::Assign,
1883                            span: 11..12,
1884                        },
1885                        value: Box::new(Expr::Literal(Literal::Integer(LitInt {
1886                            value: "6".to_string(),
1887                            span: 13..14,
1888                        }))),
1889                        span: 9..14,
1890                    }),
1891                    semicolon: Some(14..15),
1892                    span: 9..15,
1893                },
1894                Stmt {
1895                    expr: Expr::Binary(Binary {
1896                        lhs: Box::new(Expr::Literal(Literal::Symbol(LitSym {
1897                            name: "x".to_string(),
1898                            span: 16..17,
1899                        }))),
1900                        op: BinOp {
1901                            kind: BinOpKind::Add,
1902                            implicit: false,
1903                            span: 18..19,
1904                        },
1905                        rhs: Box::new(Expr::Literal(Literal::Symbol(LitSym {
1906                            name: "y".to_string(),
1907                            span: 20..21,
1908                        }))),
1909                        span: 16..21,
1910                    }),
1911                    semicolon: None,
1912                    span: 16..21,
1913                },
1914            ],
1915            span: 0..23,
1916        }));
1917    }
1918
1919    #[test]
1920    fn if_block() {
1921        let mut parser = Parser::new("if d { abs''(d) } else { f = 1; f }");
1922        let expr = parser.try_parse_full::<Expr>().unwrap();
1923
1924        assert_eq!(expr, Expr::If(If {
1925            condition: Box::new(Expr::Literal(Literal::Symbol(LitSym {
1926                name: "d".to_string(),
1927                span: 3..4,
1928            }))),
1929            then_expr: Box::new(Expr::Block(Block {
1930                stmts: vec![
1931                    Stmt {
1932                        expr: Expr::Call(Call {
1933                            name: LitSym {
1934                                name: "abs".to_string(),
1935                                span: 7..10,
1936                            },
1937                            derivatives: 2,
1938                            args: vec![
1939                                Expr::Literal(Literal::Symbol(LitSym {
1940                                    name: "d".to_string(),
1941                                    span: 13..14,
1942                                })),
1943                            ],
1944                            span: 7..15,
1945                            paren_span: 12..15,
1946                        }),
1947                        semicolon: None,
1948                        span: 7..15,
1949                    },
1950                ],
1951                span: 5..17,
1952            })),
1953            else_expr: Some(Box::new(Expr::Block(Block {
1954                stmts: vec![
1955                    Stmt {
1956                        expr: Expr::Assign(Assign {
1957                            target: AssignTarget::Symbol(LitSym {
1958                                name: "f".to_string(),
1959                                span: 25..26,
1960                            }),
1961                            op: AssignOp {
1962                                kind: AssignOpKind::Assign,
1963                                span: 27..28,
1964                            },
1965                            value: Box::new(Expr::Literal(Literal::Integer(LitInt {
1966                                value: "1".to_string(),
1967                                span: 29..30,
1968                            }))),
1969                            span: 25..30,
1970                        }),
1971                        semicolon: Some(30..31),
1972                        span: 25..31,
1973                    },
1974                    Stmt {
1975                        expr: Expr::Literal(Literal::Symbol(LitSym {
1976                            name: "f".to_string(),
1977                            span: 32..33,
1978                        })),
1979                        semicolon: None,
1980                        span: 32..33,
1981                    },
1982                ],
1983                span: 23..35,
1984            }))),
1985            span: 0..35,
1986            if_span: 0..2,
1987            else_span: Some(18..22),
1988        }));
1989    }
1990
1991    #[test]
1992    fn assign_to_var() {
1993        let mut parser = Parser::new("fx += 1 / pi");
1994        let expr = parser.try_parse_full::<Expr>().unwrap();
1995
1996        assert_eq!(expr, Expr::Assign(Assign {
1997            target: AssignTarget::Symbol(LitSym {
1998                name: "fx".to_string(),
1999                span: 0..2,
2000            }),
2001            op: AssignOp {
2002                kind: AssignOpKind::Add,
2003                span: 3..5,
2004            },
2005            value: Box::new(Expr::Binary(Binary {
2006                lhs: Box::new(Expr::Literal(Literal::Integer(LitInt {
2007                    value: "1".to_string(),
2008                    span: 6..7,
2009                }))),
2010                op: BinOp {
2011                    kind: BinOpKind::Div,
2012                    implicit: false,
2013                    span: 8..9,
2014                },
2015                rhs: Box::new(Expr::Literal(Literal::Symbol(LitSym {
2016                    name: "pi".to_string(),
2017                    span: 10..12,
2018                }))),
2019                span: 6..12,
2020            })),
2021            span: 0..12,
2022        }));
2023    }
2024
2025    #[test]
2026    fn assign_to_function() {
2027        let mut parser = Parser::new("f(x) = x^2 + 5x");
2028        let expr = parser.try_parse_full::<Expr>().unwrap();
2029
2030        assert_eq!(expr, Expr::Assign(Assign {
2031            target: AssignTarget::Func(FuncHeader {
2032                name: LitSym {
2033                    name: "f".to_string(),
2034                    span: 0..1,
2035                },
2036                params: vec![
2037                    Param::Symbol(LitSym {
2038                        name: "x".to_string(),
2039                        span: 2..3,
2040                    }),
2041                ],
2042                span: 0..4,
2043            }),
2044            op: AssignOp {
2045                kind: AssignOpKind::Assign,
2046                span: 5..6,
2047            },
2048            value: Box::new(Expr::Binary(Binary {
2049                lhs: Box::new(Expr::Binary(Binary {
2050                    lhs: Box::new(Expr::Literal(Literal::Symbol(LitSym {
2051                        name: "x".to_string(),
2052                        span: 7..8,
2053                    }))),
2054                    op: BinOp {
2055                        kind: BinOpKind::Exp,
2056                        implicit: false,
2057                        span: 8..9,
2058                    },
2059                    rhs: Box::new(Expr::Literal(Literal::Integer(LitInt {
2060                        value: "2".to_string(),
2061                        span: 9..10,
2062                    }))),
2063                    span: 7..10,
2064                })),
2065                op: BinOp {
2066                    kind: BinOpKind::Add,
2067                    implicit: false,
2068                    span: 11..12,
2069                },
2070                rhs: Box::new(Expr::Binary(Binary {
2071                    lhs: Box::new(Expr::Literal(Literal::Integer(LitInt {
2072                        value: "5".to_string(),
2073                        span: 13..14,
2074                    }))),
2075                    op: BinOp {
2076                        kind: BinOpKind::Mul,
2077                        implicit: true,
2078                        span: 14..14,
2079                    },
2080                    rhs: Box::new(Expr::Literal(Literal::Symbol(LitSym {
2081                        name: "x".to_string(),
2082                        span: 14..15,
2083                    }))),
2084                    span: 13..15,
2085                })),
2086                span: 7..15,
2087            })),
2088            span: 0..15,
2089        }));
2090    }
2091
2092    #[test]
2093    fn bad_assign_to_function() {
2094        // cannot compound assign to function
2095        let mut parser = Parser::new("g(x) += 2");
2096        let expr = parser.try_parse_full::<Expr>();
2097        assert!(expr.is_err());
2098    }
2099
2100    #[test]
2101    fn bad_assign_to_function_default_params() {
2102        // default parameters must be at the end
2103        let mut parser = Parser::new("g(x = 1, y) += 2");
2104        let expr = parser.try_parse_full::<Expr>();
2105        assert!(expr.is_err());
2106    }
2107
2108    #[test]
2109    fn assign_to_complicated_function() {
2110        let mut parser = Parser::new("discrim(a = 1, b = 5, c = 6) = return b^2 - 4a * c");
2111        let expr = parser.try_parse_full::<Expr>().unwrap();
2112
2113        assert_eq!(expr, Expr::Assign(Assign {
2114            target: AssignTarget::Func(FuncHeader {
2115                name: LitSym {
2116                    name: "discrim".to_string(),
2117                    span: 0..7,
2118                },
2119                params: vec![
2120                    Param::Default(
2121                        LitSym {
2122                            name: "a".to_string(),
2123                            span: 8..9,
2124                        },
2125                        Expr::Literal(Literal::Integer(LitInt {
2126                            value: "1".to_string(),
2127                            span: 12..13,
2128                        })),
2129                    ),
2130                    Param::Default(
2131                        LitSym {
2132                            name: "b".to_string(),
2133                            span: 15..16,
2134                        },
2135                        Expr::Literal(Literal::Integer(LitInt {
2136                            value: "5".to_string(),
2137                            span: 19..20,
2138                        })),
2139                    ),
2140                    Param::Default(
2141                        LitSym {
2142                            name: "c".to_string(),
2143                            span: 22..23,
2144                        },
2145                        Expr::Literal(Literal::Integer(LitInt {
2146                            value: "6".to_string(),
2147                            span: 26..27,
2148                        })),
2149                    ),
2150                ],
2151                span: 0..28,
2152            }),
2153            op: AssignOp {
2154                kind: AssignOpKind::Assign,
2155                span: 29..30,
2156            },
2157            value: Box::new(Expr::Return(Return {
2158                value: Some(Box::new(Expr::Binary(Binary {
2159                    lhs: Box::new(Expr::Binary(Binary {
2160                        lhs: Box::new(Expr::Literal(Literal::Symbol(LitSym {
2161                            name: "b".to_string(),
2162                            span: 38..39,
2163                        }))),
2164                        op: BinOp {
2165                            kind: BinOpKind::Exp,
2166                            implicit: false,
2167                            span: 39..40,
2168                        },
2169                        rhs: Box::new(Expr::Literal(Literal::Integer(LitInt {
2170                            value: "2".to_string(),
2171                            span: 40..41,
2172                        }))),
2173                        span: 38..41,
2174                    })),
2175                    op: BinOp {
2176                        kind: BinOpKind::Sub,
2177                        implicit: false,
2178                        span: 42..43,
2179                    },
2180                    rhs: Box::new(Expr::Binary(Binary {
2181                        lhs: Box::new(Expr::Binary(Binary {
2182                            lhs: Box::new(Expr::Literal(Literal::Integer(LitInt {
2183                                value: "4".to_string(),
2184                                span: 44..45,
2185                            }))),
2186                            op: BinOp {
2187                                kind: BinOpKind::Mul,
2188                                implicit: true,
2189                                span: 45..45,
2190                            },
2191                            rhs: Box::new(Expr::Literal(Literal::Symbol(LitSym {
2192                                name: "a".to_string(),
2193                                span: 45..46,
2194                            }))),
2195                            span: 44..46,
2196                        })),
2197                        op: BinOp {
2198                            kind: BinOpKind::Mul,
2199                            implicit: false,
2200                            span: 47..48,
2201                        },
2202                        rhs: Box::new(Expr::Literal(Literal::Symbol(LitSym {
2203                            name: "c".to_string(),
2204                            span: 49..50,
2205                        }))),
2206                        span: 44..50,
2207                    })),
2208                    span: 38..50,
2209                }))),
2210                span: 31..50,
2211                return_span: 31..37,
2212            })),
2213            span: 0..50,
2214        }));
2215    }
2216
2217    #[test]
2218    fn assign_function_to_list() {
2219        let mut parser = Parser::new("arr[0] = f() = pi");
2220        let expr = parser.try_parse_full::<Expr>().unwrap();
2221
2222        assert_eq!(expr, Expr::Assign(Assign {
2223            target: AssignTarget::Index(Index {
2224                target: Box::new(Expr::Literal(Literal::Symbol(LitSym {
2225                    name: "arr".to_string(),
2226                    span: 0..3,
2227                }))),
2228                index: Box::new(Expr::Literal(Literal::Integer(LitInt {
2229                    value: "0".to_string(),
2230                    span: 4..5,
2231                }))),
2232                span: 0..6,
2233                bracket_span: 3..6,
2234            }),
2235            op: AssignOp {
2236                kind: AssignOpKind::Assign,
2237                span: 7..8,
2238            },
2239            value: Box::new(Expr::Assign(Assign {
2240                target: AssignTarget::Func(FuncHeader {
2241                    name: LitSym {
2242                        name: "f".to_string(),
2243                        span: 9..10,
2244                    },
2245                    params: vec![],
2246                    span: 9..12,
2247                }),
2248                op: AssignOp {
2249                    kind: AssignOpKind::Assign,
2250                    span: 13..14,
2251                },
2252                value: Box::new(Expr::Literal(Literal::Symbol(LitSym {
2253                    name: "pi".to_string(),
2254                    span: 15..17,
2255                }))),
2256                span: 9..17,
2257            })),
2258            span: 0..17,
2259        }));
2260    }
2261
2262    #[test]
2263    fn range_no_float() {
2264        let mut parser = Parser::new("1..2");
2265        let expr = parser.try_parse_full::<Expr>().unwrap();
2266
2267        assert_eq!(expr, Expr::Range(ast::Range {
2268            start: Box::new(Expr::Literal(Literal::Integer(LitInt {
2269                value: "1".to_string(),
2270                span: 0..1,
2271            }))),
2272            end: Box::new(Expr::Literal(Literal::Integer(LitInt {
2273                value: "2".to_string(),
2274                span: 3..4,
2275            }))),
2276            kind: RangeKind::HalfOpen,
2277            span: 0..4,
2278        }));
2279    }
2280
2281    #[test]
2282    fn range_precedence() {
2283        let mut parser = Parser::new("3 * 4 + 1 ..= 26 + 2");
2284        let expr = parser.try_parse_full::<Expr>().unwrap();
2285
2286        assert_eq!(expr, Expr::Range(ast::Range {
2287            start: Box::new(Expr::Binary(Binary {
2288                lhs: Box::new(Expr::Binary(Binary {
2289                    lhs: Box::new(Expr::Literal(Literal::Integer(LitInt {
2290                        value: "3".to_string(),
2291                        span: 0..1,
2292                    }))),
2293                    op: BinOp {
2294                        kind: BinOpKind::Mul,
2295                        implicit: false,
2296                        span: 2..3,
2297                    },
2298                    rhs: Box::new(Expr::Literal(Literal::Integer(LitInt {
2299                        value: "4".to_string(),
2300                        span: 4..5,
2301                    }))),
2302                    span: 0..5,
2303                })),
2304                op: BinOp {
2305                    kind: BinOpKind::Add,
2306                    implicit: false,
2307                    span: 6..7,
2308                },
2309                rhs: Box::new(Expr::Literal(Literal::Integer(LitInt {
2310                    value: "1".to_string(),
2311                    span: 8..9,
2312                }))),
2313                span: 0..9,
2314            })),
2315            end: Box::new(Expr::Binary(Binary {
2316                lhs: Box::new(Expr::Literal(Literal::Integer(LitInt {
2317                    value: "26".to_string(),
2318                    span: 14..16,
2319                }))),
2320                op: BinOp {
2321                    kind: BinOpKind::Add,
2322                    implicit: false,
2323                    span: 17..18,
2324                },
2325                rhs: Box::new(Expr::Literal(Literal::Integer(LitInt {
2326                    value: "2".to_string(),
2327                    span: 19..20,
2328                }))),
2329                span: 14..20,
2330            })),
2331            kind: RangeKind::Closed,
2332            span: 0..20,
2333        }));
2334    }
2335
2336    #[test]
2337    fn function_call() {
2338        let mut parser = Parser::new("f(x)");
2339        let expr = parser.try_parse_full::<Expr>().unwrap();
2340
2341        assert_eq!(expr, Expr::Call(Call {
2342            name: LitSym {
2343                name: "f".to_string(),
2344                span: 0..1,
2345            },
2346            derivatives: 0,
2347            args: vec![
2348                Expr::Literal(Literal::Symbol(LitSym {
2349                    name: "x".to_string(),
2350                    span: 2..3,
2351                })),
2352            ],
2353            span: 0..4,
2354            paren_span: 1..4,
2355        }));
2356    }
2357
2358    #[test]
2359    fn function_call_whitespace() {
2360        let mut parser = Parser::new("ncr  ' ' ' '' ' ( 8 , 5 )");
2361        let expr = parser.try_parse_full::<Expr>().unwrap();
2362
2363        assert_eq!(expr, Expr::Call(Call {
2364            name: LitSym {
2365                name: "ncr".to_string(),
2366                span: 0..3,
2367            },
2368            derivatives: 6,
2369            args: vec![
2370                Expr::Literal(Literal::Integer(LitInt {
2371                    value: "8".to_string(),
2372                    span: 18..19,
2373                })),
2374                Expr::Literal(Literal::Integer(LitInt {
2375                    value: "5".to_string(),
2376                    span: 22..23,
2377                })),
2378            ],
2379            span: 0..25,
2380            paren_span: 16..25,
2381        }));
2382    }
2383
2384    #[test]
2385    fn blank_function_header() {
2386        let mut parser = Parser::new("f() = 5");
2387        let expr = parser.try_parse_full::<Expr>().unwrap();
2388
2389        assert_eq!(expr, Expr::Assign(Assign {
2390            target: AssignTarget::Func(FuncHeader {
2391                name: LitSym {
2392                    name: "f".to_string(),
2393                    span: 0..1,
2394                },
2395                params: vec![],
2396                span: 0..3,
2397            }),
2398            op: AssignOp {
2399                kind: AssignOpKind::Assign,
2400                span: 4..5,
2401            },
2402            value: Box::new(Expr::Literal(Literal::Integer(LitInt {
2403                value: "5".to_string(),
2404                span: 6..7,
2405            }))),
2406            span: 0..7,
2407        }));
2408    }
2409
2410    #[test]
2411    fn catastrophic_backtracking() {
2412        // parsing nested function calls like this used to take exponential time! :sweat:
2413        // a(a(a(a(a(a(...)
2414        let source = format!("{})", "a(".repeat(6000));
2415        let mut parser = Parser::new(&source);
2416        assert!(parser.try_parse_full::<Expr>().is_err());
2417    }
2418
2419    #[test]
2420    fn oneline_while_loop() {
2421        let mut parser = Parser::new("while x < 5 then x += 1");
2422        let expr = parser.try_parse_full::<Expr>().unwrap();
2423
2424        assert_eq!(expr, Expr::While(While {
2425            condition: Box::new(Expr::Binary(Binary {
2426                lhs: Box::new(Expr::Literal(Literal::Symbol(LitSym {
2427                    name: "x".to_string(),
2428                    span: 6..7,
2429                }))),
2430                op: BinOp {
2431                    kind: BinOpKind::Less,
2432                    implicit: false,
2433                    span: 8..9,
2434                },
2435                rhs: Box::new(Expr::Literal(Literal::Integer(LitInt {
2436                    value: "5".to_string(),
2437                    span: 10..11,
2438                }))),
2439                span: 6..11,
2440            })),
2441            body: Box::new(Expr::Then(Then {
2442                expr: Box::new(Expr::Assign(Assign {
2443                    target: AssignTarget::Symbol(LitSym {
2444                        name: "x".to_string(),
2445                        span: 17..18,
2446                    }),
2447                    op: AssignOp {
2448                        kind: AssignOpKind::Add,
2449                        span: 19..21,
2450                    },
2451                    value: Box::new(Expr::Literal(Literal::Integer(LitInt {
2452                        value: "1".to_string(),
2453                        span: 22..23,
2454                    }))),
2455                    span: 17..23,
2456                })),
2457                span: 12..23,
2458                then_span: 12..16,
2459            })),
2460            span: 0..23,
2461            while_span: 0..5,
2462        }));
2463    }
2464
2465    #[test]
2466    fn index_into_function() {
2467        let mut parser = Parser::new("abs()[0]");
2468        let expr = parser.try_parse_full::<Expr>().unwrap();
2469
2470        assert_eq!(expr, Expr::Index(Index {
2471            target: Box::new(Expr::Call(Call {
2472                name: LitSym {
2473                    name: "abs".to_string(),
2474                    span: 0..3,
2475                },
2476                derivatives: 0,
2477                args: vec![],
2478                span: 0..5,
2479                paren_span: 3..5,
2480            })),
2481            index: Box::new(Expr::Literal(Literal::Integer(LitInt {
2482                value: "0".to_string(),
2483                span: 6..7,
2484            }))),
2485            span: 0..8,
2486            bracket_span: 5..8,
2487        }));
2488    }
2489
2490    #[test]
2491    fn source_code() {
2492        let mut parser = Parser::new("x = 5;
2493iseven(n) = n % 2 == 0;
2494if iseven(x) {
2495    x^2 + 5x + 6
2496} else if (bool(x) && false) {
2497    exp(x)
2498} else {
2499    log(x, 2)
2500}");
2501        assert!(parser.try_parse_full_many::<Stmt>().is_ok());
2502    }
2503}