Skip to main content

cfg_history/
lib.rs

1//! Any data carried alongside a grammar rule can be its _history_. Rule histories may contain
2//! more than semantic actions.
3
4#![deny(unsafe_code)]
5#![warn(missing_docs)]
6
7use std::ops;
8
9use cfg_symbol::Symbol;
10use earley::{History, process_linked};
11
12use self::BinarizedRhsRange::*;
13
14pub mod earley;
15
16/// A history update to an existing history value,
17/// used with grammar transformations.
18#[derive(Clone, Debug)]
19pub enum LinkedHistoryNode {
20    /// Updates history during binarization of a rule.
21    /// Binarization is the process of making a rule with
22    /// any number of RHS symbols become a rule with
23    /// only one or two symbols on the RHS.
24    Binarize {
25        /// Tells us how high we are in a chain of binarized rules.
26        /// For example, when binarizing a rule A ::= B C D E, we get:
27        ///
28        /// - g0 ::= B C -- this is at height 0
29        ///
30        /// - g1 ::= g0 D -- this is at height 1
31        ///
32        /// - A ::= g1 E -- this is at height 2
33        height: u32,
34        /// Original length of the rule before binarization.
35        full_len: usize,
36        /// Whether we are at the highest rule.
37        is_top: bool,
38    },
39    /// Updates history after nulling rule elimination.
40    EliminateNulling {
41        /// The symbol at the first place in the RHS of the binarized rule
42        /// we are de-nulling, or `None` if the rule has zero symbols
43        /// to begin with.
44        rhs0: Option<Symbol>,
45        /// The symbol at the second place in the RHS of the binarized rule
46        /// we are de-nulling, or `None` if the rule has zero or one symbol
47        /// to begin with.
48        rhs1: Option<Symbol>,
49        /// Range of eliminated RHS symbols of the binary rule.
50        which: BinarizedRhsRange,
51    },
52    /// Updates history for rules built with the precedenced rule
53    /// builder.
54    AssignPrecedence {
55        /// Operator precedence, starting with highest
56        /// and loosening with increase.
57        looseness: u32,
58    },
59    /// Updates history of a rule made from a sequence rule.
60    RewriteSequence {
61        /// Whether this is the outermost level of derivation
62        /// among rules built by the sequence rewrite.
63        top: bool,
64        /// The symbol we are repeating.
65        rhs: Symbol,
66        /// Separator.
67        sep: Option<Symbol>,
68    },
69    /// The RHS as computed by the sequence rewrite.
70    /// The rule with this history was made from a sequence
71    /// rule.
72    SequenceRhs {
73        /// The RHS as computed by the sequence rewrite.
74        /// Up to three symbols may appear on the RHS.
75        rhs: [Option<Symbol>; 3],
76    },
77    /// Weight for generation for Probabilistic CFGs.
78    /// 
79    /// We generate by picking one of the alternatives
80    /// at random or from seed.
81    Weight {
82        /// Floating point weight.
83        weight: f64,
84    },
85    // Distances {
86    //     events: Vec<u32>,
87    // },
88}
89
90/// The basic semantics. They may receive further updates.
91#[derive(Clone, Copy, Debug)]
92pub enum RootHistoryNode {
93    /// Empty semantics.
94    NoOp,
95    /// This is a plain rule.
96    Rule {
97        /// Only the LHS is given. The RHS may be updated
98        /// through [`HistoryNodeRhs`].
99        lhs: Symbol,
100    },
101    /// This is a plain rule.
102    Origin {
103        /// Original rule ID is given.
104        origin: usize,
105    },
106}
107
108/// Provides information about the RHS of the rule
109/// we have semantics for.
110pub struct HistoryNodeRhs {
111    /// The history we are updating.
112    pub prev: History,
113    /// The rule RHS.
114    pub rhs: Vec<Symbol>,
115}
116
117/// Updates history during binarization of a rule.
118/// Binarization is the process of making a rule with
119/// any number of RHS symbols become a rule with
120/// only one or two symbols on the RHS.
121#[derive(Clone, Copy)]
122pub struct HistoryNodeBinarize {
123    /// The history we are updating.
124    pub prev: History,
125    /// Tells us how high we are in a chain of binarized rules.
126    /// For example, when binarizing a rule A ::= B C D E, we get:
127    ///
128    /// - g0 ::= B C -- this is at height 0
129    ///
130    /// - g1 ::= g0 D -- this is at height 1
131    ///
132    /// - A ::= g1 E -- this is at height 2
133    pub height: u32,
134    /// Original length of the rule before binarization.
135    pub full_len: usize,
136    /// Whether we are at the highest rule.
137    pub is_top: bool,
138}
139
140///
141#[derive(Clone, Copy)]
142pub struct HistoryNodeWeight {
143    /// The history we are updating.
144    pub prev: History,
145    /// Floating-point weight for generation for PCFGs.
146    pub weight: f64,
147}
148
149/// Updates history after nulling rule elimination.
150#[derive(Clone, Copy)]
151pub struct HistoryNodeEliminateNulling {
152    /// The history we are updating.
153    pub prev: History,
154    /// The symbol at the first place in the RHS of the binarized rule
155    /// we are de-nulling, or `None` if the rule has zero symbols
156    /// to begin with.
157    pub rhs0: Option<Symbol>,
158    /// The symbol at the secong place in the RHS of the binarized rule
159    /// we are de-nulling, or `None` if the rule has zero or one symbol
160    /// to begin with.
161    pub rhs1: Option<Symbol>,
162    /// Range of eliminated RHS symbols of the binary rule.
163    pub which: BinarizedRhsRange,
164}
165
166/// This is built with the precedenced rule builder.
167#[derive(Clone, Copy)]
168pub struct HistoryNodeAssignPrecedence {
169    /// The history we are updating.
170    pub prev: History,
171    /// Operator precedence, starting with highest
172    /// and loosening with increase.
173    pub looseness: u32,
174}
175
176/// This is built with the sequence rewrite.
177#[derive(Clone, Copy)]
178pub struct HistoryNodeRewriteSequence {
179    /// The history we are updating.
180    pub prev: History,
181    /// Whether this is the outermost level of derivation.
182    pub top: bool,
183    /// Symbol we are repating.
184    pub rhs: Symbol,
185    /// Our separator, or `None` for no separation.
186    pub sep: Option<Symbol>,
187}
188
189/// The RHS as computed by the sequence rewrite.
190#[derive(Clone, Copy)]
191pub struct HistoryNodeSequenceRhs {
192    /// The history we are updating.
193    pub prev: History,
194    /// The RHS as computed by the sequence rewrite.
195    /// Up to three symbols may appear on the RHS.
196    pub rhs: [Option<Symbol>; 3],
197}
198
199// impl From<HistoryNodeRhs> for HistoryNode {
200//     fn from(value: HistoryNodeRhs) -> Self {
201//         HistoryNode::Linked {
202//             prev: value.prev,
203//             node: LinkedHistoryNode::Rhs { rhs: value.rhs },
204//         }
205//     }
206// }
207
208impl From<HistoryNodeBinarize> for History {
209    fn from(value: HistoryNodeBinarize) -> Self {
210        process_linked(
211            &LinkedHistoryNode::Binarize {
212                height: value.height,
213                full_len: value.full_len,
214                is_top: value.is_top,
215            },
216            value.prev,
217        )
218    }
219}
220
221impl From<HistoryNodeWeight> for History {
222    fn from(value: HistoryNodeWeight) -> Self {
223        process_linked(
224            &LinkedHistoryNode::Weight {
225                weight: value.weight,
226            },
227            value.prev,
228        )
229    }
230}
231
232impl From<HistoryNodeEliminateNulling> for History {
233    fn from(value: HistoryNodeEliminateNulling) -> Self {
234        process_linked(
235            &LinkedHistoryNode::EliminateNulling {
236                rhs0: value.rhs0,
237                rhs1: value.rhs1,
238                which: value.which,
239            },
240            value.prev,
241        )
242    }
243}
244
245impl From<HistoryNodeAssignPrecedence> for History {
246    fn from(value: HistoryNodeAssignPrecedence) -> Self {
247        process_linked(
248            &LinkedHistoryNode::AssignPrecedence {
249                looseness: value.looseness,
250            },
251            value.prev,
252        )
253    }
254}
255
256impl From<HistoryNodeRewriteSequence> for History {
257    fn from(value: HistoryNodeRewriteSequence) -> Self {
258        process_linked(
259            &LinkedHistoryNode::RewriteSequence {
260                top: value.top,
261                rhs: value.rhs,
262                sep: value.sep,
263            },
264            value.prev,
265        )
266    }
267}
268
269impl From<HistoryNodeSequenceRhs> for History {
270    fn from(value: HistoryNodeSequenceRhs) -> Self {
271        process_linked(
272            &LinkedHistoryNode::SequenceRhs { rhs: value.rhs },
273            value.prev,
274        )
275    }
276}
277
278/// Used to inform history about which symbols on a rule's
279/// Symbol RHS are nullable, and will be eliminated.
280#[derive(Clone, Copy, Eq, PartialEq, Debug)]
281pub enum BinarizedRhsRange {
282    /// The first of two symbols.
283    Left,
284    /// The second of two symbols.
285    Right,
286    /// All 0, 1 or 2 symbols. The rule is nullable.
287    All(usize),
288}
289
290impl BinarizedRhsRange {
291    /// Turns this into a Rust `Range` of dot positions in a rule.
292    pub fn as_range(self) -> ops::Range<usize> {
293        match self {
294            Left => 0..1,
295            Right => 1..2,
296            All(num) => 0..num,
297        }
298    }
299
300    /// Flips the range to cover the rest of the rule RHS.
301    ///
302    /// # Panics
303    ///
304    /// Does not work with `All`.
305    pub fn negate(self) -> Self {
306        match self {
307            Left => Right,
308            Right => Left,
309            All(_) => unreachable!(),
310        }
311    }
312}