use intern::intern;
use grammar::repr::*;
use lr1::build_states;
use lr1::tls::Lr1Tls;
use test_util::normalized_grammar;
use tls::Tls;
use super::{ConflictClassification, ErrorReportingCx};
fn nt(t: &str) -> NonterminalString {
NonterminalString(intern(t))
}
#[test]
fn priority_conflict() {
let _tls = Tls::test();
let grammar = normalized_grammar(r#"
grammar;
pub Ty: () = {
"int" => (),
"bool" => (),
<t1:Ty> "->" <t2:Ty> => (),
};
"#);
let _lr1_tls = Lr1Tls::install(grammar.terminals.clone());
let err = build_states(&grammar, nt("Ty")).unwrap_err();
let mut cx = ErrorReportingCx::new(&grammar, &err.states, &err.conflicts);
let conflicts = super::token_conflicts(&err.conflicts);
let conflict = &conflicts[0];
println!("conflict={:?}", conflict);
match cx.classify(conflict) {
ConflictClassification::Precedence {
shift,
reduce,
nonterminal,
} => {
println!("shift={:#?}, reduce={:#?}, nonterminal={:?}",
shift, reduce, nonterminal);
assert_eq!(shift.symbols.len(), 5); assert_eq!(shift.cursor, 3); assert_eq!(shift.symbols, reduce.symbols);
assert_eq!(shift.cursor, reduce.cursor);
assert_eq!(nonterminal, nt("Ty"));
}
r => panic!("wrong classification {:#?}", r)
}
}
#[test]
fn expr_braced_conflict() {
let _tls = Tls::test();
let grammar = normalized_grammar(r#"
grammar;
pub Expr: () = {
"Id" => (),
"Id" "{" "}" => (),
"Expr" "+" "Id" => (),
"if" Expr "{" "}" => (),
};
"#);
let _lr1_tls = Lr1Tls::install(grammar.terminals.clone());
let err = build_states(&grammar, nt("Expr")).unwrap_err();
let mut cx = ErrorReportingCx::new(&grammar, &err.states, &err.conflicts);
let conflicts = super::token_conflicts(&err.conflicts);
let conflict = &conflicts[0];
println!("conflict={:?}", conflict);
match cx.classify(conflict) {
ConflictClassification::InsufficientLookahead { .. } => { }
r => panic!("wrong classification {:#?}", r)
}
}
#[test]
fn suggest_question_conflict() {
let _tls = Tls::test();
let grammar = normalized_grammar(r#"
grammar;
pub E: () = {
"L",
"&" OPT_L E
};
OPT_L: () = {
(),
"L"
};
"#);
let _lr1_tls = Lr1Tls::install(grammar.terminals.clone());
let err = build_states(&grammar, nt("E")).unwrap_err();
let mut cx = ErrorReportingCx::new(&grammar, &err.states, &err.conflicts);
let conflicts = super::token_conflicts(&err.conflicts);
let conflict = &conflicts[0];
println!("conflict={:?}", conflict);
match cx.classify(conflict) {
ConflictClassification::SuggestQuestion {
shift: _,
reduce: _,
nonterminal,
symbol,
} => {
assert_eq!(nonterminal, nt("OPT_L"));
assert_eq!(symbol, Symbol::Terminal(TerminalString::Literal(TerminalLiteral::Quoted(intern("L")))));
}
r => panic!("wrong classification {:#?}", r)
}
}
#[test]
fn suggest_inline_conflict() {
let _tls = Tls::test();
let grammar = normalized_grammar(r##"
grammar;
pub ImportDecl: () = {
"import" <Path> ";" => (),
"import" <Path> "." "*" ";" => (),
};
Path: () = {
<head: Ident> <tail: ("." <Ident>)*> => ()
};
Ident = r#"[a-zA-Z][a-zA-Z0-9]*"#;
"##);
let _lr1_tls = Lr1Tls::install(grammar.terminals.clone());
let err = build_states(&grammar, nt("ImportDecl")).unwrap_err();
let mut cx = ErrorReportingCx::new(&grammar, &err.states, &err.conflicts);
let conflicts = super::token_conflicts(&err.conflicts);
let conflict = &conflicts[0];
println!("conflict={:?}", conflict);
match cx.classify(conflict) {
ConflictClassification::SuggestInline {
shift: _,
reduce: _,
nonterminal,
} => {
assert_eq!(nonterminal, nt("Path"));
}
r => panic!("wrong classification {:#?}", r)
}
}