symrs/expr/ops/
parse.rs

1use indexmap::IndexMap;
2use regex::{Captures, Regex};
3use std::{num::ParseIntError, str::FromStr, sync::LazyLock};
4
5use crate::{expr::*, symbol};
6
7use thiserror::Error;
8
9use crate::{Equation, Expr, Integer};
10
11#[derive(Error, Debug, PartialEq)]
12pub enum ParseExprError {
13    #[error("bad equation: {0}")]
14    BadEquation(#[from] ParseEquationError),
15    #[error("parse integer: {0}")]
16    BadInt(#[from] ParseIntegerError),
17    #[error("parse symbol: {0}")]
18    BadSymbol(#[from] ParseSymbolError),
19    #[error("bad addition: {0}")]
20    BadAdd(#[from] ParseAddError),
21    #[error("bad multiplication: {0}")]
22    BadMul(#[from] ParseMulError),
23    #[error("bracket mismatch: '{0}' and '{1}'")]
24    BracketMismatch(char, char),
25    #[error("bad function: {0}")]
26    BadFunction(#[from] ParseFunctionError),
27    #[error("invalid pow: {0}")]
28    InvalidPow(#[from] ParsePowError),
29    #[error("invalid diffentiation: {0}")]
30    InvalidDiff(#[from] ParseDiffError),
31    #[error("empty expression")]
32    EmptyExpr,
33}
34
35#[derive(Error, Debug, PartialEq)]
36pub enum ParseEquationError {
37    #[error("wrong number of operands: {0}, expected: 2")]
38    WrongNumberOfOperands(usize),
39    #[error("empty operand")]
40    EmptyOperand,
41    #[error("invalid lhs: {0}")]
42    InvalidLhs(Box<ParseExprError>),
43    #[error("invalid rhs: {0}")]
44    InvalidRhs(Box<ParseExprError>),
45}
46
47#[derive(Debug, Error, PartialEq)]
48#[error("failed to parse integer: {0}")]
49pub struct ParseIntegerError(String, #[source] ParseIntError);
50
51impl FromStr for Integer {
52    type Err = ParseIntegerError;
53
54    fn from_str(s: &str) -> Result<Self, Self::Err> {
55        Ok(Integer {
56            value: s.parse().map_err(|e| ParseIntegerError(s.to_string(), e))?,
57        })
58    }
59}
60
61impl FromStr for Box<dyn Expr> {
62    type Err = ParseExprError;
63
64    fn from_str(s: &str) -> Result<Self, Self::Err> {
65        parse_expr(s)
66    }
67}
68
69impl FromStr for Equation {
70    type Err = ParseEquationError;
71
72    fn from_str(s: &str) -> Result<Self, Self::Err> {
73        let equal_pieces: Vec<_> = s.split('=').map(|s| s.trim()).collect();
74        if equal_pieces.len() != 2 {
75            Err(ParseEquationError::WrongNumberOfOperands(
76                equal_pieces.len(),
77            ))?
78        }
79
80        if equal_pieces.iter().any(|s| s.is_empty()) {
81            Err(ParseEquationError::EmptyOperand)?
82        }
83
84        Ok(Equation {
85            lhs: equal_pieces[0]
86                .parse()
87                .map_err(|e| ParseEquationError::InvalidLhs(Box::new(e)))?,
88            rhs: equal_pieces[1]
89                .parse()
90                .map_err(|e| ParseEquationError::InvalidRhs(Box::new(e)))?,
91        })
92    }
93}
94
95#[derive(Error, Debug, PartialEq)]
96pub enum ParseSymbolError {}
97
98impl FromStr for Symbol {
99    type Err = ParseSymbolError;
100
101    fn from_str(s: &str) -> Result<Self, Self::Err> {
102        Ok(Symbol::new(s))
103    }
104}
105
106#[derive(Error, Debug, PartialEq)]
107pub enum ParseAddError {
108    #[error("bad operand: {0}")]
109    BadOperand(String, #[source] Box<ParseExprError>),
110}
111
112impl FromStr for Add {
113    type Err = ParseAddError;
114
115    fn from_str(s: &str) -> Result<Self, Self::Err> {
116        Ok(Add::new_v2(
117            split_root(s, &['+', '-'])
118                .map(|(prev, piece)| -> Result<Box<dyn Expr>, ParseAddError> {
119                    let mut op: Box<dyn Expr> = piece
120                        .parse()
121                        .map_err(|e| ParseAddError::BadOperand(piece.into(), Box::new(e)))?;
122                    if let Some('-') = prev {
123                        op = -op;
124                    }
125                    Ok(op)
126                })
127                .collect::<Result<_, _>>()?,
128        ))
129    }
130}
131
132#[derive(Error, Debug, PartialEq)]
133pub enum ParseMulError {
134    #[error("bad operand: {0}")]
135    BadOperand(String, #[source] Box<ParseExprError>),
136}
137
138impl FromStr for Mul {
139    type Err = ParseMulError;
140
141    fn from_str(s: &str) -> Result<Self, Self::Err> {
142        let mut ops = Vec::new();
143        for (prev, piece) in split_root(s, &['*', '/']) {
144            let mut op: Box<dyn Expr> = piece
145                .parse()
146                .map_err(|e| ParseMulError::BadOperand(piece.into(), Box::new(e)))?;
147            if let Some('/') = prev {
148                op = op.ipow(-1);
149            }
150
151            if let Some(Mul { operands }) = op.as_mul().cloned() {
152                for op in operands {
153                    ops.push(op);
154                }
155            } else {
156                ops.push(op)
157            }
158        }
159        Ok(Mul { operands: ops })
160    }
161}
162
163const FUNC_PATTERN: &str = r"^(\w+)\((.*?)\)$";
164
165static FUNC_RE: LazyLock<Regex> = LazyLock::new(|| Regex::new(FUNC_PATTERN).unwrap());
166
167#[derive(Error, Debug, PartialEq)]
168pub enum ParseFunctionError {
169    #[error("bad args")]
170    BadArgs,
171    #[error("wrong number of arguments for {0}: {1}, expected: {2}")]
172    BadArgCount(String, usize, String),
173    #[error("invalid function expression: {0}")]
174    InvalidFuncExpr(Box<ParseExprError>),
175    #[error("invalid order format: {0}, {1}")]
176    InvalidOrderFormat(String, ParseIntError),
177    #[error("invalid argument: {0}")]
178    InvalidArg(String, #[source] Box<ParseExprError>),
179    #[error("invalid differential expression")]
180    InvalidDiff(String, #[source] ParseDiffError),
181}
182
183static D_DVAR_RE: LazyLock<Regex> = LazyLock::new(|| {
184    Regex::new(r"^[d∂]\^?([\d⁰¹²³⁴⁵⁶⁷⁸⁹]*)\s*[\/_]\s*[d∂]\(?(\w+?)\)?\^?([\d⁰¹²³⁴⁵⁶⁷⁸]*)$").unwrap()
185});
186
187static DNVAR_RE: LazyLock<Regex> =
188    LazyLock::new(|| Regex::new(r"^[d∂]\^?(?:([\d⁰¹²³⁴⁵⁶⁷⁸⁹]+))?([A-Za-z_])$").unwrap());
189
190static SUB_DNVAR: LazyLock<Regex> =
191    LazyLock::new(|| Regex::new(r"^[d∂]\^?(?:([\d⁰¹²³⁴⁵⁶⁷⁸⁹]+))?([A-Za-z_])\((.*)\)$").unwrap());
192
193pub fn parse_function(name: &str, args: &str) -> Result<Box<dyn Expr>, ParseFunctionError> {
194    let args: Vec<_> = args.split(",").map(|arg| arg.trim()).collect();
195
196    // Handle differential operators (dx(...), dt(...), etc.)
197    if let Some(captures) = DNVAR_RE.captures(name) {
198        let var = &captures[2];
199        let order = captures.get(1).map_or("1", |o| o.as_str());
200        let order = order.parse().map_err(|e| {
201            ParseFunctionError::InvalidDiff(
202                name.to_string(),
203                ParseDiffError::InvalidNumOrderFormat(order.to_string(), e),
204            )
205        })?;
206
207        let mut var_orders: IndexMap<Symbol, usize> = IndexMap::new();
208        var_orders.insert(
209            Symbol {
210                name: var.to_string(),
211            },
212            order,
213        );
214
215        let mut f = args[0].to_string();
216
217        while let Some(captures) = SUB_DNVAR.captures(&f) {
218            let var = captures[2].to_string();
219            let var_order = captures.get(1).map_or("1", |o| o.as_str());
220            let var_order: usize = var_order.parse().map_err(|e| {
221                ParseFunctionError::InvalidDiff(
222                    name.to_string(),
223                    ParseDiffError::InvalidNumOrderFormat(var_order.to_string(), e),
224                )
225            })?;
226            f = captures[3].to_string();
227            let order = var_orders.entry(Symbol { name: var }).or_insert(0);
228            *order += var_order;
229        }
230
231        return Ok(Box::new(Diff::new_v2(
232            f.parse()
233                .map_err(|e| ParseFunctionError::InvalidFuncExpr(Box::new(e)))?,
234            var_orders,
235        )));
236    }
237
238    if let Some(captures) = D_DVAR_RE.captures(name) {
239        let num_order = &captures[1];
240        let den_order = &captures[3];
241        let var = Symbol::new(&captures[2]);
242        let num_order: usize = num_order
243            .parse()
244            .map_err(|e| ParseFunctionError::InvalidOrderFormat(num_order.to_string(), e))?;
245        let den_order: usize = den_order
246            .parse()
247            .map_err(|e| ParseFunctionError::InvalidOrderFormat(den_order.to_string(), e))?;
248
249        if num_order != den_order {
250            Err(ParseFunctionError::InvalidDiff(
251                name.to_string(),
252                ParseDiffError::OrderMismatch(num_order, den_order),
253            ))?
254        }
255
256        if args.len() != 1 {
257            Err(ParseFunctionError::BadArgCount(
258                name.to_string(),
259                args.len(),
260                "1".to_string(),
261            ))?
262        }
263
264        let expr = parse_expr(args[0]).map_err(|e| {
265            ParseFunctionError::InvalidDiff(
266                args[0].to_string(),
267                ParseDiffError::BadExpr(Box::new(e)),
268            )
269        })?;
270        return Ok(Box::new(Diff::new_move(expr, vec![var; num_order])));
271    }
272
273    Ok(match name {
274        "laplacian" => {
275            let laplacian = symbol!("laplacian");
276            let f = parse_expr(args[0])
277                .map_err(|e| ParseFunctionError::InvalidFuncExpr(Box::new(e)))?;
278
279            laplacian * f
280        }
281        "diff" => {
282            let n_args = args.len();
283            if n_args < 2 || n_args > 3 {
284                Err(ParseFunctionError::BadArgCount(
285                    name.to_string(),
286                    n_args,
287                    "2 or 3".to_string(),
288                ))?
289            }
290            let f = parse_expr(args[0])
291                .map_err(|e| ParseFunctionError::InvalidFuncExpr(Box::new(e)))?;
292            let order = if n_args == 3 {
293                args[2]
294                    .parse()
295                    .map_err(|e| ParseFunctionError::InvalidOrderFormat(args[2].to_string(), e))?
296            } else {
297                1
298            };
299            f.diff(args[1], order)
300        }
301        _ => {
302            let args: Result<Vec<Box<dyn Expr>>, ParseFunctionError> = args
303                .into_iter()
304                .map(|a| -> Result<Box<dyn Expr>, ParseFunctionError> {
305                    Ok(a.parse()
306                        .map_err(|e| ParseFunctionError::InvalidArg(a.into(), Box::new(e)))?)
307                })
308                .collect();
309
310            Func::new_move_box(name.to_string(), args?)
311        }
312    })
313}
314
315#[derive(Error, Debug, PartialEq)]
316pub enum ParsePowError {
317    #[error("invalid pow format: {0}, expected 'base^exponent'")]
318    InvalidFormat(String),
319    #[error("invalid expression for base: {0}, {1}")]
320    InvalidBase(String, Box<ParseExprError>),
321    #[error("invalid expression for exponent: {0}, {1}")]
322    InvalidExponent(String, Box<ParseExprError>),
323}
324
325impl FromStr for expr::Pow {
326    type Err = ParsePowError;
327
328    fn from_str(s: &str) -> Result<Self, Self::Err> {
329        let pieces: Vec<_> = s.split("^").collect();
330        if pieces.len() != 2 {
331            Err(ParsePowError::InvalidFormat(s.to_string()))?
332        }
333        let mut parsed: Vec<_> = pieces.iter().map(|e| parse_expr(e)).collect();
334        let exponent = parsed
335            .pop()
336            .unwrap()
337            .map_err(|err| ParsePowError::InvalidExponent(pieces[1].to_string(), Box::new(err)))?;
338        let base = parsed
339            .pop()
340            .unwrap()
341            .map_err(|err| ParsePowError::InvalidBase(pieces[0].to_string(), Box::new(err)))?;
342        Ok(Pow::new_move(base, exponent))
343    }
344}
345
346static DIFF_RE: LazyLock<Regex> = LazyLock::new(|| {
347    Regex::new(
348        r"^[d∂]\^?([\d⁰¹²³⁴⁵⁶⁷⁸⁹]*)\(?(.+?)\)?\s*[/_]\s*[d∂]\(?(\w+?)\)?\^?([\d⁰¹²³⁴⁵⁶⁷⁸]*)$",
349    )
350    .unwrap()
351});
352
353#[derive(Debug, Error, PartialEq)]
354pub enum ParseDiffError {
355    #[error("invalid diffentiation format: {0}, expected 'd^n(expr) / d(var)^n'")]
356    InvalidFormat(String),
357    #[error("invalid differentiated expression")]
358    BadExpr(#[from] Box<ParseExprError>),
359    #[error("invalid order format on numerator: {0}, {1}")]
360    InvalidNumOrderFormat(String, ParseIntError),
361    #[error("invalid order format on denominator: {0}, {1}")]
362    InvalidDenOrderFormat(String, ParseIntError),
363    #[error("order mismatch: numerator: {0}, denominator: {1}")]
364    OrderMismatch(usize, usize),
365}
366
367impl FromStr for Diff {
368    type Err = ParseDiffError;
369
370    fn from_str(s: &str) -> Result<Self, Self::Err> {
371        let captures = DIFF_RE
372            .captures(s)
373            .ok_or_else(|| ParseDiffError::InvalidFormat(s.to_string()))?;
374        captures.try_into()
375    }
376}
377
378impl TryFrom<Captures<'_>> for Diff {
379    type Error = ParseDiffError;
380
381    fn try_from(value: Captures<'_>) -> Result<Self, Self::Error> {
382        let num_order = &value[1];
383        let den_order = &value[4];
384        let num_order: usize = if num_order == "" {
385            1
386        } else {
387            value[1]
388                .parse()
389                .map_err(|e| ParseDiffError::InvalidNumOrderFormat(value[1].to_string(), e))?
390        };
391        let den_order: usize = if den_order == "" {
392            1
393        } else {
394            value[4]
395                .parse()
396                .map_err(|e| ParseDiffError::InvalidDenOrderFormat(value[4].to_string(), e))?
397        };
398        let expr = parse_expr(&value[2]).map_err(|e| ParseDiffError::BadExpr(Box::new(e)))?;
399        let var = Symbol::new(&value[3]);
400
401        if num_order != den_order {
402            Err(ParseDiffError::OrderMismatch(num_order, den_order))?
403        }
404
405        Ok(Diff::new_move(expr, vec![var; num_order]))
406    }
407}
408
409#[derive(Debug, Error, PartialEq)]
410pub enum ParseRationalError {
411    #[error("invalid rational format: {0}, expected 'numerator / denominator'")]
412    InvalidFormat(String),
413    #[error("invalid numerator: {0}")]
414    InvalidNumerator(String),
415    #[error("invalid denominator: {0}")]
416    InvalidDenominator(String),
417}
418
419static RATIONAL_RE: LazyLock<Regex> =
420    LazyLock::new(|| Regex::new(r"^\s*?([^/\s]+?)\s*?(?:/\s*?([^/\s]*?)\s*?)?$").unwrap());
421
422impl FromStr for Rational {
423    type Err = ParseRationalError;
424
425    fn from_str(s: &str) -> Result<Self, Self::Err> {
426        let captures = RATIONAL_RE
427            .captures(s)
428            .ok_or_else(|| ParseRationalError::InvalidFormat(s.to_string()))?;
429        let num = &captures[1];
430
431        let num: Rational = (if let Ok(num) = num.parse::<i32>() {
432            Ok(num.into())
433        } else if let Ok(num) = num.parse::<f64>() {
434            Ok(Rational::from_float(num))
435        } else {
436            Err(ParseRationalError::InvalidNumerator(num.to_string()))
437        })?;
438
439        let den = captures.get(2);
440
441        let den = den.map(|den| -> Result<_, _> {
442            if let Ok(den) = den.as_str().parse::<i32>() {
443                Ok(den.into())
444            } else if let Ok(den) = den.as_str().parse::<f64>() {
445                Ok(Rational::from_float(den))
446            } else {
447                Err(ParseRationalError::InvalidDenominator(
448                    den.as_str().to_string(),
449                ))
450            }
451        });
452
453        let den: Rational = if let Some(den) = den { den? } else { 1.into() };
454
455        Ok(num / den)
456    }
457}
458
459/// Checks if brackets are valid.
460///
461/// Returns true if the opening brackets are matched with the appropriate closing ones.
462pub fn are_brackets_valid(s: &str) -> bool {
463    let mut stack: Vec<usize> = Vec::new();
464
465    for c in s.chars() {
466        if let Some(i) = openers.iter().position(|opener| opener == &c) {
467            stack.push(i);
468        } else if let Some(i) = closers.iter().position(|closer| closer == &c) {
469            if stack.pop() != Some(i) {
470                return false;
471            }
472        }
473    }
474    stack.is_empty()
475}
476
477pub fn parse_expr(s: &str) -> Result<Box<dyn Expr>, ParseExprError> {
478    let s = s.trim();
479    if s.len() == 0 {
480        Err(ParseExprError::EmptyExpr)?
481    }
482    Ok(if s.split("=").collect::<Vec<_>>().len() >= 2 {
483        Box::new(s.parse::<Equation>()?)
484    }
485    // Functions
486    else if let Some(captured_func) = FUNC_RE.captures(s)
487        && are_brackets_valid(&captured_func[2])
488    {
489        return Ok(parse_function(&captured_func[1], &captured_func[2])?);
490    }
491    // Integer
492    else if s
493        .chars()
494        .enumerate()
495        .all(|(i, c)| c.is_numeric() || i == 0 && c == '-')
496    {
497        Box::new(s.parse::<Integer>()?)
498    }
499    // Rationals
500    else if let Ok(r) = s.parse::<Rational>() {
501        Box::new(r)
502    }
503    // Additions, Subtractions
504    else if let Some((_, add_piece)) = split_root(s, &['+', '-']).next()
505        && add_piece.len() != s.len()
506    {
507        Box::new(s.parse::<Add>()?)
508    }
509    // Differentiations
510    else if let Some(captured_diff) = DIFF_RE.captures(s) {
511        Box::new(TryInto::<Diff>::try_into(captured_diff)?)
512    }
513    // Multiplications, Divisions
514    else if let Some((_, mul_piece)) = split_root(s, &['*', '/']).next()
515        && mul_piece.len() != s.len()
516    {
517        Box::new(s.parse::<Mul>()?)
518    }
519    // Brackets
520    else if s.len() > 0
521        && let Some(first) = s.chars().next()
522        && let Some(i_opener) = openers
523            .iter()
524            .enumerate()
525            .find_map(|(i, opener)| if opener == &first { Some(i) } else { None })
526        && let Some(last) = s.chars().last()
527        && let Some(i_closer) = closers
528            .iter()
529            .enumerate()
530            .find_map(|(i, closer)| if closer == &last { Some(i) } else { None })
531        && i_opener == i_closer
532    {
533        // let last = s.chars().last().unwrap();
534        // let closer = closers[i_opener];
535        //
536        // if closer != last {
537        //     return Err(ParseExprError::BracketMismatch(openers[i_opener], last));
538        // }
539        return parse_expr(&s[1..s.len() - 1]);
540    }
541    // Powers
542    else if s.contains("^") {
543        Box::new(s.parse::<Pow>()?)
544    }
545    // Symbols
546    else {
547        Box::new(s.parse::<Symbol>()?)
548    })
549}
550
551const openers: [char; 3] = ['(', '[', '{'];
552const closers: [char; 3] = [')', ']', '}'];
553
554pub struct RootSplitter<'a, 'b> {
555    s: &'a str,
556    patterns: &'b [char],
557    position: usize,
558    prev_splitter: Option<char>,
559    depth: i32,
560    begin: usize,
561}
562
563impl<'a, 'b> Iterator for RootSplitter<'a, 'b> {
564    type Item = (Option<char>, &'a str);
565
566    fn next(&mut self) -> Option<Self::Item> {
567        for (i, c) in self.s[self.position..].char_indices() {
568            let abs_i = self.position + i; // absolute index with respect to the original string
569
570            if openers.contains(&c) {
571                self.depth += 1;
572            } else if closers.contains(&c) {
573                self.depth -= 1;
574            } else if self.depth == 0 && self.patterns.contains(&c) {
575                let part = &self.s[self.begin..abs_i];
576                // Avoid returning empty parts
577                if part.trim().is_empty() {
578                    continue;
579                }
580                self.begin = abs_i + 1; // Start after the current pattern
581                self.position = abs_i + 1;
582                let res = (self.prev_splitter, part.trim());
583                self.prev_splitter = Some(c);
584                return Some(res);
585            }
586        }
587
588        // For the last segment (after the last pattern)
589        if self.begin < self.s.len() {
590            let part = &self.s[self.begin..];
591            self.begin = self.s.len(); // Make sure next call returns None
592            return Some((self.prev_splitter, part.trim()));
593        }
594
595        None // Return None to indicate the end of the iterator
596    }
597}
598
599pub fn split_root<'a, 'b>(s: &'a str, patterns: &'b [char]) -> RootSplitter<'a, 'b> {
600    RootSplitter {
601        s,
602        prev_splitter: None,
603        patterns,
604        position: 0,
605        depth: 0,
606        begin: 0,
607    }
608}
609
610#[cfg(test)]
611mod tests {
612    use super::*;
613    use crate::symbols;
614
615    #[test]
616    fn test_root_splitter() {
617        assert_eq!(
618            split_root("a + (b + c) + 2 - (4)", &['+', '-']).collect::<Vec<_>>(),
619            vec![
620                (None, "a"),
621                (Some('+'), "(b + c)"),
622                (Some('+'), "2"),
623                (Some('-'), "(4)")
624            ]
625        )
626    }
627
628    #[test]
629    fn test_parse_zero() {
630        let expr = parse_expr("0").unwrap();
631        assert_eq!(expr.srepr(), "Integer(0)")
632    }
633
634    #[test]
635    fn test_parse_int() {
636        let expr = parse_expr("1").unwrap();
637        assert_eq!(expr.srepr(), "Integer(1)")
638    }
639
640    #[test]
641    fn test_parse_neg_int() {
642        let expr = parse_expr("-128").unwrap();
643        assert_eq!(expr.srepr(), "Integer(-128)")
644    }
645
646    #[test]
647    fn test_parse_laplacian() {
648        let expr = parse_expr("laplacian").unwrap();
649        assert_eq!(expr.srepr(), "Symbol(Δ)")
650    }
651
652    #[test]
653    fn test_parse_x() {
654        let expr = parse_expr("x").unwrap();
655        assert_eq!(expr.srepr(), "Symbol(x)")
656    }
657
658    #[test]
659    fn test_parse_invalid_equation() {
660        let res = parse_expr("1 ==");
661        assert_eq!(
662            res,
663            Err(ParseExprError::BadEquation(
664                ParseEquationError::WrongNumberOfOperands(3)
665            ))
666        )
667    }
668
669    #[test]
670    fn test_parse_bad_eq_empty_op() {
671        let res = parse_expr("1 =");
672        assert_eq!(
673            res,
674            Err(ParseExprError::BadEquation(
675                ParseEquationError::EmptyOperand
676            ))
677        )
678    }
679
680    #[test]
681    fn parse_valid_basic_eq() {
682        let res = parse_expr("1 = 2").unwrap();
683        assert_eq!(res.srepr(), "Eq(Integer(1), Integer(2))")
684    }
685
686    #[test]
687    fn parse_add() {
688        let res = parse_expr("1 + 2").unwrap();
689        assert_eq!(res.srepr(), "Add(Integer(1), Integer(2))")
690    }
691
692    #[test]
693    fn parse_sub() {
694        let res = parse_expr("1 - x + 4").unwrap();
695        assert_eq!(
696            res.srepr(),
697            "Add(Integer(1), Mul(Integer(-1), Symbol(x)), Integer(4))"
698        )
699    }
700
701    #[test]
702    fn parse_mul() {
703        let res = parse_expr("1 * x * 4").unwrap();
704        assert_eq!(res.srepr(), "Mul(Integer(1), Symbol(x), Integer(4))")
705    }
706
707    #[test]
708    fn parse_div() {
709        let res = parse_expr("1 / x").unwrap();
710        assert_eq!(res.srepr(), "Mul(Integer(1), Pow(Symbol(x), Integer(-1)))")
711    }
712
713    #[test]
714    fn parse_deep_add() {
715        let res = parse_expr("1 + (1 + 2) * 3 + 4").unwrap();
716        assert_eq!(
717            res.srepr(),
718            "Add(Integer(1), Mul(Add(Integer(1), Integer(2)), Integer(3)), Integer(4))"
719        )
720    }
721
722    #[test]
723    fn parse_wave_eq() {
724        let res = parse_expr("diff(u, t, 2) - c^2 * laplacian * u = f").unwrap();
725        let [u, c, laplacian, f] = symbols!("u", "c", "laplacian", "f");
726        let expected = Equation::new_box(u.diff("t", 2) - c.ipow(2) * laplacian * u, f.clone_box());
727        assert_eq!(res, expected)
728    }
729
730    #[test]
731    fn parse_2d_wave_eq() {
732        let res = parse_expr("d2u/dt^2 = c^2 * (d2u/dx2 + d2u/dy2) + source").unwrap();
733        let [u, c, source] = symbols!("u", "c", "source");
734        let expected = Equation::new_box(
735            u.diff("t", 2),
736            c * c * (u.diff("x", 2) + u.diff("y", 2)) + source.clone_box(),
737        );
738        assert_eq!(res, expected)
739    }
740
741    #[test]
742    fn parse_diff_complex() {
743        let res: Box<dyn Expr> = "d^2(2*x*t + t^2 - t)/dt^2".parse().unwrap();
744        let [x, t] = symbols!("x", "t");
745        let expected = (Integer::new_box(2) * x * t + t * t - t.clone_box()).diff("t", 2);
746        assert_eq!(res, expected)
747    }
748
749    #[test]
750    fn parse_dx_syntax() {
751        let res = parse_expr("dx(dx(x))").unwrap();
752        let [x] = symbols!("x");
753        let expected = x.diff("x", 2);
754        assert_eq!(res, expected)
755    }
756
757    #[test]
758    fn parse_dx_dy_syntax() {
759        let res = parse_expr("dx(dy(x))").unwrap();
760        let [x, y] = symbols!("x", "y");
761        let expected = Diff::new(&x.clone_box(), &[x.clone_box(), y.clone_box()]);
762        assert_eq!(res, expected)
763    }
764
765    #[test]
766    fn parse_d2_dt2_syntax() {
767        let res = parse_expr("d2_dt2(u)").unwrap();
768        let [u] = symbols!("u");
769        let expected = u.diff("t", 2);
770        assert_eq!(res, expected)
771    }
772
773    #[test]
774    fn parse_d2u_dt2_syntax() {
775        let res = parse_expr("d2u_dt2").unwrap();
776        let [u] = symbols!("u");
777        let expected = u.diff("t", 2);
778        assert_eq!(res, expected)
779    }
780
781    #[test]
782    fn parse_gaussian_pulse() {
783        let res = parse_expr("exp(-100*((x-5)^2 + (y-5)^2))").unwrap();
784        let [x, y] = symbols!("x", "y");
785
786        let expected = Func::new_move_box(
787            "exp".into(),
788            vec![
789                Integer::new_box(-100)
790                    * ((x - Integer::new_box(5).get_ref()).ipow(2)
791                        + (y - Integer::new_box(5).get_ref()).ipow(2)),
792            ],
793        );
794        assert_eq!(res.get_ref(), expected.get_ref())
795    }
796
797    #[test]
798    fn parse_brackets_sum() {
799        let res = parse_expr("(1 + 2) + (3 + 4)").unwrap();
800        assert_eq!(
801            res.srepr(),
802            "Add(Add(Integer(1), Integer(2)), Add(Integer(3), Integer(4)))"
803        )
804    }
805
806    #[test]
807    fn parse_rational() {
808        let res = parse_expr("1/2").unwrap();
809        assert_eq!(res, Rational::new_box(1, 2));
810    }
811
812    #[test]
813    fn parse_float() {
814        let res = parse_expr("0.5").unwrap();
815        assert_eq!(res, Rational::new_box(1, 2));
816    }
817
818    #[test]
819    fn parse_d2t_syntax() {
820        let res = parse_expr("d2t(u)").unwrap();
821        let [u] = symbols!("u");
822        let expected = u.diff("t", 2);
823        assert_eq!(res, expected)
824    }
825
826    #[test]
827    fn parse_claud_wave_eq() {
828        let res = parse_expr("d2t(u) = c^2 * (d2x(u) + d2y(u))").unwrap();
829        let [u, c] = symbols!("u", "c");
830        let expected = Equation::new_box(
831            u.diff("t", 2),
832            c.ipow(2) * (u.diff("x", 2) + u.diff("y", 2)),
833        );
834        assert_eq!(res, expected)
835    }
836}