diff options
author | JSDurand <mmemmew@gmail.com> | 2023-02-27 12:36:41 +0800 |
---|---|---|
committer | JSDurand <mmemmew@gmail.com> | 2023-02-27 12:36:41 +0800 |
commit | fbaa420ed550e9c3e7cdc09d4a8ec22bfbd782a6 (patch) | |
tree | fad9722825bb3fa796dd52c3fd4a8bf46b958cf9 /chain/src/item/mod.rs | |
parent | afad02bdff111ecccb0077b9c989e869723c231c (diff) |
before a major refactor
I decide to adopt a new approach of recording and updating item
derivation forests. Since this affects a lot of things, I decide to
commit before the refactor, so that I can create a branch for that
refactor.
Diffstat (limited to 'chain/src/item/mod.rs')
-rw-r--r-- | chain/src/item/mod.rs | 85 |
1 files changed, 61 insertions, 24 deletions
diff --git a/chain/src/item/mod.rs b/chain/src/item/mod.rs index 284d640..39d04c7 100644 --- a/chain/src/item/mod.rs +++ b/chain/src/item/mod.rs @@ -9,43 +9,64 @@ use graph::{error::Error as GError, GraphLabel, LabelGraph, Parent, ParentsGraph use core::borrow::Borrow; -/// A parent or a segment. +/// A parent or a virtual segment. +/// +/// # Parent /// /// A parent is a node with an edge index, which represents a certain /// edge. /// -/// A segment represents every edge from the root node to the single -/// terminating node. -#[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)] -pub enum PaSe { +/// # Virtual Segment +/// +/// A virtual segment represents an expansion from a non-terminal by a +/// terminal. We do not directly add this segment when we encounter +/// this expansion at the start because this expansion might contain +/// multiple derivations some of which will not be used. +/// +/// If we add the expansion immediately when we encounter it, we have +/// to later discern and delete those unwanted derivations. This is +/// asking for trouble, in my experiences. +#[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Default)] +pub enum PaVi { /// An edge from a node, as the n-th child. Parent(usize, usize), - /// A segment from a root to the single terminating node. - Segment(usize, usize), + /// A virtual segment from a non-terminal by a terminal, rooted at + /// a node. + /// + /// # Tuple elements + /// + /// The contained tuple is of the form (nt, t, node), which means + /// a virtually added node at the `node` representing the + /// expansion from the non-terminal `nt` by the terminal `t`. + Virtual(usize, usize, usize), + /// This is an empty segment that represents the root node. This + /// is a special case for the unit state of the chain-rule + /// machine. + #[default] + Empty, } -impl From<Parent> for PaSe { +impl From<Parent> for PaVi { fn from(value: Parent) -> Self { Self::Parent(value.node(), value.edge()) } } -impl Default for PaSe { - fn default() -> Self { - Self::Segment(0, 0) - } -} - -impl core::fmt::Display for PaSe { +impl core::fmt::Display for PaVi { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { match self { Self::Parent(node, edge) => write!(f, "the {edge}-th edge from {node}"), - Self::Segment(root, leaf) => write!(f, "a segment from {root} to {leaf}"), + Self::Virtual(nt, t, node) => write!( + f, + "a virtual node for non-terminal {nt} and terminal {t} at node {node}" + ), + Self::Empty => write!(f, "empty segment at root"), } } } -impl PaSe { +impl PaVi { + /// Get the Parent variant. fn parent(self) -> Option<Parent> { if let Self::Parent(node, edge) = self { Some(Parent::new(node, edge)) @@ -54,12 +75,29 @@ impl PaSe { } } - fn segment(self) -> Option<(usize, usize)> { - if let Self::Segment(root, leaf) = self { - Some((root, leaf)) - } else { - None - } + // /// Get the "Virtual" variant. + // /// + // /// # Name + // /// + // /// We cannot use the name "virtual" since it is a reserved + // /// keyword in Rust, so we use its French name. + // /// + // /// # Tuple elements + // /// + // /// The returned tuple is of the form (nt, t, node), which means a + // /// virtually added node at the `node` representing the expansion + // /// from the non-terminal `nt` by the terminal `t`. + // fn virtuel(self) -> Option<(usize, usize, usize)> { + // if let Self::Virtual(nt, t, node) = self { + // Some((nt, t, node)) + // } else { + // None + // } + // } + + /// Is this an empty segment? + fn is_empty(self) -> bool { + self == Self::Empty } } @@ -101,7 +139,6 @@ impl<T: GraphLabel> core::fmt::Display for ForestLabel<T> { } /// The type of erros for converting forest labels. -#[non_exhaustive] #[derive(Debug, Copy, Clone, Ord, PartialOrd, Eq, PartialEq)] pub enum ForestLabelError { /// Try to pack a cloned node. |