santiago/parser/
parser_state.rs

1// SPDX-FileCopyrightText: 2022 Kevin Amado <kamadorueda@gmail.com>
2//
3// SPDX-License-Identifier: GPL-3.0-only
4
5use crate::grammar::Production;
6use std::collections::hash_map::DefaultHasher;
7use std::hash::Hash;
8use std::hash::Hasher;
9use std::rc::Rc;
10
11/// Internal representation of a [Production] that has been matched
12/// up to certain symbol,
13/// starting at `start_column` and ending at `end_column`
14/// relative the input [Lexemes](crate::lexer::Lexeme).
15pub struct ParserState<AST> {
16    pub(crate) rule_name:    Rc<String>,
17    pub(crate) production:   Rc<Production<AST>>,
18    pub(crate) dot_index:    usize,
19    pub(crate) start_column: usize,
20    pub(crate) end_column:   usize,
21}
22
23impl<AST> std::fmt::Debug for ParserState<AST> {
24    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
25        write!(f, "{self:?}")
26    }
27}
28
29impl<AST> std::fmt::Display for ParserState<AST> {
30    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
31        write!(
32            f,
33            "{:?} := {} {}• {}[{}-{}]",
34            self.rule_name,
35            self.production.kind,
36            self.production.symbols[0..self.dot_index]
37                .iter()
38                .map(|symbol| format!("{symbol:?} "))
39                .collect::<Vec<String>>()
40                .join(""),
41            self.production.symbols[self.dot_index..]
42                .iter()
43                .map(|symbol| format!("{symbol:?} "))
44                .collect::<Vec<String>>()
45                .join(""),
46            self.start_column,
47            if self.end_column == usize::MAX {
48                "".to_string()
49            } else {
50                self.end_column.to_string()
51            },
52        )
53    }
54}
55
56impl<AST> core::clone::Clone for ParserState<AST> {
57    fn clone(&self) -> ParserState<AST> {
58        ParserState {
59            rule_name:    self.rule_name.clone(),
60            production:   self.production.clone(),
61            dot_index:    self.dot_index,
62            start_column: self.start_column,
63            end_column:   self.end_column,
64        }
65    }
66}
67
68impl<AST> std::cmp::Eq for ParserState<AST> {}
69
70impl<AST> std::cmp::PartialEq for ParserState<AST> {
71    fn eq(&self, other: &ParserState<AST>) -> bool {
72        let left = (
73            &self.rule_name,
74            &self.production,
75            &self.dot_index,
76            &self.start_column,
77            &self.end_column,
78        );
79        let right = (
80            &other.rule_name,
81            &other.production,
82            &other.dot_index,
83            &other.start_column,
84            &other.end_column,
85        );
86
87        left.eq(&right)
88    }
89}
90impl<AST> ParserState<AST> {
91    pub(crate) fn completed(&self) -> bool {
92        self.dot_index >= self.production.symbols.len()
93    }
94
95    pub(crate) fn next_symbol(&self) -> Option<&String> {
96        self.production.symbols.get(self.dot_index)
97    }
98
99    pub(crate) fn hash_me(&self) -> u64 {
100        let mut hasher = DefaultHasher::new();
101        self.rule_name.hash(&mut hasher);
102        self.production.hash(&mut hasher);
103        self.dot_index.hash(&mut hasher);
104        self.start_column.hash(&mut hasher);
105        self.end_column.hash(&mut hasher);
106        hasher.finish()
107    }
108}