From af1ec8a606fb1577071cd40d01205392dd4cd8f3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Patrick=20L=C3=BChne?= Date: Fri, 13 Mar 2020 02:35:28 +0100 Subject: [PATCH] Fix term parsing and finish tests --- src/parse/terms.rs | 507 ++++++++++++++++++++++++++++++++------------- 1 file changed, 368 insertions(+), 139 deletions(-) diff --git a/src/parse/terms.rs b/src/parse/terms.rs index 19108ed..84ab2e3 100644 --- a/src/parse/terms.rs +++ b/src/parse/terms.rs @@ -48,9 +48,38 @@ fn negative<'i>(i: &'i str, d: &Declarations) -> IResult<&'i str, crate::Term> tag("-"), multispace0, ), - |i| term_precedence_0(i, d), + |i| term_precedence_1(i, d), ), - |x| crate::Term::negative(Box::new(x)), + |x| match x + { + crate::Term::Integer(value) => crate::Term::integer(-value), + crate::Term::UnaryOperation( + crate::UnaryOperation{operator: crate::UnaryOperator::Negative, argument}) + => *argument, + _ => crate::Term::negative(Box::new(x)), + } + )(i) +} + +fn absolute_value<'i>(i: &'i str, d: &Declarations) -> IResult<&'i str, crate::Term> +{ + map + ( + delimited + ( + terminated + ( + tag("|"), + multispace0, + ), + |i| term(i, d), + preceded + ( + multispace0, + tag("|"), + ), + ), + |x| crate::Term::absolute_value(Box::new(x)), )(i) } @@ -331,6 +360,7 @@ fn term_precedence_0<'a>(i: &'a str, d: &Declarations) -> IResult<&'a str, crate { alt (( + boolean, special_integer, integer, map @@ -344,6 +374,7 @@ fn term_precedence_0<'a>(i: &'a str, d: &Declarations) -> IResult<&'a str, crate |i| variable(i, d), crate::Term::Variable, ), + |i| absolute_value(i, d), |i| term_parenthesized(i, d), ))(i) } @@ -472,35 +503,9 @@ fn term_precedence_4<'a>(i: &'a str, d: &Declarations) -> IResult<&'a str, crate ))(i) } -fn term_precedence_5<'a>(i: &'a str, d: &Declarations) -> IResult<&'a str, crate::Term> -{ - alt - (( - map - ( - delimited - ( - terminated - ( - tag("|"), - multispace0, - ), - |i| term_precedence_4(i, d), - preceded - ( - multispace0, - tag("|"), - ), - ), - |argument| crate::Term::absolute_value(Box::new(argument)), - ), - |i| term_precedence_4(i, d), - ))(i) -} - pub fn term<'a>(i: &'a str, d: &Declarations) -> IResult<&'a str, crate::Term> { - term_precedence_5(i, d) + term_precedence_4(i, d) } #[cfg(test)] @@ -509,131 +514,353 @@ mod tests use crate::parse::*; use crate::{Term, VariableDeclaration, VariableDeclarationStack}; - /*#[test] - fn parse_binary_operator() + fn term(i: &str) -> Term { - assert!(binary_operator("+") == Ok(("", BinaryOperator::Add))); - assert!(binary_operator("+ ") == Ok((" ", BinaryOperator::Add))); - assert!(binary_operator("+3") == Ok(("3", BinaryOperator::Add))); - assert!(binary_operator("+ 3") == Ok((" 3", BinaryOperator::Add))); - assert!(binary_operator("+(rest") == Ok(("(rest", BinaryOperator::Add))); - assert!(binary_operator("+ (rest") == Ok((" (rest", BinaryOperator::Add))); - assert!(binary_operator("-") == Ok(("", BinaryOperator::Subtract))); - assert!(binary_operator("- ") == Ok((" ", BinaryOperator::Subtract))); - assert!(binary_operator("-3") == Ok(("3", BinaryOperator::Subtract))); - assert!(binary_operator("- 3") == Ok((" 3", BinaryOperator::Subtract))); - assert!(binary_operator("-(rest") == Ok(("(rest", BinaryOperator::Subtract))); - assert!(binary_operator("- (rest") == Ok((" (rest", BinaryOperator::Subtract))); - assert!(binary_operator("*") == Ok(("", BinaryOperator::Multiply))); - assert!(binary_operator("* ") == Ok((" ", BinaryOperator::Multiply))); - assert!(binary_operator("*3") == Ok(("3", BinaryOperator::Multiply))); - assert!(binary_operator("* 3") == Ok((" 3", BinaryOperator::Multiply))); - assert!(binary_operator("*(rest") == Ok(("(rest", BinaryOperator::Multiply))); - assert!(binary_operator("* (rest") == Ok((" (rest", BinaryOperator::Multiply))); - assert!(binary_operator("/") == Ok(("", BinaryOperator::Divide))); - assert!(binary_operator("/ ") == Ok((" ", BinaryOperator::Divide))); - assert!(binary_operator("/3") == Ok(("3", BinaryOperator::Divide))); - assert!(binary_operator("/ 3") == Ok((" 3", BinaryOperator::Divide))); - assert!(binary_operator("/(rest") == Ok(("(rest", BinaryOperator::Divide))); - assert!(binary_operator("/ (rest") == Ok((" (rest", BinaryOperator::Divide))); - assert!(binary_operator("%") == Ok(("", BinaryOperator::Modulo))); - assert!(binary_operator("% ") == Ok((" ", BinaryOperator::Modulo))); - assert!(binary_operator("%3") == Ok(("3", BinaryOperator::Modulo))); - assert!(binary_operator("% 3") == Ok((" 3", BinaryOperator::Modulo))); - assert!(binary_operator("%(rest") == Ok(("(rest", BinaryOperator::Modulo))); - assert!(binary_operator("% (rest") == Ok((" (rest", BinaryOperator::Modulo))); - assert!(binary_operator("**") == Ok(("", BinaryOperator::Exponentiate))); - assert!(binary_operator("** ") == Ok((" ", BinaryOperator::Exponentiate))); - assert!(binary_operator("**3") == Ok(("3", BinaryOperator::Exponentiate))); - assert!(binary_operator("** 3") == Ok((" 3", BinaryOperator::Exponentiate))); - assert!(binary_operator("**(rest") == Ok(("(rest", BinaryOperator::Exponentiate))); - assert!(binary_operator("** (rest") == Ok((" (rest", BinaryOperator::Exponentiate))); - }*/ + crate::parse::term(i, &Declarations::new()).unwrap().1 + } - /*#[test] - fn parse_binary_operation() + fn format_term(i: &str) -> String { - assert_eq!(binary_operation("4 + 5", Declarations::new()), - Ok(("", Term::add(Box::new(Term::integer(4)), Box::new(Term::integer(5)))))); - assert_eq!(binary_operation("4 + 5 + 7", Declarations::new()), - Ok(("", Term::add(Box::new(Term::integer(4)), Box::new(Term::integer(5)))))); - }*/ - - #[test] - fn parse_term() - { - let (rest, e1) = term("1 ** 2 ** 3 ** 4 ** 5, rest", &Declarations::new()).unwrap(); - assert_eq!(rest, ", rest"); - assert_eq!(format!("{}", e1), "1 ** 2 ** 3 ** 4 ** 5"); - - let (rest, e2) = term("1 ** (2 ** (3 ** (4 ** 5))), rest", &Declarations::new()).unwrap(); - assert_eq!(rest, ", rest"); - assert_eq!(format!("{}", e2), "1 ** 2 ** 3 ** 4 ** 5"); - - let (rest, e3) = term("(((1 ** 2) ** 3) ** 4) ** 5, rest", &Declarations::new()).unwrap(); - assert_eq!(rest, ", rest"); - assert_eq!(format!("{}", e3), "(((1 ** 2) ** 3) ** 4) ** 5"); - - assert_eq!(e1, e2); - assert_ne!(e1, e3); - - let (rest, m1) = term("1 * 2 * 3 * 4 * 5, rest", &Declarations::new()).unwrap(); - assert_eq!(rest, ", rest"); - assert_eq!(format!("{}", m1), "1 * 2 * 3 * 4 * 5"); - - let (rest, m2) = term("1 * (2 * (3 * (4 * 5))), rest", &Declarations::new()).unwrap(); - assert_eq!(rest, ", rest"); - assert_eq!(format!("{}", m2), "1 * 2 * 3 * 4 * 5"); - - let (rest, m3) = term("(((1 * 2) * 3) * 4) * 5, rest", &Declarations::new()).unwrap(); - assert_eq!(rest, ", rest"); - assert_eq!(format!("{}", m3), "1 * 2 * 3 * 4 * 5"); - - assert_eq!(m1, m2); - assert_ne!(m1, m3); + format!("{}", term(i)) } #[test] - fn parse_term_precedence_3() + fn parse_term_parenthesized() { - assert_eq!( - crate::parse::terms::term_precedence_3("1 * 2 / 3 % 4 * 5", &Declarations::new()), - Ok(("", Term::multiply( - Box::new(Term::modulo( - Box::new(Term::divide( - Box::new(Term::multiply( - Box::new(Term::integer(1)), - Box::new(Term::integer(2)))), - Box::new(Term::integer(3)))), - Box::new(Term::integer(4)))), - Box::new(Term::integer(5)))))); + assert_eq!(format_term("(1)"), format_term("1")); + assert_eq!(format_term("((1))"), format_term("1")); + assert_eq!(format_term("(-1)"), format_term("-1")); + assert_eq!(format_term("((-1))"), format_term("-1")); + assert_eq!(format_term("(-(1))"), format_term("-1")); + assert_eq!(format_term("-((1))"), format_term("-1")); + assert_eq!(format_term("(-(-1))"), format_term("1")); + assert_eq!(format_term("-((-1))"), format_term("1")); + assert_eq!(format_term("-(-(1))"), format_term("1")); + assert_eq!(format_term("-(-(-1))"), format_term("-1")); + assert_eq!(format_term("(a)"), format_term("a")); + assert_eq!(format_term("((a))"), format_term("a")); + assert_eq!(format_term("(X)"), format_term("X")); + assert_eq!(format_term("((X))"), format_term("X")); + assert_eq!(format_term("(\"test\")"), format_term("\"test\"")); + assert_eq!(format_term("((\"test\"))"), format_term("\"test\"")); + assert_eq!(format_term("(a ** b)"), format_term("a ** b")); + assert_eq!(format_term("(a * b)"), format_term("a * b")); + assert_eq!(format_term("(a / b)"), format_term("a / b")); + assert_eq!(format_term("(a % b)"), format_term("a % b")); + assert_eq!(format_term("(a + b)"), format_term("a + b")); + assert_eq!(format_term("(a - b)"), format_term("a - b")); + assert_eq!(format_term("((a ** b))"), format_term("a ** b")); + assert_eq!(format_term("((a * b))"), format_term("a * b")); + assert_eq!(format_term("((a / b))"), format_term("a / b")); + assert_eq!(format_term("((a % b))"), format_term("a % b")); + assert_eq!(format_term("((a + b))"), format_term("a + b")); + assert_eq!(format_term("((a - b))"), format_term("a - b")); + assert_eq!(format_term("(f(a, b))"), format_term("f(a, b)")); + assert_eq!(format_term("((f(a, b)))"), format_term("f(a, b)")); + assert_eq!(format_term("f((a), (b))"), format_term("f(a, b)")); + assert_eq!(format_term("f(|-a|)"), format_term("f(|-a|)")); + assert_eq!(format_term("f((|-a|))"), format_term("f(|-a|)")); + assert_eq!(format_term("f((-a))"), format_term("f(-a)")); + assert_eq!(format_term("f(((-a)))"), format_term("f(-a)")); + assert_eq!(format_term("f((a ** b))"), format_term("f(a ** b)")); + assert_eq!(format_term("f((a * b))"), format_term("f(a * b)")); + assert_eq!(format_term("f((a / b))"), format_term("f(a / b)")); + assert_eq!(format_term("f((a % b))"), format_term("f(a % b)")); + assert_eq!(format_term("f((a + b))"), format_term("f(a + b)")); + assert_eq!(format_term("f((a - b))"), format_term("f(a - b)")); + assert_eq!(format_term("f(((a ** b)))"), format_term("f(a ** b)")); + assert_eq!(format_term("f(((a * b)))"), format_term("f(a * b)")); + assert_eq!(format_term("f(((a / b)))"), format_term("f(a / b)")); + assert_eq!(format_term("f(((a % b)))"), format_term("f(a % b)")); + assert_eq!(format_term("f(((a + b)))"), format_term("f(a + b)")); + assert_eq!(format_term("f(((a - b)))"), format_term("f(a - b)")); + assert_eq!(format_term("(|a ** b|)"), format_term("|a ** b|")); + assert_eq!(format_term("|(a ** b)|"), format_term("|a ** b|")); + assert_eq!(format_term("(|(a ** b)|)"), format_term("|a ** b|")); + assert_eq!(format_term("(|a * b|)"), format_term("|a * b|")); + assert_eq!(format_term("|(a * b)|"), format_term("|a * b|")); + assert_eq!(format_term("(|(a * b)|)"), format_term("|a * b|")); + assert_eq!(format_term("(|a / b|)"), format_term("|a / b|")); + assert_eq!(format_term("|(a / b)|"), format_term("|a / b|")); + assert_eq!(format_term("(|(a / b)|)"), format_term("|a / b|")); + assert_eq!(format_term("(|a % b|)"), format_term("|a % b|")); + assert_eq!(format_term("|(a % b)|"), format_term("|a % b|")); + assert_eq!(format_term("(|(a % b)|)"), format_term("|a % b|")); } #[test] - fn parse_term_precedence_4() + fn parse_term_boolean() { - assert_eq!( - crate::parse::terms::term_precedence_4("1 + 2 - 3 + 4 - 5", &Declarations::new()), - Ok(("", Term::subtract( - Box::new(Term::add( - Box::new(Term::subtract( - Box::new(Term::add( - Box::new(Term::integer(1)), - Box::new(Term::integer(2)))), - Box::new(Term::integer(3)))), - Box::new(Term::integer(4)))), - Box::new(Term::integer(5)))))); + assert_eq!(term("true"), Term::true_()); + assert_eq!(term("false"), Term::false_()); } #[test] - fn parse_term_precedence_5() + fn parse_term_integer() { - assert_eq!( - crate::parse::terms::term_precedence_5("|1 + 2|", &Declarations::new()), - Ok(("", Term::absolute_value( - Box::new(Term::add( - Box::new(Term::integer(1)), - Box::new(Term::integer(2)))))))); + assert_eq!(term("0"), Term::integer(0)); + assert_eq!(term("10000"), Term::integer(10000)); + assert_eq!(term("+10000"), Term::integer(10000)); + assert_eq!(term("-10000"), Term::integer(-10000)); + } + + #[test] + fn parse_term_special_integer() + { + assert_eq!(term("#inf"), Term::infimum()); + assert_eq!(term("#sup"), Term::supremum()); + } + + #[test] + fn parse_term_string() + { + assert_eq!(term("\"test 123\""), Term::string("test 123".to_string())); + assert_eq!(term("\"123 test\""), Term::string("123 test".to_string())); + assert_eq!(term("\" test 123 \""), Term::string(" test 123 ".to_string())); + assert_eq!(term("\"test\\n123\""), Term::string("test\n123".to_string())); + assert_eq!(term("\"test\\\"123\""), Term::string("test\"123".to_string())); + assert_eq!(term("\"test\\\"123\\\"\""), Term::string("test\"123\"".to_string())); + assert_eq!(term("\"\\\"test 123\\\"\""), Term::string("\"test 123\"".to_string())); + assert_eq!(term("\"test\\\\123\""), Term::string("test\\123".to_string())); + assert_eq!(term("\"test\\\\123\\\\\""), Term::string("test\\123\\".to_string())); + assert_eq!(term("\"\\\\test 123\\\\\""), Term::string("\\test 123\\".to_string())); + assert_eq!(term("\"test\\n123\""), Term::string("test\n123".to_string())); + assert_eq!(term("\"test\\n123\\n\""), Term::string("test\n123\n".to_string())); + assert_eq!(term("\"\\ntest 123\\n\""), Term::string("\ntest 123\n".to_string())); + assert_eq!(term("\"test\\t123\""), Term::string("test\t123".to_string())); + assert_eq!(term("\"test\\t123\\t\""), Term::string("test\t123\t".to_string())); + assert_eq!(term("\"\\ttest 123\\t\""), Term::string("\ttest 123\t".to_string())); + assert_eq!(term("\"πŸ™‚test 123\""), Term::string("πŸ™‚test 123".to_string())); + assert_eq!(term("\"test πŸ™‚ 123\""), Term::string("test πŸ™‚ 123".to_string())); + assert_eq!(term("\"test 123πŸ™‚\""), Term::string("test 123πŸ™‚".to_string())); + } + + #[test] + fn parse_term_function() + { + let term_as_function = |i| match term(i) + { + Term::Function(function) => function, + _ => panic!("expected function"), + }; + + assert_eq!(term_as_function("s").declaration.name, "s"); + assert_eq!(term_as_function("s").declaration.arity, 0); + assert_eq!(term_as_function("s()").declaration.name, "s"); + assert_eq!(term_as_function("s").declaration.arity, 0); + assert_eq!(term_as_function("s(1, 2, 3)").declaration.name, "s"); + assert_eq!(term_as_function("s(1, 2, 3)").declaration.arity, 3); + assert_eq!(*term_as_function("s(1, 2, 3)").arguments.remove(0), Term::integer(1)); + assert_eq!(*term_as_function("s(1, 2, 3)").arguments.remove(2), Term::integer(3)); + } + + #[test] + fn parse_term_variable() + { + let term_as_variable = |i| match term(i) + { + Term::Variable(variable) => variable, + _ => panic!("expected variable"), + }; + + assert_eq!(term_as_variable("X").declaration.name, "X"); + assert_eq!(term_as_variable("Variable_123").declaration.name, "Variable_123"); + } + + #[test] + fn parse_term_unary() + { + assert_eq!(format_term("|a|"), "|a|"); + assert_eq!(format_term("||a||"), "||a||"); + assert_eq!(format_term("|a - b|"), "|a - b|"); + assert_eq!(format_term("|a| - b"), "|a| - b"); + assert_eq!(format_term("a - |b|"), "a - |b|"); + assert_eq!(format_term("||a| - b|"), "||a| - b|"); + assert_eq!(format_term("|a - |b||"), "|a - |b||"); + assert_eq!(format_term("||a| - |b||"), "||a| - |b||"); + assert_eq!(format_term("||a| - |b| - |c||"), "||a| - |b| - |c||"); + assert_eq!(format_term("||a - b| - |c - d||"), "||a - b| - |c - d||"); + assert_eq!(format_term("-a"), "-a"); + assert_eq!(format_term("--a"), "a"); + assert_eq!(format_term("---a"), "-a"); + assert_eq!(format_term("-(a + b)"), "-(a + b)"); + assert_eq!(format_term("-|a + b|"), "-|a + b|"); + assert_eq!(format_term("--|a + b|"), "|a + b|"); + assert_eq!(format_term("---|a + b|"), "-|a + b|"); + assert_eq!(term("5"), Term::integer(5)); + assert_eq!(term("-5"), Term::integer(-5)); + assert_eq!(term("--5"), Term::integer(5)); + assert_eq!(term("---5"), Term::integer(-5)); + assert_eq!(term("0"), Term::integer(0)); + assert_eq!(term("-0"), Term::integer(0)); + assert_eq!(term("--0"), Term::integer(0)); + assert_eq!(term("---0"), Term::integer(0)); + } + + #[test] + fn parse_term_exponentiate() + { + assert_eq!(term("1 ** (2 ** (3 ** (4 ** 5)))"), term("1 ** 2 ** 3 ** 4 ** 5")); + assert_eq!(format_term("1 ** 2 ** 3 ** 4 ** 5"), "1 ** 2 ** 3 ** 4 ** 5"); + assert_eq!(term("1 ** (2 ** (3 ** (4 ** 5)))"), term("1 ** 2 ** 3 ** 4 ** 5")); + // As exponentiation is right-associative, these parentheses cannot be omitted + assert_ne!(term("(((1 ** 2) ** 3) ** 4) ** 5"), term("1 ** 2 ** 3 ** 4 ** 5")); + assert_eq!(format_term("(((1 ** 2) ** 3) ** 4) ** 5"), "(((1 ** 2) ** 3) ** 4) ** 5"); + } + + #[test] + fn parse_term_multiplicative() + { + assert_eq!(format_term("(a * b) * (c * d)"), "a * b * c * d"); + assert_eq!(format_term("(a * b) * (c / d)"), "a * b * c / d"); + assert_eq!(format_term("(a * b) * (c % d)"), "a * b * (c % d)"); + assert_eq!(format_term("(a / b) * (c * d)"), "a / b * c * d"); + assert_eq!(format_term("(a / b) * (c / d)"), "a / b * c / d"); + assert_eq!(format_term("(a / b) * (c % d)"), "a / b * (c % d)"); + assert_eq!(format_term("(a % b) * (c * d)"), "a % b * c * d"); + assert_eq!(format_term("(a % b) * (c / d)"), "a % b * c / d"); + assert_eq!(format_term("(a % b) * (c % d)"), "a % b * (c % d)"); + assert_eq!(format_term("(a * b) / (c * d)"), "a * b / (c * d)"); + assert_eq!(format_term("(a * b) / (c / d)"), "a * b / (c / d)"); + assert_eq!(format_term("(a * b) / (c % d)"), "a * b / (c % d)"); + assert_eq!(format_term("(a / b) / (c * d)"), "a / b / (c * d)"); + assert_eq!(format_term("(a / b) / (c / d)"), "a / b / (c / d)"); + assert_eq!(format_term("(a / b) / (c % d)"), "a / b / (c % d)"); + assert_eq!(format_term("(a % b) / (c * d)"), "a % b / (c * d)"); + assert_eq!(format_term("(a % b) / (c / d)"), "a % b / (c / d)"); + assert_eq!(format_term("(a % b) / (c % d)"), "a % b / (c % d)"); + assert_eq!(format_term("(a * b) % (c * d)"), "a * b % (c * d)"); + assert_eq!(format_term("(a * b) % (c / d)"), "a * b % (c / d)"); + assert_eq!(format_term("(a * b) % (c % d)"), "a * b % (c % d)"); + assert_eq!(format_term("(a / b) % (c * d)"), "a / b % (c * d)"); + assert_eq!(format_term("(a / b) % (c / d)"), "a / b % (c / d)"); + assert_eq!(format_term("(a / b) % (c % d)"), "a / b % (c % d)"); + assert_eq!(format_term("(a % b) % (c * d)"), "a % b % (c * d)"); + assert_eq!(format_term("(a % b) % (c / d)"), "a % b % (c / d)"); + assert_eq!(format_term("(a % b) % (c % d)"), "a % b % (c % d)"); + } + + #[test] + fn parse_term_additive() + { + assert_eq!(format_term("(a + b) + (c + d)"), "a + b + c + d"); + assert_eq!(format_term("(a + b) + (c - d)"), "a + b + c - d"); + assert_eq!(format_term("(a - b) + (c + d)"), "a - b + c + d"); + assert_eq!(format_term("(a - b) + (c - d)"), "a - b + c - d"); + assert_eq!(format_term("(a + b) - (c + d)"), "a + b - (c + d)"); + assert_eq!(format_term("(a + b) - (c - d)"), "a + b - (c - d)"); + assert_eq!(format_term("(a - b) - (c + d)"), "a - b - (c + d)"); + assert_eq!(format_term("(a - b) - (c - d)"), "a - b - (c - d)"); + } + + #[test] + fn parse_term_precedence() + { + assert_eq!(term("-a + b"), term("(-a) + b")); + assert_eq!(term("-a + -b"), term("(-a) + (-b)")); + assert_eq!(term("-a + -b"), term("-(a) + -(b)")); + assert_eq!(format_term("-(a + b)"), "-(a + b)"); + assert_eq!(term("-a - b"), term("(-a) - b")); + assert_eq!(term("-a - -b"), term("(-a) - (-b)")); + assert_eq!(term("-a - -b"), term("-(a) - -(b)")); + assert_eq!(term("-a * b"), term("(-a) * b")); + assert_eq!(term("-a * -b"), term("(-a) * (-b)")); + assert_eq!(term("-a * -b"), term("-(a) * -(b)")); + assert_eq!(term("-a / b"), term("(-a) / b")); + assert_eq!(term("-a / -b"), term("(-a) / (-b)")); + assert_eq!(term("-a / -b"), term("-(a) / -(b)")); + assert_eq!(term("-a % b"), term("(-a) % b")); + assert_eq!(term("-a % -b"), term("(-a) % (-b)")); + assert_eq!(term("-a % -b"), term("-(a) % -(b)")); + assert_eq!(term("-a ** b"), term("(-a) ** b")); + assert_eq!(term("-a ** -b"), term("(-a) ** (-b)")); + assert_eq!(term("-a ** -b"), term("-(a) ** -(b)")); + assert_eq!(format_term("-(a + b)"), "-(a + b)"); + assert_eq!(format_term("-(a + b)"), "-(a + b)"); + assert_eq!(format_term("-(a + b)"), "-(a + b)"); + assert_eq!(format_term("-(a + b)"), "-(a + b)"); + assert_eq!(format_term("-(a + b)"), "-(a + b)"); + assert_eq!(term("a + (b * c) + d"), term("(a + (b * c)) + d")); + assert_eq!(term("a + (b / c) + d"), term("(a + (b / c)) + d")); + assert_eq!(term("a + (b % c) + d"), term("(a + (b % c)) + d")); + assert_eq!(term("a - (b * c) - d"), term("(a - (b * c)) - d")); + assert_eq!(term("a - (b / c) - d"), term("(a - (b / c)) - d")); + assert_eq!(term("a - (b % c) - d"), term("(a - (b % c)) - d")); + assert_eq!(format_term("(a + b) * (c + d)"), "(a + b) * (c + d)"); + assert_eq!(format_term("(a + b) / (c + d)"), "(a + b) / (c + d)"); + assert_eq!(format_term("(a + b) % (c + d)"), "(a + b) % (c + d)"); + assert_eq!(format_term("(a - b) * (c - d)"), "(a - b) * (c - d)"); + assert_eq!(format_term("(a - b) / (c - d)"), "(a - b) / (c - d)"); + assert_eq!(format_term("(a - b) % (c - d)"), "(a - b) % (c - d)"); + assert_eq!(term("a ** b ** c + d ** e ** f"), term("(a ** b ** c) + (d ** e ** f)")); + assert_eq!(term("a ** (b ** c + d) ** e ** f"), term("a ** ((b ** c + d) ** (e ** f))")); + assert_eq!(term("a ** b ** (c + d) ** e ** f"), term("a ** (b ** ((c + d) ** (e ** f)))")); + assert_eq!(term("a ** b ** (c + d ** e) ** f"), term("a ** (b ** ((c + d ** e) ** f))")); + assert_eq!(term("a ** b ** c - d ** e ** f"), term("(a ** b ** c) - (d ** e ** f)")); + assert_eq!(term("a ** (b ** c - d) ** e ** f"), term("a ** ((b ** c - d) ** (e ** f))")); + assert_eq!(term("a ** b ** (c - d) ** e ** f"), term("a ** (b ** ((c - d) ** (e ** f)))")); + assert_eq!(term("a ** b ** (c - d ** e) ** f"), term("a ** (b ** ((c - d ** e) ** f))")); + assert_eq!(term("a ** b ** c * d ** e ** f"), term("(a ** b ** c) * (d ** e ** f)")); + assert_eq!(term("a ** (b ** c * d) ** e ** f"), term("a ** ((b ** c * d) ** (e ** f))")); + assert_eq!(term("a ** b ** (c * d) ** e ** f"), term("a ** (b ** ((c * d) ** (e ** f)))")); + assert_eq!(term("a ** b ** (c * d ** e) ** f"), term("a ** (b ** ((c * d ** e) ** f))")); + assert_eq!(term("a ** b ** c / d ** e ** f"), term("(a ** b ** c) / (d ** e ** f)")); + assert_eq!(term("a ** (b ** c / d) ** e ** f"), term("a ** ((b ** c / d) ** (e ** f))")); + assert_eq!(term("a ** b ** (c / d) ** e ** f"), term("a ** (b ** ((c / d) ** (e ** f)))")); + assert_eq!(term("a ** b ** (c / d ** e) ** f"), term("a ** (b ** ((c / d ** e) ** f))")); + assert_eq!(term("a ** b ** c % d ** e ** f"), term("(a ** b ** c) % (d ** e ** f)")); + assert_eq!(term("a ** (b ** c % d) ** e ** f"), term("a ** ((b ** c % d) ** (e ** f))")); + assert_eq!(term("a ** b ** (c % d) ** e ** f"), term("a ** (b ** ((c % d) ** (e ** f)))")); + assert_eq!(term("a ** b ** (c % d ** e) ** f"), term("a ** (b ** ((c % d ** e) ** f))")); + } + + #[test] + fn parse_term_bounds() + { + let term = |i| crate::parse::term(i, &Declarations::new()).unwrap().0; + + assert_eq!(term("1 ** 2 ** 3, rest"), ", rest"); + assert_eq!(term("1 * 2 * 3, rest"), ", rest"); + assert_eq!(term("1 / 2 / 3, rest"), ", rest"); + assert_eq!(term("1 % 2 % 3, rest"), ", rest"); + assert_eq!(term("1 + 2 + 3, rest"), ", rest"); + assert_eq!(term("1 - 2 - 3, rest"), ", rest"); + assert_eq!(term("1, rest"), ", rest"); + assert_eq!(term("-1, rest"), ", rest"); + assert_eq!(term("--1, rest"), ", rest"); + assert_eq!(term("|1|, rest"), ", rest"); + assert_eq!(term("|1| + |-2|, rest"), ", rest"); + assert_eq!(term("||-2||, rest"), ", rest"); + assert_eq!(term("|-|-2||, rest"), ", rest"); + assert_eq!(term("(1), rest"), ", rest"); + assert_eq!(term("a, rest"), ", rest"); + assert_eq!(term("1, rest"), ", rest"); + assert_eq!(term("true, rest"), ", rest"); + assert_eq!(term("false, rest"), ", rest"); + assert_eq!(term("#inf, rest"), ", rest"); + assert_eq!(term("#sup, rest"), ", rest"); + assert_eq!(term("f(1, 2), rest"), ", rest"); + assert_eq!(term("g(1 ** 2, 3 * 4, #inf), rest"), ", rest"); + assert_eq!(term("\"test\", rest"), ", rest"); + assert_eq!(term("X, rest"), ", rest"); + assert_eq!(term("Variable, rest"), ", rest"); + assert_eq!(term("f(\"test\", Variable), rest"), ", rest"); + } + + #[test] + fn parse_term_whitespace() + { + assert_eq!(format_term("(a+b)*(c+d)"), "(a + b) * (c + d)"); + assert_eq!(format_term("( a + b ) * ( c + d )"), "(a + b) * (c + d)"); + assert_eq!(format_term("( a + b ) * ( c + d )"), "(a + b) * (c + d)"); + assert_eq!(format_term("(\ta\t+\tb\t)\t*\t(\tc\t+\td\t)"), "(a + b) * (c + d)"); + assert_eq!(format_term("(\na\n+\nb\n)\n*\n(\nc\n+\nd\n)"), "(a + b) * (c + d)"); + assert_eq!(format_term("( \t a \t + \t b \t ) \t * \t ( \t c \t + \t d \t )"), "(a + b) * (c + d)"); + assert_eq!(format_term("( \n a \n + \n b \n ) \n * \n ( \n c \n + \n d \n )"), "(a + b) * (c + d)"); + assert_eq!(format_term("f(\ta\t+\tb\t,\tc\t+\td\t)"), "f(a + b, c + d)"); + assert_eq!(format_term("f(\na\n+\nb\n,\nc\n+\nd\n)"), "f(a + b, c + d)"); + assert_eq!(format_term("f( \t a \t + \t b \t , \t c \t + \t d \t)"), "f(a + b, c + d)"); + assert_eq!(format_term("f( \n a \n + \n b \n , \n c \n + \n d \n)"), "f(a + b, c + d)"); } #[test] @@ -723,6 +950,8 @@ mod tests assert_eq!(string("\"test\\t123\\t\""), Ok(("", Term::string("test\t123\t".to_string())))); assert_eq!(string("\"\\ttest 123\\t\""), Ok(("", Term::string("\ttest 123\t".to_string())))); assert_eq!(string("\"test πŸ™‚ 123\""), Ok(("", Term::string("test πŸ™‚ 123".to_string())))); + assert_eq!(string("\"πŸ™‚test 123\""), Ok(("", Term::string("πŸ™‚test 123".to_string())))); + assert_eq!(string("\"test 123πŸ™‚\""), Ok(("", Term::string("test 123πŸ™‚".to_string())))); assert!(string("\"test 123\"a").is_err()); assert!(string("\"test\\i123\"").is_err()); assert!(string("\"test").is_err());