Implement variable parsing

This commit is contained in:
Patrick Lühne 2020-02-28 15:35:47 +01:00
parent deae102405
commit 3530364ea8
Signed by: patrick
GPG Key ID: 05F3611E97A70ABF
7 changed files with 494 additions and 86 deletions

View File

@ -174,14 +174,14 @@ pub struct Function
impl Function
{
pub fn new(declaration: &std::rc::Rc<FunctionDeclaration>, arguments: Vec<Box<Term>>) -> Self
pub fn new(declaration: std::rc::Rc<FunctionDeclaration>, arguments: Vec<Box<Term>>) -> Self
{
assert_eq!(declaration.arity, arguments.len(),
"function has a different number of arguments then declared");
Self
{
declaration: std::rc::Rc::clone(declaration),
declaration,
arguments,
}
}
@ -221,11 +221,11 @@ pub struct Variable
impl Variable
{
pub fn new(declaration: &std::rc::Rc<VariableDeclaration>) -> Self
pub fn new(declaration: std::rc::Rc<VariableDeclaration>) -> Self
{
Self
{
declaration: std::rc::Rc::clone(declaration),
declaration,
}
}
}
@ -338,14 +338,14 @@ pub struct Predicate
impl Predicate
{
pub fn new(declaration: &std::rc::Rc<PredicateDeclaration>, arguments: Vec<Box<Term>>) -> Self
pub fn new(declaration: std::rc::Rc<PredicateDeclaration>, arguments: Vec<Box<Term>>) -> Self
{
assert_eq!(declaration.arity, arguments.len(),
"predicate has a different number of arguments then declared");
Self
{
declaration: std::rc::Rc::clone(declaration),
declaration,
arguments,
}
}
@ -405,7 +405,7 @@ impl Term
Self::boolean(false)
}
pub fn function(declaration: &std::rc::Rc<FunctionDeclaration>, arguments: Vec<Box<Term>>)
pub fn function(declaration: std::rc::Rc<FunctionDeclaration>, arguments: Vec<Box<Term>>)
-> Self
{
Self::Function(Function::new(declaration, arguments))
@ -466,7 +466,7 @@ impl Term
Self::UnaryOperation(UnaryOperation::new(operator, argument))
}
pub fn variable(declaration: &std::rc::Rc<VariableDeclaration>) -> Self
pub fn variable(declaration: std::rc::Rc<VariableDeclaration>) -> Self
{
Self::Variable(Variable::new(declaration))
}
@ -579,7 +579,7 @@ impl Formula
Self::Or(arguments)
}
pub fn predicate(declaration: &std::rc::Rc<PredicateDeclaration>, arguments: Vec<Box<Term>>)
pub fn predicate(declaration: std::rc::Rc<PredicateDeclaration>, arguments: Vec<Box<Term>>)
-> Self
{
Self::Predicate(Predicate::new(declaration, arguments))

69
src/error.rs Normal file
View File

@ -0,0 +1,69 @@
pub type Source = Box<dyn std::error::Error>;
pub enum Kind
{
Logic(&'static str),
}
pub struct Error
{
pub kind: Kind,
pub source: Option<Source>,
}
impl Error
{
pub(crate) fn new(kind: Kind) -> Self
{
Self
{
kind,
source: None,
}
}
pub(crate) fn with<S: Into<Source>>(mut self, source: S) -> Self
{
self.source = Some(source.into());
self
}
pub(crate) fn new_logic(description: &'static str) -> Self
{
Self::new(Kind::Logic(description))
}
}
impl std::fmt::Debug for Error
{
fn fmt(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result
{
match &self.kind
{
Kind::Logic(ref description) => write!(formatter,
"logic error, please report to bug tracker ({})", description),
}?;
Ok(())
}
}
impl std::fmt::Display for Error
{
fn fmt(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result
{
write!(formatter, "{:?}", self)
}
}
impl std::error::Error for Error
{
fn source(&self) -> Option<&(dyn std::error::Error + 'static)>
{
match &self.source
{
Some(source) => Some(source.as_ref()),
None => None,
}
}
}

View File

@ -1,6 +1,10 @@
mod ast;
mod error;
pub mod format;
#[cfg(feature = "parse")]
pub mod parse;
mod utils;
pub use ast::*;
pub use error::Error;
pub use utils::VariableDeclarationStack;

View File

@ -3,8 +3,30 @@ mod names;
mod terms;
pub(crate) use helpers::word_boundary;
pub use names::{function_name, predicate_name, variable_name};
pub use terms::{boolean, integer, special_integer, string};
pub use names::{function_or_predicate_name, variable_name};
pub use terms::{boolean, function, integer, predicate, special_integer, string, variable,
variable_declaration};
pub struct Declarations
{
function_declarations: std::cell::RefCell<crate::FunctionDeclarations>,
predicate_declarations: std::cell::RefCell<crate::PredicateDeclarations>,
variable_declaration_stack: std::cell::RefCell<crate::VariableDeclarationStack>,
}
impl Declarations
{
pub fn new() -> Self
{
Self
{
function_declarations: std::cell::RefCell::new(crate::FunctionDeclarations::new()),
predicate_declarations: std::cell::RefCell::new(crate::PredicateDeclarations::new()),
variable_declaration_stack:
std::cell::RefCell::new(crate::VariableDeclarationStack::new()),
}
}
}
/*
use nom::

View File

@ -28,7 +28,7 @@ fn is_variable_name_character_body(c: char) -> bool
c.is_alphanumeric() || c == '_'
}
pub fn function_name(i: &str) -> IResult<&str, &str>
pub fn function_or_predicate_name(i: &str) -> IResult<&str, &str>
{
recognize
(
@ -44,11 +44,6 @@ pub fn function_name(i: &str) -> IResult<&str, &str>
)(i)
}
pub fn predicate_name(i: &str) -> IResult<&str, &str>
{
function_name(i)
}
pub fn variable_name(i: &str) -> IResult<&str, &str>
{
recognize
@ -71,32 +66,20 @@ mod tests
use crate::parse::*;
#[test]
fn parse_function_name()
fn parse_function_or_predicate_name()
{
assert_eq!(function_name("f rest"), Ok((" rest", "f")));
assert_eq!(function_name("function_123 rest"), Ok((" rest", "function_123")));
assert!(function_name("0 rest").is_err());
assert!(function_name("123_asd rest").is_err());
assert!(function_name("F rest").is_err());
assert!(function_name("Function_123 rest").is_err());
assert!(function_name("_ rest").is_err());
assert!(function_name("_function_123 rest").is_err());
assert!(function_name(" ").is_err());
}
#[test]
fn parse_predicate_name()
{
assert_eq!(predicate_name("p rest"), Ok((" rest", "p")));
assert_eq!(predicate_name("p, rest"), Ok((", rest", "p")));
assert_eq!(predicate_name("predicate_123 rest"), Ok((" rest", "predicate_123")));
assert!(predicate_name("0 rest").is_err());
assert!(predicate_name("123_asd rest").is_err());
assert!(predicate_name("P rest").is_err());
assert!(predicate_name("Predicate_123 rest").is_err());
assert!(predicate_name("_ rest").is_err());
assert!(predicate_name("_predicate_123 rest").is_err());
assert!(predicate_name(" ").is_err());
assert_eq!(function_or_predicate_name("p rest"), Ok((" rest", "p")));
assert_eq!(function_or_predicate_name("f rest"), Ok((" rest", "f")));
assert_eq!(function_or_predicate_name("p, rest"), Ok((", rest", "p")));
assert_eq!(function_or_predicate_name("f, rest"), Ok((", rest", "f")));
assert_eq!(function_or_predicate_name("name_123 rest"), Ok((" rest", "name_123")));
assert!(function_or_predicate_name("0 rest").is_err());
assert!(function_or_predicate_name("123_asd rest").is_err());
assert!(function_or_predicate_name("P rest").is_err());
assert!(function_or_predicate_name("Predicate_123 rest").is_err());
assert!(function_or_predicate_name("_ rest").is_err());
assert!(function_or_predicate_name("_predicate_123 rest").is_err());
assert!(function_or_predicate_name(" ").is_err());
}
#[test]

View File

@ -3,12 +3,13 @@ use nom::
IResult,
branch::alt,
bytes::complete::{escaped_transform, tag},
character::complete::{digit1, none_of},
character::complete::{digit1, multispace0, none_of},
combinator::{map, map_res, opt, recognize},
sequence::{delimited, pair, terminated},
multi::separated_list,
sequence::{delimited, pair, preceded, terminated},
};
use super::word_boundary;
use super::{Declarations, function_or_predicate_name, word_boundary, variable_name};
fn true_(i: &str) -> IResult<&str, crate::Term>
{
@ -148,61 +149,150 @@ pub fn string(i: &str) -> IResult<&str, crate::Term>
)(i)
}
/*
fn function<'a>(i: &'a str, declarations: &Declarations) -> IResult<&'a str, crate::Formula>
fn function_or_predicate<'i>(i: &'i str, declarations: &Declarations)
-> IResult<&'i str, (&'i str, Option<Vec<Box<crate::Term>>>)>
{
alt
((
function_n_ary,
function_0_ary
))(i)
}
fn function_0_ary<'a>(i: &'a str, declarations: &Declarations) -> IResult<&'a str, crate::Term>
{
map
pair
(
delimited(multispace0, function_identifier, multispace0),
|name| crate::Formula::function(
crate::FunctionDeclaration
{
name: name,
arity: 0,
},
vec![])
)(i)
}
fn function_n_ary<'a>(i: &'a str, declarations: &Declarations) -> IResult<&'a str, crate::Term>
{
map
(
pair
function_or_predicate_name,
opt
(
delimited(multispace0, function_identifier, multispace0),
delimited
(
multispace0,
delimited
(
multispace0,
tag("("),
separated_list(tag(","), term),
tag(")")
multispace0,
),
separated_list
(
delimited
(
multispace0,
tag(","),
multispace0,
),
// TODO: fix
map
(
integer,
Box::new,
),
),
preceded
(
multispace0,
tag(")"),
),
multispace0
)
),
|(name, arguments)| crate::Formula::function(
crate::PredicateDeclaration
{
name: name,
arity: arguments.len(),
},
arguments)
)(i)
}
*/
pub fn function<'i>(i: &'i str, declarations: &Declarations) -> IResult<&'i str, crate::Function>
{
map
(
|i| function_or_predicate(i, declarations),
|(name, arguments)|
{
let arguments = match arguments
{
Some(arguments) => arguments,
None => vec![],
};
let mut function_declarations = declarations.function_declarations.borrow_mut();
let declaration = match function_declarations.iter()
.find(|x| x.name == name && x.arity == arguments.len())
{
Some(declaration) => std::rc::Rc::clone(&declaration),
None =>
{
let declaration = crate::FunctionDeclaration
{
name: name.to_string(),
arity: arguments.len(),
};
let declaration = std::rc::Rc::new(declaration);
function_declarations.insert(std::rc::Rc::clone(&declaration));
declaration
},
};
crate::Function::new(declaration, arguments)
},
)(i)
}
pub fn predicate<'i>(i: &'i str, declarations: &Declarations) -> IResult<&'i str, crate::Predicate>
{
map
(
|i| function_or_predicate(i, declarations),
|(name, arguments)|
{
let arguments = match arguments
{
Some(arguments) => arguments,
None => vec![],
};
let mut predicate_declarations = declarations.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)
}
pub fn variable_declaration(i: &str) -> IResult<&str, crate::VariableDeclaration>
{
map
(
variable_name,
|name| crate::VariableDeclaration::new(name.to_string())
)(i)
}
pub fn variable<'i>(i: &'i str, declarations: &Declarations) -> IResult<&'i str, crate::Variable>
{
map
(
variable_name,
|name|
{
let mut variable_declaration_stack =
declarations.variable_declaration_stack.borrow_mut();
let declaration = variable_declaration_stack.find_or_create(name);
crate::Variable::new(declaration)
},
)(i)
}
#[cfg(test)]
mod tests
@ -304,4 +394,172 @@ mod tests
assert!(string("-").is_err());
assert!(string(" ").is_err());
}
#[test]
fn parse_function()
{
assert_eq!(function("s", &Declarations::new())
.map(|(i, x)| (i, x.declaration.name.clone())),
Ok(("", "s".to_string())));
assert_eq!(function("s", &Declarations::new())
.map(|(i, x)| (i, x.declaration.arity)),
Ok(("", 0)));
assert_eq!(function("s ( )", &Declarations::new())
.map(|(i, x)| (i, x.declaration.name.clone())),
Ok(("", "s".to_string())));
assert_eq!(function("s ( )", &Declarations::new())
.map(|(i, x)| (i, x.declaration.arity)),
Ok(("", 0)));
assert_eq!(function("s ( 1 , 2 , 3 )", &Declarations::new())
.map(|(i, x)| (i, x.declaration.name.clone())),
Ok(("", "s".to_string())));
assert_eq!(function("s ( 1 , 2 , 3 )", &Declarations::new())
.map(|(i, x)| (i, x.declaration.arity)),
Ok(("", 3)));
assert_eq!(function("s ( 1 , 2 , 3 )", &Declarations::new())
.map(|(i, mut x)| (i, x.arguments.remove(0))),
Ok(("", Box::new(Term::integer(1)))));
assert_eq!(function("s ( 1 , 2 , 3 )", &Declarations::new())
.map(|(i, mut x)| (i, x.arguments.remove(2))),
Ok(("", Box::new(Term::integer(3)))));
assert_eq!(function("s ( ), rest", &Declarations::new())
.map(|(i, x)| (i, x.declaration.name.clone())),
Ok((", rest", "s".to_string())));
assert_eq!(function("s ( ), rest", &Declarations::new())
.map(|(i, x)| (i, x.declaration.arity)),
Ok((", rest", 0)));
assert_eq!(function("s ( 1 , 2 , 3 ), rest", &Declarations::new())
.map(|(i, x)| (i, x.declaration.name.clone())),
Ok((", rest", "s".to_string())));
assert_eq!(function("s ( 1 , 2 , 3 ), rest", &Declarations::new())
.map(|(i, x)| (i, x.declaration.arity)),
Ok((", rest", 3)));
}
#[test]
fn parse_variable_declaration()
{
assert_eq!(variable_declaration("X Rest")
.map(|(i, x)| (i, x.name.clone())), Ok((" Rest", "X".to_string())));
assert_eq!(variable_declaration("X, Rest")
.map(|(i, x)| (i, x.name.clone())), Ok((", Rest", "X".to_string())));
// Variable declarations parsed at different locations should not be considered equal
assert_ne!(variable_declaration("X"), variable_declaration("X"));
assert_eq!(variable_declaration("Variable_123 Rest")
.map(|(i, x)| (i, x.name.clone())), Ok((" Rest", "Variable_123".to_string())));
assert!(variable_declaration("0 Rest").is_err());
assert!(variable_declaration("123_Asd Rest").is_err());
assert!(variable_declaration("x Rest").is_err());
assert!(variable_declaration("variable_123 Rest").is_err());
assert!(variable_declaration("_ Rest").is_err());
assert!(variable_declaration("_variable_123 Rest").is_err());
assert!(variable_declaration(" ").is_err());
}
#[test]
fn parse_variable()
{
assert_eq!(variable("X Rest", &Declarations::new())
.map(|(i, x)| (i, x.declaration.name.clone())), Ok((" Rest", "X".to_string())));
assert_eq!(variable("X, Rest", &Declarations::new())
.map(|(i, x)| (i, x.declaration.name.clone())), Ok((", Rest", "X".to_string())));
assert_eq!(variable("Variable_123 Rest", &Declarations::new())
.map(|(i, x)| (i, x.declaration.name.clone())),
Ok((" Rest", "Variable_123".to_string())));
assert!(variable("0 Rest", &Declarations::new()).is_err());
assert!(variable("123_Asd Rest", &Declarations::new()).is_err());
assert!(variable("x Rest", &Declarations::new()).is_err());
assert!(variable("variable_123 Rest", &Declarations::new()).is_err());
assert!(variable("_ Rest", &Declarations::new()).is_err());
assert!(variable("_variable_123 Rest", &Declarations::new()).is_err());
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())))
.collect());
let layer_1 = new_variable_declarations(&["A", "B", "X"]);
let layer_2 = new_variable_declarations(&["C", "D", "X"]);
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 mut declarations = Declarations::new();
declarations.variable_declaration_stack =
std::cell::RefCell::new(variable_declaration_stack);
let (_, x1) = variable("X", &declarations).unwrap();
assert_eq!(declarations.variable_declaration_stack.borrow()
.free_variable_declarations.len(), 1);
let (_, x2) = variable("X", &declarations).unwrap();
assert_eq!(declarations.variable_declaration_stack.borrow()
.free_variable_declarations.len(), 1);
assert_eq!(x1.declaration, x2.declaration);
let (_, y1) = variable("Y", &declarations).unwrap();
assert_eq!(declarations.variable_declaration_stack.borrow()
.free_variable_declarations.len(), 2);
assert_ne!(x1.declaration, y1.declaration);
assert_ne!(x2.declaration, y1.declaration);
declarations.variable_declaration_stack.borrow_mut().push(layer_1);
let (_, x3) = variable("X", &declarations).unwrap();
assert_eq!(declarations.variable_declaration_stack.borrow()
.free_variable_declarations.len(), 2);
assert_ne!(x1.declaration, x3.declaration);
let (_, x4) = variable("X", &declarations).unwrap();
assert_eq!(declarations.variable_declaration_stack.borrow()
.free_variable_declarations.len(), 2);
assert_eq!(x3.declaration, x4.declaration);
let (_, a1) = variable("A", &declarations).unwrap();
assert_eq!(declarations.variable_declaration_stack.borrow()
.free_variable_declarations.len(), 2);
assert_ne!(x3.declaration, a1.declaration);
let (_, y2) = variable("Y", &declarations).unwrap();
assert_eq!(declarations.variable_declaration_stack.borrow()
.free_variable_declarations.len(), 2);
assert_eq!(y1.declaration, y2.declaration);
declarations.variable_declaration_stack.borrow_mut().push(layer_2);
let (_, x5) = variable("X", &declarations).unwrap();
assert_eq!(declarations.variable_declaration_stack.borrow()
.free_variable_declarations.len(), 2);
assert_ne!(x1.declaration, x5.declaration);
assert_ne!(x3.declaration, x5.declaration);
let (_, x6) = variable("X", &declarations).unwrap();
assert_eq!(declarations.variable_declaration_stack.borrow()
.free_variable_declarations.len(), 2);
assert_eq!(x5.declaration, x6.declaration);
let (_, a2) = variable("A", &declarations).unwrap();
assert_eq!(declarations.variable_declaration_stack.borrow()
.free_variable_declarations.len(), 2);
assert_eq!(a1.declaration, a2.declaration);
declarations.variable_declaration_stack.borrow_mut().push(layer_3);
let (_, x7) = variable("X", &declarations).unwrap();
assert_eq!(declarations.variable_declaration_stack.borrow()
.free_variable_declarations.len(), 2);
assert_eq!(x5.declaration, x7.declaration);
let (_, y3) = variable("Y", &declarations).unwrap();
assert_eq!(declarations.variable_declaration_stack.borrow()
.free_variable_declarations.len(), 2);
assert_ne!(y2.declaration, y3.declaration);
declarations.variable_declaration_stack.borrow_mut().push(layer_4);
let (_, x8) = variable("X", &declarations).unwrap();
assert_eq!(declarations.variable_declaration_stack.borrow()
.free_variable_declarations.len(), 2);
assert_ne!(x7.declaration, x8.declaration);
let (_, y4) = variable("Y", &declarations).unwrap();
assert_eq!(declarations.variable_declaration_stack.borrow()
.free_variable_declarations.len(), 2);
assert_eq!(y3.declaration, y4.declaration);
let _ = variable("I", &declarations).unwrap();
assert_eq!(declarations.variable_declaration_stack.borrow()
.free_variable_declarations.len(), 3);
}
}

