Skip to main content

wagon_gll/
state.rs

1use std::{collections::{HashSet, HashMap}, rc::Rc, usize};
2
3use indexmap::IndexSet;
4use petgraph::{Direction::Outgoing, prelude::EdgeIndex};
5use regex_automata::dfa::Automaton;
6
7use crate::{label::RegexTerminal, value::Value, AttributeKey, AttributeMap, GLLResult, ReturnMap};
8use crate::{GLLImplementationError, ImplementationResult, GLLError};
9use crate::{gss::{GSS, GSSNodeIndex, GSSNode}, sppf::{SPPF, SPPFNodeIndex, SPPFNode}, descriptor::Descriptor, GrammarSlot, ParseResult, GLLParseError, Terminal, Ident, ROOT_UUID, GLLBlockLabel};
10
11/// A map from a uuid to a specific [`GLLBlockLabel`].
12pub type LabelMap<'a> = HashMap<&'a str, GLLBlockLabel<'a>>;
13/// A map representing a rule and the constituent [`Ident`]s of that rule. 
14pub type RuleMap<'a> = HashMap<&'a str, Rc<Vec<Ident>>>;
15/// A map from a regular expression to the [`RegexTerminal`] that it represents.
16pub type RegexMap<'a> = HashMap<&'a str, Rc<RegexTerminal<'a>>>;
17
18/// The state object for the GLL parse process.
19///
20/// This object handles the bulk of the GLL parsing. It runs the code for the labels as needed, keeps track of
21/// the [`GSS`] and the [`SPPF`], holds the common methods etc.
22///
23/// # Example
24/// ```
25/// # use std::collections::HashMap;
26/// use wagon_gll::{GLLState, ParseResult, ROOT_UUID, Label, GLLBlockLabel, value::Value, LabelMap, RuleMap, RegexMap, ImplementationResult, GLLResult};
27/// use wagon_ident::Ident;
28/// use std::rc::Rc;
29/// #[derive(Debug)]
30/// struct Root;
31/// impl<'a> Label<'a> for Root {
32///#    fn first_set(&self, state: &wagon_gll::GLLState<'a>) -> ImplementationResult<'a, Vec<(Vec<wagon_gll::GLLBlockLabel<'a>>, Option<wagon_gll::Terminal<'a>>)>> {
33///#        Ok(vec![(vec![state.get_label_by_uuid(ROOT_UUID)?], None)])
34///#    }
35///#    fn is_eps(&self) -> bool {
36///#        false
37///#    }
38///#    fn uuid(&self) -> &str {
39///#        ROOT_UUID
40///#    }
41///#    fn to_string(&self) -> &str {
42///#        ROOT_UUID
43///#    }
44///#    fn str_parts(&self) -> Vec<&str> {
45///#        vec![ROOT_UUID]
46///#    }
47///#    fn code(&self, _: &mut wagon_gll::GLLState<'a>) -> GLLResult<'a, ()> {
48///#        unreachable!("This should never be called");
49///#    }
50///#    fn attr_rep_map(&self) -> (Vec<&str>, Vec<&str>) { 
51///#        (Vec::new(), Vec::new())
52///#    }
53///#    fn _weight(&self, _state: &wagon_gll::GLLState<'a>) -> Option<ImplementationResult<'a, Value<'a>>> {
54///#        unreachable!("This should never be called");
55///#    }
56/// }
57///# fn main() -> GLLResult<'static, ()> {
58///     let mut l_map: LabelMap = HashMap::new();
59///     let mut r_map: RuleMap = HashMap::new();
60///     let mut regex_map: RegexMap = HashMap::new();
61///     let root_label = Rc::new(Root{});
62///     let root_rule = Rc::new(vec![]);
63///     l_map.insert(ROOT_UUID, root_label);
64///     r_map.insert(ROOT_UUID, root_rule);
65///     let input = "".as_bytes();
66///     let mut state = GLLState::init(input, l_map, r_map, regex_map)?;
67///     state.main();
68///#    Ok(())
69///# }
70/// ```
71pub struct GLLState<'a> {
72    // Main structures
73    input: &'a [u8],
74    gss: GSS<'a>,
75    sppf: SPPF<'a>,
76    // Pointers
77    /// A pointer to where in the input we currently are.
78    ///
79    /// `C_i` in the original paper.
80    pub input_pointer: usize, //C_i
81    /// A pointer to where in the GSS we currently are.
82    ///
83    /// `C_u` in the original paper.
84    pub gss_pointer: GSSNodeIndex, // C_u
85    gss_root: GSSNodeIndex, // Points to <⊥, 0>
86    context_pointer: GSSNodeIndex, // Points to where the current context is stored
87    /// A pointer to where in the SPPF we currently are.
88    ///
89    /// `C_n` in the original paper.
90    pub sppf_pointer: SPPFNodeIndex, // C_n
91    /// A simple pointer to $ for comparison purposes.
92    pub sppf_root: SPPFNodeIndex, // Points to $
93    // Memoization
94    todo: IndexSet<Descriptor<'a>>, // R
95    visited: HashSet<Descriptor<'a>>, // U
96    pop: HashMap<GSSNodeIndex, Vec<SPPFNodeIndex>>, // P
97    // Easy Maps
98    gss_map: HashMap<Rc<GSSNode<'a>>, GSSNodeIndex>,
99    sppf_map: HashMap<SPPFNode<'a>, SPPFNodeIndex>,
100    label_map: LabelMap<'a>,
101    rule_map: RuleMap<'a>,
102    regex_map: RegexMap<'a>,
103    /// All the errors
104    pub errors: Vec<GLLError<'a>>
105}
106
107impl<'a> GLLState<'a> {
108    /// Initialize the state.
109    ///
110    /// Takes the input data as a byte-array. As well as a mapping of specific [`Label::uuid`](`crate::Label::uuid`) to the associated label and another mapping of a uuid to a specific rule. 
111    ///
112    /// # Errors
113    /// Returns [`GLLImplementationError::MissingRoot`] if no data was found in the `label_map` or `rule_map` for [`ROOT_UUID`]. 
114    pub fn init(input: &'a [u8], label_map: LabelMap<'a>, rule_map: RuleMap<'a>, regex_map: RegexMap<'a>) -> ImplementationResult<'a, Self> {
115        let mut sppf = SPPF::default();
116        let mut gss = GSS::default();
117        let mut sppf_map = HashMap::new();
118        let mut gss_map = HashMap::new();
119        let root_slot = Rc::new(GrammarSlot::new(label_map.get(ROOT_UUID).ok_or(GLLImplementationError::MissingRoot)?.clone(), rule_map.get(ROOT_UUID).ok_or(GLLImplementationError::MissingRoot)?.clone(), 0, 0, ROOT_UUID));
120        let gss_root_node = Rc::new(GSSNode::new(root_slot.clone(), 0, Vec::default()));
121        let sppf_root = sppf.add_node(SPPFNode::Dummy);
122        let gss_root = gss.add_node(gss_root_node.clone());
123        sppf_map.insert(SPPFNode::Dummy, sppf_root);
124        gss_map.insert(gss_root_node, gss_root);
125        let mut state = GLLState { 
126            input, 
127            gss, 
128            sppf, 
129            input_pointer: 0, 
130            gss_pointer: gss_root,
131            gss_root, 
132            context_pointer: gss_root,
133            sppf_pointer: sppf_root, 
134            sppf_root, 
135            todo: IndexSet::default(), 
136            visited: HashSet::default(), 
137            pop: HashMap::default(), 
138            gss_map, 
139            sppf_map,
140            rule_map,
141            label_map,
142            regex_map,
143            errors: Vec::default(),
144        };
145        state.add(root_slot, gss_root, 0, sppf_root, gss_root);
146        Ok(state)
147    }
148
149    /// Create a new GSS node.
150    ///
151    /// This is the `create` method in the original paper. The arguments to that method are mapped as follows:
152    /// * `L` => `slot`.
153    /// * `u` => `self.gss_pointer`.
154    /// * `i` => `self.input_pointer`.
155    /// * `w` => `self.sppf_pointer`.
156    ///
157    /// Differently from the paper, this method also takes a list of attributes that are passed along to the `GSS`.
158    ///
159    /// # Errors
160    /// Returns a [`GLLParseError`] if something unexpected happens.
161    pub fn create(&mut self, slot: &Rc<GrammarSlot<'a>>, args: AttributeMap<'a>) -> ImplementationResult<'a, GSSNodeIndex> {
162        let candidate = GSSNode::new(slot.clone(), self.input_pointer, args);
163        let v = self.find_or_create_gss_node(candidate);
164        if self.gss.find_edge(v, self.gss_pointer).is_none() {
165            self.gss.add_edge(v, self.gss_pointer, self.sppf_pointer);
166            let pop = std::mem::take(&mut self.pop); // scary again
167            if let Some(nodes) = pop.get(&v) {
168                for sppf_node in nodes {
169                    let y = self.get_node_p(slot.clone(), self.sppf_pointer, *sppf_node, v, v == self.gss_pointer)?;
170                    self.add(
171                        slot.clone(), 
172                        self.gss_pointer, 
173                        self.get_sppf_node(*sppf_node)?.right_extend()?, 
174                        y,
175                        v
176                    );
177                }
178            }
179            self.pop = pop;
180        }
181        Ok(v)
182    }
183
184    /// Try finding a packed node that is a child of `parent` and matches `ref_slot` and `i`.
185    fn get_packed_node(&self, parent: SPPFNodeIndex, ref_slot: &Rc<GrammarSlot<'a>>, i: usize, l: Option<SPPFNodeIndex>, r: SPPFNodeIndex) -> Option<SPPFNodeIndex> {
186        for child in self.sppf.neighbors_directed(parent, Outgoing) {
187            match self.sppf.node_weight(child) {
188                Some(SPPFNode::Packed { slot, split, left, right }) if slot == ref_slot && *split == i && *left == l && *right == r => return Some(child),
189                _ => {} 
190            }
191        }
192        None
193    }
194
195    /// Find or create an [`SPPFNode::Packed`].
196    ///
197    /// This is `get_node_p` from the original paper. Differently from that paper, this also takes a `context_pointer`, which tells the intermediate node we are
198    /// retrieving/creating where it can find it's context.
199    ///
200    /// # Errors
201    /// Returns an error either because something is inexplicably missing in one of the state datastructures, or because the weight evaluation failed.
202    pub fn get_node_p(&mut self, slot: Rc<GrammarSlot<'a>>, left: SPPFNodeIndex, right: SPPFNodeIndex, context_pointer: GSSNodeIndex, gss_cycle: bool) -> ImplementationResult<'a, SPPFNodeIndex> {
203        if self.is_special_slot(&slot)? {
204            Ok(right)
205        } else {
206            let left_node = self.get_sppf_node(left)?;
207            let right_node = self.get_sppf_node(right)?;
208            let j =  right_node.right_extend()?;
209            let (t, weight) = if slot.is_last(self) {
210                let new_slot = Rc::new(GrammarSlot { label: slot.label.clone(), rule: slot.rule.clone(), dot: slot.rule.len()+1, pos: 0, uuid: slot.uuid});
211                let weight = self.get_label(&slot.rule[0])._weight(self);
212                (new_slot, weight)
213            } else {
214                (slot.clone(), None)
215            };
216            if matches!(left_node, SPPFNode::Dummy) {
217                let i = right_node.left_extend()?;
218                let node = self.find_or_create_sppf_intermediate(&t, i, j, context_pointer)?;
219                if (gss_cycle || right != node) && self.get_packed_node(node, &slot, i, None, right).is_none() {
220                    let packed = SPPFNode::Packed { slot, split: i, left: None, right };
221                    let ix = self.sppf.add_node(packed);
222                    self.sppf.add_edge(ix, right, None);
223                    self.sppf.add_edge(node, ix, weight.transpose()?);
224                }
225                Ok(node)
226            } else {
227                let (i, k) = (left_node.left_extend()?, left_node.right_extend()?);
228                let node = self.find_or_create_sppf_intermediate(&t, i, j, context_pointer)?;
229                if (gss_cycle || (right != node && left != node)) && self.get_packed_node(node, &slot, k, Some(left), right).is_none() {
230                    let packed = SPPFNode::Packed { slot, split: k, left: Some(left), right };
231                    let ix = self.sppf.add_node(packed);
232                    self.sppf.add_edge(ix, left, None);
233                    self.sppf.add_edge(ix, right, None);
234                    self.sppf.add_edge(node, ix, weight.transpose()?);
235                }
236                Ok(node)
237            }
238        }
239    }
240
241    /// Find or create an [`SPPFNode::Symbol`].
242    ///
243    /// `get_node_t` from the original paper.
244    pub fn get_node_t(&mut self, terminal: &'a [u8], left: usize, right: usize) -> SPPFNodeIndex {
245        self.find_or_create_sppf_symbol(terminal, left, right)
246    }
247
248    /// Get the [`GSSNode`] `self.gss_pointer` is currently pointing to.
249    ///
250    /// # Errors
251    /// Returns [`GLLImplementationError::MissingGSSNode`] if for some inexplicable reason the node does not exist.
252    pub fn get_current_gss_node(&self) -> ImplementationResult<'a, &Rc<GSSNode<'a>>> {
253        self.get_gss_node(self.gss_pointer)
254    }
255
256    /// Get the [`SPPFNode`] `self.sppf_pointer` is currently pointing to.
257    ///
258    /// # Errors
259    /// Returns [`GLLImplementationError::MissingSPPFNode`] if for some inexplicable reason the node does not exist.
260    pub fn get_current_sppf_node(&self) -> ImplementationResult<'a, &SPPFNode<'a>> {
261        self.get_sppf_node(self.sppf_pointer)
262    }
263
264    pub(crate) fn get_sppf_node(&self, i: SPPFNodeIndex) -> ImplementationResult<'a, &SPPFNode<'a>> {
265        self.sppf.node_weight(i).ok_or_else(|| GLLImplementationError::MissingSPPFNode(i))
266    }
267
268    fn get_sppf_node_mut(&mut self, i: SPPFNodeIndex) -> ImplementationResult<'a, &mut SPPFNode<'a>> {
269        self.sppf.node_weight_mut(i).ok_or_else(|| GLLImplementationError::MissingSPPFNode(i))
270    }
271
272    fn get_gss_node(&self, i: GSSNodeIndex) -> ImplementationResult<'a, &Rc<GSSNode<'a>>> {
273        self.gss.node_weight(i).ok_or_else(|| GLLImplementationError::MissingGSSNode(i))
274    }
275
276    fn get_gss_edge_endpoints(&self, i: EdgeIndex) -> ImplementationResult<'a, (GSSNodeIndex, GSSNodeIndex)> {
277        self.gss.edge_endpoints(i).ok_or_else(|| GLLImplementationError::MissingGSSEdge(i))
278    }
279
280    fn get_gss_edge_weight(&self, i: EdgeIndex) -> ImplementationResult<'a, &SPPFNodeIndex> {
281        self.gss.edge_weight(i).ok_or_else(|| GLLImplementationError::MissingGSSEdge(i))
282    }
283
284    fn find_or_create_sppf_symbol(&mut self, terminal: &'a [u8], left: usize, right: usize) -> SPPFNodeIndex {
285        let candidate = SPPFNode::Symbol { terminal, left, right };
286        self.find_or_create_sppf(candidate)
287    }
288
289    fn find_or_create_sppf_intermediate(&mut self, slot: &Rc<GrammarSlot<'a>>, left: usize, right: usize, context_pointer: GSSNodeIndex) -> ImplementationResult<'a, SPPFNodeIndex> {
290        let context_node = self.get_gss_node(context_pointer)?.clone();
291        let candidate = SPPFNode::Intermediate { 
292            slot: slot.clone(), 
293            left, 
294            right, 
295            ret: Vec::default(), 
296            context: context_node,
297        };
298        Ok(self.find_or_create_sppf(candidate))
299    }
300
301    fn find_or_create_gss_node(&mut self, node: GSSNode<'a>) -> GSSNodeIndex {
302        if let Some(i) = self.gss_map.get(&node) {
303            i.to_owned()
304        } else {
305            let rc = Rc::new(node);
306            let i = self.gss.add_node(rc.clone());
307            self.gss_map.insert(rc, i);
308            i
309        }
310    }
311
312    /// Creates/Returns the index of an [`SPPFNode`].
313    ///
314    /// If a vertex with the exact same data as `candidate` already exists in the SPPF, we return that vertex. 
315    /// Otherwise, we create a new vertex with `candidate` as the data and return that.
316    fn find_or_create_sppf(&mut self, candidate: SPPFNode<'a>) -> SPPFNodeIndex {
317        if let Some(ix) = self.sppf_map.get(&candidate) {
318            *ix
319        } else {
320            let ix = self.sppf.add_node(candidate.clone());
321            self.sppf_map.insert(candidate, ix);
322            ix
323        }
324    }
325
326    /// Add a new slot to the `self.visited` and `self.todo` sets.
327    ///
328    /// `add` from the original paper.
329    pub fn add(&mut self, slot: Rc<GrammarSlot<'a>>, g: GSSNodeIndex, i: usize, s: SPPFNodeIndex, context_pointer: GSSNodeIndex) {
330        let d = Descriptor::new(slot, g, i, s, context_pointer);
331        if !self.visited.contains(&d) {
332            self.visited.insert(d.clone());
333            self.todo.insert(d);
334        }
335    }
336
337    /*
338    From the original paper:
339    u => Cu => gss_pointer (always)
340    i => Ci => input_pointer (always)
341    z => Cn => sppf_pointer (always)
342    */
343    /// Pop context back after a non-terminal was parsed.
344    ///
345    /// `pop` from the original paper. The arguments to that method are mapped as follows:
346    /// * `u` => `self.gss_pointer`
347    /// * `i` => `self.input_pointer`
348    /// * `z` => `self.sppf_pointer`
349    ///
350    /// Additionally, this method takes a list of attributes that are returned after the non-terminal was parsed.
351    ///
352    /// # Errors
353    /// Returns an error for the same reasons as [`GLLState::get_node_p`].
354    pub fn pop(&mut self, ret_vals: &ReturnMap<'a>, attrs: AttributeMap<'a>) -> ImplementationResult<'a, ()> {
355        let slot = self.get_current_gss_node()?.slot.clone();
356        let ctx_node = self.find_or_create_gss_node(GSSNode::new(slot.clone(), self.input_pointer, attrs));
357        let ctx = self.get_gss_node(ctx_node)?.clone();
358        let curr_sppf = self.get_sppf_node_mut(self.sppf_pointer)?;
359        if let SPPFNode::Intermediate { context, .. } = curr_sppf {
360            *context = ctx; // Values may still have changed
361        }
362        if self.gss_pointer != self.gss_root {
363            if let Some(map) = self.pop.get_mut(&self.gss_pointer) {
364                map.push(self.sppf_pointer); 
365            } else {
366                let map = vec![self.sppf_pointer];
367                self.pop.insert(self.gss_pointer, map);
368            }
369            let mut detached = self.gss.neighbors_directed(self.gss_pointer, Outgoing).detach();
370            while let Some(edge) = detached.next_edge(&self.gss) {
371                let v = self.get_gss_edge_endpoints(edge)?.1;
372                let y = self.get_node_p(slot.clone(), *self.get_gss_edge_weight(edge)?, self.sppf_pointer, self.gss_pointer, v == self.gss_pointer)?;
373                self.get_sppf_node_mut(y)?.insert_ret_vals(ret_vals.clone())?;
374                self.add(slot.clone(), v, self.input_pointer, y, self.gss_pointer);
375            }
376        }
377        Ok(())
378    }
379
380    // TODO: Make this cached
381    fn __next(bytes: Terminal<'a>, start_pointer: usize, input: &'a [u8]) -> ParseResult<'a, usize> {
382        let mut pointer = start_pointer;
383        let input_len = input.len();
384        while pointer < input_len && input[pointer].is_ascii_whitespace() { // left trim the input
385            pointer += 1;
386        }
387        for expected in bytes {
388            if pointer >= input_len {
389                return Err(GLLParseError::TooLong { pointer, offender: bytes })
390            }
391            let check = input[pointer];
392            if check != *expected && !check.is_ascii_whitespace() {
393                return Err(GLLParseError::UnexpectedByte { pointer, expected: *expected, offender: check })
394            }
395            pointer += 1;
396        }
397        Ok(pointer)
398    }
399
400    // This one only exists to work around the borrow checker.
401    fn _next(&self, bytes: Terminal<'a>) -> ParseResult<'a, usize> {
402        Self::__next(bytes, self.input_pointer, self.input)
403    }
404
405    /// Consume the following bytes from the input string. 
406    ///
407    /// If the bytes we just consumed are not the expected bytes, we return an error.
408    ///
409    /// If no error is returned, we move `self.input_pointer` forward as much as needed.
410    ///
411    /// # Errors
412    /// Returns either a [`GLLParseError::TooLong`] or [`GLLParseError::UnexpectedByte`] depending on the expected bytes and state of the input.
413    pub fn next(&mut self, bytes: Terminal<'a>) -> ParseResult<'a, ()> {
414        let pointer = self._next(bytes)?;
415        self.input_pointer = pointer;
416        Ok(())
417    }
418
419    /// Check if the following bytes **can** be consumed, but do not consume them.
420    pub fn has_next(&mut self, bytes: Terminal<'a>) -> bool {
421        self._next(bytes).is_ok()
422    }
423
424    #[must_use]
425    fn _next_regex(regex: &RegexTerminal<'a>, start_pointer: usize, input: &[u8]) -> Option<usize> {
426        let current_byte = &input[start_pointer..=start_pointer];
427        let Ok(mut curr_state) = regex.automaton.start_state_forward(&current_byte.into()) else { // Check if we have a valid start state.
428            return None
429        };
430        let input_len = input.len();
431        let mut i = 0;
432        let mut last_match = None;
433        while !regex.automaton.is_dead_state(curr_state) && !regex.automaton.is_quit_state(curr_state)  { // Until we encounter a dead state or a quit state
434            let pointer = start_pointer + i; // Increment the pointer.
435            if pointer >= input_len { // If our pointer exceeds the input, stop looping.
436                break;
437            }
438            let byte = input[pointer];
439            curr_state = regex.automaton.next_state(curr_state, byte); // Move the automaton forward based on the current byte.
440            if regex.automaton.is_match_state(curr_state) { // If this is a potential match, store it.
441                last_match = Some(i); // We do not break as this is a greedy algorithm and we may find a longer match.
442            }
443            i += 1;
444        }
445        if regex.automaton.is_quit_state(curr_state) || regex.automaton.is_dead_state(curr_state) { // If we stopped the loop because we reached a dead or quit state.
446            last_match // Return the last found match
447        } else { // If we stopped the loop because the pointer exceeded the input
448            let state = regex.automaton.next_eoi_state(curr_state); // Move the automaton forward by 1 step (because of library reasons).
449            if regex.automaton.is_match_state(state) { // Check if this last state is accepting.
450                Some(i)
451            } else {
452                last_match // If it is not, return the last found match.
453            }
454        }
455    }
456
457    /// Check if the given regex is accepting.
458    ///
459    /// If it is, we move the pointer forwards and return the accepted bytes. If no bytes are accepted, we return [`None`].
460    ///
461    /// # Errors
462    /// Returns an error if the regex completely fails to build.
463    pub fn next_regex(&mut self, pattern: &'a str) -> GLLResult<'a, Option<Terminal<'a>>> {
464        let regex = self.get_regex_automaton(pattern)?;
465        if let Some(j) = Self::_next_regex(&regex, self.input_pointer, self.input) {
466            let result = &self.input[self.input_pointer..self.input_pointer + j];
467            self.input_pointer += j + 1;
468            Ok(Some(result))
469        } else {
470            Ok(None)
471        }
472    }
473
474    /// Check if the following pattern **can** be matched, but do not consume the resulting bytes.
475    ///
476    /// # Errors
477    /// Returns an error if the regex completely fails to build.
478    pub fn has_regex(&self, pattern: &'a str) -> GLLResult<'a, bool> {
479        let regex = self.get_regex_automaton(pattern)?;
480        Ok(Self::_next_regex(&regex, self.input_pointer, self.input).is_some())
481    }
482
483    /// Get the bytes matched by the pattern based on where the current input pointer is, but do not consume these bytes.
484    ///
485    /// Similar to [`GLLState::next_regex`] but without consuming bytes.
486    ///
487    /// # Errors
488    /// Returns an error if the regex completely fails to build.
489    pub fn regex_bytes(&self, pattern: &'a str) -> GLLResult<'a, Option<Terminal<'a>>> {
490        let regex = self.get_regex_automaton(pattern)?;
491        Ok(Self::_next_regex(&regex, self.input_pointer, self.input).map(|j| &self.input[self.input_pointer..self.input_pointer + j]))
492    }
493
494    /// Get the current input byte for the state
495    #[must_use]
496    pub fn current_byte(&self) -> &[u8] {
497        &self.input[self.input_pointer..=self.input_pointer]
498    }
499
500    /// Check if, given the current state, the [`Label`](crate::Label)'s first-follow set is accepting.
501    ///
502    /// # Errors
503    /// Returns an error if something goes wrong during the first checking.
504    pub fn test_next(&mut self, label: &GLLBlockLabel<'a>) -> GLLResult<'a, bool> {
505        label.first(self)
506    }
507
508    /// Get a specific rule by its uuid.
509    ///
510    /// # Errors
511    /// Returns a [`GLLImplementationError::UnknownRule`] if the rule does not exist.
512    pub fn get_rule(&self, ident: &'a str) -> ImplementationResult<'a, Rc<Vec<Ident>>> {
513        Ok(self.rule_map.get(ident).ok_or_else(|| GLLImplementationError::UnknownRule(ident))?.clone())
514    }
515
516    /// Get a specific [`Label`](crate::Label) as identified by the given [`Ident`].
517    #[must_use] 
518    pub fn get_label(&self, ident: &Ident) -> GLLBlockLabel<'a> {
519        let raw_string = ident.extract_string();
520        self.label_map.get(raw_string).map_or_else(|| todo!(), std::clone::Clone::clone)
521    }
522
523    /// Get a specific [`Label`](crate::Label) by its uuid.
524    ///
525    /// # Errors
526    /// Returns a [`GLLImplementationError::UnknownLabel`] if the label can not be found.
527    pub fn get_label_by_uuid(&self, label: &'a str) -> ImplementationResult<'a, GLLBlockLabel<'a>> {
528        Ok(self.label_map.get(label).ok_or_else(|| GLLImplementationError::UnknownLabel(label))?.clone())
529    }
530
531    /// Get a specific [`RegexTerminal`] by its pattern.
532    ///
533    /// This differs from [`Self::get_label_by_uuid`] in that it specifically returns a [`RegexTerminal`], as opposed to some trait object.
534    ///
535    /// # Errors
536    /// Returns a [`GLLImplementationError::UnknownLabel`] if the dfa can not be found.
537    pub fn get_regex_automaton(&self, regex: &'a str) -> ImplementationResult<'a, Rc<RegexTerminal<'a>>> {
538        Ok(self.regex_map.get(regex).ok_or_else(|| GLLImplementationError::UnknownLabel(regex))?.clone())
539    }
540
541    /// Get an attribute from the node pointed at by `self.gss_pointer`.
542    ///
543    /// # Errors
544    /// Returns a [`GLLImplementationError::MissingAttribute`] if the `i`th attribute was never passed.
545    pub fn get_attribute(&self, i: AttributeKey) -> ImplementationResult<'a, &Value<'a>> {
546        let node = self.get_gss_node(self.gss_pointer)?;
547        node.get_attribute(i).ok_or_else(|| GLLImplementationError::MissingAttribute(i, node.clone()))
548    }
549
550    /// Get an attribute from the node pointed at by `self.context_pointer`.
551    ///
552    /// # Errors
553    /// Returns a [`GLLImplementationError::MissingContext`] if the `i`th attribute is not in context.
554    pub fn restore_attribute(&self, i: AttributeKey) -> ImplementationResult<'a, &Value<'a>> {
555        let node = self.get_gss_node(self.context_pointer)?;
556        node.get_attribute(i).ok_or_else(|| GLLImplementationError::MissingContext(i, node.clone()))
557    }
558
559    // pub(crate) fn get_attribute_at_gss_node(&self, pointer: GSSNodeIndex, i: AttributeKey) -> ParseResult<'a, Option<&Value<'a>>> {
560    //  Ok(self.get_gss_node(pointer)?.get_attribute(i))
561    // }
562
563    /// Get an attribute from the return arguments at the node currently pointed to by `self.sppf_pointer`.
564    ///
565    /// # Errors
566    /// Returns a [`GLLImplementationError::MissingSPPFNode`] if [`GLLState::sppf_pointer`] inexplicably points at a non-existant SPPF node.
567    pub fn get_ret_val(&self, i: AttributeKey) -> ImplementationResult<'a, Option<&Value<'a>>> {
568        self.get_sppf_node(self.sppf_pointer)?.get_ret_val(i)
569    }
570
571    /// Check if we have a special case slot.
572    ///
573    /// This concept comes from the OOGLL paper and is required in [`Self::get_node_p`] to instantly return the `right`.
574    ///
575    /// A special slot is defined as any slot `S -> α•β` where |α| == 1 && α is non-terminal or a non-nullable terminal && |β| != 0. 
576    fn is_special_slot(&self, slot: &GrammarSlot<'a>) -> ImplementationResult<'a, bool> {
577        Ok(if slot.dot == 1 && slot.pos == 0 && !slot.is_last(self) {
578            match slot.rule.first() {
579                Some(r) => {
580                    let a = self.get_label(r);
581                    a.str_parts().len() == 1 && (a.is_terminal() || !(a.is_nullable(self)?))
582                },
583                None => false
584            }
585        } else {
586            false
587        })
588    }
589
590    fn get_current_label_slot(&self, slot: &GrammarSlot<'a>) -> ImplementationResult<'a, GLLBlockLabel<'a>> {
591        Ok(self.get_label(slot.rule.get(slot.dot).ok_or_else(|| GLLImplementationError::CompletedSlot(slot.to_string(self, false)))?))
592    }
593
594    /// The goto function of the OOGLL paper.
595    ///
596    /// Calls [`crate::label::Label::code`]. If an error occurs for any reason, we store it in the `errors` vector.
597    fn goto(&mut self, slot: &GrammarSlot<'a>) {
598        match self.get_current_label_slot(slot) {
599            Ok(label) => {
600                if let Err(e) = label.code(self) {
601                    self.errors.push(e);
602                }
603            },
604            Err(e) => self.errors.push(e.into())
605        }
606    }
607
608    /// Run the parsing process.
609    ///
610    /// Once this has finished running, we either completed parsing or ran into an error somewhere.
611    pub fn main(&mut self) {
612        while let Some(Descriptor {slot, gss, pointer, sppf, context_pointer}) = self.todo.pop() {
613            self.sppf_pointer = sppf;
614            self.gss_pointer = gss;
615            self.input_pointer = pointer;
616            self.context_pointer = context_pointer;
617            self.goto(&slot);
618        }
619    }
620
621    /// Print current SPPF graph in graphviz format
622    ///
623    /// # Errors
624    /// Returns a [`GLLImplementationError::Utf8Error`] if there is non-utf8 data anywhere in the SPPF.
625    pub fn print_sppf_dot(&mut self, crop: bool, math_mode: bool) -> ImplementationResult<'a, String> {
626        if crop {
627            self.sppf.crop(self.find_roots_sppf());
628        }
629        self.sppf.to_dot(self, math_mode, &self.find_roots_sppf()) // Need to recalculate due to crop
630    }
631
632    /// Print current GSS graph in graphviz format
633    ///
634    /// # Errors
635    /// Return a [`GLLImplementationError::Fatal`] if it is unable to find an SPPF node stored on an edge.
636    pub fn print_gss_dot(&self, math_mode: bool) -> ImplementationResult<'a, String> {
637        self.gss.to_dot(self, math_mode)
638    }
639    
640    /// Checks whether the current parser state has accepted the string
641    #[must_use] 
642    pub fn accepts(&self) -> bool {
643        !self.find_roots_sppf().is_empty()
644    }
645
646    /// Checks whether the parser is accepting. If it isn't, and no errors were encountered, add an error.
647    ///
648    /// This is the method you should use at the end to fully confirm whether the state is accepting.
649    #[must_use] 
650    pub fn final_accepts(&mut self) -> bool {
651        let success = self.accepts();
652        if !success && self.errors.is_empty() {
653            self.errors.push(GLLError::ImplementationError(GLLImplementationError::Fatal("Parser is not accepting, but no errors were encountered.")));
654        }
655        success
656    }
657
658    #[allow(clippy::expect_used)]
659    fn find_roots_sppf(&self) -> Vec<SPPFNodeIndex> {
660        let s_p = self.label_map.get(ROOT_UUID).expect("S' label not found in state. Should be impossible.");
661        let start_label = s_p.first_set(self).expect("Unable to get root uuid from S'. Should be impossible.");
662        let uuid = start_label[0].0[0].uuid();
663        self.sppf.find_accepting_roots(Some(self.input.len()), uuid)
664    }
665}