use std::convert::AsRef;
use crate::history::{HistoryNodeRhs, LinkedHistoryNode, RootHistoryNode};
use crate::precedence::PrecedencedRuleBuilder;
use crate::prelude::*;
pub struct RuleBuilder<C>
where
C: RuleContainer,
{
lhs: Option<Symbol>,
history: Option<HistoryId>,
rules: C,
}
impl<C> RuleBuilder<C>
where
C: RuleContainer,
{
pub fn new(rules: C) -> RuleBuilder<C> {
RuleBuilder {
lhs: None,
history: None,
rules: rules,
}
}
}
impl<C> RuleBuilder<C>
where
C: RuleContainer,
{
pub fn rule(mut self, lhs: Symbol) -> Self {
self.lhs = Some(lhs);
self.history = None;
self
}
pub fn history(mut self, history: HistoryId) -> Self {
self.history = Some(history);
self
}
pub fn rhs<S>(mut self, syms: S) -> Self
where
S: AsRef<[Symbol]>,
{
let new_history = match self.history.take() {
Some(history) => self.rules.add_history_node(
HistoryNodeRhs {
prev: history,
rhs: syms.as_ref().to_vec(),
}
.into(),
),
None => {
let base_id = self.rules.add_history_node(
RootHistoryNode::Rule {
lhs: self.lhs.unwrap(),
}
.into(),
);
self.rules.add_history_node(
HistoryNodeRhs {
prev: base_id,
rhs: syms.as_ref().to_vec(),
}
.into(),
)
}
};
self.rhs_with_history(syms, new_history)
}
pub fn rhs_with_history<Sr>(mut self, syms: Sr, history_id: HistoryId) -> Self
where
Sr: AsRef<[Symbol]>,
{
self.rules
.add_rule(self.lhs.unwrap(), syms.as_ref(), history_id);
self
}
pub fn rhs_with_linked_history<Sr>(
mut self,
syms: Sr,
linked_history: LinkedHistoryNode,
) -> Self
where
Sr: AsRef<[Symbol]>,
{
let base_id = self.rules.add_history_node(
RootHistoryNode::Rule {
lhs: self.lhs.unwrap(),
}
.into(),
);
let new_history = self.rules.add_history_node(
HistoryNodeRhs {
prev: base_id,
rhs: syms.as_ref().to_vec(),
}
.into(),
);
let history_id = self.rules.add_history_node(HistoryNode::Linked {
prev: new_history,
node: linked_history,
});
self.rules
.add_rule(self.lhs.unwrap(), syms.as_ref(), history_id);
self
}
pub fn precedenced_rule(self, lhs: Symbol) -> PrecedencedRuleBuilder<C> {
PrecedencedRuleBuilder::new(self.rules, lhs)
}
}