From 9a317e56f8a6126583f7d0c431bf878d9b1fe7b1 Mon Sep 17 00:00:00 2001 From: JSDurand Date: Sat, 8 Jul 2023 12:30:21 +0800 Subject: Finished the Emacs binding. Now the binding part is finished. What remains is a bug encountered when planting a fragment to the forest which intersects a packed node, which would lead to invalid forests. This will also cause problem when planting a packed fragment, but until now my testing grammars do not produce packed fragments, so this problem is not encountered yet. I am still figuring out efficient ways to solve this problem. --- nfa/src/default/regex.rs | 70 ++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 65 insertions(+), 5 deletions(-) (limited to 'nfa/src') 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 DefaultRegex { 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 DefaultRegex { } 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 DefaultRegex { } 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 DefaultRegex { Ok(result) } + + /// Use a function transform the labels of a regular expression. + pub fn maps_to( + &self, + f: impl Fn(T) -> Result, + ) -> Result, E> { + let root = self.root(); + + let graph = self.internal_graph(); + + let types: Vec> = 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::>()?; + + 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 Display for DefaultRegex { -- cgit v1.2.3-18-g5258