#[cfg(test)]
mod tests {
use crate::engine::parser::Parser;
fn assert_parses_without_errors(input: &str) {
let mut parser = Parser::new(input);
let output = parser.parse_with_recovery();
let sexp = output.ast.to_sexp();
assert!(
!sexp.contains("ERROR"),
"Expected no ERROR nodes for input: {}\nAST: {}",
input,
sexp,
);
assert!(
output.diagnostics.is_empty(),
"Expected no diagnostics for input: {}\nDiagnostics: {:?}",
input,
output.diagnostics,
);
}
fn parse_sexp(input: &str) -> String {
let mut parser = Parser::new(input);
let output = parser.parse_with_recovery();
output.ast.to_sexp()
}
#[test]
fn test_eval_block_or_pattern() {
assert_parses_without_errors(r#"eval { die "oops" } or warn "caught: $@";"#);
}
#[test]
fn test_eval_block_in_assignment() {
assert_parses_without_errors("my $result = eval { complex_operation() };");
}
#[test]
fn test_eval_block_defined_or() {
assert_parses_without_errors("eval { 1 } // do { handle_error() };");
}
#[test]
fn test_eval_block_logical_or() {
assert_parses_without_errors(r#"eval { 1 } || die "failed";"#);
}
#[test]
fn test_eval_block_logical_and() {
assert_parses_without_errors(r#"eval { 1 } && print "ok";"#);
}
#[test]
fn test_eval_string_or_pattern() {
assert_parses_without_errors(r#"eval $code or die "eval failed: $@";"#);
}
#[test]
fn test_eval_block_produces_eval_node() {
let sexp = parse_sexp("eval { 1 };");
assert!(sexp.contains("eval"), "Expected eval node in AST: {}", sexp,);
}
#[test]
fn test_goto_label() {
assert_parses_without_errors("goto LABEL;");
}
#[test]
fn test_goto_sub_reference() {
assert_parses_without_errors("goto &other_sub;");
}
#[test]
fn test_goto_produces_goto_node() {
let sexp = parse_sexp("goto LABEL;");
assert!(sexp.contains("goto"), "Expected goto node in AST: {}", sexp,);
}
#[test]
fn test_goto_sub_reference_produces_goto_node() {
let sexp = parse_sexp("goto &other_sub;");
assert!(sexp.contains("goto"), "Expected goto node in AST: {}", sexp,);
}
#[test]
fn test_goto_computed_label() {
assert_parses_without_errors("goto $label;");
}
}