use nom:: { IResult, branch::alt, bytes::complete::{escaped_transform, tag}, character::complete::{digit1, multispace0, none_of}, combinator::{map, map_res, opt, recognize}, multi::{many1, separated_list}, sequence::{delimited, pair, preceded, terminated}, }; use super::{Declarations, function_or_predicate_name, word_boundary, variable_name}; // TODO: avoid code duplication fn true_(i: &str) -> IResult<&str, crate::Formula> { map ( terminated ( tag("true"), word_boundary, ), |_| crate::Formula::true_(), )(i) } fn false_(i: &str) -> IResult<&str, crate::Formula> { map ( terminated ( tag("false"), word_boundary, ), |_| crate::Formula::false_(), )(i) } pub fn boolean(i: &str) -> IResult<&str, crate::Formula> { alt (( true_, false_, ))(i) } /*fn formula_parenthesized<'a>(i: &'a str, d: &Declarations) -> IResult<&'a str, crate::Formula> { delimited ( terminated ( tag("("), multispace0, ), |i| formula(i, d), preceded ( multispace0, tag(")"), ), )(i) } fn term_precedence_0<'a>(i: &'a str, d: &Declarations) -> IResult<&'a str, crate::Term> { alt (( boolean, special_integer, integer, map ( |i| function(i, d), crate::Term::Function, ), string, map ( |i| variable(i, d), crate::Term::Variable, ), |i| absolute_value(i, d), |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) } pub fn formula<'a>(i: &'a str, d: &Declarations) -> IResult<&'a str, crate::Formula> { formula_precedence_4(i, d) }*/ #[cfg(test)] mod tests { use crate::parse::formulas::*; use crate::{Formula, VariableDeclaration, VariableDeclarationStack}; /*fn formula(i: &str) -> Formula { crate::parse::formula(i, &Declarations::new()).unwrap().1 } fn format_formula(i: &str) -> String { format!("{}", formula(i)) } #[test] fn parse_formula_boolean() { assert_eq!(formula("true"), Formula::true_()); assert_eq!(formula("false"), Formula::false_()); }*/ #[test] fn parse_boolean() { assert_eq!(boolean("true"), Ok(("", Formula::true_()))); assert_eq!(boolean("false"), Ok(("", Formula::false_()))); assert_eq!(boolean("true false"), Ok((" false", Formula::true_()))); assert_eq!(boolean("false true"), Ok((" true", Formula::false_()))); assert_eq!(boolean("true,"), Ok((",", Formula::true_()))); assert_eq!(boolean("false,"), Ok((",", Formula::false_()))); assert!(boolean("truefalse").is_err()); assert!(boolean("falsetrue").is_err()); assert!(boolean("truea").is_err()); assert!(boolean("falsea").is_err()); assert!(boolean("a").is_err()); assert!(boolean("-").is_err()); assert!(boolean(" ").is_err()); } }