Skip to main content

grammar_utils/lr1/
table.rs

1use std::collections::BTreeMap;
2
3use crate::*;
4use super::*;
5
6/// An LR(1) parse table.
7#[derive(Debug)]
8pub struct ParseTable<'g> {
9    grammar: &'g Grammar,
10    states: Vec<State<'g>>,
11    actions: BTreeMap<(StateIndex, Option<Symbol<'g>>), Vec<Action<'g>>>,
12}
13
14/// An LR action.
15#[derive(Debug)]
16#[derive(Clone, Copy, PartialEq, Eq)]
17pub enum Action<'g> {
18    /// Shift the next symbol from the input stream onto the stack.
19    /// Then enter the give state.
20    ///
21    /// `Shift` is also used to represent a GOTO transition.
22    Shift(StateIndex),
23
24    /// Use the given rule to reduce.
25    /// This pops elements off the stack equal to the number of symbols on the right hand side.
26    /// These become the children of the parse tree with the left hand side being the root.
27    ///
28    /// Conceptually, this pushes the nonterminal back into the input stream.
29    /// This will always be followed by applying a `Shift` action
30    /// to remove the nonterminal that was just generated off of input stream
31    /// and back onto the stack.
32    Reduce(Rule<'g>),
33
34    /// The machine successfully consumed the start rule.
35    /// If there is no more input remaining, the parse was successful.
36    Halt,
37}
38
39/// Information on a conflict found in the given grammar.
40#[derive(Clone)]
41pub struct Conflict<'g, 't> {
42    table: &'t ParseTable<'g>,
43    state: StateIndex,
44    symbol: Option<Symbol<'g>>,
45    actions: Vec<Action<'g>>,
46}
47
48impl<'g> ParseTable<'g> {
49    /// Build a parse table from a gramar.
50    ///
51    /// The `start_rule` will be used as the top-level production for the table.
52    pub fn build(grammar: &'g Grammar, start_rule: Rule<'g>) -> ParseTable<'g> {
53        let analysis = GrammarAnalysis::build(grammar);
54        let states = Self::build_states(&grammar, &analysis, start_rule);
55        let actions = Self::build_actions(&grammar, &analysis, &states, start_rule);
56
57        ParseTable {
58            grammar,
59            states,
60            actions,
61        }
62    }
63
64    /// Get the underlying grammar for this parse table.
65    pub fn grammar(&self) -> &'g Grammar {
66        self.grammar
67    }
68
69    /// Get a slice of all of the states for this table.
70    pub fn states(&self) -> &[State<'g>] {
71        &self.states
72    }
73
74    fn build_states(
75        grammar: &'g Grammar,
76        analysis: &GrammarAnalysis<'g>,
77        start_rule: Rule<'g>,
78    ) -> Vec<State<'g>> {
79        let mut states = vec![];
80        let start_state = State::singleton(Item::new(start_rule, 0, vec![None].into_iter().collect()), analysis);
81        let mut states_remaining = vec![start_state];
82
83        while let Some(state) = states_remaining.pop() {
84            for symbol in grammar.symbols() {
85                let next_state = state.follow(analysis, symbol);
86
87                if next_state.items().is_empty() {
88                    continue;
89                }
90
91                if !states.contains(&next_state) {
92                    states_remaining.push(next_state);
93                }
94            }
95
96            states.push(state);
97        }
98
99        states
100    }
101
102    fn build_actions(
103        grammar: &'g Grammar,
104        analysis: &GrammarAnalysis<'g>,
105        states: &[State<'g>],
106        start_rule: Rule<'g>,
107    ) -> BTreeMap<(StateIndex, Option<Symbol<'g>>), Vec<Action<'g>>> {
108
109        let mut actions = BTreeMap::new();
110
111        // Pre-allocate an empty list for all (state_i, maybe_symbol)-pairs
112        for (src_state_index, _src_state) in states.iter().enumerate() {
113            let src_state_index = StateIndex(src_state_index);
114            for symbol in grammar.symbols() {
115                let key = (src_state_index, Some(symbol));
116                actions.insert(key, vec![]);
117            }
118            actions.insert((src_state_index, None), vec![]);
119        }
120
121        for (src_state_index, src_state) in states.iter().enumerate() {
122            let src_state_index = StateIndex(src_state_index);
123            for src_item in src_state.items() {
124                match src_item.next_symbol() {
125                    Some(symbol) => {
126                        let dst_state = src_state.follow(&analysis, symbol);
127                        let dst_state_index = Self::state_index(&dst_state, states);
128                        let key = (src_state_index, Some(symbol));
129                        let actions_for = actions.get_mut(&key).unwrap();
130
131                        let action = Action::Shift(StateIndex(dst_state_index));
132                        if !actions_for.contains(&action) {
133                            actions_for.push(action);
134                        }
135
136                    }
137                    None => {
138                        for symbol in src_item.lookahead() {
139                            let key = (src_state_index, *symbol);
140                            let actions_for = actions.get_mut(&key).unwrap();
141                            actions_for.push(Action::Reduce(src_item.rule()));
142                        }
143                    }
144                }
145            }
146        }
147
148        let key = (StateIndex(0), Some(start_rule.lhs()));
149        actions.get_mut(&key).unwrap().insert(0, Action::Halt);
150
151        actions
152    }
153
154    fn state_index(state: &State, states: &[State]) -> usize {
155        states
156            .iter()
157            .enumerate()
158            .find_map(|(j, st)| {
159                if state == st {
160                    Some(j)
161                } else {
162                    None
163                }
164            })
165            .unwrap()
166    }
167
168    /// Return a list of all of the conflicts found in this table.
169    pub fn conflicts(&self) -> Vec<Conflict> {
170        let mut conflicts = vec![];
171        for (state_index, _state) in self.states.iter().enumerate() {
172            let state_index = StateIndex(state_index);
173            for symbol in self.grammar.symbols() {
174                let key = (state_index, Some(symbol));
175                let actions = &self.actions[&key];
176                if actions.len() > 1 {
177                    conflicts.push(Conflict {
178                        table: self,
179                        state: state_index,
180                        symbol: Some(symbol),
181                        actions: actions.clone(),
182                    });
183                }
184            }
185        }
186        conflicts
187    }
188
189    pub fn get(&self, state_index: StateIndex, symbol: Option<Symbol<'g>>) -> Vec<Action<'g>> {
190        let key = (state_index, symbol);
191        self.actions.get(&key).unwrap().to_vec()
192    }
193
194    pub fn dump(&self) {
195        for (state_index, state) in self.states.iter().enumerate() {
196            let state_index = StateIndex(state_index);
197            eprintln!("{state_index:?}");
198            eprintln!("{state:?}");
199
200            for symbol in self.grammar.symbols() {
201                eprintln!("    {symbol:?} => {:?}", self.get(state_index, Some(symbol)));
202            }
203            eprintln!("    None => {:?}", self.get(state_index, None));
204            eprintln!();
205        }
206    }
207}
208
209impl<'g, 't> std::fmt::Debug for Conflict<'g, 't> {
210    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
211        let state_id = self.state;
212        let symbol = self.symbol;
213        let actions = &self.actions;
214        write!(f, "Conflict(state={state_id:?}, symbol={symbol:?}, actions={actions:?})")?;
215        Ok(())
216    }
217}
218
219impl<'g, 't> Conflict<'g, 't> {
220    pub fn table(&self) -> &'t ParseTable<'g> {
221        self.table
222    }
223
224    pub fn state(&self) -> &'t State {
225        &self.table.states[usize::from(self.state)]
226    }
227
228    pub fn symbol(&self) -> Option<Symbol<'g>> {
229        self.symbol
230    }
231
232    pub fn actions(&self) -> &[Action<'g>] {
233        &self.actions
234    }
235}
236
237impl<'g> std::ops::Index<StateIndex> for ParseTable<'g> {
238    type Output = State<'g>;
239
240    fn index(&self, index: StateIndex) -> &Self::Output {
241        &self.states[usize::from(index)]
242    }
243}