use tabnas::Tabnas;
use tabnas_debug::{apply, model, DebugOptions};
fn build() -> Tabnas {
let mut parser = tabnas_expr::make();
apply(&mut parser, DebugOptions::quiet()).expect("the debug plugin installs over expr");
parser
}
#[test]
fn parses_normally_with_the_debug_plugin_installed() {
let parser = build();
let value = tabnas_expr::parse_with(&parser, "1+2*3").expect("a mixed-precedence sum parses");
assert_eq!(
tabnas_expr::simplify(&value).to_string(),
r#"["+",1,["*",2,3]]"#
);
}
#[test]
fn the_model_is_the_structured_expr_grammar() {
let parser = build();
let m = model(&parser);
let mut names: Vec<&str> = m.rules.iter().map(|rule| rule.name.as_str()).collect();
names.sort_unstable();
assert_eq!(
names,
["elem", "expr", "list", "map", "pair", "paren", "val"]
);
assert_eq!(m.config.start, "val");
assert!(
m.plugins
.iter()
.any(|plugin| plugin.name == tabnas_expr::PLUGIN_NAME),
"plugins should list {}: {:?}",
tabnas_expr::PLUGIN_NAME,
m.plugins
.iter()
.map(|plugin| &plugin.name)
.collect::<Vec<_>>()
);
let pushes = |rule: &str, target: &str| {
m.rules
.iter()
.find(|candidate| candidate.name == rule)
.unwrap_or_else(|| panic!("a {rule} rule"))
.open
.iter()
.any(|alt| alt.push.as_deref() == Some(target))
};
for (rule, target) in [
("val", "expr"),
("val", "map"),
("val", "list"),
("expr", "paren"),
("expr", "val"),
("paren", "val"),
] {
assert!(pushes(rule, target), "{rule} should push {target}");
}
}
#[test]
fn the_model_survives_json() {
let m = model(&build());
let round: serde_json::Value =
serde_json::from_str(&serde_json::to_string(&m).expect("the model serialises"))
.expect("and parses back");
let mut names: Vec<&str> = round["rules"]
.as_array()
.expect("rules is an array")
.iter()
.map(|rule| rule["name"].as_str().expect("a rule name"))
.collect();
names.sort_unstable();
assert_eq!(
names,
["elem", "expr", "list", "map", "pair", "paren", "val"]
);
assert_eq!(round["config"]["start"], "val");
}