#![warn(missing_docs)] //! This module implements the type of items for the chain-rule //! machine. //! //! More specifically, it implements the iten derivation forests for //! the machine. use graph::{error::Error as GError, GraphLabel, LabelGraph, Parent, ParentsGraph}; use std::borrow::Borrow; use forest::{Forest, ForestLabel, ForestLabelError, ForestLabelType}; /// A parent or a virtual segment. /// /// # Parent /// /// A parent is a node with an edge index, which represents a certain /// edge. /// /// # 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 might 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, as I learned from experiences. /// /// # Empty /// /// Also this might be empty if it represents the root node. #[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Default)] pub enum PaVi { /// An edge from a node, as the n-th child, along with the /// nth-child node number. Parent(usize, 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 std::fmt::Display for PaVi { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { match self { Self::Parent(node, edge, child) => { write!(f, "the {edge}-th edge from {node} to {child}") } 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 PaVi { /// Get the Parent variant. fn parent(self) -> Option { if let Self::Parent(node, edge, _) = self { Some(Parent::new(node, edge)) } else { None } } fn is_virtual(self) -> bool { matches!(self, Self::Virtual(_, _, _)) } /// Is this an empty segment? fn is_empty(self) -> bool { self == Self::Empty } } pub mod default; pub mod genins; pub use genins::generate_fragment; pub mod reduction;