2020-04-22 20:01:29 +02:00
|
|
|
|
use super::tokens::*;
|
2020-02-25 15:36:34 +01:00
|
|
|
|
|
2020-04-22 20:01:29 +02:00
|
|
|
|
pub fn parse_formula(input: &str) -> Result<crate::Formula, crate::parse::Error>
|
|
|
|
|
{
|
|
|
|
|
let formula_str = FormulaStr::new(input);
|
|
|
|
|
formula_str.parse(0)?;
|
2020-02-25 15:36:34 +01:00
|
|
|
|
|
2020-04-22 20:01:29 +02:00
|
|
|
|
// TODO: implement correctly
|
|
|
|
|
Ok(crate::Formula::true_())
|
2020-02-25 15:36:34 +01:00
|
|
|
|
}
|
|
|
|
|
|
2020-04-22 20:01:29 +02:00
|
|
|
|
#[derive(Clone, Copy, Eq, PartialEq)]
|
|
|
|
|
enum FormulaInfixOperator
|
2020-02-25 15:36:34 +01:00
|
|
|
|
{
|
2020-04-22 20:01:29 +02:00
|
|
|
|
And,
|
|
|
|
|
IfAndOnlyIf,
|
|
|
|
|
ImpliesLeftToRight,
|
|
|
|
|
ImpliesRightToLeft,
|
|
|
|
|
Or,
|
2020-02-25 15:36:34 +01:00
|
|
|
|
}
|
|
|
|
|
|
2020-04-22 20:01:29 +02:00
|
|
|
|
impl FormulaInfixOperator
|
2020-02-25 15:36:34 +01:00
|
|
|
|
{
|
2020-04-22 20:01:29 +02:00
|
|
|
|
fn level(&self) -> usize
|
|
|
|
|
{
|
|
|
|
|
match self
|
2020-02-25 15:36:34 +01:00
|
|
|
|
{
|
2020-04-22 20:01:29 +02:00
|
|
|
|
Self::And => 1,
|
|
|
|
|
Self::Or => 2,
|
|
|
|
|
Self::ImpliesLeftToRight
|
|
|
|
|
| Self::ImpliesRightToLeft => 3,
|
|
|
|
|
Self::IfAndOnlyIf => 4,
|
2020-02-25 15:36:34 +01:00
|
|
|
|
}
|
2020-04-22 20:01:29 +02:00
|
|
|
|
}
|
2020-02-25 15:36:34 +01:00
|
|
|
|
}
|
|
|
|
|
|
2020-04-22 20:01:29 +02:00
|
|
|
|
impl std::fmt::Debug for FormulaInfixOperator
|
2020-02-25 15:36:34 +01:00
|
|
|
|
{
|
2020-04-22 20:01:29 +02:00
|
|
|
|
fn fmt(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result
|
|
|
|
|
{
|
|
|
|
|
match &self
|
2020-02-25 15:36:34 +01:00
|
|
|
|
{
|
2020-04-22 20:01:29 +02:00
|
|
|
|
Self::And => write!(formatter, "and"),
|
|
|
|
|
Self::IfAndOnlyIf => write!(formatter, "<->"),
|
|
|
|
|
Self::ImpliesLeftToRight => write!(formatter, "->"),
|
|
|
|
|
Self::ImpliesRightToLeft => write!(formatter, "<-"),
|
|
|
|
|
Self::Or => write!(formatter, "or"),
|
2020-02-25 15:36:34 +01:00
|
|
|
|
}
|
2020-04-22 20:01:29 +02:00
|
|
|
|
}
|
2020-02-25 15:36:34 +01:00
|
|
|
|
}
|
|
|
|
|
|
2020-04-22 20:01:29 +02:00
|
|
|
|
struct FormulaStr<'i>
|
2020-02-25 15:36:34 +01:00
|
|
|
|
{
|
2020-04-22 20:01:29 +02:00
|
|
|
|
input: &'i str,
|
2020-02-25 15:36:34 +01:00
|
|
|
|
}
|
|
|
|
|
|
2020-04-22 20:01:29 +02:00
|
|
|
|
impl<'i> FormulaStr<'i>
|
2020-02-25 15:36:34 +01:00
|
|
|
|
{
|
2020-04-22 20:01:29 +02:00
|
|
|
|
pub fn new(input: &'i str) -> Self
|
|
|
|
|
{
|
|
|
|
|
Self
|
|
|
|
|
{
|
|
|
|
|
input,
|
|
|
|
|
}
|
|
|
|
|
}
|
2020-02-25 15:36:34 +01:00
|
|
|
|
|
2020-04-22 20:01:29 +02:00
|
|
|
|
pub fn top_level_infix_operator(&self)
|
|
|
|
|
-> Result<Option<FormulaInfixOperator>, crate::parse::Error>
|
|
|
|
|
{
|
|
|
|
|
let mut top_level_infix_operator = None;
|
|
|
|
|
|
|
|
|
|
for infix_operator in self.iter_infix_operators()
|
2020-02-25 15:36:34 +01:00
|
|
|
|
{
|
2020-04-22 20:01:29 +02:00
|
|
|
|
let (_, _, infix_operator) = infix_operator?;
|
|
|
|
|
|
|
|
|
|
top_level_infix_operator = match top_level_infix_operator
|
2020-02-25 15:36:34 +01:00
|
|
|
|
{
|
2020-04-22 20:01:29 +02:00
|
|
|
|
None => Some(infix_operator),
|
|
|
|
|
Some(top_level_infix_operator) =>
|
|
|
|
|
{
|
|
|
|
|
if (infix_operator == FormulaInfixOperator::ImpliesLeftToRight
|
|
|
|
|
&& top_level_infix_operator == FormulaInfixOperator::ImpliesRightToLeft)
|
|
|
|
|
|| (infix_operator == FormulaInfixOperator::ImpliesRightToLeft
|
|
|
|
|
&& top_level_infix_operator == FormulaInfixOperator::ImpliesLeftToRight)
|
|
|
|
|
{
|
|
|
|
|
return Err(crate::parse::Error::new_mixed_implication_directions(
|
|
|
|
|
crate::parse::error::Location::new(0, Some(0)),
|
|
|
|
|
crate::parse::error::Location::new(0, Some(0))));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if infix_operator.level() > top_level_infix_operator.level()
|
|
|
|
|
{
|
|
|
|
|
Some(infix_operator)
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
Some(top_level_infix_operator)
|
|
|
|
|
}
|
|
|
|
|
},
|
2020-02-25 15:36:34 +01:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2020-04-22 20:01:29 +02:00
|
|
|
|
Ok(top_level_infix_operator)
|
|
|
|
|
}
|
2020-02-25 15:36:34 +01:00
|
|
|
|
|
2020-04-22 20:01:29 +02:00
|
|
|
|
pub fn iter_infix_operators(&self) -> FormulaInfixOperatorIterator<'i>
|
|
|
|
|
{
|
|
|
|
|
FormulaInfixOperatorIterator::new(self.input)
|
|
|
|
|
}
|
2020-02-25 15:36:34 +01:00
|
|
|
|
|
2020-04-22 20:01:29 +02:00
|
|
|
|
pub fn split_at_infix_operator(&self, infix_operator: FormulaInfixOperator)
|
|
|
|
|
-> SplitFormulaAtInfixOperator<'i>
|
|
|
|
|
{
|
|
|
|
|
SplitFormulaAtInfixOperator::new(self, infix_operator)
|
|
|
|
|
}
|
2020-02-25 15:36:34 +01:00
|
|
|
|
|
2020-04-22 20:01:29 +02:00
|
|
|
|
pub fn parse(&self, level: usize) -> Result<(), crate::parse::Error>
|
|
|
|
|
{
|
|
|
|
|
let indentation = " ".repeat(level);
|
|
|
|
|
println!("{}- parsing: {}", indentation, self.input);
|
2020-02-25 15:36:34 +01:00
|
|
|
|
|
2020-04-22 20:01:29 +02:00
|
|
|
|
let input = self.input.trim_start();
|
2020-02-25 15:36:34 +01:00
|
|
|
|
|
2020-04-22 20:01:29 +02:00
|
|
|
|
match self.top_level_infix_operator()?
|
|
|
|
|
{
|
|
|
|
|
None =>
|
|
|
|
|
{
|
|
|
|
|
if let Some((identifier, _)) = identifier(input)
|
|
|
|
|
{
|
|
|
|
|
match identifier
|
|
|
|
|
{
|
|
|
|
|
"exists" => println!("{} parsing “exists” expression from: {}", indentation, input),
|
|
|
|
|
"forall" => println!("{} parsing “forall” expression from: {}", indentation, input),
|
|
|
|
|
_ => (),
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
println!("{} can’t break down any further: {}", indentation, input)
|
|
|
|
|
},
|
|
|
|
|
Some(top_level_infix_operator) =>
|
|
|
|
|
{
|
|
|
|
|
println!("{} parsing “{:?}” expression from: {}", indentation,
|
|
|
|
|
top_level_infix_operator, input);
|
|
|
|
|
|
|
|
|
|
for subformula in self.split_at_infix_operator(top_level_infix_operator)
|
|
|
|
|
{
|
|
|
|
|
FormulaStr::new(subformula?).parse(level + 1)?;
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
}
|
2020-02-25 15:36:34 +01:00
|
|
|
|
|
2020-04-22 20:01:29 +02:00
|
|
|
|
Ok(())
|
|
|
|
|
}
|
2020-02-25 15:36:34 +01:00
|
|
|
|
}
|
|
|
|
|
|
2020-04-22 20:01:29 +02:00
|
|
|
|
struct FormulaInfixOperatorIterator<'i>
|
2020-02-25 15:36:34 +01:00
|
|
|
|
{
|
2020-04-22 20:01:29 +02:00
|
|
|
|
original_input: &'i str,
|
|
|
|
|
input: &'i str,
|
2020-02-25 15:36:34 +01:00
|
|
|
|
}
|
|
|
|
|
|
2020-04-22 20:01:29 +02:00
|
|
|
|
impl<'i> FormulaInfixOperatorIterator<'i>
|
2020-02-25 15:36:34 +01:00
|
|
|
|
{
|
2020-04-22 20:01:29 +02:00
|
|
|
|
pub fn new(input: &'i str) -> Self
|
|
|
|
|
{
|
|
|
|
|
Self
|
|
|
|
|
{
|
|
|
|
|
original_input: input,
|
|
|
|
|
input,
|
|
|
|
|
}
|
|
|
|
|
}
|
2020-02-25 15:36:34 +01:00
|
|
|
|
}
|
|
|
|
|
|
2020-04-22 20:01:29 +02:00
|
|
|
|
impl<'i> std::iter::Iterator for FormulaInfixOperatorIterator<'i>
|
2020-02-25 15:36:34 +01:00
|
|
|
|
{
|
2020-04-22 20:01:29 +02:00
|
|
|
|
type Item = Result<(&'i str, &'i str, FormulaInfixOperator), crate::parse::Error>;
|
2020-02-25 15:36:34 +01:00
|
|
|
|
|
2020-04-22 20:01:29 +02:00
|
|
|
|
fn next(&mut self) -> Option<Self::Item>
|
|
|
|
|
{
|
|
|
|
|
loop
|
|
|
|
|
{
|
|
|
|
|
self.input = self.input.trim_start();
|
2020-02-25 15:36:34 +01:00
|
|
|
|
|
2020-04-22 20:01:29 +02:00
|
|
|
|
let first_character = match self.input.chars().next()
|
|
|
|
|
{
|
|
|
|
|
None => return None,
|
|
|
|
|
Some(first_character) => first_character,
|
|
|
|
|
};
|
2020-02-25 15:36:34 +01:00
|
|
|
|
|
2020-04-22 20:01:29 +02:00
|
|
|
|
if self.input.starts_with(")")
|
|
|
|
|
{
|
|
|
|
|
return Some(Err(crate::parse::Error::new_unmatched_parenthesis(
|
|
|
|
|
crate::parse::error::Location::new(0, Some(1)))));
|
|
|
|
|
}
|
2020-02-25 15:36:34 +01:00
|
|
|
|
|
2020-04-22 20:01:29 +02:00
|
|
|
|
match parenthesized_expression(self.input)
|
|
|
|
|
{
|
|
|
|
|
Ok(Some((_, remaining_input))) =>
|
|
|
|
|
{
|
|
|
|
|
self.input = remaining_input;
|
|
|
|
|
continue;
|
|
|
|
|
},
|
|
|
|
|
Ok(None) => (),
|
|
|
|
|
Err(error) => return Some(Err(error)),
|
|
|
|
|
}
|
2020-02-25 15:36:34 +01:00
|
|
|
|
|
2020-04-22 20:01:29 +02:00
|
|
|
|
match number(self.input)
|
|
|
|
|
{
|
|
|
|
|
Ok(Some((_, remaining_input))) =>
|
|
|
|
|
{
|
|
|
|
|
self.input = remaining_input;
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
Ok(None) => (),
|
|
|
|
|
Err(error) => return Some(Err(error)),
|
|
|
|
|
}
|
2020-02-25 15:36:34 +01:00
|
|
|
|
|
2020-04-22 20:01:29 +02:00
|
|
|
|
let index_left = self.input.as_ptr() as usize - self.original_input.as_ptr() as usize;
|
|
|
|
|
let input_left = self.original_input.split_at(index_left).0.trim_end();
|
2020-02-25 15:36:34 +01:00
|
|
|
|
|
2020-04-22 20:01:29 +02:00
|
|
|
|
if let Some((identifier, remaining_input)) = identifier(self.input)
|
|
|
|
|
{
|
|
|
|
|
self.input = remaining_input;
|
|
|
|
|
|
|
|
|
|
match identifier
|
|
|
|
|
{
|
|
|
|
|
"and" =>
|
|
|
|
|
return Some(Ok((input_left, remaining_input, FormulaInfixOperator::And))),
|
|
|
|
|
"or" =>
|
|
|
|
|
return Some(Ok((input_left, remaining_input, FormulaInfixOperator::Or))),
|
|
|
|
|
_ => continue,
|
|
|
|
|
}
|
|
|
|
|
}
|
2020-02-25 15:36:34 +01:00
|
|
|
|
|
2020-04-22 20:01:29 +02:00
|
|
|
|
if let Some((symbol, remaining_input)) = symbol(self.input)
|
|
|
|
|
{
|
|
|
|
|
self.input = remaining_input;
|
|
|
|
|
|
|
|
|
|
match symbol
|
|
|
|
|
{
|
|
|
|
|
Symbol::ArrowLeft => return Some(Ok((input_left, remaining_input,
|
|
|
|
|
FormulaInfixOperator::ImpliesRightToLeft))),
|
|
|
|
|
Symbol::ArrowLeftAndRight => return Some(Ok((input_left, remaining_input,
|
|
|
|
|
FormulaInfixOperator::IfAndOnlyIf))),
|
|
|
|
|
Symbol::ArrowRight => return Some(Ok((input_left, remaining_input,
|
|
|
|
|
FormulaInfixOperator::ImpliesLeftToRight))),
|
|
|
|
|
_ => continue,
|
|
|
|
|
}
|
|
|
|
|
}
|
2020-02-25 15:36:34 +01:00
|
|
|
|
|
2020-04-22 20:01:29 +02:00
|
|
|
|
return Some(Err(crate::parse::Error::new_character_not_allowed(first_character,
|
|
|
|
|
crate::parse::error::Location::new(0, Some(0)))));
|
|
|
|
|
}
|
2020-02-25 15:36:34 +01:00
|
|
|
|
}
|
2020-04-22 20:01:29 +02:00
|
|
|
|
}
|
2020-02-25 15:36:34 +01:00
|
|
|
|
|
2020-04-22 20:01:29 +02:00
|
|
|
|
struct SplitFormulaAtInfixOperator<'i>
|
|
|
|
|
{
|
|
|
|
|
infix_operator_iterator: FormulaInfixOperatorIterator<'i>,
|
|
|
|
|
infix_operator: FormulaInfixOperator,
|
|
|
|
|
previous_index: usize,
|
|
|
|
|
}
|
2020-04-20 02:40:13 +02:00
|
|
|
|
|
2020-04-22 20:01:29 +02:00
|
|
|
|
impl<'i> SplitFormulaAtInfixOperator<'i>
|
|
|
|
|
{
|
|
|
|
|
pub fn new(input: &FormulaStr<'i>, infix_operator: FormulaInfixOperator)
|
|
|
|
|
-> Self
|
2020-02-25 15:36:34 +01:00
|
|
|
|
{
|
2020-04-22 20:01:29 +02:00
|
|
|
|
Self
|
2020-02-25 15:36:34 +01:00
|
|
|
|
{
|
2020-04-22 20:01:29 +02:00
|
|
|
|
infix_operator_iterator: input.iter_infix_operators(),
|
|
|
|
|
infix_operator,
|
|
|
|
|
previous_index: 0,
|
|
|
|
|
}
|
2020-02-25 15:36:34 +01:00
|
|
|
|
}
|
2020-04-22 20:01:29 +02:00
|
|
|
|
}
|
2020-02-25 15:36:34 +01:00
|
|
|
|
|
2020-04-22 20:01:29 +02:00
|
|
|
|
impl<'i> std::iter::Iterator for SplitFormulaAtInfixOperator<'i>
|
|
|
|
|
{
|
|
|
|
|
type Item = Result<&'i str, crate::parse::Error>;
|
2020-02-25 15:36:34 +01:00
|
|
|
|
|
2020-04-22 20:01:29 +02:00
|
|
|
|
fn next(&mut self) -> Option<Self::Item>
|
2020-02-25 15:36:34 +01:00
|
|
|
|
{
|
2020-04-22 20:01:29 +02:00
|
|
|
|
loop
|
2020-02-25 15:36:34 +01:00
|
|
|
|
{
|
2020-04-22 20:01:29 +02:00
|
|
|
|
let (input_left, input_right, infix_operator) =
|
|
|
|
|
match self.infix_operator_iterator.next()
|
|
|
|
|
{
|
|
|
|
|
Some(Err(error)) => return Some(Err(error)),
|
|
|
|
|
Some(Ok(infix_operator_iterator_next)) => infix_operator_iterator_next,
|
|
|
|
|
None => break,
|
|
|
|
|
};
|
2020-02-25 15:36:34 +01:00
|
|
|
|
|
2020-04-22 20:01:29 +02:00
|
|
|
|
if infix_operator == self.infix_operator
|
|
|
|
|
{
|
|
|
|
|
// TODO: refactor
|
|
|
|
|
let index = input_left.as_ptr() as usize
|
|
|
|
|
+ input_left.len()
|
|
|
|
|
- self.infix_operator_iterator.original_input.as_ptr() as usize;
|
|
|
|
|
let split_input = &self.infix_operator_iterator
|
|
|
|
|
.original_input[self.previous_index..index].trim();
|
|
|
|
|
self.previous_index = input_right.as_ptr() as usize
|
|
|
|
|
- self.infix_operator_iterator.original_input.as_ptr() as usize;
|
|
|
|
|
|
|
|
|
|
return Some(Ok(split_input));
|
|
|
|
|
}
|
|
|
|
|
}
|
2020-02-25 15:36:34 +01:00
|
|
|
|
|
2020-04-22 20:01:29 +02:00
|
|
|
|
let remaining_input = self.infix_operator_iterator
|
|
|
|
|
.original_input[self.previous_index..].trim();
|
2020-02-25 15:36:34 +01:00
|
|
|
|
|
2020-04-22 20:01:29 +02:00
|
|
|
|
if remaining_input.is_empty()
|
2020-02-25 15:36:34 +01:00
|
|
|
|
{
|
2020-04-22 20:01:29 +02:00
|
|
|
|
None
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
self.previous_index = self.infix_operator_iterator.original_input.len();
|
2020-02-25 15:36:34 +01:00
|
|
|
|
|
2020-04-22 20:01:29 +02:00
|
|
|
|
Some(Ok(remaining_input))
|
|
|
|
|
}
|
2020-02-25 15:36:34 +01:00
|
|
|
|
}
|
2020-04-22 20:01:29 +02:00
|
|
|
|
}
|
2020-02-25 15:36:34 +01:00
|
|
|
|
|
2020-04-22 20:01:29 +02:00
|
|
|
|
#[cfg(test)]
|
|
|
|
|
mod tests
|
|
|
|
|
{
|
|
|
|
|
use super::*;
|
2020-02-25 15:36:34 +01:00
|
|
|
|
|
|
|
|
|
#[test]
|
2020-04-22 20:01:29 +02:00
|
|
|
|
fn tokenize_formula_infix_operators()
|
2020-02-25 15:36:34 +01:00
|
|
|
|
{
|
2020-04-22 20:01:29 +02:00
|
|
|
|
let f = FormulaStr::new("((forall X exists Y (p(X) -> q(Y)) and false) or p) -> false");
|
|
|
|
|
assert_eq!(f.top_level_infix_operator().unwrap(),
|
|
|
|
|
Some(FormulaInfixOperator::ImpliesLeftToRight));
|
|
|
|
|
let mut i = f.iter_infix_operators();
|
|
|
|
|
assert_eq!(i.next().unwrap().unwrap().2, FormulaInfixOperator::ImpliesLeftToRight);
|
|
|
|
|
assert!(i.next().is_none());
|
|
|
|
|
|
|
|
|
|
let f = FormulaStr::new("forall X exists Y (p(X) -> q(Y)) and false or p -> false");
|
|
|
|
|
assert_eq!(f.top_level_infix_operator().unwrap(),
|
|
|
|
|
Some(FormulaInfixOperator::ImpliesLeftToRight));
|
|
|
|
|
let mut i = f.iter_infix_operators();
|
|
|
|
|
assert_eq!(i.next().unwrap().unwrap().2, FormulaInfixOperator::And);
|
|
|
|
|
assert_eq!(i.next().unwrap().unwrap().2, FormulaInfixOperator::Or);
|
|
|
|
|
assert_eq!(i.next().unwrap().unwrap().2, FormulaInfixOperator::ImpliesLeftToRight);
|
|
|
|
|
assert!(i.next().is_none());
|
|
|
|
|
|
|
|
|
|
let f = FormulaStr::new(" p -> forall X exists Y (p(X) -> q(Y)) and false or p -> false ");
|
|
|
|
|
assert_eq!(f.top_level_infix_operator().unwrap(),
|
|
|
|
|
Some(FormulaInfixOperator::ImpliesLeftToRight));
|
|
|
|
|
let mut i = f.split_at_infix_operator(FormulaInfixOperator::ImpliesLeftToRight);
|
|
|
|
|
assert_eq!(i.next().unwrap().unwrap(), "p");
|
|
|
|
|
assert_eq!(i.next().unwrap().unwrap(), "forall X exists Y (p(X) -> q(Y)) and false or p");
|
|
|
|
|
assert_eq!(i.next().unwrap().unwrap(), "false");
|
|
|
|
|
assert!(i.next().is_none());
|
|
|
|
|
|
|
|
|
|
let f = FormulaStr::new(" p -> forall X exists Y (p(X) -> q(Y)) and false or p -> false ");
|
|
|
|
|
assert_eq!(f.top_level_infix_operator().unwrap(),
|
|
|
|
|
Some(FormulaInfixOperator::ImpliesLeftToRight));
|
|
|
|
|
let mut i = f.split_at_infix_operator(FormulaInfixOperator::And);
|
|
|
|
|
assert_eq!(i.next().unwrap().unwrap(), "p -> forall X exists Y (p(X) -> q(Y))");
|
|
|
|
|
assert_eq!(i.next().unwrap().unwrap(), "false or p -> false");
|
|
|
|
|
assert!(i.next().is_none());
|
|
|
|
|
|
|
|
|
|
let f = FormulaStr::new(" p and forall X exists Y (p(X) -> q(Y)) and false or p or false ");
|
|
|
|
|
assert_eq!(f.top_level_infix_operator().unwrap(), Some(FormulaInfixOperator::Or));
|
|
|
|
|
let mut i = f.split_at_infix_operator(FormulaInfixOperator::Or);
|
|
|
|
|
assert_eq!(i.next().unwrap().unwrap(), "p and forall X exists Y (p(X) -> q(Y)) and false");
|
|
|
|
|
assert_eq!(i.next().unwrap().unwrap(), "p");
|
|
|
|
|
assert_eq!(i.next().unwrap().unwrap(), "false");
|
|
|
|
|
assert!(i.next().is_none());
|
|
|
|
|
|
|
|
|
|
let f = FormulaStr::new(" (p and q) ");
|
|
|
|
|
assert!(f.top_level_infix_operator().unwrap().is_none());
|
|
|
|
|
let mut i = f.split_at_infix_operator(FormulaInfixOperator::And);
|
|
|
|
|
assert_eq!(i.next().unwrap().unwrap(), "(p and q)");
|
|
|
|
|
assert!(i.next().is_none());
|
|
|
|
|
|
|
|
|
|
assert!(FormulaStr::new(" a -> b -> c ").parse(0).is_ok());
|
|
|
|
|
assert!(FormulaStr::new(" a -> b <- c ").parse(0).is_err());
|
|
|
|
|
|
|
|
|
|
assert!(!FormulaStr::new(" p -> forall X exists Y (p(X) -> q(Y)) and false or p -> false ")
|
|
|
|
|
.parse(0).is_ok());
|
2020-02-25 15:36:34 +01:00
|
|
|
|
}
|
|
|
|
|
}
|