From 918235659f7b0d80bfa305875ab7cc988cc51761 Mon Sep 17 00:00:00 2001 From: JSDurand Date: Fri, 16 Oct 2026 18:16:36 +0800 Subject: partial commit, before trying the new guide by claude --- chain/src/lib.rs | 72 +++++++++++++++++++++++++++++++++++++++++++------------- 1 file changed, 56 insertions(+), 16 deletions(-) (limited to 'chain/src/lib.rs') 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 { 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); -- cgit v1.2.3-18-g5258