summaryrefslogtreecommitdiff
path: root/nfa
diff options
context:
space:
mode:
authorJSDurand <mmemmew@gmail.com>2023-07-08 12:30:21 +0800
committerJSDurand <mmemmew@gmail.com>2023-07-08 12:31:13 +0800
commit9a317e56f8a6126583f7d0c431bf878d9b1fe7b1 (patch)
tree7bb6004196b38446a5ab0cb3a0ab642d35f113e9 /nfa
parent691f969eb104fa3d4c2a1667693fd0382eb9d6b5 (diff)
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.
Diffstat (limited to 'nfa')
-rw-r--r--nfa/src/default/regex.rs70
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> {