symrs/expr/ops/
parse.rs

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