diff options
Diffstat (limited to 'nfa')
-rw-r--r-- | nfa/src/default/regex.rs | 70 |
1 files changed, 65 insertions, 5 deletions
diff --git a/nfa/src/default/regex.rs b/nfa/src/default/regex.rs index 1b1b325..9b5fab1 100644 --- a/nfa/src/default/regex.rs +++ b/nfa/src/default/regex.rs @@ -1,6 +1,9 @@ //! This file provides a default implementation of Regex. -use graph::{error::Error as GError, ALGraph, ExtGraph, Graph, GraphLabel}; +use graph::{ + adlist::ALGBuilderMut, builder::BuilderMut, error::Error as GError, ALGraph, ExtGraph, Graph, + GraphLabel, +}; use crate::{desrec::DesRec, error::Error, Regex}; @@ -10,6 +13,7 @@ use graph_macro::Graph; use receme::{algebra::Algebra, catana::Cata}; use std::{ + borrow::BorrowMut, collections::HashMap, fmt::{Debug, Display, Write}, marker::PhantomData, @@ -271,10 +275,8 @@ impl<T: GraphLabel> DefaultRegex<T> { if !top.is_seen() { stack.push(Seen(top.index())); - if self.degree(top.index()).unwrap() > 1 { - write!(result, "(")?; - stack.push(Unseen(types.len() - 1)); - } + write!(result, "(")?; + stack.push(Unseen(types.len() - 1)); stack.extend( self.graph @@ -289,7 +291,11 @@ impl<T: GraphLabel> DefaultRegex<T> { } RegexType::Plus => { if !top.is_seen() { + write!(result, "(")?; + stack.push(Seen(top.index())); + stack.push(Unseen(types.len() - 1)); + stack.extend( self.graph .children_of(top.index()) @@ -303,7 +309,11 @@ impl<T: GraphLabel> DefaultRegex<T> { } RegexType::Optional => { if !top.is_seen() { + write!(result, "(")?; + stack.push(Seen(top.index())); + stack.push(Unseen(types.len() - 1)); + stack.extend( self.graph .children_of(top.index()) @@ -504,6 +514,56 @@ impl<T: GraphLabel> DefaultRegex<T> { Ok(result) } + + /// Use a function transform the labels of a regular expression. + pub fn maps_to<S: GraphLabel, E>( + &self, + f: impl Fn(T) -> Result<S, E>, + ) -> Result<DefaultRegex<S>, E> { + let root = self.root(); + + let graph = self.internal_graph(); + + let types: Vec<RegexType<S>> = self + .types + .iter() + .map(|element| match element { + RegexType::Lit(value) => f(*value).map(RegexType::Lit), + RegexType::Kleene => Ok(RegexType::Kleene), + RegexType::Plus => Ok(RegexType::Plus), + RegexType::Optional => Ok(RegexType::Optional), + RegexType::Or => Ok(RegexType::Or), + RegexType::Paren => Ok(RegexType::Paren), + RegexType::Empty => Ok(RegexType::Empty), + }) + .collect::<Result<_, E>>()?; + + Ok(DefaultRegex { graph, types, root }) + } + + /// Append another regular expression to the end of this regular + /// expression. + pub fn append(&mut self, other: Self) { + if self.is_empty() { + // copy the other here + self.graph = other.graph; + self.types = other.types; + self.root = other.root; + } else if other.is_empty() { + // nothing to do + } else { + let mut builder_mut = ALGBuilderMut::from_graph_mut(self.graph.borrow_mut()); + + let old_len = builder_mut.nodes_len(); + + builder_mut.append(other.graph); + + if let Some(root) = self.root { + // Deliberately ignore errors here. + let _ = builder_mut.add_edge(root, old_len, ()); + } + } + } } impl<T: GraphLabel> Display for DefaultRegex<T> { |