72
src/utils.rs Normal file
View File

@ -0,0 +1,72 @@
pub struct VariableDeclarationStack
{
pub free_variable_declarations: crate::VariableDeclarations,
bound_variable_declaration_stack: Vec<std::rc::Rc<crate::VariableDeclarations>>,
}
impl VariableDeclarationStack
{
pub fn new() -> Self
{
Self
{
free_variable_declarations: crate::VariableDeclarations::new(),
bound_variable_declaration_stack: vec![],
}
}
pub fn find(&self, variable_name: &str) -> Option<std::rc::Rc<crate::VariableDeclaration>>
{
for variable_declarations in self.bound_variable_declaration_stack.iter().rev()
{
if let Some(variable_declaration) = variable_declarations.iter()
.find(|x| x.name == variable_name)
{
return Some(std::rc::Rc::clone(&variable_declaration));
}
}
if let Some(variable_declaration) = self.free_variable_declarations.iter()
.find(|x| x.name == variable_name)
{
return Some(std::rc::Rc::clone(&variable_declaration));
}
None
}
pub fn find_or_create(&mut self, variable_name: &str) -> std::rc::Rc<crate::VariableDeclaration>
{
if let Some(variable_declaration) = self.find(variable_name)
{
return variable_declaration;
}
let variable_declaration = crate::VariableDeclaration
{
name: variable_name.to_owned(),
};
let variable_declaration = std::rc::Rc::new(variable_declaration);
self.free_variable_declarations.push(std::rc::Rc::clone(&variable_declaration));
variable_declaration
}
pub fn is_empty(&self) -> bool
{
self.free_variable_declarations.is_empty()
&& self.bound_variable_declaration_stack.is_empty()
}
pub fn push(&mut self, bound_variable_declarations: std::rc::Rc<crate::VariableDeclarations>)
{
self.bound_variable_declaration_stack.push(bound_variable_declarations);
}
pub fn pop(&mut self) -> Result<(), crate::Error>
{
self.bound_variable_declaration_stack.pop().map(|_| ())
.ok_or(crate::Error::new_logic("variable stack not in expected state"))
}
}