156 lines
3.9 KiB
Rust
156 lines
3.9 KiB
Rust
use prometeu_compiler::frontends::pbs::parser::Parser;
|
|
use prometeu_compiler::frontends::pbs::ast::*;
|
|
use serde_json;
|
|
|
|
#[test]
|
|
fn test_parse_empty_file() {
|
|
let mut parser = Parser::new("", 0);
|
|
let result = parser.parse_file().unwrap();
|
|
assert_eq!(result.imports.len(), 0);
|
|
assert_eq!(result.decls.len(), 0);
|
|
}
|
|
|
|
#[test]
|
|
fn test_parse_imports() {
|
|
let source = r#"
|
|
import std.io from "std";
|
|
import math from "./math.pbs";
|
|
"#;
|
|
let mut parser = Parser::new(source, 0);
|
|
let result = parser.parse_file().unwrap();
|
|
assert_eq!(result.imports.len(), 2);
|
|
|
|
if let Node::Import(ref imp) = result.imports[0] {
|
|
assert_eq!(imp.from, "std");
|
|
if let Node::ImportSpec(ref spec) = *imp.spec {
|
|
assert_eq!(spec.path, vec!["std", "io"]);
|
|
} else { panic!("Expected ImportSpec"); }
|
|
} else { panic!("Expected Import"); }
|
|
}
|
|
|
|
#[test]
|
|
fn test_parse_fn_decl() {
|
|
let source = r#"
|
|
fn add(a: int, b: int) -> int {
|
|
return a + b;
|
|
}
|
|
"#;
|
|
let mut parser = Parser::new(source, 0);
|
|
let result = parser.parse_file().unwrap();
|
|
assert_eq!(result.decls.len(), 1);
|
|
|
|
if let Node::FnDecl(ref f) = result.decls[0] {
|
|
assert_eq!(f.name, "add");
|
|
assert_eq!(f.params.len(), 2);
|
|
assert_eq!(f.params[0].name, "a");
|
|
assert_eq!(f.params[1].name, "b");
|
|
} else { panic!("Expected FnDecl"); }
|
|
}
|
|
|
|
#[test]
|
|
fn test_parse_type_decl() {
|
|
let source = r#"
|
|
pub declare struct Point {
|
|
x: int,
|
|
y: int
|
|
}
|
|
"#;
|
|
let mut parser = Parser::new(source, 0);
|
|
let result = parser.parse_file().unwrap();
|
|
assert_eq!(result.decls.len(), 1);
|
|
|
|
if let Node::TypeDecl(ref t) = result.decls[0] {
|
|
assert_eq!(t.name, "Point");
|
|
assert_eq!(t.type_kind, "struct");
|
|
assert_eq!(t.vis, Some("pub".to_string()));
|
|
} else { panic!("Expected TypeDecl"); }
|
|
}
|
|
|
|
#[test]
|
|
fn test_parse_service_decl() {
|
|
let source = r#"
|
|
pub service Audio {
|
|
fn play(sound: Sound);
|
|
fn stop() -> bool;
|
|
}
|
|
"#;
|
|
let mut parser = Parser::new(source, 0);
|
|
let result = parser.parse_file().unwrap();
|
|
assert_eq!(result.decls.len(), 1);
|
|
|
|
if let Node::ServiceDecl(ref s) = result.decls[0] {
|
|
assert_eq!(s.name, "Audio");
|
|
assert_eq!(s.members.len(), 2);
|
|
} else { panic!("Expected ServiceDecl"); }
|
|
}
|
|
|
|
#[test]
|
|
fn test_parse_expressions() {
|
|
let source = r#"
|
|
fn main() {
|
|
let x = 10 + 20 * 30;
|
|
let y = (x - 5) / 2;
|
|
foo(x, y);
|
|
}
|
|
"#;
|
|
let mut parser = Parser::new(source, 0);
|
|
let result = parser.parse_file().unwrap();
|
|
assert_eq!(result.decls.len(), 1);
|
|
}
|
|
|
|
#[test]
|
|
fn test_parse_if_when() {
|
|
let source = r#"
|
|
fn main(x: int) {
|
|
if x > 0 {
|
|
print("positive");
|
|
} else {
|
|
print("non-positive");
|
|
}
|
|
|
|
let msg = when {
|
|
x == 0 -> { return "zero"; },
|
|
x == 1 -> { return "one"; }
|
|
};
|
|
}
|
|
"#;
|
|
let mut parser = Parser::new(source, 0);
|
|
let result = parser.parse_file().unwrap();
|
|
assert_eq!(result.decls.len(), 1);
|
|
}
|
|
|
|
#[test]
|
|
fn test_parse_error_recovery() {
|
|
let source = r#"
|
|
fn bad() {
|
|
let x = ; // Missing init
|
|
let y = 10;
|
|
}
|
|
|
|
fn good() {}
|
|
"#;
|
|
let mut parser = Parser::new(source, 0);
|
|
let result = parser.parse_file();
|
|
// It should fail but we should see both good and bad decls if we didn't return Err early
|
|
// Currently parse_file returns Err if there are any errors.
|
|
assert!(result.is_err());
|
|
}
|
|
|
|
#[test]
|
|
fn test_ast_json_snapshot() {
|
|
let source = r#"
|
|
fn main() {
|
|
return 42;
|
|
}
|
|
"#;
|
|
let mut parser = Parser::new(source, 0);
|
|
let result = parser.parse_file().unwrap();
|
|
let json = serde_json::to_string_pretty(&Node::File(result)).unwrap();
|
|
|
|
// We don't assert the exact string here because spans will vary,
|
|
// but we check that it serializes correctly and has the "kind" field.
|
|
assert!(json.contains("\"kind\": \"File\""));
|
|
assert!(json.contains("\"kind\": \"FnDecl\""));
|
|
assert!(json.contains("\"name\": \"main\""));
|
|
}
|