Implement variable parsing
This commit is contained in:
parent
deae102405
commit
3530364ea8
18
src/ast.rs
18
src/ast.rs
@ -174,14 +174,14 @@ pub struct Function
|
|||||||
|
|
||||||
impl 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(),
|
assert_eq!(declaration.arity, arguments.len(),
|
||||||
"function has a different number of arguments then declared");
|
"function has a different number of arguments then declared");
|
||||||
|
|
||||||
Self
|
Self
|
||||||
{
|
{
|
||||||
declaration: std::rc::Rc::clone(declaration),
|
declaration,
|
||||||
arguments,
|
arguments,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -221,11 +221,11 @@ pub struct Variable
|
|||||||
|
|
||||||
impl Variable
|
impl Variable
|
||||||
{
|
{
|
||||||
pub fn new(declaration: &std::rc::Rc<VariableDeclaration>) -> Self
|
pub fn new(declaration: std::rc::Rc<VariableDeclaration>) -> Self
|
||||||
{
|
{
|
||||||
Self
|
Self
|
||||||
{
|
{
|
||||||
declaration: std::rc::Rc::clone(declaration),
|
declaration,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -338,14 +338,14 @@ pub struct Predicate
|
|||||||
|
|
||||||
impl 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(),
|
assert_eq!(declaration.arity, arguments.len(),
|
||||||
"predicate has a different number of arguments then declared");
|
"predicate has a different number of arguments then declared");
|
||||||
|
|
||||||
Self
|
Self
|
||||||
{
|
{
|
||||||
declaration: std::rc::Rc::clone(declaration),
|
declaration,
|
||||||
arguments,
|
arguments,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -405,7 +405,7 @@ impl Term
|
|||||||
Self::boolean(false)
|
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
|
||||||
{
|
{
|
||||||
Self::Function(Function::new(declaration, arguments))
|
Self::Function(Function::new(declaration, arguments))
|
||||||
@ -466,7 +466,7 @@ impl Term
|
|||||||
Self::UnaryOperation(UnaryOperation::new(operator, argument))
|
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))
|
Self::Variable(Variable::new(declaration))
|
||||||
}
|
}
|
||||||
@ -579,7 +579,7 @@ impl Formula
|
|||||||
Self::Or(arguments)
|
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
|
||||||
{
|
{
|
||||||
Self::Predicate(Predicate::new(declaration, arguments))
|
Self::Predicate(Predicate::new(declaration, arguments))
|
||||||
|
69
src/error.rs
Normal file
69
src/error.rs
Normal 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,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,6 +1,10 @@
|
|||||||
mod ast;
|
mod ast;
|
||||||
|
mod error;
|
||||||
pub mod format;
|
pub mod format;
|
||||||
#[cfg(feature = "parse")]
|
#[cfg(feature = "parse")]
|
||||||
pub mod parse;
|
pub mod parse;
|
||||||
|
mod utils;
|
||||||
|
|
||||||
pub use ast::*;
|
pub use ast::*;
|
||||||
|
pub use error::Error;
|
||||||
|
pub use utils::VariableDeclarationStack;
|
||||||
|
26
src/parse.rs
26
src/parse.rs
@ -3,8 +3,30 @@ mod names;
|
|||||||
mod terms;
|
mod terms;
|
||||||
|
|
||||||
pub(crate) use helpers::word_boundary;
|
pub(crate) use helpers::word_boundary;
|
||||||
pub use names::{function_name, predicate_name, variable_name};
|
pub use names::{function_or_predicate_name, variable_name};
|
||||||
pub use terms::{boolean, integer, special_integer, string};
|
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::
|
use nom::
|
||||||
|
@ -28,7 +28,7 @@ fn is_variable_name_character_body(c: char) -> bool
|
|||||||
c.is_alphanumeric() || c == '_'
|
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
|
recognize
|
||||||
(
|
(
|
||||||
@ -44,11 +44,6 @@ pub fn function_name(i: &str) -> IResult<&str, &str>
|
|||||||
)(i)
|
)(i)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn predicate_name(i: &str) -> IResult<&str, &str>
|
|
||||||
{
|
|
||||||
function_name(i)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn variable_name(i: &str) -> IResult<&str, &str>
|
pub fn variable_name(i: &str) -> IResult<&str, &str>
|
||||||
{
|
{
|
||||||
recognize
|
recognize
|
||||||
@ -71,32 +66,20 @@ mod tests
|
|||||||
use crate::parse::*;
|
use crate::parse::*;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn parse_function_name()
|
fn parse_function_or_predicate_name()
|
||||||
{
|
{
|
||||||
assert_eq!(function_name("f rest"), Ok((" rest", "f")));
|
assert_eq!(function_or_predicate_name("p rest"), Ok((" rest", "p")));
|
||||||
assert_eq!(function_name("function_123 rest"), Ok((" rest", "function_123")));
|
assert_eq!(function_or_predicate_name("f rest"), Ok((" rest", "f")));
|
||||||
assert!(function_name("0 rest").is_err());
|
assert_eq!(function_or_predicate_name("p, rest"), Ok((", rest", "p")));
|
||||||
assert!(function_name("123_asd rest").is_err());
|
assert_eq!(function_or_predicate_name("f, rest"), Ok((", rest", "f")));
|
||||||
assert!(function_name("F rest").is_err());
|
assert_eq!(function_or_predicate_name("name_123 rest"), Ok((" rest", "name_123")));
|
||||||
assert!(function_name("Function_123 rest").is_err());
|
assert!(function_or_predicate_name("0 rest").is_err());
|
||||||
assert!(function_name("_ rest").is_err());
|
assert!(function_or_predicate_name("123_asd rest").is_err());
|
||||||
assert!(function_name("_function_123 rest").is_err());
|
assert!(function_or_predicate_name("P rest").is_err());
|
||||||
assert!(function_name(" ").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());
|
||||||
#[test]
|
assert!(function_or_predicate_name(" ").is_err());
|
||||||
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());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -3,12 +3,13 @@ use nom::
|
|||||||
IResult,
|
IResult,
|
||||||
branch::alt,
|
branch::alt,
|
||||||
bytes::complete::{escaped_transform, tag},
|
bytes::complete::{escaped_transform, tag},
|
||||||
character::complete::{digit1, none_of},
|
character::complete::{digit1, multispace0, none_of},
|
||||||
combinator::{map, map_res, opt, recognize},
|
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>
|
fn true_(i: &str) -> IResult<&str, crate::Term>
|
||||||
{
|
{
|
||||||
@ -148,61 +149,150 @@ pub fn string(i: &str) -> IResult<&str, crate::Term>
|
|||||||
)(i)
|
)(i)
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
fn function_or_predicate<'i>(i: &'i str, declarations: &Declarations)
|
||||||
fn function<'a>(i: &'a str, declarations: &Declarations) -> IResult<&'a str, crate::Formula>
|
-> IResult<&'i str, (&'i str, Option<Vec<Box<crate::Term>>>)>
|
||||||
{
|
{
|
||||||
alt
|
pair
|
||||||
((
|
|
||||||
function_n_ary,
|
|
||||||
function_0_ary
|
|
||||||
))(i)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn function_0_ary<'a>(i: &'a str, declarations: &Declarations) -> IResult<&'a str, crate::Term>
|
|
||||||
{
|
|
||||||
map
|
|
||||||
(
|
(
|
||||||
delimited(multispace0, function_identifier, multispace0),
|
function_or_predicate_name,
|
||||||
|name| crate::Formula::function(
|
opt
|
||||||
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
|
|
||||||
(
|
(
|
||||||
delimited(multispace0, function_identifier, multispace0),
|
|
||||||
delimited
|
delimited
|
||||||
(
|
(
|
||||||
multispace0,
|
|
||||||
delimited
|
delimited
|
||||||
(
|
(
|
||||||
|
multispace0,
|
||||||
tag("("),
|
tag("("),
|
||||||
separated_list(tag(","), term),
|
multispace0,
|
||||||
tag(")")
|
),
|
||||||
|
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)
|
)(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)]
|
#[cfg(test)]
|
||||||
mod tests
|
mod tests
|
||||||
@ -304,4 +394,172 @@ mod tests
|
|||||||
assert!(string("-").is_err());
|
assert!(string("-").is_err());
|
||||||
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
72
src/utils.rs
Normal 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"))
|
||||||
|
}
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user