MalachScript/tests/ParserTests/VirtPropTests.cpp

203 lines
15 KiB
C++

#include "../../extern/doctest.hpp"
#include "../../src/Parser/Parser.hpp"
using namespace MalachScript;
#define PARSER_TEST(name, tokens, asserts) \
TEST_CASE(name) { \
std::vector<Parser::LexToken*> vec = { \
tokens, \
new Parser::LexTokenImpl<Parser::LexTokenKind::EndOfFile>(TextSpan(0, 0)), \
}; \
for (size_t i = 0; i < vec.size() - 1; i++) { \
vec[i]->SetNext(vec[i + 1]); \
} \
Diagnostics::Logger diags; \
auto* script = Parser::Parser::Parse(vec.front(), &diags); \
REQUIRE(diags.GetMessages().empty()); \
asserts; \
delete vec[0]; \
delete script; \
}
#define PARSER_TEST_TOKENS(...) __VA_ARGS__
#define TextSpan(a, b) ScriptTextSpan(a, b, "")
PARSER_TEST("Parse class foobar { bool foo { get; set; } }",
PARSER_TEST_TOKENS(
new Parser::LexTokenImpl<Parser::LexTokenKind::ClassKeyword>(TextSpan(0, 0)),
new Parser::IdentifierToken(TextSpan(0, 0), "foobar"),
new Parser::LexTokenImpl<Parser::LexTokenKind::OpenCurlyParenthesisSymbol>(TextSpan(0, 0)),
new Parser::IdentifierToken(TextSpan(0, 0), "bool"), new Parser::IdentifierToken(TextSpan(0, 0), "foo"),
new Parser::LexTokenImpl<Parser::LexTokenKind::OpenCurlyParenthesisSymbol>(TextSpan(0, 0)),
new Parser::LexTokenImpl<Parser::LexTokenKind::GetKeyword>(TextSpan(0, 0)),
new Parser::LexTokenImpl<Parser::LexTokenKind::SemicolonSymbol>(TextSpan(0, 0)),
new Parser::LexTokenImpl<Parser::LexTokenKind::SetKeyword>(TextSpan(0, 0)),
new Parser::LexTokenImpl<Parser::LexTokenKind::SemicolonSymbol>(TextSpan(0, 0)),
new Parser::LexTokenImpl<Parser::LexTokenKind::CloseCurlyParenthesisSymbol>(TextSpan(0, 0)),
new Parser::LexTokenImpl<Parser::LexTokenKind::CloseCurlyParenthesisSymbol>(TextSpan(0, 0))),
{
REQUIRE(script->GetStatements().size() == 1);
auto firstStatement = script->GetStatements()[0].get();
REQUIRE(firstStatement->GetKind() == Parser::ParsedStatementKind::Class);
auto firstClassStatement =
dynamic_cast<const MalachScript::Parser::ParsedClassStatement*>(firstStatement)->GetBody()[0].get();
REQUIRE(firstClassStatement->GetKind() == Parser::ParsedStatementKind::VirtProp);
auto virtPropStatement =
dynamic_cast<const MalachScript::Parser::ParsedVirtPropStatement*>(firstClassStatement);
REQUIRE(virtPropStatement->GetAccess() == MalachScript::AccessModifier::Public);
REQUIRE(virtPropStatement->GetIdentifier().GetString() == "foo");
REQUIRE(virtPropStatement->HasGet());
REQUIRE(virtPropStatement->HasSet());
REQUIRE_FALSE(virtPropStatement->IsGetConst());
REQUIRE_FALSE(virtPropStatement->IsSetConst());
REQUIRE(virtPropStatement->GetGetStatement() == nullptr);
REQUIRE(virtPropStatement->GetSetStatement() == nullptr);
})
PARSER_TEST("Parse class foobar { bool foo { get const; set const; } }",
PARSER_TEST_TOKENS(
new Parser::LexTokenImpl<Parser::LexTokenKind::ClassKeyword>(TextSpan(0, 0)),
new Parser::IdentifierToken(TextSpan(0, 0), "foobar"),
new Parser::LexTokenImpl<Parser::LexTokenKind::OpenCurlyParenthesisSymbol>(TextSpan(0, 0)),
new Parser::IdentifierToken(TextSpan(0, 0), "bool"), new Parser::IdentifierToken(TextSpan(0, 0), "foo"),
new Parser::LexTokenImpl<Parser::LexTokenKind::OpenCurlyParenthesisSymbol>(TextSpan(0, 0)),
new Parser::LexTokenImpl<Parser::LexTokenKind::GetKeyword>(TextSpan(0, 0)),
new Parser::LexTokenImpl<Parser::LexTokenKind::ConstKeyword>(TextSpan(0, 0)),
new Parser::LexTokenImpl<Parser::LexTokenKind::SemicolonSymbol>(TextSpan(0, 0)),
new Parser::LexTokenImpl<Parser::LexTokenKind::SetKeyword>(TextSpan(0, 0)),
new Parser::LexTokenImpl<Parser::LexTokenKind::ConstKeyword>(TextSpan(0, 0)),
new Parser::LexTokenImpl<Parser::LexTokenKind::SemicolonSymbol>(TextSpan(0, 0)),
new Parser::LexTokenImpl<Parser::LexTokenKind::CloseCurlyParenthesisSymbol>(TextSpan(0, 0)),
new Parser::LexTokenImpl<Parser::LexTokenKind::CloseCurlyParenthesisSymbol>(TextSpan(0, 0))),
{
REQUIRE(script->GetStatements().size() == 1);
auto firstStatement = script->GetStatements()[0].get();
REQUIRE(firstStatement->GetKind() == Parser::ParsedStatementKind::Class);
auto firstClassStatement =
dynamic_cast<const MalachScript::Parser::ParsedClassStatement*>(firstStatement)->GetBody()[0].get();
REQUIRE(firstClassStatement->GetKind() == Parser::ParsedStatementKind::VirtProp);
auto virtPropStatement =
dynamic_cast<const MalachScript::Parser::ParsedVirtPropStatement*>(firstClassStatement);
REQUIRE(virtPropStatement->GetAccess() == MalachScript::AccessModifier::Public);
REQUIRE(virtPropStatement->GetIdentifier().GetString() == "foo");
REQUIRE(virtPropStatement->HasGet());
REQUIRE(virtPropStatement->HasSet());
REQUIRE(virtPropStatement->IsGetConst());
REQUIRE(virtPropStatement->IsSetConst());
REQUIRE(virtPropStatement->GetGetStatement() == nullptr);
REQUIRE(virtPropStatement->GetSetStatement() == nullptr);
})
PARSER_TEST("Parse class foobar { bool foo { get const override; set const override; } }",
PARSER_TEST_TOKENS(
new Parser::LexTokenImpl<Parser::LexTokenKind::ClassKeyword>(TextSpan(0, 0)),
new Parser::IdentifierToken(TextSpan(0, 0), "foobar"),
new Parser::LexTokenImpl<Parser::LexTokenKind::OpenCurlyParenthesisSymbol>(TextSpan(0, 0)),
new Parser::IdentifierToken(TextSpan(0, 0), "bool"), new Parser::IdentifierToken(TextSpan(0, 0), "foo"),
new Parser::LexTokenImpl<Parser::LexTokenKind::OpenCurlyParenthesisSymbol>(TextSpan(0, 0)),
new Parser::LexTokenImpl<Parser::LexTokenKind::GetKeyword>(TextSpan(0, 0)),
new Parser::LexTokenImpl<Parser::LexTokenKind::ConstKeyword>(TextSpan(0, 0)),
new Parser::LexTokenImpl<Parser::LexTokenKind::OverrideKeyword>(TextSpan(0, 0)),
new Parser::LexTokenImpl<Parser::LexTokenKind::SemicolonSymbol>(TextSpan(0, 0)),
new Parser::LexTokenImpl<Parser::LexTokenKind::SetKeyword>(TextSpan(0, 0)),
new Parser::LexTokenImpl<Parser::LexTokenKind::ConstKeyword>(TextSpan(0, 0)),
new Parser::LexTokenImpl<Parser::LexTokenKind::OverrideKeyword>(TextSpan(0, 0)),
new Parser::LexTokenImpl<Parser::LexTokenKind::SemicolonSymbol>(TextSpan(0, 0)),
new Parser::LexTokenImpl<Parser::LexTokenKind::CloseCurlyParenthesisSymbol>(TextSpan(0, 0)),
new Parser::LexTokenImpl<Parser::LexTokenKind::CloseCurlyParenthesisSymbol>(TextSpan(0, 0))),
{
REQUIRE(script->GetStatements().size() == 1);
auto firstStatement = script->GetStatements()[0].get();
REQUIRE(firstStatement->GetKind() == Parser::ParsedStatementKind::Class);
auto firstClassStatement =
dynamic_cast<const MalachScript::Parser::ParsedClassStatement*>(firstStatement)->GetBody()[0].get();
REQUIRE(firstClassStatement->GetKind() == Parser::ParsedStatementKind::VirtProp);
auto virtPropStatement =
dynamic_cast<const MalachScript::Parser::ParsedVirtPropStatement*>(firstClassStatement);
REQUIRE(virtPropStatement->GetAccess() == MalachScript::AccessModifier::Public);
REQUIRE(virtPropStatement->GetIdentifier().GetString() == "foo");
REQUIRE(virtPropStatement->HasGet());
REQUIRE(virtPropStatement->HasSet());
REQUIRE(virtPropStatement->IsGetConst());
REQUIRE(virtPropStatement->IsSetConst());
REQUIRE(FuncAttrHelpers::Contains(virtPropStatement->GetGetFuncAttr(), FuncAttr::Override));
REQUIRE(FuncAttrHelpers::Contains(virtPropStatement->GetSetFuncAttr(), FuncAttr::Override));
REQUIRE(virtPropStatement->GetGetStatement() == nullptr);
REQUIRE(virtPropStatement->GetSetStatement() == nullptr);
})
/// class foobar {
// int i;
// bool foo {
// get {
// if (true) return true;
// return false;
// }
// set{
// if (1 == 1) i++;
// i--;
// }
// }
//}
PARSER_TEST("Virtprops with bodies",
PARSER_TEST_TOKENS(
new Parser::LexTokenImpl<Parser::LexTokenKind::ClassKeyword>(TextSpan(0, 0)),
new Parser::IdentifierToken(TextSpan(0, 0), "foobar"),
new Parser::LexTokenImpl<Parser::LexTokenKind::OpenCurlyParenthesisSymbol>(TextSpan(0, 0)),
new Parser::IdentifierToken(TextSpan(0, 0), "int"), new Parser::IdentifierToken(TextSpan(0, 0), "i"),
new Parser::LexTokenImpl<Parser::LexTokenKind::SemicolonSymbol>(TextSpan(0, 0)),
new Parser::IdentifierToken(TextSpan(0, 0), "bool"), new Parser::IdentifierToken(TextSpan(0, 0), "foo"),
new Parser::LexTokenImpl<Parser::LexTokenKind::OpenCurlyParenthesisSymbol>(TextSpan(0, 0)),
new Parser::LexTokenImpl<Parser::LexTokenKind::GetKeyword>(TextSpan(0, 0)),
new Parser::LexTokenImpl<Parser::LexTokenKind::OpenCurlyParenthesisSymbol>(TextSpan(0, 0)),
new Parser::LexTokenImpl<Parser::LexTokenKind::IfKeyword>(TextSpan(0, 0)),
new Parser::LexTokenImpl<Parser::LexTokenKind::OpenParenthesisSymbol>(TextSpan(0, 0)),
new Parser::LexTokenImpl<Parser::LexTokenKind::TrueKeyword>(TextSpan(0, 0)),
new Parser::LexTokenImpl<Parser::LexTokenKind::CloseParenthesisSymbol>(TextSpan(0, 0)),
new Parser::LexTokenImpl<Parser::LexTokenKind::ReturnKeyword>(TextSpan(0, 0)),
new Parser::LexTokenImpl<Parser::LexTokenKind::TrueKeyword>(TextSpan(0, 0)),
new Parser::LexTokenImpl<Parser::LexTokenKind::SemicolonSymbol>(TextSpan(0, 0)),
new Parser::LexTokenImpl<Parser::LexTokenKind::ReturnKeyword>(TextSpan(0, 0)),
new Parser::LexTokenImpl<Parser::LexTokenKind::FalseKeyword>(TextSpan(0, 0)),
new Parser::LexTokenImpl<Parser::LexTokenKind::SemicolonSymbol>(TextSpan(0, 0)),
new Parser::LexTokenImpl<Parser::LexTokenKind::CloseCurlyParenthesisSymbol>(TextSpan(0, 0)),
new Parser::LexTokenImpl<Parser::LexTokenKind::SetKeyword>(TextSpan(0, 0)),
new Parser::LexTokenImpl<Parser::LexTokenKind::OpenCurlyParenthesisSymbol>(TextSpan(0, 0)),
new Parser::LexTokenImpl<Parser::LexTokenKind::IfKeyword>(TextSpan(0, 0)),
new Parser::LexTokenImpl<Parser::LexTokenKind::OpenParenthesisSymbol>(TextSpan(0, 0)),
new Parser::IntegerLiteral(TextSpan(0, 0), 1),
new Parser::LexTokenImpl<Parser::LexTokenKind::EqualsEqualsSymbol>(TextSpan(0, 0)),
new Parser::IntegerLiteral(TextSpan(0, 0), 1),
new Parser::LexTokenImpl<Parser::LexTokenKind::CloseParenthesisSymbol>(TextSpan(0, 0)),
new Parser::IdentifierToken(TextSpan(0, 0), "i"),
new Parser::LexTokenImpl<Parser::LexTokenKind::PlusPlusSymbol>(TextSpan(0, 0)),
new Parser::LexTokenImpl<Parser::LexTokenKind::SemicolonSymbol>(TextSpan(0, 0)),
new Parser::IdentifierToken(TextSpan(0, 0), "i"),
new Parser::LexTokenImpl<Parser::LexTokenKind::MinusMinusSymbol>(TextSpan(0, 0)),
new Parser::LexTokenImpl<Parser::LexTokenKind::SemicolonSymbol>(TextSpan(0, 0)),
new Parser::LexTokenImpl<Parser::LexTokenKind::CloseCurlyParenthesisSymbol>(TextSpan(0, 0)),
new Parser::LexTokenImpl<Parser::LexTokenKind::CloseCurlyParenthesisSymbol>(TextSpan(0, 0)),
new Parser::LexTokenImpl<Parser::LexTokenKind::CloseCurlyParenthesisSymbol>(TextSpan(0, 0))),
{
REQUIRE(script->GetStatements().size() == 1);
auto firstStatement = script->GetStatements()[0].get();
REQUIRE(firstStatement->GetKind() == Parser::ParsedStatementKind::Class);
auto firstClassStatement =
dynamic_cast<const MalachScript::Parser::ParsedClassStatement*>(firstStatement)->GetBody()[1].get();
REQUIRE(firstClassStatement->GetKind() == Parser::ParsedStatementKind::VirtProp);
auto virtPropStatement =
dynamic_cast<const MalachScript::Parser::ParsedVirtPropStatement*>(firstClassStatement);
REQUIRE(virtPropStatement->GetAccess() == MalachScript::AccessModifier::Public);
REQUIRE(virtPropStatement->GetIdentifier().GetString() == "foo");
REQUIRE(virtPropStatement->HasGet());
REQUIRE(virtPropStatement->HasSet());
REQUIRE_FALSE(virtPropStatement->IsGetConst());
REQUIRE_FALSE(virtPropStatement->IsSetConst());
REQUIRE(virtPropStatement->GetGetStatement() != nullptr);
REQUIRE(virtPropStatement->GetSetStatement() != nullptr);
})