diff --git a/src/parse.rs b/src/parse.rs index cd278a5..d7695a6 100644 --- a/src/parse.rs +++ b/src/parse.rs @@ -4,7 +4,7 @@ mod terms; pub(crate) use helpers::word_boundary; pub use names::{function_or_predicate_name, variable_name}; -pub use terms::{boolean, function, integer, predicate, special_integer, string, variable, +pub use terms::{boolean, function, integer, predicate, special_integer, string, term, variable, variable_declaration}; pub struct Declarations diff --git a/src/parse/terms.rs b/src/parse/terms.rs index 4bcf548..f2cc1ba 100644 --- a/src/parse/terms.rs +++ b/src/parse/terms.rs @@ -5,7 +5,7 @@ use nom:: bytes::complete::{escaped_transform, tag}, character::complete::{digit1, multispace0, none_of}, combinator::{map, map_res, opt, recognize}, - multi::separated_list, + multi::{many1, separated_list}, sequence::{delimited, pair, preceded, terminated}, }; @@ -37,6 +37,23 @@ fn false_(i: &str) -> IResult<&str, crate::Term> )(i) } +fn negative<'i>(i: &'i str, d: &Declarations) -> IResult<&'i str, crate::Term> +{ + map + ( + preceded + ( + terminated + ( + tag("-"), + multispace0, + ), + |i| term_precedence_0(i, d), + ), + |x| crate::Term::negative(Box::new(x)), + )(i) +} + pub fn boolean(i: &str) -> IResult<&str, crate::Term> { alt @@ -149,7 +166,7 @@ pub fn string(i: &str) -> IResult<&str, crate::Term> )(i) } -fn function_or_predicate<'i>(i: &'i str, declarations: &Declarations) +fn function_or_predicate<'i>(i: &'i str, d: &Declarations) -> IResult<&'i str, (&'i str, Option>>)> { pair @@ -173,10 +190,9 @@ fn function_or_predicate<'i>(i: &'i str, declarations: &Declarations) tag(","), multispace0, ), - // TODO: fix map ( - integer, + |i| term(i, d), Box::new, ), ), @@ -190,11 +206,11 @@ fn function_or_predicate<'i>(i: &'i str, declarations: &Declarations) )(i) } -pub fn function<'i>(i: &'i str, declarations: &Declarations) -> IResult<&'i str, crate::Function> +pub fn function<'i>(i: &'i str, d: &Declarations) -> IResult<&'i str, crate::Function> { map ( - |i| function_or_predicate(i, declarations), + |i| function_or_predicate(i, d), |(name, arguments)| { let arguments = match arguments @@ -203,7 +219,7 @@ pub fn function<'i>(i: &'i str, declarations: &Declarations) -> IResult<&'i str, None => vec![], }; - let mut function_declarations = declarations.function_declarations.borrow_mut(); + let mut function_declarations = d.function_declarations.borrow_mut(); let declaration = match function_declarations.iter() .find(|x| x.name == name && x.arity == arguments.len()) @@ -229,11 +245,11 @@ pub fn function<'i>(i: &'i str, declarations: &Declarations) -> IResult<&'i str, )(i) } -pub fn predicate<'i>(i: &'i str, declarations: &Declarations) -> IResult<&'i str, crate::Predicate> +pub fn predicate<'i>(i: &'i str, d: &Declarations) -> IResult<&'i str, crate::Predicate> { map ( - |i| function_or_predicate(i, declarations), + |i| function_or_predicate(i, d), |(name, arguments)| { let arguments = match arguments @@ -242,7 +258,7 @@ pub fn predicate<'i>(i: &'i str, declarations: &Declarations) -> IResult<&'i str None => vec![], }; - let mut predicate_declarations = declarations.predicate_declarations.borrow_mut(); + let mut predicate_declarations = d.predicate_declarations.borrow_mut(); let declaration = match predicate_declarations.iter() .find(|x| x.name == name && x.arity == arguments.len()) @@ -277,15 +293,14 @@ pub fn variable_declaration(i: &str) -> IResult<&str, crate::VariableDeclaration )(i) } -pub fn variable<'i>(i: &'i str, declarations: &Declarations) -> IResult<&'i str, crate::Variable> +pub fn variable<'i>(i: &'i str, d: &Declarations) -> IResult<&'i str, crate::Variable> { map ( variable_name, |name| { - let mut variable_declaration_stack = - declarations.variable_declaration_stack.borrow_mut(); + let mut variable_declaration_stack = d.variable_declaration_stack.borrow_mut(); let declaration = variable_declaration_stack.find_or_create(name); @@ -294,11 +309,310 @@ pub fn variable<'i>(i: &'i str, declarations: &Declarations) -> IResult<&'i str, )(i) } +fn term_parenthesized<'a>(i: &'a str, d: &Declarations) -> IResult<&'a str, crate::Term> +{ + delimited + ( + terminated + ( + tag("("), + multispace0, + ), + |i| term(i, d), + preceded + ( + multispace0, + tag(")"), + ), + )(i) +} + +fn term_precedence_0<'a>(i: &'a str, d: &Declarations) -> IResult<&'a str, crate::Term> +{ + alt + (( + special_integer, + integer, + map + ( + |i| function(i, d), + crate::Term::Function, + ), + string, + map + ( + |i| variable(i, d), + crate::Term::Variable, + ), + |i| term_parenthesized(i, d), + ))(i) +} + +fn term_precedence_1<'a>(i: &'a str, d: &Declarations) -> IResult<&'a str, crate::Term> +{ + alt + (( + |i| negative(i, d), + |i| term_precedence_0(i, d), + ))(i) +} + +fn term_precedence_2<'a>(i: &'a str, d: &Declarations) -> IResult<&'a str, crate::Term> +{ + alt + (( + map + ( + pair + ( + many1 + ( + terminated + ( + |i| term_precedence_1(i, d), + delimited + ( + multispace0, + tag("**"), + multispace0, + ), + ) + ), + |i| term_precedence_1(i, d), + ), + |(arguments, last_argument)| arguments.into_iter().rev().fold(last_argument, + |accumulator, argument| + crate::Term::exponentiate(Box::new(argument), Box::new(accumulator))), + ), + |i| term_precedence_1(i, d), + ))(i) +} + +fn term_precedence_3<'a>(i: &'a str, d: &Declarations) -> IResult<&'a str, crate::Term> +{ + alt + (( + map + ( + pair + ( + |i| term_precedence_2(i, d), + many1 + ( + pair + ( + delimited + ( + multispace0, + alt + (( + tag("*"), + tag("/"), + tag("%"), + )), + multispace0, + ), + |i| term_precedence_2(i, d), + ) + ), + ), + |(first_argument, arguments)| arguments.into_iter().fold(first_argument, + |accumulator, (operator, argument)| + match operator + { + "*" => crate::Term::multiply(Box::new(accumulator), Box::new(argument)), + "/" => crate::Term::divide(Box::new(accumulator), Box::new(argument)), + "%" => crate::Term::modulo(Box::new(accumulator), Box::new(argument)), + // TODO: handle appropriately + _ => panic!("test"), + }) + ), + |i| term_precedence_2(i, d), + ))(i) +} + +fn term_precedence_4<'a>(i: &'a str, d: &Declarations) -> IResult<&'a str, crate::Term> +{ + alt + (( + map + ( + pair + ( + |i| term_precedence_3(i, d), + many1 + ( + pair + ( + delimited + ( + multispace0, + alt + (( + tag("+"), + tag("-"), + )), + multispace0, + ), + |i| term_precedence_3(i, d), + ) + ), + ), + |(first_argument, arguments)| arguments.into_iter().fold(first_argument, + |accumulator, (operator, argument)| + match operator + { + "+" => crate::Term::add(Box::new(accumulator), Box::new(argument)), + "-" => crate::Term::subtract(Box::new(accumulator), Box::new(argument)), + // TODO: handle appropriately + _ => panic!("test"), + }) + ), + |i| term_precedence_3(i, d), + ))(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) +} + #[cfg(test)] mod tests { use crate::parse::*; - use crate::Term; + use crate::{Term, VariableDeclaration, VariableDeclarationStack}; + + /*#[test] + fn parse_binary_operator() + { + 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))); + }*/ + + /*#[test] + fn parse_binary_operation() + { + 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_precedence_2() + { + assert_eq!( + crate::parse::terms::term_precedence_2("1 ** 2 ** 3 ** 4 ** 5", &Declarations::new()), + Ok(("", Term::exponentiate(Box::new(Term::integer(1)), + Box::new(Term::exponentiate(Box::new(Term::integer(2)), + Box::new(Term::exponentiate(Box::new(Term::integer(3)), + Box::new(Term::exponentiate(Box::new(Term::integer(4)), + Box::new(Term::integer(5)))))))))))); + } + + #[test] + fn parse_term_precedence_3() + { + 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)))))); + } + + #[test] + fn parse_term_precedence_4() + { + 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)))))); + } + + #[test] + fn parse_term_precedence_5() + { + 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)))))))); + } #[test] fn parse_boolean() @@ -475,7 +789,7 @@ mod tests assert!(variable(" ", &Declarations::new()).is_err()); let new_variable_declarations = |names: &[&str]| std::rc::Rc::new(names.iter() - .map(|name| std::rc::Rc::new(crate::VariableDeclaration::new(name.to_string()))) + .map(|name| std::rc::Rc::new(VariableDeclaration::new(name.to_string()))) .collect()); let layer_1 = new_variable_declarations(&["A", "B", "X"]); @@ -483,7 +797,7 @@ mod tests let layer_3 = new_variable_declarations(&["E", "F", "Y"]); let layer_4 = new_variable_declarations(&["G", "H", "X"]); - let variable_declaration_stack = crate::VariableDeclarationStack::new(); + let variable_declaration_stack = VariableDeclarationStack::new(); let mut declarations = Declarations::new(); declarations.variable_declaration_stack =