use crate::choices::{First, Second};
use crate::symbols::{Equivalence, Metasymbol, TerminalSymbol, E};
use std::collections::HashMap;
use std::hash::Hash;
#[derive(Clone, Debug, PartialEq)]
pub struct RightRule<T, V> {
pub first: First<E<T, V>>,
pub second: Second<E<T, V>>,
}
impl<T, V> RightRule<T, V> {
pub fn new(first: First<E<T, V>>, second: Second<E<T, V>>) -> Self {
Self { first, second }
}
pub fn from_right_rule_kind(
first: (RightRuleKind<T, V>, RightRuleKind<T, V>),
second: RightRuleKind<T, V>,
) -> Self {
Self {
first: First::new(first.0.into(), first.1.into()),
second: Second::new(second.into()),
}
}
}
pub enum RightRuleKind<T, V> {
Empty,
Failure,
Any(usize),
All,
T(T),
V(V),
}
impl<T, V> From<RightRuleKind<T, V>> for E<T, V> {
fn from(right_rule_kind: RightRuleKind<T, V>) -> Self {
match right_rule_kind {
RightRuleKind::Empty => Metasymbol::Empty.into(),
RightRuleKind::Failure => Metasymbol::Failure.into(),
RightRuleKind::Any(n) => Metasymbol::Any(n).into(),
RightRuleKind::All => Metasymbol::All.into(),
RightRuleKind::T(t) => E::T(TerminalSymbol::Original(t)),
RightRuleKind::V(v) => E::V(v),
}
}
}
pub type Rule<T, V> = Equivalence<V, RightRule<T, V>>;
pub trait Rules<T, V> {
fn get(&self, variable: &V) -> Option<&RightRule<T, V>>;
}
impl<T, V> Rules<T, V> for HashMap<V, RightRule<T, V>>
where
V: Eq + Hash,
{
fn get(&self, variable: &V) -> Option<&RightRule<T, V>> {
self.get(variable)
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::symbols::{Metasymbol, TerminalSymbol};
#[test]
fn rules() {
#[derive(Copy, Clone, Debug, Hash, Eq, PartialEq)]
enum BinDigitTerminal {
Char(char),
}
#[derive(Copy, Clone, Debug, Hash, Eq, PartialEq)]
enum BinDigitVariable {
BinDigit,
One,
}
let mut rules: HashMap<BinDigitVariable, RightRule<BinDigitTerminal, BinDigitVariable>> =
HashMap::new();
rules.insert(
BinDigitVariable::BinDigit,
RightRule::new(
First::new(
TerminalSymbol::from_original(BinDigitTerminal::Char('0')).into(),
Metasymbol::Empty.into(),
),
Second::new(E::from_v(BinDigitVariable::One)),
),
);
rules.insert(
BinDigitVariable::One,
RightRule::new(
First::new(
TerminalSymbol::from_original(BinDigitTerminal::Char('1')).into(),
Metasymbol::Empty.into(),
),
Second::new(Metasymbol::Failure.into()),
),
);
let mut rules2: HashMap<BinDigitVariable, RightRule<BinDigitTerminal, BinDigitVariable>> =
HashMap::new();
rules2.insert(
BinDigitVariable::BinDigit,
RightRule::from_right_rule_kind(
(
RightRuleKind::T(BinDigitTerminal::Char('0')),
RightRuleKind::Empty,
),
RightRuleKind::V(BinDigitVariable::One),
),
);
rules2.insert(
BinDigitVariable::One,
RightRule::from_right_rule_kind(
(
RightRuleKind::T(BinDigitTerminal::Char('1')),
RightRuleKind::Empty,
),
RightRuleKind::Failure,
),
);
assert_eq!(
rules[&BinDigitVariable::BinDigit],
rules2[&BinDigitVariable::BinDigit]
);
assert_eq!(
rules[&BinDigitVariable::One],
rules2[&BinDigitVariable::One]
);
}
}