131 lines
9.8 KiB
C++
131 lines
9.8 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::Diagnostics diags; \
|
||
|
auto parser = Parser::Parser(u8"scriptname", vec.front(), &diags); \
|
||
|
auto* script = parser.Parse(); \
|
||
|
REQUIRE(diags.GetMessages().empty()); \
|
||
|
asserts; \
|
||
|
delete vec[0]; \
|
||
|
delete script; \
|
||
|
}
|
||
|
|
||
|
#define PARSER_TEST_TOKENS(...) __VA_ARGS__
|
||
|
|
||
|
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), u8"foobar"),
|
||
|
new Parser::LexTokenImpl<Parser::LexTokenKind::OpenCurlyParenthesisSymbol>(TextSpan(0, 0)),
|
||
|
new Parser::IdentifierToken(TextSpan(0, 0), u8"bool"),
|
||
|
new Parser::IdentifierToken(TextSpan(0, 0), u8"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() == u8"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), u8"foobar"),
|
||
|
new Parser::LexTokenImpl<Parser::LexTokenKind::OpenCurlyParenthesisSymbol>(TextSpan(0, 0)),
|
||
|
new Parser::IdentifierToken(TextSpan(0, 0), u8"bool"),
|
||
|
new Parser::IdentifierToken(TextSpan(0, 0), u8"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() == u8"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), u8"foobar"),
|
||
|
new Parser::LexTokenImpl<Parser::LexTokenKind::OpenCurlyParenthesisSymbol>(TextSpan(0, 0)),
|
||
|
new Parser::IdentifierToken(TextSpan(0, 0), u8"bool"),
|
||
|
new Parser::IdentifierToken(TextSpan(0, 0), u8"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() == u8"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);
|
||
|
})
|