use super::{Atom, ComparisonExpr, FnCall};
use crate::common::FileId;
use crate::parser::error::{grammar_bug, ParseError};
use crate::parser::{Lexeme, Rule};
use pest::iterators::Pair;
use std::fmt;
#[derive(Clone, PartialEq, Eq, Hash)]
pub(crate) enum Predicate {
PositiveAtom(Atom),
NegativeAtom(Atom),
Compare(ComparisonExpr),
FnCall(FnCall),
}
#[cfg(test)]
impl Predicate {
pub(crate) fn name(&self) -> &str {
match self {
Self::PositiveAtom(atom) | Self::NegativeAtom(atom) => atom.name(),
Self::Compare(_) => unreachable!("no name on Compare"),
Self::FnCall(_) => unreachable!("no name on FnCall"),
}
}
}
impl fmt::Display for Predicate {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::PositiveAtom(atom) => write!(f, "{atom}"),
Self::NegativeAtom(atom) => write!(f, "!{atom}"),
Self::Compare(expr) => write!(f, "{expr}"),
Self::FnCall(fc) => write!(f, "{fc}"),
}
}
}
impl fmt::Debug for Predicate {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::PositiveAtom(atom) => write!(f, "{atom:?}"),
Self::NegativeAtom(atom) => write!(f, "!{atom:?}"),
Self::Compare(expr) => write!(f, "{expr}"),
Self::FnCall(fc) => write!(f, "{fc}"),
}
}
}
impl Lexeme for Predicate {
fn from_parsed_rule(parsed_rule: Pair<Rule>, file: FileId) -> Result<Self, ParseError> {
let inner = parsed_rule
.into_inner()
.next()
.ok_or_else(|| grammar_bug("expected inner rule for predicate"))?;
Ok(match inner.as_rule() {
Rule::atom => Self::PositiveAtom(Atom::from_parsed_rule(inner, file)?),
Rule::negative_atom => {
let atom_rule = inner
.into_inner()
.next()
.ok_or_else(|| grammar_bug("negative_atom missing inner atom"))?;
Self::NegativeAtom(Atom::from_parsed_rule(atom_rule, file)?)
}
Rule::compare_expr => Self::Compare(ComparisonExpr::from_parsed_rule(inner, file)?),
Rule::fn_call_expr => Self::FnCall(FnCall::from_parsed_rule(inner, file)?),
other => return Err(grammar_bug(format!("invalid predicate type: {other:?}"))),
})
}
}