diff options
author | JSDurand <mmemmew@gmail.com> | 2022-11-15 12:01:28 +0800 |
---|---|---|
committer | JSDurand <mmemmew@gmail.com> | 2022-11-15 12:01:28 +0800 |
commit | cb7bcfad4ab0041aaf3fde3185e27ee46bb37788 (patch) | |
tree | a4fd99b138b72617b6c4c2b04f5d2655d0fedcc5 /nfa/src/default/mod.rs |
Initial commit
Basic GNU standard files are added, and we now stop worrying about
monadic anamorphisms.
The current focus is on testing the correctness of the algorithm, so I
need convenient support for manipulating, interpreting, examining, and
per chance animating nondeterministic automata.
Diffstat (limited to 'nfa/src/default/mod.rs')
-rw-r--r-- | nfa/src/default/mod.rs | 123 |
1 files changed, 123 insertions, 0 deletions
diff --git a/nfa/src/default/mod.rs b/nfa/src/default/mod.rs new file mode 100644 index 0000000..805540b --- /dev/null +++ b/nfa/src/default/mod.rs @@ -0,0 +1,123 @@ +//! This file provides a structure that implements the trait +//! [`NFA`][super::Nfa]. +//! +//! It is used as the default implementation. + +use graph::{error::Error as GError, DLGraph, Graph, GraphLabel, LabelGraph}; + +use super::{error::Error, Nfa, Regex}; + +// TODO: Store the regular expression in the NFA as well. +// +// The current focus of the project is to understand the growth rate +// of the algorithm, to know whether I made a mistake in the previous +// iteration of the implementation, or the algorithm is not as fast as +// the author estimated, which is not quite likely, of course. +// +// Thus I shall establish a friendly interface that allows me to view +// and debug the atomic languages and the languages, transparently. + +#[non_exhaustive] +#[derive(Debug)] +/// Default NFA implementation. +pub struct DefaultNFA<T: GraphLabel> { + graph: DLGraph<T>, +} + +impl<T: GraphLabel> Default for DefaultNFA<T> { + fn default() -> Self { + let graph = Default::default(); + Self { graph } + } +} + +impl<T: GraphLabel> Graph for DefaultNFA<T> { + type Iter<'a> = <DLGraph<T> as Graph>::Iter<'a> where T: 'a; + + #[inline] + fn is_empty(&self) -> bool { + self.graph.is_empty() + } + + #[inline] + fn nodes_len(&self) -> usize { + self.graph.nodes_len() + } + + #[inline] + fn children_of(&self, node_id: usize) -> Result<Self::Iter<'_>, GError> { + self.graph.children_of(node_id) + } + + #[inline] + fn degree(&self, node_id: usize) -> Result<usize, GError> { + self.graph.degree(node_id) + } + + #[inline] + fn is_empty_node(&self, node_id: usize) -> Result<bool, GError> { + self.graph.is_empty_node(node_id) + } + + #[inline] + fn has_edge(&self, source: usize, target: usize) -> Result<bool, GError> { + self.graph.has_edge(source, target) + } +} + +impl<T: GraphLabel> LabelGraph<T> for DefaultNFA<T> { + type Iter<'a> = <DLGraph<T> as LabelGraph<T>>::Iter<'a> where T: 'a; + + type LabelIter<'a> = <DLGraph<T> as LabelGraph<T>>::LabelIter<'a> where T: 'a; + + // TODO: Return the label from the contained regular language. + #[inline] + fn vertex_label(&self, node_id: usize) -> Result<Option<T>, GError> { + if self.has_node(node_id) { + todo!() + } else { + Err(GError::IndexOutOfBounds(node_id, self.nodes_len())) + } + } + + #[inline] + fn edge_label(&self, source: usize, target: usize) -> Result<Vec<T>, GError> { + self.graph.edge_label(source, target) + } + + #[inline] + fn find_children_with_label( + &self, + node_id: usize, + label: &T, + ) -> Result<<Self as LabelGraph<T>>::Iter<'_>, GError> { + self.graph.find_children_with_label(node_id, label) + } + + #[inline] + fn labels_of(&self, node_id: usize) -> Result<Self::LabelIter<'_>, GError> { + self.graph.labels_of(node_id) + } +} + +impl<T: GraphLabel> Nfa<T> for DefaultNFA<T> { + #[allow(unused)] + fn to_nfa(regex: impl Regex<T>) -> Self { + todo!() + } + + fn remove_epsilon(&mut self) -> Result<(), Error> { + todo!() + } + + fn remove_dead(&mut self) -> Result<(), Error> { + todo!() + } + + fn nulling(&mut self) -> Result<(), Error> { + todo!() + } +} + +#[cfg(test)] +mod default_nfa_test {} |