Fix term parsing and finish tests
This commit is contained in:
		@@ -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());
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user