use super::*;
pub 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
"#;
pub fn arithmetic_grammar() -> Grammar {
Grammar::load(ARITHMETIC_GRAMMAR).expect("failed to load arithmetic grammar")
}
pub fn valid_expressions_cases() -> Vec<ParseTestCase> {
vec![
ParseTestCase::valid("empty", ""),
ParseTestCase::valid("single digit", "1"),
ParseTestCase::valid("multi digit", "42"),
ParseTestCase::valid("large number", "9999"),
ParseTestCase::valid("simple var", "x"),
ParseTestCase::valid("longer var", "abc"),
ParseTestCase::valid("var with digits", "x1"),
ParseTestCase::valid("add prefix", "1 +"),
ParseTestCase::valid("sub prefix", "x -"),
ParseTestCase::valid("mul prefix", "2 *"),
ParseTestCase::valid("div prefix", "y /"),
ParseTestCase::valid("simple add", "1 + 2"),
ParseTestCase::valid("chain ops", "1 + 2 * 3"),
ParseTestCase::valid("open paren", "("),
ParseTestCase::valid("paren number", "(42"),
ParseTestCase::valid("closed paren", "(42)"),
ParseTestCase::valid("nested parens", "((1))"),
ParseTestCase::valid("complex paren", "(x + y) * z"),
]
}
pub fn invalid_expressions_cases() -> Vec<ParseTestCase> {
vec![
ParseTestCase::invalid("close paren first", ")"),
ParseTestCase::invalid("operator first", "+ 1"),
ParseTestCase::invalid("double operator", "1 ++"),
ParseTestCase::invalid("invalid char", "@"),
ParseTestCase::invalid("percent op", "1 %"),
ParseTestCase::invalid("extra close", "1)"),
ParseTestCase::invalid("misplaced close", "(1))"),
ParseTestCase::invalid("empty close after operator", "1 + )"),
ParseTestCase::invalid("dangling nested operator", "(1 +) *"),
ParseTestCase::invalid("double close suffix", "((1 + 2)))"),
ParseTestCase::invalid("identifier starts with digit", "1abc"),
]
}
#[test]
fn valid_expressions_arithmetic() {
let mut grammar = arithmetic_grammar();
let cases = valid_expressions_cases();
let (res, _cases_json) = run_parse_batch(&mut grammar, &cases);
assert_eq!(res.failed, 0, "{}", res.format_failures());
}
#[test]
fn invalid_expressions_arithmetic() {
let mut grammar = arithmetic_grammar();
let cases = invalid_expressions_cases();
let (res, _cases_json) = run_parse_batch(&mut grammar, &cases);
assert_eq!(res.failed, 0, "{}", res.format_failures());
}