189 lines
4.0 KiB
Rust
189 lines
4.0 KiB
Rust
use owo_colors::{OwoColorize, colors::css::Gray};
|
|
|
|
use std::fmt::Display;
|
|
|
|
use crate::domain::Domain;
|
|
|
|
#[derive(Clone, PartialEq, Eq, Debug, Hash)]
|
|
pub struct Variable(pub String, pub Option<usize>);
|
|
|
|
#[derive(Clone, Debug)]
|
|
pub struct Module
|
|
{
|
|
pub clauses: Vec<Clause>,
|
|
}
|
|
|
|
#[derive(Clone, Debug)]
|
|
pub struct Clause
|
|
{
|
|
pub head: Predicate,
|
|
pub body: Option<Body>,
|
|
}
|
|
|
|
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
|
|
pub enum Body
|
|
{
|
|
Term(Predicate),
|
|
And(Vec<Body>),
|
|
Or(Vec<Body>),
|
|
}
|
|
|
|
#[derive(Clone, Debug, Eq, PartialEq, Hash)]
|
|
pub enum Predicate
|
|
{
|
|
Variable(Variable), // Upercase variable like X
|
|
Fixed(Functor, Vec<Predicate>),
|
|
Domain(Domain),
|
|
}
|
|
|
|
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
|
|
pub enum Functor
|
|
{
|
|
Operator(Operator),
|
|
Functor(String),
|
|
}
|
|
|
|
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
|
|
pub struct Operator
|
|
{
|
|
pub op: String,
|
|
pub precedence: usize,
|
|
pub op_type: OperatorType,
|
|
}
|
|
|
|
impl Operator
|
|
{
|
|
pub fn new(op: String, precedence: usize, op_type: OperatorType) -> Self
|
|
{
|
|
Self {
|
|
op,
|
|
precedence,
|
|
op_type,
|
|
}
|
|
}
|
|
}
|
|
|
|
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
|
|
pub enum OperatorType
|
|
{
|
|
Prefix,
|
|
Postfix,
|
|
LeftInfix,
|
|
RightInfix,
|
|
}
|
|
|
|
impl Display for Body
|
|
{
|
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result
|
|
{
|
|
match self
|
|
{
|
|
Body::Term(predicate) => write!(f, "{}", predicate),
|
|
Body::And(items) | Body::Or(items) =>
|
|
{
|
|
let len = items.len();
|
|
for (i, item) in items.iter().enumerate()
|
|
{
|
|
write!(f, "{}", item)?;
|
|
if i != len - 1
|
|
{
|
|
write!(f, ",")?;
|
|
}
|
|
}
|
|
Ok(())
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
impl Display for Variable
|
|
{
|
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result
|
|
{
|
|
write!(f, "{}", self.0)?;
|
|
if let Some(num) = self.1
|
|
{
|
|
write!(f, "{}", format!("[{}]", num).fg::<Gray>())?;
|
|
}
|
|
Ok(())
|
|
}
|
|
}
|
|
|
|
impl Display for Predicate
|
|
{
|
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result
|
|
{
|
|
match self
|
|
{
|
|
Predicate::Variable(variable) => write!(f, "{}", variable),
|
|
Predicate::Fixed(name, predicates) =>
|
|
{
|
|
write!(f, "{}", name)?;
|
|
if !predicates.is_empty()
|
|
{
|
|
write!(f, "(")?;
|
|
let len = predicates.len();
|
|
for (i, predicate) in predicates.iter().enumerate()
|
|
{
|
|
write!(f, "{}", predicate)?;
|
|
if i != len - 1
|
|
{
|
|
write!(f, ", ")?;
|
|
}
|
|
}
|
|
write!(f, ")")
|
|
}
|
|
else
|
|
{
|
|
Ok(())
|
|
}
|
|
}
|
|
Predicate::Domain(domain) => write!(f, "{domain}"),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl Display for Clause
|
|
{
|
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result
|
|
{
|
|
write!(f, "{}", self.head)?;
|
|
self.body
|
|
.as_ref()
|
|
.map_or_else(|| Ok(()), |body| write!(f, ":- {}", body))?;
|
|
write!(f, ".")
|
|
}
|
|
}
|
|
|
|
impl Display for Module
|
|
{
|
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result
|
|
{
|
|
for clause in self.clauses.iter()
|
|
{
|
|
writeln!(f, "{}", clause)?;
|
|
}
|
|
Ok(())
|
|
}
|
|
}
|
|
|
|
impl Display for Functor
|
|
{
|
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result
|
|
{
|
|
match self
|
|
{
|
|
Functor::Operator(op) => write!(f, "{}", op),
|
|
Functor::Functor(name) => write!(f, "{}", name),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl Display for Operator
|
|
{
|
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result
|
|
{
|
|
write!(f, "{}", self.op)
|
|
}
|
|
}
|