SeraphScript/src/parsing/parser/parser_tests.rs

380 lines
12 KiB
Rust
Raw Normal View History

use super::parse;
use super::parsed_statement::ParsedStatement;
2022-01-01 16:48:57 +00:00
use crate::modifiers::TypeModifier;
use crate::parsing::lexer::lex_tokens::{LexToken, TokenType};
2022-04-02 21:30:05 +00:00
use crate::parsing::parser::parsed_statement::ParsedStatement::DataTypeAuto;
use crate::parsing::parser::parser_operators::{BinaryOperator, PreOperator};
use crate::span::Span;
2022-01-01 16:48:57 +00:00
use enumflags2::BitFlags;
fn create_tokens(types: Vec<TokenType>) -> Vec<LexToken> {
let mut v = Vec::with_capacity(types.len());
for t in types {
v.push(LexToken {
token_type: t,
span: Span::new(0, 0),
});
}
v
}
#[test]
fn test_empty_namespace() {
2021-06-05 19:03:14 +00:00
let script = parse(
create_tokens(vec![
TokenType::NamespaceKeyword,
TokenType::WhiteSpace,
TokenType::Identifier("foo".to_string()),
TokenType::WhiteSpace,
TokenType::OpenCurlyBracket,
TokenType::CloseCurlyBracket,
TokenType::EndOfFile,
]),
&mut |_message, _span| {
2022-01-01 16:48:57 +00:00
std::panic::panic_any(_message.stringify());
2021-06-05 19:03:14 +00:00
},
);
2022-01-01 16:48:57 +00:00
if let ParsedStatement::Script { statements } = script.as_ref() {
assert_eq!(1, statements.len());
if let ParsedStatement::Namespace { identifier, script } = &statements[0] {
assert_eq!(identifier, "foo");
2022-01-01 16:48:57 +00:00
if let ParsedStatement::Script { statements } = script.as_ref() {
assert_eq!(0, statements.len());
} else {
unreachable!();
}
} else {
unreachable!()
}
} else {
unreachable!();
}
}
2022-01-01 16:48:57 +00:00
#[test]
fn test_empty_interface() {
let script = parse(
create_tokens(vec![
TokenType::InterfaceKeyword,
TokenType::WhiteSpace,
TokenType::Identifier("foo".to_string()),
TokenType::WhiteSpace,
TokenType::OpenCurlyBracket,
TokenType::CloseCurlyBracket,
TokenType::EndOfFile,
]),
&mut |_message, _span| {
std::panic::panic_any(_message.stringify());
},
);
if let ParsedStatement::Script { statements } = script.as_ref() {
assert_eq!(1, statements.len());
if let ParsedStatement::Interface {
type_mod,
identifier,
inherits,
statements,
} = &statements[0]
{
assert!(type_mod.is_empty());
assert_eq!(identifier, "foo");
assert_eq!(inherits.len(), 0);
assert_eq!(statements.len(), 0);
} else {
unreachable!()
}
} else {
unreachable!();
}
}
#[test]
fn test_empty_external_shared_interface() {
let script = parse(
create_tokens(vec![
TokenType::ExternalKeyword,
TokenType::SharedKeyword,
TokenType::InterfaceKeyword,
TokenType::WhiteSpace,
TokenType::Identifier("foo".to_string()),
TokenType::WhiteSpace,
TokenType::OpenCurlyBracket,
TokenType::CloseCurlyBracket,
TokenType::EndOfFile,
]),
&mut |_message, _span| {
std::panic::panic_any(_message.stringify());
},
);
if let ParsedStatement::Script { statements } = script.as_ref() {
assert_eq!(1, statements.len());
if let ParsedStatement::Interface {
type_mod,
identifier,
inherits,
statements,
} = &statements[0]
{
assert!(!type_mod.is_empty());
assert!(type_mod.contains(TypeModifier::External));
assert!(type_mod.contains(TypeModifier::Shared));
assert_eq!(identifier, "foo");
assert_eq!(inherits.len(), 0);
assert_eq!(statements.len(), 0);
} else {
unreachable!()
}
} else {
unreachable!();
}
}
#[test]
fn test_interface_with_virtprop() {
let script = parse(
create_tokens(vec![
TokenType::InterfaceKeyword,
TokenType::WhiteSpace,
TokenType::Identifier("foo".to_string()),
TokenType::WhiteSpace,
TokenType::OpenCurlyBracket,
TokenType::Identifier("bar".to_string()),
TokenType::Identifier("get_bar".to_string()),
TokenType::OpenCurlyBracket,
TokenType::GetKeyword,
TokenType::Semicolon,
TokenType::SetKeyword,
TokenType::Semicolon,
TokenType::CloseCurlyBracket,
TokenType::CloseCurlyBracket,
TokenType::EndOfFile,
]),
&mut |_message, _span| {
std::panic::panic_any(_message.stringify());
},
);
if let ParsedStatement::Script { statements } = script.as_ref() {
assert_eq!(1, statements.len());
if let ParsedStatement::Interface {
type_mod,
identifier,
inherits,
statements,
} = &statements[0]
{
assert!(type_mod.is_empty());
assert_eq!(identifier, "foo");
assert_eq!(inherits.len(), 0);
assert_eq!(statements.len(), 1);
if let ParsedStatement::VirtProp {
field_mod,
property_type,
identifier,
is_handle,
has_get,
is_get_const,
get_statement,
has_set,
is_set_const,
set_statement,
} = &statements[0]
{
assert_eq!(*field_mod, BitFlags::empty());
if let ParsedStatement::Type {
2022-04-02 21:30:05 +00:00
is_const, datatype, ..
2022-01-01 16:48:57 +00:00
} = property_type.as_ref()
{
assert!(!is_const);
2022-04-02 21:30:05 +00:00
if let ParsedStatement::DataTypeIdentifier { identifier, .. } =
datatype.as_ref()
{
assert_eq!(identifier, "bar");
} else {
unreachable!()
}
2022-01-01 16:48:57 +00:00
} else {
unreachable!()
}
assert_eq!(identifier, "get_bar");
assert!(has_get);
assert!(!is_get_const);
assert!(has_set);
assert!(!is_set_const);
assert!(get_statement.is_none());
assert!(set_statement.is_none());
assert!(!is_handle);
} else {
unreachable!()
}
} else {
unreachable!()
}
} else {
unreachable!();
}
}
2022-04-02 21:30:05 +00:00
#[test]
fn test_assign_to_global_variable() {
let script = parse(
create_tokens(vec![
TokenType::AutoKeyword,
TokenType::WhiteSpace,
TokenType::Identifier("foo".to_string()),
TokenType::WhiteSpace,
TokenType::Equals,
TokenType::WhiteSpace,
TokenType::IntegerLiteral(100),
TokenType::EndOfFile,
]),
&mut |_message, _span| {
std::panic::panic_any(_message.stringify());
},
);
if let ParsedStatement::Script { statements } = script.as_ref() {
assert_eq!(1, statements.len());
if let ParsedStatement::Var {
modifier,
var_type,
identifier,
assignment,
} = &statements[0]
{
assert!(modifier.is_empty());
assert_eq!(
*var_type.as_ref(),
ParsedStatement::Type {
is_const: false,
scope: None,
datatype: Box::from(DataTypeAuto {}),
modifiers: vec![]
}
);
assert_eq!(identifier, "foo");
assert!(assignment.is_some());
assert_eq!(
*(assignment.as_ref().unwrap().as_ref()),
2022-04-03 13:25:26 +00:00
ParsedStatement::IntegerLiteral(100)
2022-04-02 21:30:05 +00:00
);
} else {
unreachable!()
}
} else {
unreachable!();
}
}
#[test]
fn test_assign_negative_to_global_variable() {
let script = parse(
create_tokens(vec![
TokenType::AutoKeyword,
TokenType::WhiteSpace,
TokenType::Identifier("foo".to_string()),
TokenType::WhiteSpace,
TokenType::Equals,
TokenType::WhiteSpace,
TokenType::Minus,
TokenType::IntegerLiteral(100),
TokenType::EndOfFile,
]),
&mut |_message, _span| {
std::panic::panic_any(_message.stringify());
},
);
if let ParsedStatement::Script { statements } = script.as_ref() {
assert_eq!(1, statements.len());
if let ParsedStatement::Var {
modifier,
var_type,
identifier,
assignment,
} = &statements[0]
{
assert!(modifier.is_empty());
assert_eq!(
*var_type.as_ref(),
ParsedStatement::Type {
is_const: false,
scope: None,
datatype: Box::from(DataTypeAuto {}),
modifiers: vec![]
}
);
assert_eq!(identifier, "foo");
assert!(assignment.is_some());
assert_eq!(
*(assignment.as_ref().unwrap().as_ref()),
2022-04-03 13:25:26 +00:00
ParsedStatement::ExprPreOp {
operator: PreOperator::Negative,
operand: Box::from(ParsedStatement::IntegerLiteral(100)),
2022-04-02 21:30:05 +00:00
}
);
} else {
unreachable!()
}
} else {
unreachable!();
}
}
#[test]
fn test_assign_addition_to_global_variable() {
let script = parse(
create_tokens(vec![
TokenType::AutoKeyword,
TokenType::WhiteSpace,
TokenType::Identifier("foo".to_string()),
TokenType::WhiteSpace,
TokenType::Equals,
TokenType::WhiteSpace,
TokenType::IntegerLiteral(100),
TokenType::Plus,
TokenType::Minus,
TokenType::IntegerLiteral(20),
TokenType::EndOfFile,
]),
&mut |_message, _span| {
std::panic::panic_any(_message.stringify());
},
);
if let ParsedStatement::Script { statements } = script.as_ref() {
assert_eq!(1, statements.len());
if let ParsedStatement::Var {
modifier,
var_type,
identifier,
assignment,
} = &statements[0]
{
assert!(modifier.is_empty());
assert_eq!(
*var_type.as_ref(),
ParsedStatement::Type {
is_const: false,
scope: None,
datatype: Box::from(DataTypeAuto {}),
modifiers: vec![]
}
);
assert_eq!(identifier, "foo");
assert!(assignment.is_some());
assert_eq!(
*(assignment.as_ref().unwrap().as_ref()),
ParsedStatement::BinaryExpr {
2022-04-03 13:25:26 +00:00
left: Box::new(ParsedStatement::IntegerLiteral(100)),
2022-04-02 21:30:05 +00:00
operator: BinaryOperator::Addition,
2022-04-03 13:25:26 +00:00
right: Box::new(ParsedStatement::ExprPreOp {
operator: PreOperator::Negative,
operand: Box::new(ParsedStatement::IntegerLiteral(20)),
2022-04-02 21:30:05 +00:00
}),
}
);
} else {
unreachable!()
}
} else {
unreachable!();
}
}