mirror of
https://github.com/fluencelabs/lalrpop
synced 2025-03-16 17:00:53 +00:00
Merge pull request #259 from nikomatsakis/issue-249
avoid out-of-bounds error in error classification
This commit is contained in:
commit
4176ff6313
@ -444,6 +444,12 @@ impl<'cx, 'grammar> ErrorReportingCx<'cx, 'grammar> {
|
||||
action_examples.sort_by(|e, f| e.symbols.len().cmp(&f.symbols.len()));
|
||||
reduce_examples.sort_by(|e, f| e.symbols.len().cmp(&f.symbols.len()));
|
||||
|
||||
// This really shouldn't happen, but if we've failed to come
|
||||
// up with examples, then report a "naive" error.
|
||||
if action_examples.is_empty() || reduce_examples.is_empty() {
|
||||
return ConflictClassification::Naive;
|
||||
}
|
||||
|
||||
if let Some(classification) = self.try_classify_ambiguity(conflict,
|
||||
&action_examples,
|
||||
&reduce_examples) {
|
||||
@ -532,6 +538,9 @@ impl<'cx, 'grammar> ErrorReportingCx<'cx, 'grammar> {
|
||||
return None;
|
||||
}
|
||||
|
||||
debug!("try_classify_question: action_examples={:?}", action_examples);
|
||||
debug!("try_classify_question: reduce_examples={:?}", reduce_examples);
|
||||
|
||||
let nt = conflict.production.nonterminal;
|
||||
let nt_productions = self.grammar.productions_for(nt);
|
||||
if nt_productions.len() == 2 {
|
||||
|
@ -148,3 +148,25 @@ Ident = r#"[a-zA-Z][a-zA-Z0-9]*"#;
|
||||
r => panic!("wrong classification {:#?}", r)
|
||||
}
|
||||
}
|
||||
|
||||
/// This example used to cause an out-of-bounds error.
|
||||
#[test]
|
||||
fn issue_249() {
|
||||
let _tls = Tls::test();
|
||||
let grammar = normalized_grammar(r##"
|
||||
grammar;
|
||||
|
||||
pub Func = StructDecl* VarDecl*;
|
||||
StructDecl = "<" StructParameter* ">";
|
||||
StructParameter = "may_dangle"?;
|
||||
VarDecl = "let";
|
||||
"##);
|
||||
let _lr1_tls = Lr1Tls::install(grammar.terminals.clone());
|
||||
let err = build_states(&grammar, nt("Func")).unwrap_err();
|
||||
let mut cx = ErrorReportingCx::new(&grammar, &err.states, &err.conflicts);
|
||||
let conflicts = super::token_conflicts(&err.conflicts);
|
||||
for conflict in &conflicts {
|
||||
println!("conflict={:?}", conflict);
|
||||
cx.classify(conflict);
|
||||
}
|
||||
}
|
||||
|
@ -60,6 +60,8 @@ impl<'grammar> LaneTableConstruct<'grammar> {
|
||||
// We failed because of irreconcilable conflicts
|
||||
// somewhere. Just compute the conflicts from the final set of
|
||||
// states.
|
||||
debug!("construct: failed to resolve inconsistencies in state {:#?}",
|
||||
states[i]);
|
||||
let conflicts: Vec<Conflict<'grammar, TokenSet>> =
|
||||
states.iter()
|
||||
.flat_map(|s| Lookahead::conflicts(&s))
|
||||
@ -167,7 +169,10 @@ impl<'grammar> LaneTableConstruct<'grammar> {
|
||||
for beachhead_state in beachhead_states {
|
||||
match merge.start(beachhead_state) {
|
||||
Ok(()) => { }
|
||||
Err((source, _)) => return Err(source),
|
||||
Err((source, _)) => {
|
||||
debug!("resolve_inconsistencies: failed to merge, source={:?}", source);
|
||||
return Err(source);
|
||||
}
|
||||
}
|
||||
}
|
||||
merge.patch_target_starts(&actions);
|
||||
|
@ -118,13 +118,19 @@ impl<'grammar> LaneTable<'grammar> {
|
||||
pub fn rows(&self) -> Result<Map<StateIndex, ContextSet>, StateIndex> {
|
||||
let mut map = Map::new();
|
||||
for (&(state_index, conflict_index), token_set) in &self.lookaheads {
|
||||
debug!("rows: inserting state_index={:?} conflict_index={:?} token_set={:?}",
|
||||
state_index, conflict_index, token_set);
|
||||
match {
|
||||
map.entry(state_index)
|
||||
.or_insert_with(|| ContextSet::new(self.conflicts))
|
||||
.insert(conflict_index, token_set)
|
||||
} {
|
||||
Ok(_changed) => { }
|
||||
Err(OverlappingLookahead) => return Err(state_index)
|
||||
Err(OverlappingLookahead) => {
|
||||
debug!("rows: intra-row conflict inserting state_index={:?} conflict_index={:?} token_set={:?}",
|
||||
state_index, conflict_index, token_set);
|
||||
return Err(state_index);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user