#![allow(dead_code)]
use super::*;
pub fn suites() -> Vec<(&'static str, Grammar, Vec<TypedCompletionTestCase>)> {
let g = arithmetic_grammar();
vec![("arithmetic::completable", g, completable_cases())]
}
use TypedCompletionTestCase as T;
fn completable_cases() -> Vec<TypedCompletionTestCase> {
vec![
T::ok("empty", "", 3),
T::ok("single digit", "1", 1),
T::ok("multi digit", "42", 1),
T::ok("large number", "9999", 1),
T::ok("simple var", "x", 1),
T::ok("longer var", "abc", 1),
T::ok("var with digits", "x1", 1),
T::ok("add prefix", "1 +", 2),
T::ok("sub prefix", "x -", 2),
T::ok("mul prefix", "2 *", 2),
T::ok("div prefix", "y /", 2),
T::ok("simple add", "1 + 2", 1),
T::ok("chain ops", "1 + 2 * 3", 1),
T::ok("open paren", "(", 3),
T::ok("paren number", "(42", 2),
T::ok("closed paren", "(42)", 1),
T::ok("nested parens", "((1))", 2),
T::ok("complex paren", "(x + y) * z", 2),
]
}
const ARITHMETIC_GRAMMAR: &str = r#"
Number ::= /[0-9]+/
Identifier ::= /[a-z][a-zA-Z0-9]*/
Literal ::= Number
Variable ::= Identifier
Operator ::= '+' | '-' | '*' | '/'
Primary ::= Literal | Variable | '(' Expression ')'
Expression ::= Primary | Primary Operator Expression
"#;
fn arithmetic_grammar() -> Grammar {
load_inline_grammar(ARITHMETIC_GRAMMAR)
}
#[test]
fn check_completable() {
let grammar = arithmetic_grammar();
let res = run_test_batch(&grammar, &completable_cases());
res.assert_all_passed();
}
#[test]
#[ignore = "debug probe"]
fn debug_arith_completions() {
use crate::logic::partial::MetaParser;
use crate::logic::typing::Context;
use crate::validation::completability::complete;
let grammar = arithmetic_grammar();
let input = "1 +";
let ctx = Context::new();
let mut meta = MetaParser::new(grammar.clone());
let (partial1, depth1) = meta.partial_with_depth(input).unwrap();
println!(
"First parse: depth={} roots={} last_used={:?}",
depth1,
partial1.roots().len(),
meta.last_used_depth()
);
let typed1 = partial1.typed_ctx(&grammar, &ctx).unwrap();
let comps1 = typed1.completions(&grammar);
println!(
"Completions1: {:?}",
comps1.iter().map(|t| t.to_string()).collect::<Vec<_>>()
);
let floor = depth1.max(1);
let ceil = depth1 + 2;
println!("Second parse with bounds [{}, {}]:", floor, ceil);
match meta.partial_with_bounds(input, floor, ceil) {
Ok((partial2, depth2)) => {
println!(
"Second parse OK: depth={} roots={}",
depth2,
partial2.roots().len()
);
match partial2.typed_ctx(&grammar, &ctx) {
Ok(typed2) => {
let comps2 = typed2.completions(&grammar);
println!(
"Completions2: {:?}",
comps2.iter().map(|t| t.to_string()).collect::<Vec<_>>()
);
}
Err(e) => println!("typed_ctx2 FAILED: {}", e),
}
}
Err(e) => {
println!("Second parse FAILED: {}", e);
for d in floor..=ceil {
match meta.partial_with_bounds(input, d, d) {
Ok((p, dep)) => println!(" depth={} OK: roots={}", dep, p.roots().len()),
Err(e2) => println!(" depth={} FAILED: {}", d, e2),
}
}
}
}
let result = complete(&grammar, input, 4, Some(ctx));
println!("Complete result: {:?}", result);
}
#[test]
#[ignore = "debug probe 2 - cache poisoning"]
fn debug_arith_cache_poisoning() {
use crate::logic::partial::MetaParser;
let grammar = arithmetic_grammar();
let input = "1 +";
{
let mut meta = MetaParser::new(grammar.clone());
let r = meta.partial_with_bounds(input, 5, 5);
println!(
"Fresh meta, bounds [5,5]: {}",
match &r {
Ok((a, d)) => format!("OK roots={} depth={}", a.roots().len(), d),
Err(e) => format!("FAIL: {}", e),
}
);
}
{
let mut meta = MetaParser::new(grammar.clone());
let r1 = meta.partial_with_depth(input);
println!(
"After unconstrained parse (depth={:?}), bounds [5,5]:",
r1.as_ref().map(|(_, d)| *d).ok()
);
let r2 = meta.partial_with_bounds(input, 5, 5);
println!(
" result: {}",
match &r2 {
Ok((a, d)) => format!("OK roots={} depth={}", a.roots().len(), d),
Err(e) => format!("FAIL: {}", e),
}
);
}
{
let mut meta = MetaParser::new(grammar.clone());
let _ = meta.partial_with_depth(input);
meta.clear_cache();
let r2 = meta.partial_with_bounds(input, 5, 5);
println!(
"After clear_cache, bounds [5,5]: {}",
match &r2 {
Ok((a, d)) => format!("OK roots={} depth={}", a.roots().len(), d),
Err(e) => format!("FAIL: {}", e),
}
);
}
}