2020-04-27 19:30:25 +02:00
|
|
|
|
use super::tokens::*;
|
|
|
|
|
|
|
|
|
|
pub(crate) fn function_name(input: &str) -> Option<(&str, &str)>
|
|
|
|
|
{
|
|
|
|
|
let (identifier, remaining_input) = identifier(input)?;
|
|
|
|
|
|
|
|
|
|
if is_keyword(identifier)
|
|
|
|
|
{
|
|
|
|
|
return None;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
let mut characters = identifier.chars();
|
|
|
|
|
|
|
|
|
|
while let Some(character) = characters.next()
|
|
|
|
|
{
|
|
|
|
|
match character
|
|
|
|
|
{
|
|
|
|
|
'_' => continue,
|
|
|
|
|
_ if character.is_ascii_lowercase() => return Some((identifier, remaining_input)),
|
|
|
|
|
_ => return None,
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
None
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn variable_name(input: &str) -> Option<(&str, &str)>
|
|
|
|
|
{
|
|
|
|
|
let (identifier, remaining_input) = identifier(input)?;
|
|
|
|
|
|
|
|
|
|
let mut characters = identifier.chars();
|
|
|
|
|
|
|
|
|
|
while let Some(character) = characters.next()
|
|
|
|
|
{
|
|
|
|
|
match character
|
|
|
|
|
{
|
|
|
|
|
'_' => continue,
|
|
|
|
|
_ if character.is_ascii_uppercase() => return Some((identifier, remaining_input)),
|
|
|
|
|
_ => return None,
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
None
|
|
|
|
|
}
|
|
|
|
|
|
2020-04-28 05:21:58 +02:00
|
|
|
|
pub fn is_function_name(identifier: &str) -> bool
|
|
|
|
|
{
|
|
|
|
|
if is_keyword(identifier)
|
|
|
|
|
{
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
let mut characters = identifier.chars();
|
|
|
|
|
|
|
|
|
|
while let Some(character) = characters.next()
|
|
|
|
|
{
|
|
|
|
|
match character
|
|
|
|
|
{
|
|
|
|
|
'_' => continue,
|
|
|
|
|
_ if character.is_ascii_lowercase() => return true,
|
|
|
|
|
_ => return false,
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
false
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn is_variable_name(identifier: &str) -> bool
|
|
|
|
|
{
|
|
|
|
|
let mut characters = identifier.chars();
|
|
|
|
|
|
|
|
|
|
while let Some(character) = characters.next()
|
|
|
|
|
{
|
|
|
|
|
match character
|
|
|
|
|
{
|
|
|
|
|
'_' => continue,
|
|
|
|
|
_ if character.is_ascii_uppercase() => return true,
|
|
|
|
|
_ => return false,
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
false
|
|
|
|
|
}
|
|
|
|
|
|
2020-07-07 08:15:52 +02:00
|
|
|
|
pub(crate) fn variable_declaration<P>(input: &str)
|
|
|
|
|
-> Option<(<P::Flavor as crate::flavor::Flavor>::VariableDeclaration, &str)>
|
2020-05-19 15:39:20 +02:00
|
|
|
|
where
|
2020-07-07 08:15:52 +02:00
|
|
|
|
P: crate::parse::Parser,
|
2020-04-27 19:30:25 +02:00
|
|
|
|
{
|
|
|
|
|
variable_name(input)
|
|
|
|
|
.map(|(variable_name, remaining_input)|
|
2020-07-07 08:15:52 +02:00
|
|
|
|
(<P as crate::parse::Parser>::new_variable_declaration(variable_name.to_string()),
|
|
|
|
|
remaining_input))
|
2020-04-27 19:30:25 +02:00
|
|
|
|
}
|
|
|
|
|
|
2020-07-07 08:15:52 +02:00
|
|
|
|
pub(crate) fn variable_declarations<P>(input: &str)
|
|
|
|
|
-> Result<Option<(crate::VariableDeclarations<P::Flavor>, &str)>, crate::parse::Error>
|
2020-05-19 15:39:20 +02:00
|
|
|
|
where
|
2020-07-07 08:15:52 +02:00
|
|
|
|
P: crate::parse::Parser,
|
2020-04-27 19:30:25 +02:00
|
|
|
|
{
|
|
|
|
|
let mut variable_declarations = vec![];
|
|
|
|
|
|
2020-07-07 08:15:52 +02:00
|
|
|
|
let (first_variable_declaration, mut input) = match variable_declaration::<P>(input)
|
2020-04-27 19:30:25 +02:00
|
|
|
|
{
|
|
|
|
|
Some(first_variable_declaration) => first_variable_declaration,
|
|
|
|
|
None => return Ok(None),
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
variable_declarations.push(std::rc::Rc::new(first_variable_declaration));
|
|
|
|
|
|
|
|
|
|
loop
|
|
|
|
|
{
|
2020-05-12 05:55:23 +02:00
|
|
|
|
input = trim_start(input);
|
2020-04-27 19:30:25 +02:00
|
|
|
|
|
|
|
|
|
input = match symbol(input)
|
|
|
|
|
{
|
|
|
|
|
Some((Symbol::Comma, input)) => input,
|
|
|
|
|
// TODO: detect redeclarations, such as in “exists X, Y, X”
|
|
|
|
|
_ => return Ok(Some((variable_declarations, input))),
|
|
|
|
|
};
|
|
|
|
|
|
2020-05-12 05:55:23 +02:00
|
|
|
|
input = trim_start(input);
|
2020-04-27 19:30:25 +02:00
|
|
|
|
|
2020-07-07 08:15:52 +02:00
|
|
|
|
let (variable_declaration, remaining_input) = match variable_declaration::<P>(input)
|
2020-04-27 19:30:25 +02:00
|
|
|
|
{
|
|
|
|
|
Some(variable_declaration) => variable_declaration,
|
|
|
|
|
None => return Err(crate::parse::Error::new_expected_variable_declaration(
|
|
|
|
|
crate::parse::error::Location::new(0, Some(0)))),
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
input = remaining_input;
|
|
|
|
|
|
|
|
|
|
variable_declarations.push(std::rc::Rc::new(variable_declaration));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[derive(Clone, Copy, Eq, PartialEq)]
|
2020-04-28 05:21:58 +02:00
|
|
|
|
pub(crate) enum ArithmeticOperatorClass
|
2020-04-27 19:30:25 +02:00
|
|
|
|
{
|
2020-04-28 05:21:58 +02:00
|
|
|
|
Exponential,
|
|
|
|
|
Multiplicative,
|
|
|
|
|
Additive,
|
2020-04-27 19:30:25 +02:00
|
|
|
|
}
|
|
|
|
|
|
2020-04-28 05:21:58 +02:00
|
|
|
|
impl ArithmeticOperatorClass
|
2020-04-27 19:30:25 +02:00
|
|
|
|
{
|
|
|
|
|
fn level(&self) -> usize
|
|
|
|
|
{
|
|
|
|
|
match self
|
|
|
|
|
{
|
2020-04-28 05:21:58 +02:00
|
|
|
|
Self::Exponential => 1,
|
|
|
|
|
Self::Multiplicative => 2,
|
|
|
|
|
Self::Additive => 3,
|
2020-04-27 19:30:25 +02:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2020-04-28 05:21:58 +02:00
|
|
|
|
impl std::fmt::Debug for ArithmeticOperatorClass
|
2020-04-27 19:30:25 +02:00
|
|
|
|
{
|
|
|
|
|
fn fmt(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result
|
|
|
|
|
{
|
|
|
|
|
match &self
|
|
|
|
|
{
|
2020-04-28 05:21:58 +02:00
|
|
|
|
Self::Exponential => write!(formatter, "exponential"),
|
|
|
|
|
Self::Multiplicative => write!(formatter, "multiplicative"),
|
|
|
|
|
Self::Additive => write!(formatter, "additive"),
|
2020-04-27 19:30:25 +02:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2020-07-07 08:15:52 +02:00
|
|
|
|
pub(crate) struct TermStr<'i, 'd, 'v, 'p, P>
|
2020-05-19 15:39:20 +02:00
|
|
|
|
where
|
2020-07-07 08:15:52 +02:00
|
|
|
|
P: super::Parser,
|
2020-04-27 19:30:25 +02:00
|
|
|
|
{
|
|
|
|
|
input: &'i str,
|
2020-07-07 08:15:52 +02:00
|
|
|
|
parser: &'d P,
|
|
|
|
|
variable_declaration_stack: &'v crate::VariableDeclarationStackLayer<'p, P::Flavor>,
|
2020-04-27 19:30:25 +02:00
|
|
|
|
}
|
|
|
|
|
|
2020-07-07 08:15:52 +02:00
|
|
|
|
impl<'i, 'd, 'v, 'p, P> TermStr<'i, 'd, 'v, 'p, P>
|
2020-05-04 16:53:42 +02:00
|
|
|
|
where
|
2020-07-07 08:15:52 +02:00
|
|
|
|
P: super::Parser,
|
2020-04-27 19:30:25 +02:00
|
|
|
|
{
|
2020-07-07 08:15:52 +02:00
|
|
|
|
pub fn new(input: &'i str, parser: &'d P,
|
|
|
|
|
variable_declaration_stack: &'v crate::VariableDeclarationStackLayer<'p, P::Flavor>)
|
2020-05-04 16:53:42 +02:00
|
|
|
|
-> Self
|
2020-04-27 19:30:25 +02:00
|
|
|
|
{
|
|
|
|
|
Self
|
|
|
|
|
{
|
|
|
|
|
input,
|
2020-07-07 08:15:52 +02:00
|
|
|
|
parser,
|
2020-05-04 16:53:42 +02:00
|
|
|
|
variable_declaration_stack,
|
2020-04-27 19:30:25 +02:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2020-04-28 05:21:58 +02:00
|
|
|
|
fn arithmetic_operator_classes(&self) -> Tokens<'i, impl FnMut(Token<'i>)
|
|
|
|
|
-> Option<ArithmeticOperatorClass>>
|
2020-04-27 19:30:25 +02:00
|
|
|
|
{
|
2020-04-28 05:21:58 +02:00
|
|
|
|
let functor = |token| match token
|
|
|
|
|
{
|
|
|
|
|
Token::Symbol(Symbol::Exponentiation) => Some(ArithmeticOperatorClass::Exponential),
|
|
|
|
|
Token::Symbol(Symbol::Multiplication) => Some(ArithmeticOperatorClass::Multiplicative),
|
|
|
|
|
Token::Symbol(Symbol::Division) => Some(ArithmeticOperatorClass::Multiplicative),
|
|
|
|
|
Token::Symbol(Symbol::Percent) => Some(ArithmeticOperatorClass::Multiplicative),
|
|
|
|
|
Token::Symbol(Symbol::Plus) => Some(ArithmeticOperatorClass::Additive),
|
|
|
|
|
Token::Symbol(Symbol::Minus) => Some(ArithmeticOperatorClass::Additive),
|
|
|
|
|
_ => None,
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// TODO: refactor so that self.input is always set correctly
|
|
|
|
|
Tokens::new_filter_map(self.input, functor)
|
2020-04-27 19:30:25 +02:00
|
|
|
|
}
|
|
|
|
|
|
2020-04-28 05:21:58 +02:00
|
|
|
|
fn filter_by_arithmetic_operator_class(&self,
|
|
|
|
|
arithmetic_operator_class: ArithmeticOperatorClass)
|
|
|
|
|
-> Tokens<'i, impl FnMut(Token<'i>) -> Option<crate::BinaryOperator>>
|
2020-04-27 19:30:25 +02:00
|
|
|
|
{
|
2020-04-28 05:21:58 +02:00
|
|
|
|
let functor = move |token| match token
|
|
|
|
|
{
|
|
|
|
|
Token::Symbol(Symbol::Exponentiation) =>
|
|
|
|
|
if arithmetic_operator_class == ArithmeticOperatorClass::Exponential
|
|
|
|
|
{
|
|
|
|
|
Some(crate::BinaryOperator::Exponentiate)
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
None
|
|
|
|
|
},
|
|
|
|
|
Token::Symbol(Symbol::Multiplication) =>
|
|
|
|
|
if arithmetic_operator_class == ArithmeticOperatorClass::Multiplicative
|
|
|
|
|
{
|
|
|
|
|
Some(crate::BinaryOperator::Multiply)
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
None
|
|
|
|
|
},
|
|
|
|
|
Token::Symbol(Symbol::Division) =>
|
|
|
|
|
if arithmetic_operator_class == ArithmeticOperatorClass::Multiplicative
|
|
|
|
|
{
|
|
|
|
|
Some(crate::BinaryOperator::Divide)
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
None
|
|
|
|
|
},
|
|
|
|
|
Token::Symbol(Symbol::Percent) =>
|
|
|
|
|
if arithmetic_operator_class == ArithmeticOperatorClass::Multiplicative
|
|
|
|
|
{
|
|
|
|
|
Some(crate::BinaryOperator::Modulo)
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
None
|
|
|
|
|
},
|
|
|
|
|
Token::Symbol(Symbol::Plus) =>
|
|
|
|
|
if arithmetic_operator_class == ArithmeticOperatorClass::Additive
|
|
|
|
|
{
|
|
|
|
|
Some(crate::BinaryOperator::Add)
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
None
|
|
|
|
|
},
|
|
|
|
|
Token::Symbol(Symbol::Minus) =>
|
|
|
|
|
if arithmetic_operator_class == ArithmeticOperatorClass::Additive
|
|
|
|
|
{
|
|
|
|
|
Some(crate::BinaryOperator::Subtract)
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
None
|
|
|
|
|
},
|
|
|
|
|
_ => None,
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
Tokens::new_filter_map(self.input, functor)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn top_level_arithmetic_operator_class(&self)
|
|
|
|
|
-> Result<Option<ArithmeticOperatorClass>, crate::parse::Error>
|
|
|
|
|
{
|
|
|
|
|
let mut top_level_arithmetic_operator_class = None;
|
|
|
|
|
|
|
|
|
|
for arithmetic_operator_class in self.arithmetic_operator_classes()
|
|
|
|
|
{
|
|
|
|
|
let (_, arithmetic_operator_class) = arithmetic_operator_class?;
|
|
|
|
|
|
|
|
|
|
top_level_arithmetic_operator_class = match top_level_arithmetic_operator_class
|
|
|
|
|
{
|
|
|
|
|
None => Some(arithmetic_operator_class),
|
|
|
|
|
Some(top_level_arithmetic_operator_class) =>
|
|
|
|
|
{
|
|
|
|
|
if arithmetic_operator_class.level()
|
|
|
|
|
> top_level_arithmetic_operator_class.level()
|
|
|
|
|
{
|
|
|
|
|
Some(arithmetic_operator_class)
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
Some(top_level_arithmetic_operator_class)
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Ok(top_level_arithmetic_operator_class)
|
2020-04-27 19:30:25 +02:00
|
|
|
|
}
|
|
|
|
|
|
2020-07-07 08:15:52 +02:00
|
|
|
|
pub fn parse(&self, level: usize) -> Result<crate::Term<P::Flavor>, crate::parse::Error>
|
2020-04-27 19:30:25 +02:00
|
|
|
|
{
|
|
|
|
|
let indentation = " ".repeat(level);
|
2020-05-05 19:43:41 +02:00
|
|
|
|
log::trace!("{}- parsing term: {}", indentation, self.input);
|
2020-04-27 19:30:25 +02:00
|
|
|
|
|
2020-05-12 05:55:23 +02:00
|
|
|
|
let input = trim_start(self.input);
|
2020-04-27 19:30:25 +02:00
|
|
|
|
|
2020-04-28 05:21:58 +02:00
|
|
|
|
match input.chars().next()
|
2020-04-27 19:30:25 +02:00
|
|
|
|
{
|
2020-04-28 05:21:58 +02:00
|
|
|
|
Some(')') => return Err(crate::parse::Error::new_unmatched_parenthesis(
|
|
|
|
|
crate::parse::error::Location::new(0, Some(0)))),
|
|
|
|
|
// TODO: implement absolute value function
|
|
|
|
|
Some('|') => unimplemented!(),
|
|
|
|
|
None => return Err(crate::parse::Error::new_empty_expression(
|
|
|
|
|
crate::parse::error::Location::new(0, Some(0)))),
|
|
|
|
|
_ => (),
|
2020-04-27 19:30:25 +02:00
|
|
|
|
}
|
|
|
|
|
|
2020-04-28 05:21:58 +02:00
|
|
|
|
// Parse arithmetic infix operations
|
|
|
|
|
if let Some(top_level_arithmetic_operator_class) =
|
|
|
|
|
self.top_level_arithmetic_operator_class()?
|
2020-04-27 19:30:25 +02:00
|
|
|
|
{
|
2020-05-05 19:43:41 +02:00
|
|
|
|
log::trace!("{} parsing {:?} arithmetic term", indentation,
|
2020-04-28 05:21:58 +02:00
|
|
|
|
top_level_arithmetic_operator_class);
|
2020-04-27 19:30:25 +02:00
|
|
|
|
|
2020-04-28 05:21:58 +02:00
|
|
|
|
if top_level_arithmetic_operator_class == ArithmeticOperatorClass::Exponential
|
2020-04-27 19:30:25 +02:00
|
|
|
|
{
|
2020-05-04 16:53:42 +02:00
|
|
|
|
return self.exponentiate(
|
2020-04-28 05:21:58 +02:00
|
|
|
|
self.filter_by_arithmetic_operator_class(top_level_arithmetic_operator_class)
|
|
|
|
|
.split(), level + 1);
|
2020-04-27 19:30:25 +02:00
|
|
|
|
}
|
|
|
|
|
|
2020-04-28 05:21:58 +02:00
|
|
|
|
// Parse arguments of arithmetic infix operations
|
|
|
|
|
let mut argument_iterator =
|
|
|
|
|
self.filter_by_arithmetic_operator_class(top_level_arithmetic_operator_class);
|
|
|
|
|
|
|
|
|
|
let (first_argument, first_binary_operator) = argument_iterator.next().ok_or_else(||
|
|
|
|
|
crate::parse::Error::new_expected_term(
|
|
|
|
|
crate::parse::error::Location::new(0, Some(0))))??;
|
2020-05-04 16:53:42 +02:00
|
|
|
|
let first_argument =
|
2020-07-07 08:15:52 +02:00
|
|
|
|
TermStr::new(first_argument, self.parser, self.variable_declaration_stack)
|
2020-05-04 16:53:42 +02:00
|
|
|
|
.parse(level + 1)?;
|
2020-04-28 05:21:58 +02:00
|
|
|
|
// TODO: improve error handling if the terms between the operators are invalid
|
|
|
|
|
|
|
|
|
|
let (accumulator, last_binary_operator) =
|
|
|
|
|
argument_iterator.try_fold((first_argument, first_binary_operator),
|
|
|
|
|
|(accumulator, binary_operator), argument|
|
|
|
|
|
{
|
|
|
|
|
let (argument, next_binary_operator) = argument?;
|
2020-07-07 08:15:52 +02:00
|
|
|
|
let argument = TermStr::new(argument, self.parser,
|
2020-05-04 16:53:42 +02:00
|
|
|
|
self.variable_declaration_stack)
|
|
|
|
|
.parse(level + 1)?;
|
2020-04-28 05:21:58 +02:00
|
|
|
|
let binary_operation =
|
|
|
|
|
crate::BinaryOperation::new(binary_operator, Box::new(accumulator),
|
|
|
|
|
Box::new(argument));
|
|
|
|
|
let formula = crate::Term::BinaryOperation(binary_operation);
|
|
|
|
|
|
|
|
|
|
Ok((formula, next_binary_operator))
|
|
|
|
|
})?;
|
|
|
|
|
|
|
|
|
|
// The last item hasn’t been consumed yet, so it’s safe to unwrap it
|
|
|
|
|
let last_argument = argument_iterator.remaining_input().unwrap();
|
2020-05-04 16:53:42 +02:00
|
|
|
|
let last_argument =
|
2020-07-07 08:15:52 +02:00
|
|
|
|
TermStr::new(last_argument, self.parser, self.variable_declaration_stack)
|
2020-05-04 16:53:42 +02:00
|
|
|
|
.parse(level + 1)?;
|
2020-04-28 05:21:58 +02:00
|
|
|
|
let last_binary_operation =
|
|
|
|
|
crate::BinaryOperation::new(last_binary_operator, Box::new(accumulator),
|
|
|
|
|
Box::new(last_argument));
|
|
|
|
|
|
|
|
|
|
return Ok(crate::Term::BinaryOperation(last_binary_operation));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if let Some((number, input)) = number(input)?
|
|
|
|
|
{
|
|
|
|
|
if !input.trim().is_empty()
|
2020-04-27 19:30:25 +02:00
|
|
|
|
{
|
2020-04-28 05:21:58 +02:00
|
|
|
|
return Err(crate::parse::Error::new_unexpected_token(
|
|
|
|
|
crate::parse::error::Location::new(0, Some(0))));
|
2020-04-27 19:30:25 +02:00
|
|
|
|
}
|
|
|
|
|
|
2020-04-28 05:21:58 +02:00
|
|
|
|
return Ok(crate::Term::integer(number as i32));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if let Some((identifier, input)) = identifier(input)
|
|
|
|
|
{
|
|
|
|
|
match identifier
|
2020-04-27 19:30:25 +02:00
|
|
|
|
{
|
2020-04-28 05:21:58 +02:00
|
|
|
|
"inf" =>
|
2020-04-27 19:30:25 +02:00
|
|
|
|
{
|
2020-04-28 05:21:58 +02:00
|
|
|
|
if !input.trim().is_empty()
|
|
|
|
|
{
|
|
|
|
|
return Err(crate::parse::Error::new_unexpected_token(
|
|
|
|
|
crate::parse::error::Location::new(0, Some(0))))
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return Ok(crate::Term::infimum());
|
2020-04-27 19:30:25 +02:00
|
|
|
|
},
|
2020-04-28 05:21:58 +02:00
|
|
|
|
"sup" =>
|
|
|
|
|
{
|
|
|
|
|
if !input.trim().is_empty()
|
|
|
|
|
{
|
|
|
|
|
return Err(crate::parse::Error::new_unexpected_token(
|
|
|
|
|
crate::parse::error::Location::new(0, Some(0))))
|
|
|
|
|
}
|
2020-04-27 19:30:25 +02:00
|
|
|
|
|
2020-04-28 05:21:58 +02:00
|
|
|
|
return Ok(crate::Term::supremum());
|
|
|
|
|
},
|
|
|
|
|
"true" =>
|
2020-04-27 19:30:25 +02:00
|
|
|
|
{
|
2020-04-28 05:21:58 +02:00
|
|
|
|
if !input.trim().is_empty()
|
|
|
|
|
{
|
|
|
|
|
return Err(crate::parse::Error::new_unexpected_token(
|
|
|
|
|
crate::parse::error::Location::new(0, Some(0))))
|
|
|
|
|
}
|
2020-04-27 19:30:25 +02:00
|
|
|
|
|
2020-04-28 05:21:58 +02:00
|
|
|
|
return Ok(crate::Term::true_());
|
|
|
|
|
},
|
|
|
|
|
"false" =>
|
|
|
|
|
{
|
|
|
|
|
if !input.trim().is_empty()
|
|
|
|
|
{
|
|
|
|
|
return Err(crate::parse::Error::new_unexpected_token(
|
|
|
|
|
crate::parse::error::Location::new(0, Some(0))))
|
|
|
|
|
}
|
2020-04-27 19:30:25 +02:00
|
|
|
|
|
2020-04-28 05:21:58 +02:00
|
|
|
|
return Ok(crate::Term::false_());
|
|
|
|
|
},
|
|
|
|
|
_ if is_variable_name(identifier) =>
|
|
|
|
|
{
|
|
|
|
|
if !input.trim().is_empty()
|
|
|
|
|
{
|
|
|
|
|
return Err(crate::parse::Error::new_unexpected_token(
|
|
|
|
|
crate::parse::error::Location::new(0, Some(0))))
|
|
|
|
|
}
|
|
|
|
|
|
2020-07-07 08:15:52 +02:00
|
|
|
|
let declaration = P::find_or_create_variable_declaration(
|
|
|
|
|
self.variable_declaration_stack, identifier);
|
2020-04-28 05:21:58 +02:00
|
|
|
|
return Ok(crate::Term::variable(declaration));
|
|
|
|
|
},
|
|
|
|
|
_ if is_function_name(identifier) =>
|
|
|
|
|
{
|
|
|
|
|
let function_name = identifier;
|
2020-05-05 19:43:41 +02:00
|
|
|
|
log::trace!("{} parsing function {}", indentation, function_name);
|
2020-04-28 05:21:58 +02:00
|
|
|
|
|
2020-05-12 05:55:23 +02:00
|
|
|
|
let input = trim_start(input);
|
2020-04-28 05:21:58 +02:00
|
|
|
|
|
|
|
|
|
// Parse arguments if there are any
|
|
|
|
|
let (arguments, input) = match parenthesized_expression(input)?
|
|
|
|
|
{
|
|
|
|
|
Some((parenthesized_expression, input)) =>
|
|
|
|
|
{
|
|
|
|
|
let functor = |token: &_| *token == Token::Symbol(Symbol::Comma);
|
|
|
|
|
let arguments = Tokens::new_filter(parenthesized_expression, functor).split()
|
2020-07-07 08:15:52 +02:00
|
|
|
|
.map(|argument| TermStr::new(argument?, self.parser,
|
2020-05-04 16:53:42 +02:00
|
|
|
|
self.variable_declaration_stack)
|
|
|
|
|
.parse(level + 1))
|
2020-04-28 05:21:58 +02:00
|
|
|
|
.collect::<Result<_, _>>()?;
|
|
|
|
|
|
|
|
|
|
(arguments, input)
|
|
|
|
|
}
|
|
|
|
|
None => (vec![], input),
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
if !input.trim().is_empty()
|
|
|
|
|
{
|
|
|
|
|
return Err(crate::parse::Error::new_unexpected_token(
|
|
|
|
|
crate::parse::error::Location::new(0, Some(0))))
|
|
|
|
|
}
|
|
|
|
|
|
2020-07-07 08:15:52 +02:00
|
|
|
|
let declaration = self.parser.find_or_create_function_declaration(
|
2020-05-04 16:56:03 +02:00
|
|
|
|
function_name, arguments.len());
|
2020-04-28 05:21:58 +02:00
|
|
|
|
return Ok(crate::Term::function(declaration, arguments));
|
|
|
|
|
},
|
|
|
|
|
_ => (),
|
2020-04-27 19:30:25 +02:00
|
|
|
|
}
|
2020-04-28 05:21:58 +02:00
|
|
|
|
}
|
2020-04-27 19:30:25 +02:00
|
|
|
|
|
2020-04-28 05:21:58 +02:00
|
|
|
|
// TODO: parse negative value
|
2020-04-27 19:30:25 +02:00
|
|
|
|
|
2020-04-28 05:21:58 +02:00
|
|
|
|
// Parse parenthesized terms
|
|
|
|
|
if let Some((parenthesized_expression, input)) = parenthesized_expression(input)?
|
|
|
|
|
{
|
|
|
|
|
if !input.trim().is_empty()
|
|
|
|
|
{
|
|
|
|
|
return Err(crate::parse::Error::new_unexpected_token(
|
|
|
|
|
crate::parse::error::Location::new(0, Some(0))));
|
2020-04-27 19:30:25 +02:00
|
|
|
|
}
|
|
|
|
|
|
2020-07-07 08:15:52 +02:00
|
|
|
|
return TermStr::new(parenthesized_expression, self.parser,
|
2020-05-04 16:53:42 +02:00
|
|
|
|
self.variable_declaration_stack)
|
|
|
|
|
.parse(level + 1);
|
2020-04-27 19:30:25 +02:00
|
|
|
|
}
|
|
|
|
|
|
2020-04-28 05:21:58 +02:00
|
|
|
|
Err(crate::parse::Error::new_unexpected_token(
|
|
|
|
|
crate::parse::error::Location::new(0, Some(0))))
|
|
|
|
|
}
|
2020-04-27 19:30:25 +02:00
|
|
|
|
|
2020-05-04 16:53:42 +02:00
|
|
|
|
// TODO: refactor
|
|
|
|
|
fn exponentiate_inner<T>(&self, mut argument_iterator: T, level: usize)
|
2020-07-07 08:15:52 +02:00
|
|
|
|
-> Result<Option<crate::Term<P::Flavor>>, crate::parse::Error>
|
2020-05-04 16:53:42 +02:00
|
|
|
|
where
|
|
|
|
|
T: std::iter::Iterator<Item = Result<&'i str, crate::parse::Error>>
|
2020-04-27 19:30:25 +02:00
|
|
|
|
{
|
2020-05-04 16:53:42 +02:00
|
|
|
|
match argument_iterator.next()
|
2020-04-27 19:30:25 +02:00
|
|
|
|
{
|
2020-05-04 16:53:42 +02:00
|
|
|
|
Some(argument) =>
|
2020-04-28 05:21:58 +02:00
|
|
|
|
{
|
2020-05-04 16:53:42 +02:00
|
|
|
|
// TODO: improve error handling if antecedent cannot be parsed
|
|
|
|
|
let argument =
|
2020-07-07 08:15:52 +02:00
|
|
|
|
TermStr::new(argument?, self.parser, self.variable_declaration_stack)
|
2020-05-04 16:53:42 +02:00
|
|
|
|
.parse(level)?;
|
|
|
|
|
match self.exponentiate_inner(argument_iterator, level)?
|
|
|
|
|
{
|
|
|
|
|
Some(next_argument) => Ok(Some(crate::Term::exponentiate(Box::new(argument),
|
|
|
|
|
Box::new(next_argument)))),
|
|
|
|
|
None => Ok(Some(argument)),
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
None => Ok(None),
|
|
|
|
|
}
|
2020-04-27 19:30:25 +02:00
|
|
|
|
}
|
|
|
|
|
|
2020-05-04 16:53:42 +02:00
|
|
|
|
fn exponentiate<T>(&self, mut argument_iterator: T, level: usize)
|
2020-07-07 08:15:52 +02:00
|
|
|
|
-> Result<crate::Term<P::Flavor>, crate::parse::Error>
|
2020-05-04 16:53:42 +02:00
|
|
|
|
where
|
|
|
|
|
T: std::iter::Iterator<Item = Result<&'i str, crate::parse::Error>>
|
2020-04-27 19:30:25 +02:00
|
|
|
|
{
|
2020-05-04 16:53:42 +02:00
|
|
|
|
match argument_iterator.next()
|
2020-04-27 19:30:25 +02:00
|
|
|
|
{
|
2020-05-04 16:53:42 +02:00
|
|
|
|
Some(argument) =>
|
2020-04-27 19:30:25 +02:00
|
|
|
|
{
|
2020-05-04 16:53:42 +02:00
|
|
|
|
// TODO: improve error handling if antecedent cannot be parsed
|
|
|
|
|
let argument =
|
2020-07-07 08:15:52 +02:00
|
|
|
|
TermStr::new(argument?, self.parser, self.variable_declaration_stack)
|
2020-05-04 16:53:42 +02:00
|
|
|
|
.parse(level)?;
|
|
|
|
|
match self.exponentiate_inner(argument_iterator, level)?
|
|
|
|
|
{
|
|
|
|
|
Some(next_argument) =>
|
|
|
|
|
Ok(crate::Term::exponentiate(Box::new(argument), Box::new(next_argument))),
|
|
|
|
|
None => Err(crate::parse::Error::new_expected_term(
|
|
|
|
|
crate::parse::error::Location::new(0, Some(0)))),
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
None => Err(crate::parse::Error::new_expected_term(
|
|
|
|
|
crate::parse::error::Location::new(0, Some(0)))),
|
|
|
|
|
}
|
2020-04-27 19:30:25 +02:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[cfg(test)]
|
|
|
|
|
mod tests
|
|
|
|
|
{
|
|
|
|
|
use super::*;
|
|
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
|
fn parse_variable_name()
|
|
|
|
|
{
|
|
|
|
|
assert_eq!(variable_name("X").unwrap(), ("X", ""));
|
|
|
|
|
assert_eq!(variable_name("_X").unwrap(), ("_X", ""));
|
|
|
|
|
assert_eq!(variable_name("__X").unwrap(), ("__X", ""));
|
|
|
|
|
assert_eq!(variable_name("Variable").unwrap(), ("Variable", ""));
|
|
|
|
|
assert_eq!(variable_name("_Variable").unwrap(), ("_Variable", ""));
|
|
|
|
|
assert_eq!(variable_name("__Variable").unwrap(), ("__Variable", ""));
|
|
|
|
|
assert_eq!(variable_name("X,").unwrap(), ("X", ","));
|
|
|
|
|
assert_eq!(variable_name("_X,").unwrap(), ("_X", ","));
|
|
|
|
|
assert_eq!(variable_name("__X,").unwrap(), ("__X", ","));
|
|
|
|
|
assert_eq!(variable_name("Variable,").unwrap(), ("Variable", ","));
|
|
|
|
|
assert_eq!(variable_name("_Variable,").unwrap(), ("_Variable", ","));
|
|
|
|
|
assert_eq!(variable_name("__Variable,").unwrap(), ("__Variable", ","));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
|
fn parse_variable_declaration()
|
|
|
|
|
{
|
2020-05-19 15:39:20 +02:00
|
|
|
|
let variable_declaration =
|
2020-07-07 08:15:52 +02:00
|
|
|
|
|x| super::variable_declaration::<crate::parse::DefaultParser>(x);
|
2020-05-19 15:39:20 +02:00
|
|
|
|
|
2020-04-27 19:30:25 +02:00
|
|
|
|
let v = variable_declaration("X").unwrap();
|
|
|
|
|
assert_eq!((v.0.name.as_str(), v.1), ("X", ""));
|
|
|
|
|
let v = variable_declaration("_X").unwrap();
|
|
|
|
|
assert_eq!((v.0.name.as_str(), v.1), ("_X", ""));
|
|
|
|
|
let v = variable_declaration("__X").unwrap();
|
|
|
|
|
assert_eq!((v.0.name.as_str(), v.1), ("__X", ""));
|
|
|
|
|
let v = variable_declaration("Variable").unwrap();
|
|
|
|
|
assert_eq!((v.0.name.as_str(), v.1), ("Variable", ""));
|
|
|
|
|
let v = variable_declaration("_Variable").unwrap();
|
|
|
|
|
assert_eq!((v.0.name.as_str(), v.1), ("_Variable", ""));
|
|
|
|
|
let v = variable_declaration("__Variable").unwrap();
|
|
|
|
|
assert_eq!((v.0.name.as_str(), v.1), ("__Variable", ""));
|
|
|
|
|
let v = variable_declaration("X,").unwrap();
|
|
|
|
|
assert_eq!((v.0.name.as_str(), v.1), ("X", ","));
|
|
|
|
|
let v = variable_declaration("_X,").unwrap();
|
|
|
|
|
assert_eq!((v.0.name.as_str(), v.1), ("_X", ","));
|
|
|
|
|
let v = variable_declaration("__X,").unwrap();
|
|
|
|
|
assert_eq!((v.0.name.as_str(), v.1), ("__X", ","));
|
|
|
|
|
let v = variable_declaration("Variable,").unwrap();
|
|
|
|
|
assert_eq!((v.0.name.as_str(), v.1), ("Variable", ","));
|
|
|
|
|
let v = variable_declaration("_Variable,").unwrap();
|
|
|
|
|
assert_eq!((v.0.name.as_str(), v.1), ("_Variable", ","));
|
|
|
|
|
let v = variable_declaration("__Variable,").unwrap();
|
|
|
|
|
assert_eq!((v.0.name.as_str(), v.1), ("__Variable", ","));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
|
fn parse_variable_declarations()
|
|
|
|
|
{
|
2020-05-19 15:39:20 +02:00
|
|
|
|
let variable_declarations =
|
2020-07-07 08:15:52 +02:00
|
|
|
|
|x| super::variable_declarations::<crate::parse::DefaultParser>(x);
|
2020-05-19 15:39:20 +02:00
|
|
|
|
|
2020-04-27 19:30:25 +02:00
|
|
|
|
let v = variable_declarations("X.").unwrap().unwrap();
|
|
|
|
|
assert_eq!(v.0.len(), 1);
|
|
|
|
|
assert_eq!(v.0[0].name.as_str(), "X");
|
|
|
|
|
assert_eq!(v.1, ".");
|
|
|
|
|
|
|
|
|
|
let v = variable_declarations("X,Y,Z.").unwrap().unwrap();
|
|
|
|
|
assert_eq!(v.0.len(), 3);
|
|
|
|
|
assert_eq!(v.0[0].name.as_str(), "X");
|
|
|
|
|
assert_eq!(v.0[1].name.as_str(), "Y");
|
|
|
|
|
assert_eq!(v.0[2].name.as_str(), "Z");
|
|
|
|
|
assert_eq!(v.1, ".");
|
|
|
|
|
|
|
|
|
|
let v = variable_declarations("X, Y, Z.").unwrap().unwrap();
|
|
|
|
|
assert_eq!(v.0.len(), 3);
|
|
|
|
|
assert_eq!(v.0[0].name.as_str(), "X");
|
|
|
|
|
assert_eq!(v.0[1].name.as_str(), "Y");
|
|
|
|
|
assert_eq!(v.0[2].name.as_str(), "Z");
|
|
|
|
|
assert_eq!(v.1, ".");
|
|
|
|
|
|
|
|
|
|
let v = variable_declarations("X , Y , Z.").unwrap().unwrap();
|
|
|
|
|
assert_eq!(v.0.len(), 3);
|
|
|
|
|
assert_eq!(v.0[0].name.as_str(), "X");
|
|
|
|
|
assert_eq!(v.0[1].name.as_str(), "Y");
|
|
|
|
|
assert_eq!(v.0[2].name.as_str(), "Z");
|
|
|
|
|
assert_eq!(v.1, ".");
|
|
|
|
|
|
|
|
|
|
assert!(variable_declarations("test").unwrap().is_none());
|
|
|
|
|
assert!(variable_declarations("X, test").is_err());
|
|
|
|
|
assert!(variable_declarations("X ,test").is_err());
|
|
|
|
|
assert!(variable_declarations("X,Y,Z, test").is_err());
|
|
|
|
|
assert!(variable_declarations("X,Y,Z ,test").is_err());
|
|
|
|
|
}
|
|
|
|
|
}
|