summaryrefslogtreecommitdiff
path: root/chain/src/item/mod.rs
blob: 54ea168bcd944561e5539c92f17284ae6783739c (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
#![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<Parent> {
        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;