393 lines
8.3 KiB
Rust
393 lines
8.3 KiB
Rust
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)
|
|
}
|
|
|
|
pub fn predicate<'i>(i: &'i str, d: &Declarations) -> IResult<&'i str, crate::Predicate>
|
|
{
|
|
map
|
|
(
|
|
|i| crate::parse::terms::function_or_predicate(i, d),
|
|
|(name, arguments)|
|
|
{
|
|
let arguments = match arguments
|
|
{
|
|
Some(arguments) => arguments,
|
|
None => vec![],
|
|
};
|
|
|
|
let mut predicate_declarations = d.predicate_declarations.borrow_mut();
|
|
|
|
let declaration = match predicate_declarations.iter()
|
|
.find(|x| x.name == name && x.arity == arguments.len())
|
|
{
|
|
Some(declaration) => std::rc::Rc::clone(&declaration),
|
|
None =>
|
|
{
|
|
let declaration = crate::PredicateDeclaration
|
|
{
|
|
name: name.to_string(),
|
|
arity: arguments.len(),
|
|
};
|
|
let declaration = std::rc::Rc::new(declaration);
|
|
|
|
predicate_declarations.insert(std::rc::Rc::clone(&declaration));
|
|
|
|
declaration
|
|
},
|
|
};
|
|
|
|
crate::Predicate::new(declaration, arguments)
|
|
},
|
|
)(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 formula_precedence_0<'a>(i: &'a str, d: &Declarations) -> IResult<&'a str, crate::Formula>
|
|
{
|
|
alt
|
|
((
|
|
boolean,
|
|
map
|
|
(
|
|
|i| predicate(i, d),
|
|
crate::Formula::Predicate,
|
|
),
|
|
// TODO: comparisons
|
|
// TODO: quantified expressions
|
|
// TODO: negation
|
|
|i| formula_parenthesized(i, d),
|
|
))(i)
|
|
}
|
|
|
|
fn formula_precedence_3<'a>(i: &'a str, d: &Declarations) -> IResult<&'a str, crate::Formula>
|
|
{
|
|
alt
|
|
((
|
|
map_res
|
|
(
|
|
separated_list
|
|
(
|
|
delimited
|
|
(
|
|
multispace0,
|
|
terminated
|
|
(
|
|
tag("and"),
|
|
word_boundary,
|
|
),
|
|
multispace0,
|
|
),
|
|
// TODO: fix
|
|
|i| formula_precedence_0(i, d),
|
|
),
|
|
|arguments| -> Result<_, (_, _)>
|
|
{
|
|
if arguments.len() >= 2
|
|
{
|
|
Ok(crate::Formula::and(arguments.into_iter().map(Box::new).collect()))
|
|
}
|
|
else
|
|
{
|
|
Err(nom::error::make_error(i, nom::error::ErrorKind::Many1))
|
|
}
|
|
}
|
|
),
|
|
// TODO: fix
|
|
|i| formula_precedence_0(i, d),
|
|
))(i)
|
|
}
|
|
|
|
fn formula_precedence_4<'a>(i: &'a str, d: &Declarations) -> IResult<&'a str, crate::Formula>
|
|
{
|
|
alt
|
|
((
|
|
map_res
|
|
(
|
|
separated_list
|
|
(
|
|
delimited
|
|
(
|
|
multispace0,
|
|
terminated
|
|
(
|
|
tag("or"),
|
|
word_boundary,
|
|
),
|
|
multispace0,
|
|
),
|
|
|i| formula_precedence_3(i, d),
|
|
),
|
|
|arguments| -> Result<_, (_, _)>
|
|
{
|
|
if arguments.len() >= 2
|
|
{
|
|
Ok(crate::Formula::or(arguments.into_iter().map(Box::new).collect()))
|
|
}
|
|
else
|
|
{
|
|
Err(nom::error::make_error(i, nom::error::ErrorKind::Many1))
|
|
}
|
|
}
|
|
),
|
|
|i| formula_precedence_3(i, d),
|
|
))(i)
|
|
}
|
|
|
|
fn implication_left_to_right<'a>(i: &'a str, d: &Declarations)
|
|
-> IResult<&'a str, crate::Formula>
|
|
{
|
|
alt
|
|
((
|
|
map
|
|
(
|
|
pair
|
|
(
|
|
many1
|
|
(
|
|
terminated
|
|
(
|
|
|i| formula_precedence_4(i, d),
|
|
delimited
|
|
(
|
|
multispace0,
|
|
tag("->"),
|
|
multispace0,
|
|
),
|
|
)
|
|
),
|
|
|i| formula_precedence_4(i, d),
|
|
),
|
|
|(arguments, last_argument)| arguments.into_iter().rev().fold(last_argument,
|
|
|accumulator, argument|
|
|
crate::Formula::implies(crate::ImplicationDirection::LeftToRight,
|
|
Box::new(accumulator), Box::new(argument)))
|
|
),
|
|
|i| formula_precedence_4(i, d),
|
|
))(i)
|
|
}
|
|
|
|
fn implication_right_to_left<'a>(i: &'a str, d: &Declarations)
|
|
-> IResult<&'a str, crate::Formula>
|
|
{
|
|
alt
|
|
((
|
|
map
|
|
(
|
|
pair
|
|
(
|
|
|i| formula_precedence_4(i, d),
|
|
many1
|
|
(
|
|
preceded
|
|
(
|
|
delimited
|
|
(
|
|
multispace0,
|
|
tag("<-"),
|
|
multispace0,
|
|
),
|
|
|i| formula_precedence_4(i, d),
|
|
)
|
|
),
|
|
),
|
|
|(first_argument, arguments)| arguments.into_iter().fold(first_argument,
|
|
|accumulator, argument|
|
|
crate::Formula::implies(crate::ImplicationDirection::RightToLeft,
|
|
Box::new(accumulator), Box::new(argument)))
|
|
),
|
|
|i| formula_precedence_4(i, d),
|
|
))(i)
|
|
}
|
|
|
|
fn formula_precedence_5<'a>(i: &'a str, d: &Declarations) -> IResult<&'a str, crate::Formula>
|
|
{
|
|
alt
|
|
((
|
|
|i| implication_right_to_left(i, d),
|
|
|i| implication_left_to_right(i, d),
|
|
))(i)
|
|
}
|
|
|
|
fn formula_precedence_6<'a>(i: &'a str, d: &Declarations) -> IResult<&'a str, crate::Formula>
|
|
{
|
|
alt
|
|
((
|
|
map_res
|
|
(
|
|
separated_list
|
|
(
|
|
delimited
|
|
(
|
|
multispace0,
|
|
tag("<->"),
|
|
multispace0,
|
|
),
|
|
|i| formula_precedence_5(i, d),
|
|
),
|
|
|arguments| -> Result<_, (_, _)>
|
|
{
|
|
if arguments.len() >= 2
|
|
{
|
|
Ok(crate::Formula::if_and_only_if(
|
|
arguments.into_iter().map(Box::new).collect()))
|
|
}
|
|
else
|
|
{
|
|
Err(nom::error::make_error(i, nom::error::ErrorKind::Many1))
|
|
}
|
|
}
|
|
),
|
|
|i| formula_precedence_5(i, d),
|
|
))(i)
|
|
}
|
|
|
|
pub fn formula<'a>(i: &'a str, d: &Declarations) -> IResult<&'a str, crate::Formula>
|
|
{
|
|
formula_precedence_6(i, d)
|
|
}
|
|
|
|
#[cfg(test)]
|
|
mod tests
|
|
{
|
|
use crate::parse::formulas::*;
|
|
use crate::{Formula, Term, 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());
|
|
}
|
|
|
|
#[test]
|
|
fn parse_predicate()
|
|
{
|
|
assert_eq!(predicate("s", &Declarations::new())
|
|
.map(|(i, x)| (i, x.declaration.name.clone())),
|
|
Ok(("", "s".to_string())));
|
|
assert_eq!(predicate("s", &Declarations::new())
|
|
.map(|(i, x)| (i, x.declaration.arity)),
|
|
Ok(("", 0)));
|
|
assert_eq!(predicate("s ( )", &Declarations::new())
|
|
.map(|(i, x)| (i, x.declaration.name.clone())),
|
|
Ok(("", "s".to_string())));
|
|
assert_eq!(predicate("s ( )", &Declarations::new())
|
|
.map(|(i, x)| (i, x.declaration.arity)),
|
|
Ok(("", 0)));
|
|
assert_eq!(predicate("s ( 1 , 2 , 3 )", &Declarations::new())
|
|
.map(|(i, x)| (i, x.declaration.name.clone())),
|
|
Ok(("", "s".to_string())));
|
|
assert_eq!(predicate("s ( 1 , 2 , 3 )", &Declarations::new())
|
|
.map(|(i, x)| (i, x.declaration.arity)),
|
|
Ok(("", 3)));
|
|
assert_eq!(predicate("s ( 1 , 2 , 3 )", &Declarations::new())
|
|
.map(|(i, mut x)| (i, x.arguments.remove(0))),
|
|
Ok(("", Box::new(Term::integer(1)))));
|
|
assert_eq!(predicate("s ( 1 , 2 , 3 )", &Declarations::new())
|
|
.map(|(i, mut x)| (i, x.arguments.remove(2))),
|
|
Ok(("", Box::new(Term::integer(3)))));
|
|
assert_eq!(predicate("s ( ), rest", &Declarations::new())
|
|
.map(|(i, x)| (i, x.declaration.name.clone())),
|
|
Ok((", rest", "s".to_string())));
|
|
assert_eq!(predicate("s ( ), rest", &Declarations::new())
|
|
.map(|(i, x)| (i, x.declaration.arity)),
|
|
Ok((", rest", 0)));
|
|
assert_eq!(predicate("s ( 1 , 2 , 3 ), rest", &Declarations::new())
|
|
.map(|(i, x)| (i, x.declaration.name.clone())),
|
|
Ok((", rest", "s".to_string())));
|
|
assert_eq!(predicate("s ( 1 , 2 , 3 ), rest", &Declarations::new())
|
|
.map(|(i, x)| (i, x.declaration.arity)),
|
|
Ok((", rest", 3)));
|
|
}
|
|
}
|