1 //! The "Lane Table". In the paper, this is depicted like so:
2 //!
3 //! ```
4 //! +-------+----+-----+----+------------+
5 //! + State | C1 | ... | Cn | Successors |
6 //! +-------+----+-----+----+------------+
7 //! ```
8 //!
9 //! where each row summarizes some state that potentially contributes
10 //! lookahead to the conflict. The columns `Ci` represent each of the
11 //! conflicts we are trying to disentangle; their values are each
12 //! `TokenSet` indicating the lookahead contributing by this state.
13 //! The Successors is a vector of further successors. For simplicity
14 //! though we store this using maps, at least for now.
15 
16 use collections::{Map, Multimap, Set};
17 use grammar::repr::*;
18 use lr1::core::*;
19 use lr1::lookahead::*;
20 use std::default::Default;
21 use std::fmt::{Debug, Error, Formatter};
22 use std::iter;
23 
24 pub mod context_set;
25 use self::context_set::{ContextSet, OverlappingLookahead};
26 
27 #[derive(Copy, Clone, Debug, PartialOrd, Ord, PartialEq, Eq)]
28 pub struct ConflictIndex {
29     index: usize,
30 }
31 
32 impl ConflictIndex {
new(index: usize) -> ConflictIndex33     pub fn new(index: usize) -> ConflictIndex {
34         ConflictIndex { index: index }
35     }
36 }
37 
38 pub struct LaneTable<'grammar> {
39     _grammar: &'grammar Grammar,
40     conflicts: usize,
41     lookaheads: Map<(StateIndex, ConflictIndex), TokenSet>,
42     successors: Multimap<StateIndex, Set<StateIndex>>,
43 }
44 
45 impl<'grammar> LaneTable<'grammar> {
new(grammar: &'grammar Grammar, conflicts: usize) -> LaneTable46     pub fn new(grammar: &'grammar Grammar, conflicts: usize) -> LaneTable {
47         LaneTable {
48             _grammar: grammar,
49             conflicts: conflicts,
50             lookaheads: Map::default(),
51             successors: Multimap::default(),
52         }
53     }
54 
add_lookahead(&mut self, state: StateIndex, conflict: ConflictIndex, tokens: &TokenSet)55     pub fn add_lookahead(&mut self, state: StateIndex, conflict: ConflictIndex, tokens: &TokenSet) {
56         self.lookaheads
57             .entry((state, conflict))
58             .or_insert_with(|| TokenSet::new())
59             .union_with(&tokens);
60     }
61 
add_successor(&mut self, state: StateIndex, succ: StateIndex)62     pub fn add_successor(&mut self, state: StateIndex, succ: StateIndex) {
63         self.successors.push(state, succ);
64     }
65 
66     /// Unions together the lookaheads for each column and returns a
67     /// context set containing all of them. For an LALR(1) grammar,
68     /// these token sets will be mutually disjoint, as discussed in
69     /// the [README]; otherwise `Err` will be returned.
70     ///
71     /// [README]: ../README.md
columns(&self) -> Result<ContextSet, OverlappingLookahead>72     pub fn columns(&self) -> Result<ContextSet, OverlappingLookahead> {
73         let mut columns = ContextSet::new(self.conflicts);
74         for (&(_, conflict_index), set) in &self.lookaheads {
75             columns.insert(conflict_index, set)?;
76         }
77         Ok(columns)
78     }
79 
successors(&self, state: StateIndex) -> Option<&Set<StateIndex>>80     pub fn successors(&self, state: StateIndex) -> Option<&Set<StateIndex>> {
81         self.successors.get(&state)
82     }
83 
84     /// Returns the state of states in the table that are **not**
85     /// reachable from another state in the table. These are called
86     /// "beachhead states".
beachhead_states(&self) -> Set<StateIndex>87     pub fn beachhead_states(&self) -> Set<StateIndex> {
88         // set of all states that are reachable from another state
89         let reachable: Set<StateIndex> = self
90             .successors
91             .iter()
92             .flat_map(|(_pred, succ)| succ)
93             .cloned()
94             .collect();
95 
96         self.lookaheads
97             .keys()
98             .map(|&(state_index, _)| state_index)
99             .filter(|s| !reachable.contains(s))
100             .collect()
101     }
102 
context_set(&self, state: StateIndex) -> Result<ContextSet, OverlappingLookahead>103     pub fn context_set(&self, state: StateIndex) -> Result<ContextSet, OverlappingLookahead> {
104         let mut set = ContextSet::new(self.conflicts);
105         for (&(state_index, conflict_index), token_set) in &self.lookaheads {
106             if state_index == state {
107                 set.insert(conflict_index, token_set)?;
108             }
109         }
110         Ok(set)
111     }
112 
113     /// Returns a map containing all states that appear in the table,
114     /// along with the context set for each state (i.e., each row in
115     /// the table, basically). Returns Err if any state has a conflict
116     /// between the context sets even within its own row.
rows(&self) -> Result<Map<StateIndex, ContextSet>, StateIndex>117     pub fn rows(&self) -> Result<Map<StateIndex, ContextSet>, StateIndex> {
118         let mut map = Map::new();
119         for (&(state_index, conflict_index), token_set) in &self.lookaheads {
120             debug!(
121                 "rows: inserting state_index={:?} conflict_index={:?} token_set={:?}",
122                 state_index, conflict_index, token_set
123             );
124             match {
125                 map.entry(state_index)
126                     .or_insert_with(|| ContextSet::new(self.conflicts))
127                     .insert(conflict_index, token_set)
128             } {
129                 Ok(_changed) => {}
130                 Err(OverlappingLookahead) => {
131                     debug!("rows: intra-row conflict inserting state_index={:?} conflict_index={:?} token_set={:?}",
132                            state_index, conflict_index, token_set);
133                     return Err(state_index);
134                 }
135             }
136         }
137 
138         // In some cases, there are states that have no context at
139         // all, only successors. In that case, make sure to add an
140         // empty row for them.
141         for (&state_index, _) in &self.successors {
142             map.entry(state_index)
143                 .or_insert_with(|| ContextSet::new(self.conflicts));
144         }
145 
146         Ok(map)
147     }
148 }
149 
150 impl<'grammar> Debug for LaneTable<'grammar> {
fmt(&self, fmt: &mut Formatter) -> Result<(), Error>151     fn fmt(&self, fmt: &mut Formatter) -> Result<(), Error> {
152         let indices: Set<StateIndex> = self
153             .lookaheads
154             .keys()
155             .map(|&(state, _)| state)
156             .chain(self.successors.iter().map(|(key, _)| key.clone()))
157             .collect();
158 
159         let header = iter::once(format!("State"))
160             .chain((0..self.conflicts).map(|i| format!("C{}", i)))
161             .chain(Some(format!("Successors")))
162             .collect();
163 
164         let rows = indices.iter().map(|&index| {
165             iter::once(format!("{:?}", index))
166                 .chain((0..self.conflicts).map(|i| {
167                     self.lookaheads
168                         .get(&(index, ConflictIndex::new(i)))
169                         .map(|token_set| format!("{:?}", token_set))
170                         .unwrap_or(String::new())
171                 }))
172                 .chain(Some(
173                     self.successors
174                         .get(&index)
175                         .map(|c| format!("{:?}", c))
176                         .unwrap_or(String::new()),
177                 ))
178                 .collect()
179         });
180 
181         let table: Vec<Vec<_>> = iter::once(header).chain(rows).collect();
182 
183         let columns = 2 + self.conflicts;
184 
185         let widths: Vec<_> = (0..columns)
186             .map(|c| {
187                 // find the max width of any row at this column
188                 table.iter().map(|r| r[c].len()).max().unwrap()
189             })
190             .collect();
191 
192         for row in &table {
193             try!(write!(fmt, "| "));
194             for (i, column) in row.iter().enumerate() {
195                 if i > 0 {
196                     try!(write!(fmt, " | "));
197                 }
198                 try!(write!(fmt, "{0:1$}", column, widths[i]));
199             }
200             try!(write!(fmt, " |\n"));
201         }
202 
203         Ok(())
204     }
205 }
206