diff --git a/src/token/mod.rs b/src/token/mod.rs index f80cf86..12fe5ac 100644 --- a/src/token/mod.rs +++ b/src/token/mod.rs @@ -124,44 +124,83 @@ impl From for When { } #[derive(Clone, Copy, Debug, Eq, PartialEq)] -pub enum Composition { - Conjunctive(T), - Disjunctive(T), +pub enum Composition { + Conjunctive(C), + Disjunctive(D), } -impl Composition { - pub fn into_inner(self) -> T { +pub type TokenComposition = Composition; + +impl Composition { + pub fn map_conjunctive(self, f: F) -> Composition + where + F: FnOnce(C) -> T, + { match self { - Composition::Conjunctive(inner) | Composition::Disjunctive(inner) => inner, + Composition::Conjunctive(inner) => Composition::Conjunctive(f(inner)), + Composition::Disjunctive(inner) => Composition::Disjunctive(inner), } } - pub fn map(self, f: F) -> Composition + pub fn map_disjunctive(self, f: F) -> Composition where - F: FnOnce(T) -> U, + F: FnOnce(D) -> T, { match self { - Composition::Conjunctive(inner) => Composition::Conjunctive(f(inner)), + Composition::Conjunctive(inner) => Composition::Conjunctive(inner), Composition::Disjunctive(inner) => Composition::Disjunctive(f(inner)), } } - pub fn conjunctive(self) -> Option { + pub fn conjunctive(self) -> Option { match self { Composition::Conjunctive(inner) => Some(inner), _ => None, } } - pub fn disjunctive(self) -> Option { + pub fn disjunctive(self) -> Option { match self { Composition::Disjunctive(inner) => Some(inner), _ => None, } } + + pub fn as_ref(&self) -> Composition<&C, &D> { + match self { + Composition::Conjunctive(ref inner) => Composition::Conjunctive(inner), + Composition::Disjunctive(ref inner) => Composition::Disjunctive(inner), + } + } +} + +impl Composition { + pub fn into_inner(self) -> T { + match self { + Composition::Conjunctive(inner) | Composition::Disjunctive(inner) => inner, + } + } + + pub fn map(self, f: F) -> Composition + where + F: FnOnce(T) -> U, + { + match self { + Composition::Conjunctive(inner) => Composition::Conjunctive(f(inner)), + Composition::Disjunctive(inner) => Composition::Disjunctive(f(inner)), + } + } + + pub fn get(&self) -> &T { + AsRef::as_ref(self) + } + + pub fn get_mut(&mut self) -> &mut T { + AsMut::as_mut(self) + } } -impl AsMut for Composition { +impl AsMut for Composition { fn as_mut(&mut self) -> &mut T { match self { Composition::Conjunctive(ref mut inner) => inner, @@ -170,7 +209,7 @@ impl AsMut for Composition { } } -impl AsRef for Composition { +impl AsRef for Composition { fn as_ref(&self) -> &T { match self { Composition::Conjunctive(ref inner) => inner, @@ -354,7 +393,7 @@ impl<'t, A> Token<'t, A> { } } - pub fn tokens(&self) -> Option> { + pub fn tokens(&self) -> Option> { self.as_branch().map(BranchKind::tokens) } @@ -397,7 +436,7 @@ impl<'t, A> Token<'t, A> { } } - pub fn composition(&self) -> Composition<()> { + pub fn composition(&self) -> TokenComposition<()> { self.as_branch() .map_or(Composition::Conjunctive(()), |branch| branch.composition()) } @@ -530,9 +569,9 @@ impl<'t, A> Token<'t, A> { // NOTE: False positives in this function may cause logic errors and are completely // unacceptable. The discovery of a false positive here is likely a serious bug. pub fn is_exhaustive(&self) -> bool { - type TokenComposition<'i, 't, A> = Composition>; + type TokenNode<'i, 't, A> = TokenComposition>; - impl<'i, 't, A> TokenComposition<'i, 't, A> { + impl<'i, 't, A> TokenNode<'i, 't, A> { // NOTE: This differs from the `VarianceFold` implementations for branch tokens. fn fold(&mut self, depth: VarianceOf) { use Bound::Unbounded; @@ -569,7 +608,7 @@ impl<'t, A> Token<'t, A> { fn finalize(self, parent: Option<&mut Self>) -> Result, ()> { use Variance::{Invariant, Variant}; - let sum = self.as_ref(); + let sum = self.get(); let term = sum.branch.map_or(sum.depth, |branch| match branch { branch @ BranchKind::Repetition(_) => match sum.depth { // When folding a term into a repetition, only finalize variant terms @@ -597,7 +636,7 @@ impl<'t, A> Token<'t, A> { } } - impl<'i, 't, A> From<&'i BranchKind<'t, A>> for TokenComposition<'i, 't, A> { + impl<'i, 't, A> From<&'i BranchKind<'t, A>> for TokenNode<'i, 't, A> { fn from(branch: &'i BranchKind<'t, A>) -> Self { let sum = TokenSum { depth: Variance::identity(), @@ -618,13 +657,13 @@ impl<'t, A> Token<'t, A> { } } - impl<'i, 't, A> From<&'i Token<'t, A>> for TokenComposition<'i, 't, A> { + impl<'i, 't, A> From<&'i Token<'t, A>> for TokenNode<'i, 't, A> { fn from(token: &'i Token<'t, A>) -> Self { if let Some(branch) = token.as_branch() { Self::from(branch) } else { - TokenComposition::Conjunctive(TokenSum { + TokenNode::Conjunctive(TokenSum { depth: Variance::identity(), branch: None, tokens: vec![token], @@ -692,17 +731,17 @@ impl<'t, A> Token<'t, A> { } } - let mut tokens = vec![TokenComposition::from(self)]; - 'composition: while let Some(mut composition) = tokens.pop() { - eprintln!("Popped composition: {}", display_sum(composition.as_ref())); - 'sum: while let Some(token) = composition.as_mut().tokens.pop() { + let mut tokens = vec![TokenNode::from(self)]; + 'node: while let Some(mut node) = tokens.pop() { + eprintln!("Popped node: {}", display_sum(node.get())); + 'sum: while let Some(token) = node.as_mut().tokens.pop() { eprintln!("Popped token: {}", display_token(&token)); match token.topology() { TokenTopology::Branch(branch) => { - eprintln!("Pushing composition and token."); - tokens.push(composition); + eprintln!("Pushing node and token."); + tokens.push(node); tokens.push(branch.into()); - continue 'composition; + continue 'node; }, TokenTopology::Leaf(leaf) => { if let None | Some(Boundary::Component) = token.boundary() { @@ -715,39 +754,33 @@ impl<'t, A> Token<'t, A> { breadth, text, ); - let sum = composition.as_mut(); + let sum = node.as_mut(); if sum .depth .variant() .map_or(true, |bound| bound.upper().into_bound().is_bounded()) { eprintln!( - "Composition has bounded depth: {:?}. Resetting.", - sum.depth + "Node has bounded depth: {:?}. Resetting.", + sum.depth, ); sum.reset(); } - eprintln!( - "Composition is now: {}", - display_sum(composition.as_ref()) - ); + eprintln!("Node is now: {}", display_sum(node.get())); break 'sum; } eprintln!("Token has unbounded breadth and text."); } let depth = leaf.term(); - eprintln!("Folding token depth into composition: {:?}", depth); - composition.fold(depth); - eprintln!("Composition is now: {}", display_sum(composition.as_ref())); + eprintln!("Folding token depth into node: {:?}", depth); + node.fold(depth); + eprintln!("Node is now: {}", display_sum(node.get())); }, } } - eprintln!("Stopped or exhausted tokens in composition. Finalizing."); - if let Ok(term) = composition.finalize(tokens.last_mut()) { - eprintln!( - "Exhausted compositions in tree. Exiting.\n\tDepth: {:?}", - term - ); + eprintln!("Stopped or exhausted tokens in node. Finalizing."); + if let Ok(term) = node.finalize(tokens.last_mut()) { + eprintln!("Exhausted nodes in tree. Exiting.\n\tDepth: {:?}", term); //return term.is_unbounded(); return term .variant() @@ -954,7 +987,7 @@ impl<'t, A> BranchKind<'t, A> { } } - pub fn tokens(&self) -> Composition<&[Token<'t, A>]> { + pub fn tokens(&self) -> TokenComposition<&[Token<'t, A>]> { use BranchKind::{Alternation, Concatenation, Repetition}; use Composition::{Conjunctive, Disjunctive}; @@ -965,7 +998,7 @@ impl<'t, A> BranchKind<'t, A> { } } - pub fn composition(&self) -> Composition<()> { + pub fn composition(&self) -> TokenComposition<()> { self.tokens().map(|_| ()) }