use super::*;
use alloc::borrow::Cow;
use alloc::collections::VecDeque;
use alloc::vec;
#[derive(Debug, Clone)]
pub(crate) struct UniConversionRule<'p> {
pub(crate) ante: &'p [parse::Element],
pub(crate) key: &'p [parse::Element],
pub(crate) post: &'p [parse::Element],
pub(crate) replacement: &'p [parse::Element],
}
pub(crate) type RuleGroups<'p> = Vec<(Vec<Cow<'p, parse::SingleId>>, Vec<UniConversionRule<'p>>)>;
enum UniRule<'p> {
Conversion(UniConversionRule<'p>),
Transform(Cow<'p, parse::SingleId>),
}
#[derive(Debug, Clone)]
pub(crate) struct ForwardRuleGroupAggregator<'p> {
current: ForwardRuleGroup<'p>,
groups: RuleGroups<'p>,
preceding_transform_group: Option<Vec<Cow<'p, parse::SingleId>>>,
}
impl<'p> ForwardRuleGroupAggregator<'p> {
pub(crate) fn new() -> Self {
Self {
current: ForwardRuleGroup::Transform(Vec::new()),
groups: Vec::new(),
preceding_transform_group: None,
}
}
pub(crate) fn push(&mut self, rule: &'p parse::Rule) {
match rule {
parse::Rule::Conversion(source_half, dir, target_half) => {
if !dir.permits(Direction::Forward) {
return;
}
let ante = &source_half.ante;
let key = &source_half.key;
let post = &source_half.post;
let replacement = &target_half.key;
let rule = UniConversionRule {
ante,
key,
post,
replacement,
};
let finished_group = self.current.push(UniRule::Conversion(rule));
if let Some(finished_group) = finished_group {
self.push_rule_group(finished_group);
}
}
parse::Rule::Transform(fwd, _) => {
let finished_group = self.current.push(UniRule::Transform(Cow::Borrowed(fwd)));
if let Some(finished_group) = finished_group {
self.push_rule_group(finished_group);
}
}
parse::Rule::VariableDefinition(..) => {
}
parse::Rule::GlobalFilter(..) | parse::Rule::GlobalInverseFilter(..) => {
}
}
}
fn push_rule_group(&mut self, group: ForwardRuleGroup<'p>) {
match group {
ForwardRuleGroup::Transform(transform_group) => {
debug_assert!(self.preceding_transform_group.is_none());
self.preceding_transform_group = Some(transform_group);
}
ForwardRuleGroup::Conversion(conversion_group) => {
let associated_transform_group =
self.preceding_transform_group.take().unwrap_or_default();
self.groups
.push((associated_transform_group, conversion_group));
}
}
}
pub(crate) fn finalize(mut self) -> RuleGroups<'p> {
self.push_rule_group(self.current.clone());
if let Some(transform_group) = self.preceding_transform_group.take() {
self.groups.push((transform_group, Vec::new()));
}
self.groups
}
}
#[derive(Debug, Clone)]
enum ForwardRuleGroup<'p> {
Conversion(Vec<UniConversionRule<'p>>),
Transform(Vec<Cow<'p, parse::SingleId>>),
}
impl<'p> ForwardRuleGroup<'p> {
fn new_conversion(rule: UniConversionRule<'p>) -> Self {
Self::Conversion(vec![rule])
}
fn new_transform(rule: Cow<'p, parse::SingleId>) -> Self {
Self::Transform(vec![rule])
}
fn push(&mut self, rule: UniRule<'p>) -> Option<Self> {
match (&mut *self, rule) {
(Self::Conversion(group), UniRule::Conversion(rule)) => {
group.push(rule);
None
}
(Self::Transform(group), UniRule::Transform(rule)) => {
group.push(rule);
None
}
(Self::Conversion(_), UniRule::Transform(new_rule)) => {
Some(core::mem::replace(self, Self::new_transform(new_rule)))
}
(Self::Transform(_), UniRule::Conversion(new_rule)) => {
Some(core::mem::replace(self, Self::new_conversion(new_rule)))
}
}
}
}
#[derive(Debug, Clone)]
pub(crate) struct ReverseRuleGroupAggregator<'p> {
current: ReverseRuleGroup<'p>,
groups: VecDeque<(Vec<Cow<'p, parse::SingleId>>, Vec<UniConversionRule<'p>>)>,
preceding_conversion_group: Option<Vec<UniConversionRule<'p>>>,
}
impl<'p> ReverseRuleGroupAggregator<'p> {
pub(crate) fn new() -> Self {
Self {
current: ReverseRuleGroup::Conversion(Vec::new()),
groups: VecDeque::new(),
preceding_conversion_group: None,
}
}
pub(crate) fn push(&mut self, rule: &'p parse::Rule) {
match rule {
parse::Rule::Conversion(target_half, dir, source_half) => {
if !dir.permits(Direction::Reverse) {
return;
}
let ante = &source_half.ante;
let key = &source_half.key;
let post = &source_half.post;
let replacement = &target_half.key;
let rule = UniConversionRule {
ante,
key,
post,
replacement,
};
let finished_group = self.current.push(UniRule::Conversion(rule));
if let Some(finished_group) = finished_group {
self.push_rule_group(finished_group);
}
}
parse::Rule::Transform(fwd, rev) => {
let rev = rev.clone().unwrap_or_else(|| fwd.clone().reverse());
let finished_group = self.current.push(UniRule::Transform(Cow::Owned(rev)));
if let Some(finished_group) = finished_group {
self.push_rule_group(finished_group);
}
}
parse::Rule::VariableDefinition(..) => {
}
parse::Rule::GlobalFilter(..) | parse::Rule::GlobalInverseFilter(..) => {
}
}
}
fn push_rule_group(&mut self, group: ReverseRuleGroup<'p>) {
match group {
ReverseRuleGroup::Conversion(conv_group) => {
debug_assert!(self.preceding_conversion_group.is_none());
self.preceding_conversion_group = Some(conv_group);
}
ReverseRuleGroup::Transform(transform_group) => {
let associated_conv_group =
self.preceding_conversion_group.take().unwrap_or_default();
let vec_transform_group = transform_group.into(); self.groups
.push_front((vec_transform_group, associated_conv_group));
}
}
}
pub(crate) fn finalize(mut self) -> RuleGroups<'p> {
self.push_rule_group(self.current.clone());
if let Some(conv_group) = self.preceding_conversion_group.take() {
self.groups.push_front((Vec::new(), conv_group));
}
self.groups.into() }
}
#[derive(Debug, Clone)]
enum ReverseRuleGroup<'p> {
Conversion(Vec<UniConversionRule<'p>>),
Transform(VecDeque<Cow<'p, parse::SingleId>>),
}
impl Default for ReverseRuleGroup<'_> {
fn default() -> Self {
Self::Conversion(Vec::new())
}
}
impl<'p> ReverseRuleGroup<'p> {
fn new_conversion(rule: UniConversionRule<'p>) -> Self {
Self::Conversion(vec![rule])
}
fn new_transform(rule: Cow<'p, parse::SingleId>) -> Self {
let mut group = VecDeque::new();
group.push_front(rule);
Self::Transform(group)
}
fn push(&mut self, rule: UniRule<'p>) -> Option<Self> {
match (&mut *self, rule) {
(Self::Conversion(group), UniRule::Conversion(rule)) => {
group.push(rule);
None
}
(Self::Transform(group), UniRule::Transform(rule)) => {
group.push_front(rule);
None
}
(Self::Conversion(_), UniRule::Transform(new_rule)) => {
Some(core::mem::replace(self, Self::new_transform(new_rule)))
}
(Self::Transform(_), UniRule::Conversion(new_rule)) => {
Some(core::mem::replace(self, Self::new_conversion(new_rule)))
}
}
}
}