aboutsummaryrefslogtreecommitdiff
path: root/chain/src/lib.rs
diff options
context:
space:
mode:
authorJSDurand <mmemmew@gmail.com>2026-10-16 18:16:36 +0800
committerJSDurand <mmemmew@gmail.com>2026-10-16 18:16:36 +0800
commit918235659f7b0d80bfa305875ab7cc988cc51761 (patch)
treeee657d85a6954a9d4327cc0d938e605cbb8637d1 /chain/src/lib.rs
parentfba9a90cfc6aca2a26cce72f55fb261789139781 (diff)
partial commit, before trying the new guide by claudeattempt1
Diffstat (limited to 'chain/src/lib.rs')
-rw-r--r--chain/src/lib.rs72
1 files changed, 56 insertions, 16 deletions
diff --git a/chain/src/lib.rs b/chain/src/lib.rs
index 10143dd..24598a8 100644
--- a/chain/src/lib.rs
+++ b/chain/src/lib.rs
@@ -32,17 +32,21 @@ pub struct Edge {
true_source: PaVi,
/// Whether or not this edge is "accepting".
accepting: bool,
+ /// The non-terminal that starts this edge.
+ frame_nt: usize,
}
impl Edge {
/// Construct a new edge.
pub fn new(label: usize, forest_source: PaVi, accepting: bool) -> Self {
let true_source = forest_source;
+ let frame_nt = 0usize;
Self {
label,
forest_source,
accepting,
true_source,
+ frame_nt,
}
}
@@ -61,6 +65,24 @@ impl Edge {
self.forest_source
}
+ /// Return the frame non-terminal of the edge.
+ pub fn frame_nt(&self) -> usize {
+ self.frame_nt
+ }
+
+ /// Set the frame non-terminal.
+ pub fn set_frame_nt(&mut self, nt: usize) {
+ self.frame_nt = nt;
+ }
+
+ /// Build a new edge with a given frame non-terminal.
+ pub fn with_frame_nt(self, nt: usize) -> Self {
+ Self {
+ frame_nt: nt,
+ ..self
+ }
+ }
+
/// Set the associated forest edge of the edge of the edge.
pub fn set_forest_source(&mut self, source: PaVi) {
self.forest_source = source;
@@ -161,7 +183,7 @@ pub enum TwoLayers {
/// the source of the associated forest edge of the second layer,
/// and the third is a list of edges, which are the common first
/// layers.
- Two(usize, PaVi, bool, Vec<(Roi, usize)>),
+ Two(usize, PaVi, bool, usize, Vec<(Roi, usize)>),
}
/// The type of a collapsed iterator.
@@ -203,12 +225,22 @@ where
if let Some(two_layer) = self.iter.next() {
match two_layer {
TwoLayers::One(edge, to) => Some(Ok((edge, to))),
- TwoLayers::Two(label, forest_source, accepting, edges) => {
- let new_index = match self.chain.extend(
- edges
- .into_iter()
- .filter_map(|(roi, target)| roi.real_part().map(|edge| (edge, target))),
- ) {
+ TwoLayers::Two(label, forest_source, accepting, frame_nt, edges) => {
+ let imaginary: Vec<(Roi, usize)> = edges
+ .iter()
+ .filter(|(roi, _)| roi.imaginary_part().is_some())
+ .map(|(roi, target)| (*roi, *target))
+ .collect();
+
+ let real: Vec<(Edge, usize)> = edges
+ .into_iter()
+ .filter_map(|(roi, target)| roi.real_part().map(|edge| (edge, target)))
+ .collect();
+
+ let new_index = match self
+ .chain
+ .extend(real.iter().map(|(edge, target)| (*edge, *target)))
+ {
Ok(new) => new,
Err(error) => {
// Prevent further iterations.
@@ -218,8 +250,15 @@ where
}
};
+ if let Err(err) = self.chain.update_epsilon(new_index, imaginary.into_iter()) {
+ self.stop = true;
+ return Some(Err(err));
+ };
+
Some(Ok((
- Edge::new(label, forest_source, accepting).into(),
+ Edge::new(label, forest_source, accepting)
+ .with_frame_nt(frame_nt)
+ .into(),
new_index,
)))
}
@@ -302,15 +341,16 @@ pub trait Chain: LabelExtGraph<Edge> {
let edges = self.union(der_iter)?;
- let new_index = self.extend(
- edges
- .iter()
- .filter_map(|(roi, target)| roi.real_part().map(|edge| (edge, *target))),
- )?;
+ let real: Vec<(Edge, usize)> = edges
+ .iter()
+ .filter_map(|(roi, target)| roi.real_part().map(|edge| (edge, *target)))
+ .collect();
- if self.is_empty_node(new_index)? {
- self.update_epsilon(new_index, edges.into_iter())?;
- }
+ let new_index = self.extend(real.iter().map(|(edge, target)| (*edge, *target)))?;
+
+ // Imaginary edges can make the node accepting even when the
+ // node has real edges.
+ self.update_epsilon(new_index, edges.into_iter())?;
self.update_history(new_index);