aufbau 0.1.2

Generalized prefix parsing for a class of context-dependent languages
Documentation
//! IMP Language Completion Tests
//!
//! Tests typed completion for the IMP imperative language with:
//! - Variable declarations with type annotations
//! - Integer arithmetic operations
//! - While loops with conditions
//! - Boolean expressions
//! - Variable scoping

use super::*;

/// Load IMP grammar from examples/imp.auf
pub fn imp_grammar() -> Grammar {
    load_example_grammar("imp")
}

// ============================================================================
// Suite Definitions (used by validate binary)
// ============================================================================

pub fn suites() -> Vec<(&'static str, Grammar, Vec<TypedCompletionTestCase>)> {
    let g = imp_grammar();
    vec![("imp::completable", g, completable_cases())]
}

use TypedCompletionTestCase as T;

fn completable_cases() -> Vec<TypedCompletionTestCase> {
    vec![
        // Already complete (wrapped as a top-level Block)
        T::ok("var decl", "{ let x:Int=5; }", 2),
        T::ok("var init zero", "{ let x:Int=0; }", 2),
        T::ok("var large", "{ let x:Int=999; }", 2),
        T::ok("bool decl", "{ let flag:Bool=true; }", 2),
        T::ok("union decl", "{ let u:Int|Bool=true; }", 2),
        // Nearly complete
        T::ok("var no semicolon", "{ let x:Int=5", 2),
        T::ok("var no equals", "{ let x:Int", 4),
        T::ok("var no value", "{ let x:Int=", 3),
        T::ok("empty", "", 3),
        // Sequences
        T::ok("two decls", "{ let x:Int=5; let y:Int=3; }", 3),
        T::ok(
            "long decl chain partial tail",
            "{ let a:Int=1; let b:Int=2; let c:Int=3; let d:Int=4; let e:Int=5; let f:Int=6; a",
            6,
        ),
        T::ok("sequence partial", "{ let x:Int=5; x", 6),
        // Arithmetic expressions
        T::ok("simple add", "{ let x:Int=1+2; }", 2),
        T::ok("add chain", "{ let u:Int=1+2+3; }", 2),
        T::ok("subtract", "{ let x:Int=10-5; }", 2),
        T::ok("multiply", "{ let z:Int=2*3; }", 2),
        T::ok("divide", "{ let x:Int=6/2; }", 2),
        // Parentheses in expressions
        T::ok("paren add", "{ let x:Int=(1+2); }", 2),
        T::ok("nested parens", "{ let x:Int=((1+2)); }", 2),
        T::ok("paren partial", "{ let x:Int=(1", 3),
        // Complex expressions
        T::ok("mixed ops", "{ let x:Int=1+2*3; }", 1),
        T::ok("all ops", "{ let x:Int=1+2-3*4/5; }", 1),
        // Variable references in expressions
        T::ok("use var", "{ let x:Int=5; let y:Int=x; }", 1),
        T::ok("use in expr", "{ let x:Int=5; let y:Int=x+1; }", 1),
        // Control flow
        T::ok(
            "if statement",
            "{ if (1==1) { let x:Int=1; } else { let x:Int=2; } }",
            2,
        ),
        T::ok("while statement", "{ while (1==1) { let x:Int=1; } }", 2),
    ]
}

// ============================================================================
// Batch Test Cases
// ============================================================================

#[test]
fn check_completable() {
    let grammar = imp_grammar();
    let res = run_test_batch(&grammar, &completable_cases());
    res.assert_all_passed();
}