1 //! 2 3 use collections::{Map, Set}; 4 use ena::unify::InPlaceUnificationTable; 5 use grammar::repr::*; 6 use lr1::build; 7 use lr1::core::*; 8 use lr1::first::FirstSets; 9 use lr1::lane_table::lane::LaneTracer; 10 use lr1::lane_table::table::context_set::OverlappingLookahead; 11 use lr1::lane_table::table::{ConflictIndex, LaneTable}; 12 use lr1::lookahead::{Lookahead, TokenSet}; 13 use lr1::state_graph::StateGraph; 14 use std::rc::Rc; 15 16 mod merge; 17 use self::merge::Merge; 18 19 mod state_set; 20 use self::state_set::StateSet; 21 22 pub struct LaneTableConstruct<'grammar> { 23 grammar: &'grammar Grammar, 24 first_sets: FirstSets, 25 start_nt: NonterminalString, 26 } 27 28 impl<'grammar> LaneTableConstruct<'grammar> { new(grammar: &'grammar Grammar, start_nt: NonterminalString) -> Self29 pub fn new(grammar: &'grammar Grammar, start_nt: NonterminalString) -> Self { 30 let first_sets = FirstSets::new(grammar); 31 LaneTableConstruct { 32 grammar, 33 start_nt, 34 first_sets, 35 } 36 } 37 construct(self) -> Result<Vec<LR1State<'grammar>>, LR1TableConstructionError<'grammar>>38 pub fn construct(self) -> Result<Vec<LR1State<'grammar>>, LR1TableConstructionError<'grammar>> { 39 let states = { 40 match build::build_lr0_states(self.grammar, self.start_nt.clone()) { 41 Ok(states) => { 42 // In this case, the grammar is actually 43 // LR(0). This is very rare -- it means that the 44 // grammar does not need lookahead to execute. In 45 // principle, we could stop here, except that if 46 // we do so, then the lookahead values that we get 47 // are very broad. 48 // 49 // Broad lookahead values will cause "eager" 50 // reduce at runtime -- i.e., if there is some 51 // scenario where the lookahead tells you we are 52 // in error, but we would have to reduce a few 53 // states before we see it. This, in turn, can 54 // cause infinite loops around error recovery 55 // (#240). 56 // 57 // Since we want to behave as a LR(1) parser 58 // would, we'll just go ahead and run the 59 // algorithm. 60 states 61 } 62 Err(TableConstructionError { states, .. }) => states, 63 } 64 }; 65 66 // Convert the LR(0) states into LR(0-1) states. 67 let mut states = self.promote_lr0_states(states); 68 69 // For each inconsistent state, apply the lane-table algorithm to 70 // resolve it. 71 for i in 0.. { 72 if i >= states.len() { 73 break; 74 } 75 76 match self.resolve_inconsistencies(&mut states, StateIndex(i)) { 77 Ok(()) => {} 78 Err(_) => { 79 // We failed because of irreconcilable conflicts 80 // somewhere. Just compute the conflicts from the final set of 81 // states. 82 debug!( 83 "construct: failed to resolve inconsistencies in state {:#?}", 84 states[i] 85 ); 86 let conflicts: Vec<Conflict<'grammar, TokenSet>> = states 87 .iter() 88 .flat_map(|s| Lookahead::conflicts(&s)) 89 .collect(); 90 return Err(TableConstructionError { states, conflicts }); 91 } 92 } 93 } 94 95 Ok(states) 96 } 97 98 /// Given a set of LR0 states, returns LR1 states where the lookahead 99 /// is always `TokenSet::all()`. We refer to these states as LR(0-1) 100 /// states in the README. promote_lr0_states(&self, lr0: Vec<LR0State<'grammar>>) -> Vec<LR1State<'grammar>>101 fn promote_lr0_states(&self, lr0: Vec<LR0State<'grammar>>) -> Vec<LR1State<'grammar>> { 102 let all = TokenSet::all(); 103 debug!("promote_lr0_states: all={:?}", all); 104 lr0.into_iter() 105 .map(|s| { 106 let items = s 107 .items 108 .vec 109 .iter() 110 .map(|item| Item { 111 production: item.production, 112 index: item.index, 113 lookahead: all.clone(), 114 }) 115 .collect(); 116 let reductions = s 117 .reductions 118 .into_iter() 119 .map(|(_, p)| (all.clone(), p)) 120 .collect(); 121 State { 122 index: s.index, 123 items: Items { 124 vec: Rc::new(items), 125 }, 126 shifts: s.shifts, 127 reductions, 128 gotos: s.gotos, 129 } 130 }) 131 .collect() 132 } 133 resolve_inconsistencies( &self, states: &mut Vec<LR1State<'grammar>>, inconsistent_state: StateIndex, ) -> Result<(), StateIndex>134 fn resolve_inconsistencies( 135 &self, 136 states: &mut Vec<LR1State<'grammar>>, 137 inconsistent_state: StateIndex, 138 ) -> Result<(), StateIndex> { 139 debug!( 140 "resolve_inconsistencies(inconsistent_state={:?}/{:#?}", 141 inconsistent_state, states[inconsistent_state.0] 142 ); 143 144 let mut actions = super::conflicting_actions(&states[inconsistent_state.0]); 145 if actions.is_empty() { 146 // This can mean one of two things: only shifts, or a 147 // single reduction. We have to be careful about states 148 // with a single reduction: even though such a state is 149 // not inconsistent (there is only one possible course of 150 // action), we still want to run the lane table algorithm, 151 // because otherwise we get states with "complete" 152 // lookahead, which messes with error recovery. 153 // 154 // In particular, if there is too much lookahead, we will 155 // reduce even when it is inappropriate to do so. 156 actions = states[inconsistent_state.0] 157 .reductions 158 .iter() 159 .map(|&(_, prod)| Action::Reduce(prod)) 160 .collect(); 161 if actions.is_empty() { 162 return Ok(()); 163 } 164 } 165 166 debug!("resolve_inconsistencies: conflicting_actions={:?}", actions); 167 168 let table = self.build_lane_table(states, inconsistent_state, &actions); 169 170 // Consider first the "LALR" case, where the lookaheads for each 171 // action are completely disjoint. 172 if self.attempt_lalr(&mut states[inconsistent_state.0], &table, &actions) { 173 return Ok(()); 174 } 175 176 // Construct the initial states; each state will map to a 177 // context-set derived from its row in the lane-table. This is 178 // fallible, because a state may be internally inconstent. 179 // 180 // (To handle unification, we also map each state to a 181 // `StateSet` that is its entry in the `ena` table.) 182 let rows = table.rows()?; 183 let mut unify = InPlaceUnificationTable::<StateSet>::new(); 184 let mut state_sets = Map::new(); 185 for (&state_index, context_set) in &rows { 186 let state_set = unify.new_key(context_set.clone()); 187 state_sets.insert(state_index, state_set); 188 debug!( 189 "resolve_inconsistencies: state_index={:?}, state_set={:?}", 190 state_index, state_set 191 ); 192 } 193 194 // Now merge state-sets, cloning states where needed. 195 let mut merge = Merge::new( 196 &table, 197 &mut unify, 198 states, 199 &mut state_sets, 200 inconsistent_state, 201 ); 202 let beachhead_states = table.beachhead_states(); 203 for beachhead_state in beachhead_states { 204 match merge.start(beachhead_state) { 205 Ok(()) => {} 206 Err((source, _)) => { 207 debug!( 208 "resolve_inconsistencies: failed to merge, source={:?}", 209 source 210 ); 211 return Err(source); 212 } 213 } 214 } 215 merge.patch_target_starts(&actions); 216 217 Ok(()) 218 } 219 attempt_lalr( &self, state: &mut LR1State<'grammar>, table: &LaneTable<'grammar>, actions: &Set<Action<'grammar>>, ) -> bool220 fn attempt_lalr( 221 &self, 222 state: &mut LR1State<'grammar>, 223 table: &LaneTable<'grammar>, 224 actions: &Set<Action<'grammar>>, 225 ) -> bool { 226 match table.columns() { 227 Ok(columns) => { 228 debug!("attempt_lalr, columns={:#?}", columns); 229 columns.apply(state, actions); 230 debug!("attempt_lalr, state={:#?}", state); 231 true 232 } 233 Err(OverlappingLookahead) => { 234 debug!("attempt_lalr, OverlappingLookahead"); 235 false 236 } 237 } 238 } 239 build_lane_table( &self, states: &[LR1State<'grammar>], inconsistent_state: StateIndex, actions: &Set<Action<'grammar>>, ) -> LaneTable<'grammar>240 fn build_lane_table( 241 &self, 242 states: &[LR1State<'grammar>], 243 inconsistent_state: StateIndex, 244 actions: &Set<Action<'grammar>>, 245 ) -> LaneTable<'grammar> { 246 let state_graph = StateGraph::new(states); 247 let mut tracer = LaneTracer::new( 248 self.grammar, 249 self.start_nt.clone(), 250 states, 251 &self.first_sets, 252 &state_graph, 253 actions.len(), 254 ); 255 for (i, action) in actions.iter().enumerate() { 256 tracer.start_trace(inconsistent_state, ConflictIndex::new(i), action.clone()); 257 } 258 tracer.into_table() 259 } 260 } 261