Fix term parsing and finish tests

This commit is contained in:
Patrick Lühne 2020-03-13 02:35:28 +01:00
parent 2907d10148
commit af1ec8a606
Signed by: patrick
GPG Key ID: 05F3611E97A70ABF
1 changed files with 368 additions and 139 deletions

View File

@ -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());