raa_tt 0.9.1

Proves sentences of propositional calculus
Documentation
use std::{
    collections::BTreeSet,
    fmt::{Debug, Display, Error, Formatter},
};

use crate::{
    bi_implication::BiImplication, conjunction::Conjunction, disjunction::Disjunction,
    implication::Implication, negation::Negation,
};

#[derive(Clone, Debug, Default, PartialEq, Eq)]
pub enum Proposition {
    #[default]
    Void,
    Atom(String),
    Negation(Negation),
    Implication(Implication),
    BiImplication(BiImplication),
    Disjunction(Disjunction),
    Conjunction(Conjunction),
}
impl Proposition {
    pub(crate) fn get_variables(&self) -> BTreeSet<String> {
        let mut vars = BTreeSet::new();
        self.inner_get_variables(&mut vars);
        vars
    }

    fn inner_get_variables(&self, vars: &mut BTreeSet<String>) {
        match self {
            Proposition::Void => (),
            Proposition::Atom(v) => {
                vars.insert(v.clone());
            }
            Proposition::Negation(Negation { inner }) => inner.inner_get_variables(vars),
            Proposition::Implication(Implication { left, right }) => {
                left.inner_get_variables(vars);
                right.inner_get_variables(vars);
            }
            Proposition::BiImplication(BiImplication { left, right }) => {
                left.inner_get_variables(vars);
                right.inner_get_variables(vars);
            }
            Proposition::Disjunction(Disjunction { left, right }) => {
                left.inner_get_variables(vars);
                right.inner_get_variables(vars);
            }
            Proposition::Conjunction(Conjunction { left, right }) => {
                left.inner_get_variables(vars);
                right.inner_get_variables(vars);
            }
        }
    }
}

impl Display for Proposition {
    fn fmt(&self, f: &mut Formatter<'_>) -> std::result::Result<(), Error> {
        match self {
            Proposition::Void => write!(f, "()"),
            Proposition::Atom(v) => write!(f, "{}", v),
            Proposition::Negation(e) => write!(f, "{}", e),
            Proposition::Implication(i) => write!(f, "{}", i),
            Proposition::BiImplication(b) => write!(f, "{}", b),
            Proposition::Disjunction(d) => write!(f, "{}", d),
            Proposition::Conjunction(c) => write!(f, "{}", c),
        }
    }
}

impl From<&str> for Proposition {
    fn from(value: &str) -> Self {
        Proposition::Atom(value.to_owned())
    }
}

impl From<&crate::raa_tt_grammar_trait::RaaTtList<'_>> for Proposition {
    fn from(value: &crate::raa_tt_grammar_trait::RaaTtList<'_>) -> Self {
        (&value.biconditional).into()
    }
}

impl From<&crate::raa_tt_grammar_trait::Biconditional<'_>> for Proposition {
    fn from(value: &crate::raa_tt_grammar_trait::Biconditional<'_>) -> Self {
        let crate::raa_tt_grammar_trait::Biconditional {
            conditional,
            biconditional_list,
        } = value;
        if biconditional_list.is_empty() {
            conditional.into()
        } else {
            biconditional_list
                .iter()
                .fold(conditional.into(), |left: Proposition, b| {
                    Proposition::BiImplication(BiImplication {
                        left: Box::new(left),
                        right: Box::new((&b.conditional).into()),
                    })
                })
        }
    }
}

impl From<&crate::raa_tt_grammar_trait::Conditional<'_>> for Proposition {
    fn from(value: &crate::raa_tt_grammar_trait::Conditional<'_>) -> Self {
        let crate::raa_tt_grammar_trait::Conditional {
            disjunction,
            conditional_list,
        } = value;
        if conditional_list.is_empty() {
            disjunction.into()
        } else {
            conditional_list
                .iter()
                .fold(disjunction.into(), |left: Proposition, b| {
                    Proposition::Implication(Implication {
                        left: Box::new(left),
                        right: Box::new((&b.disjunction).into()),
                    })
                })
        }
    }
}

impl From<&crate::raa_tt_grammar_trait::Disjunction<'_>> for Proposition {
    fn from(value: &crate::raa_tt_grammar_trait::Disjunction<'_>) -> Self {
        let crate::raa_tt_grammar_trait::Disjunction {
            conjunction,
            disjunction_list,
        } = value;
        if disjunction_list.is_empty() {
            conjunction.into()
        } else {
            disjunction_list
                .iter()
                .fold(conjunction.into(), |left: Proposition, b| {
                    Proposition::Disjunction(Disjunction {
                        left: Box::new(left),
                        right: Box::new((&b.conjunction).into()),
                    })
                })
        }
    }
}

impl From<&crate::raa_tt_grammar_trait::Conjunction<'_>> for Proposition {
    fn from(value: &crate::raa_tt_grammar_trait::Conjunction<'_>) -> Self {
        let crate::raa_tt_grammar_trait::Conjunction {
            factor,
            conjunction_list,
        } = value;
        if conjunction_list.is_empty() {
            factor.into()
        } else {
            conjunction_list
                .iter()
                .fold(factor.into(), |left: Proposition, b| {
                    Proposition::Conjunction(Conjunction {
                        left: Box::new(left),
                        right: Box::new((&b.factor).into()),
                    })
                })
        }
    }
}

impl From<&crate::raa_tt_grammar_trait::Factor<'_>> for Proposition {
    fn from(value: &crate::raa_tt_grammar_trait::Factor<'_>) -> Self {
        match value {
            crate::raa_tt_grammar_trait::Factor::Var(crate::raa_tt_grammar_trait::FactorVar {
                var,
            }) => Proposition::Atom(var.var.text().to_owned()),
            crate::raa_tt_grammar_trait::Factor::Negation(f) => Proposition::Negation(Negation {
                inner: Box::new((&f.negation.factor).into()),
            }),
            crate::raa_tt_grammar_trait::Factor::LParBiconditionalRPar(b) => {
                (&*b.biconditional).into()
            }
        }
    }
}