Cleanup of parser class.
All checks were successful
continuous-integration/drone/push Build is passing
All checks were successful
continuous-integration/drone/push Build is passing
This commit is contained in:
parent
5ac627a9b3
commit
5d57838bec
@ -1 +0,0 @@
|
|||||||
#include "Diagnostics.hpp"
|
|
1
src/Diagnostics/Logger.cpp
Normal file
1
src/Diagnostics/Logger.cpp
Normal file
@ -0,0 +1 @@
|
|||||||
|
#include "Logger.hpp"
|
@ -1,11 +1,11 @@
|
|||||||
#ifndef MALACHSCRIPT_DIAGNOSTICS_HPP
|
#ifndef MALACHSCRIPT_LOGGER_HPP
|
||||||
#define MALACHSCRIPT_DIAGNOSTICS_HPP
|
#define MALACHSCRIPT_LOGGER_HPP
|
||||||
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include "Diagnostic.hpp"
|
#include "Diagnostic.hpp"
|
||||||
|
|
||||||
namespace MalachScript::Diagnostics {
|
namespace MalachScript::Diagnostics {
|
||||||
class Diagnostics {
|
class Logger {
|
||||||
std::vector<Diagnostic> _messages;
|
std::vector<Diagnostic> _messages;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
@ -32,4 +32,4 @@ namespace MalachScript::Diagnostics {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // MALACHSCRIPT_DIAGNOSTICS_HPP
|
#endif // MALACHSCRIPT_LOGGER_HPP
|
@ -2,16 +2,16 @@
|
|||||||
#define MALACHSCRIPT_LEXER_HPP
|
#define MALACHSCRIPT_LEXER_HPP
|
||||||
|
|
||||||
#include <string_view>
|
#include <string_view>
|
||||||
#include "../../Diagnostics/Diagnostics.hpp"
|
#include "../../Diagnostics/Logger.hpp"
|
||||||
#include "../../Utils/MemoryPool.hpp"
|
#include "../../Utils/MemoryPool.hpp"
|
||||||
#include "LexToken.hpp"
|
#include "LexToken.hpp"
|
||||||
|
|
||||||
namespace MalachScript::Parser {
|
namespace MalachScript::Parser {
|
||||||
class Lexer {
|
class Lexer {
|
||||||
public:
|
public:
|
||||||
Lexer(const char8_t* scriptName, const char8_t* script, Diagnostics::Diagnostics* diag)
|
Lexer(const char8_t* scriptName, const char8_t* script, Diagnostics::Logger* diag)
|
||||||
: Lexer(std::u8string_view(scriptName), std::u8string_view(script), diag) {}
|
: Lexer(std::u8string_view(scriptName), std::u8string_view(script), diag) {}
|
||||||
Lexer(std::u8string_view scriptName, std::u8string_view script, Diagnostics::Diagnostics* diag)
|
Lexer(std::u8string_view scriptName, std::u8string_view script, Diagnostics::Logger* diag)
|
||||||
: _scriptName(scriptName), _script(script), _scriptLength(script.size()), _diagnostics(diag) {}
|
: _scriptName(scriptName), _script(script), _scriptLength(script.size()), _diagnostics(diag) {}
|
||||||
const LexToken* Lex();
|
const LexToken* Lex();
|
||||||
|
|
||||||
@ -20,7 +20,7 @@ namespace MalachScript::Parser {
|
|||||||
std::u8string_view _script;
|
std::u8string_view _script;
|
||||||
size_t _position = -1;
|
size_t _position = -1;
|
||||||
size_t _scriptLength;
|
size_t _scriptLength;
|
||||||
Diagnostics::Diagnostics* _diagnostics;
|
Diagnostics::Logger* _diagnostics;
|
||||||
|
|
||||||
Utils::MemoryPool<2048, 1024> _allocator;
|
Utils::MemoryPool<2048, 1024> _allocator;
|
||||||
|
|
||||||
|
@ -10,23 +10,27 @@
|
|||||||
|
|
||||||
#define EXPECT_TOKEN(token, kind) \
|
#define EXPECT_TOKEN(token, kind) \
|
||||||
if (token->GetKind() != LexTokenKind::kind) { \
|
if (token->GetKind() != LexTokenKind::kind) { \
|
||||||
logError(Diagnostics::DiagnosticType::UnexpectedToken, token->GetSpan()); \
|
logError(DiagnosticType::UnexpectedToken, token->GetSpan()); \
|
||||||
} else { \
|
} else { \
|
||||||
PROGRESS_TOKEN(token); \
|
PROGRESS_TOKEN(token); \
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define logError(type, span) log(DiagnosticLevel::Error, type, span)
|
||||||
|
|
||||||
namespace MalachScript::Parser {
|
namespace MalachScript::Parser {
|
||||||
|
using namespace Diagnostics;
|
||||||
|
|
||||||
const ParsedScriptStatement* Parser::Parse(const LexToken* firstToken, std::u8string_view scriptName,
|
const ParsedScriptStatement* Parser::Parse(const LexToken* firstToken, std::u8string_view scriptName,
|
||||||
Diagnostics::Diagnostics* diagnostics) {
|
Logger* diagnostics) {
|
||||||
const error_log_func& errorLog = [diagnostics, scriptName](Diagnostics::DiagnosticType type,
|
const log_func& log = [diagnostics, scriptName](DiagnosticLevel level, DiagnosticType type,
|
||||||
const TextSpan& span) {
|
const TextSpan& span) {
|
||||||
diagnostics->LogError(type, scriptName, span);
|
diagnostics->Log(level, type, scriptName, span);
|
||||||
};
|
};
|
||||||
|
|
||||||
return ParseScript(firstToken, errorLog);
|
return ParseScript(firstToken, log);
|
||||||
}
|
}
|
||||||
|
|
||||||
const ParsedScriptStatement* Parser::ParseScript(const LexToken* firstToken, const error_log_func& logError) {
|
const ParsedScriptStatement* Parser::ParseScript(const LexToken* firstToken, const log_func& log) {
|
||||||
std::vector<const ParsedStatement*> statements;
|
std::vector<const ParsedStatement*> statements;
|
||||||
statements.reserve(32);
|
statements.reserve(32);
|
||||||
size_t current = 0;
|
size_t current = 0;
|
||||||
@ -39,9 +43,8 @@ namespace MalachScript::Parser {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
ScopedPtr<const ParsedStatement> statement;
|
ScopedPtr<const ParsedStatement> statement;
|
||||||
auto result = ParseClass(statement, currentToken, logError) ||
|
auto result = ParseClass(statement, currentToken, log) || ParseFunc(statement, currentToken, log) ||
|
||||||
ParseFunc(statement, currentToken, logError) ||
|
ParseNamespace(statement, currentToken, log);
|
||||||
ParseNamespace(statement, currentToken, logError);
|
|
||||||
if (!result) {
|
if (!result) {
|
||||||
// TODO: Log error
|
// TODO: Log error
|
||||||
PROGRESS_TOKEN(currentToken);
|
PROGRESS_TOKEN(currentToken);
|
||||||
@ -57,8 +60,7 @@ namespace MalachScript::Parser {
|
|||||||
}
|
}
|
||||||
return new ParsedScriptStatement(TextSpan(0, end), statements);
|
return new ParsedScriptStatement(TextSpan(0, end), statements);
|
||||||
}
|
}
|
||||||
bool Parser::ParseClass(ScopedPtr<const ParsedStatement>& out, const LexToken*& currentToken,
|
bool Parser::ParseClass(ScopedPtr<const ParsedStatement>& out, const LexToken*& currentToken, const log_func& log) {
|
||||||
const error_log_func& logError) {
|
|
||||||
const auto* current = currentToken;
|
const auto* current = currentToken;
|
||||||
auto start = current->GetSpan().GetStart();
|
auto start = current->GetSpan().GetStart();
|
||||||
bool lookingForClass = true;
|
bool lookingForClass = true;
|
||||||
@ -76,7 +78,7 @@ namespace MalachScript::Parser {
|
|||||||
// After class keyword, an identifier should always follow, if it doesn't, log an error.
|
// After class keyword, an identifier should always follow, if it doesn't, log an error.
|
||||||
Identifier identifier;
|
Identifier identifier;
|
||||||
if (!ParseIdentifier(identifier, current)) {
|
if (!ParseIdentifier(identifier, current)) {
|
||||||
logError(Diagnostics::DiagnosticType::UnexpectedToken, current->GetSpan());
|
logError(DiagnosticType::UnexpectedToken, current->GetSpan());
|
||||||
}
|
}
|
||||||
PROGRESS_TOKEN(current);
|
PROGRESS_TOKEN(current);
|
||||||
std::vector<Identifier> inherits;
|
std::vector<Identifier> inherits;
|
||||||
@ -92,19 +94,19 @@ namespace MalachScript::Parser {
|
|||||||
PROGRESS_TOKEN(current);
|
PROGRESS_TOKEN(current);
|
||||||
Identifier id;
|
Identifier id;
|
||||||
if (!ParseIdentifier(id, current)) {
|
if (!ParseIdentifier(id, current)) {
|
||||||
logError(Diagnostics::DiagnosticType::UnexpectedToken, current->GetSpan());
|
logError(DiagnosticType::UnexpectedToken, current->GetSpan());
|
||||||
}
|
}
|
||||||
inherits.push_back(id);
|
inherits.push_back(id);
|
||||||
while (current->GetKind() == LexTokenKind::CommaSymbol) {
|
while (current->GetKind() == LexTokenKind::CommaSymbol) {
|
||||||
PROGRESS_TOKEN(current);
|
PROGRESS_TOKEN(current);
|
||||||
if (!ParseIdentifier(id, current)) {
|
if (!ParseIdentifier(id, current)) {
|
||||||
logError(Diagnostics::DiagnosticType::UnexpectedToken, current->GetSpan());
|
logError(DiagnosticType::UnexpectedToken, current->GetSpan());
|
||||||
}
|
}
|
||||||
inherits.push_back(id);
|
inherits.push_back(id);
|
||||||
PROGRESS_TOKEN(current);
|
PROGRESS_TOKEN(current);
|
||||||
}
|
}
|
||||||
if (current->GetKind() != LexTokenKind::OpenCurlyParenthesisSymbol) {
|
if (current->GetKind() != LexTokenKind::OpenCurlyParenthesisSymbol) {
|
||||||
logError(Diagnostics::DiagnosticType::UnexpectedToken, current->GetSpan());
|
logError(DiagnosticType::UnexpectedToken, current->GetSpan());
|
||||||
}
|
}
|
||||||
[[fallthrough]];
|
[[fallthrough]];
|
||||||
// Intentionally don't break so we continue into the inner body statement.
|
// Intentionally don't break so we continue into the inner body statement.
|
||||||
@ -119,9 +121,9 @@ namespace MalachScript::Parser {
|
|||||||
}
|
}
|
||||||
ScopedPtr<const ParsedStatement> statement = nullptr;
|
ScopedPtr<const ParsedStatement> statement = nullptr;
|
||||||
// TODO: Sort by complexity
|
// TODO: Sort by complexity
|
||||||
if (!ParseVirtProp(statement, current, logError) && !ParseFunc(statement, current, logError) &&
|
if (!ParseVirtProp(statement, current, log) && !ParseFunc(statement, current, log) &&
|
||||||
!ParseVar(statement, current, logError) && !ParseFuncDef(statement, current, logError)) {
|
!ParseVar(statement, current, log) && !ParseFuncDef(statement, current, log)) {
|
||||||
logError(Diagnostics::DiagnosticType::UnexpectedToken, current->GetSpan());
|
logError(DiagnosticType::UnexpectedToken, current->GetSpan());
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
body.push_back(statement.TakeOwnership());
|
body.push_back(statement.TakeOwnership());
|
||||||
@ -135,7 +137,7 @@ namespace MalachScript::Parser {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
bool Parser::ParseTypeDef(ScopedPtr<const ParsedStatement>& out, const LexToken*& currentToken,
|
bool Parser::ParseTypeDef(ScopedPtr<const ParsedStatement>& out, const LexToken*& currentToken,
|
||||||
const error_log_func& logError) {
|
const log_func& log) {
|
||||||
const auto* current = currentToken;
|
const auto* current = currentToken;
|
||||||
if (current->GetKind() != LexTokenKind::TypedefKeyword) {
|
if (current->GetKind() != LexTokenKind::TypedefKeyword) {
|
||||||
return false;
|
return false;
|
||||||
@ -143,14 +145,14 @@ namespace MalachScript::Parser {
|
|||||||
auto start = current->GetSpan().GetStart();
|
auto start = current->GetSpan().GetStart();
|
||||||
PROGRESS_TOKEN(current);
|
PROGRESS_TOKEN(current);
|
||||||
Identifier defineFrom;
|
Identifier defineFrom;
|
||||||
if (!ParsePrimType(defineFrom, current, logError) && !ParseIdentifier(defineFrom, current)) {
|
if (!ParsePrimType(defineFrom, current, log) && !ParseIdentifier(defineFrom, current)) {
|
||||||
logError(Diagnostics::DiagnosticType::UnexpectedToken, current->GetSpan());
|
logError(DiagnosticType::UnexpectedToken, current->GetSpan());
|
||||||
}
|
}
|
||||||
|
|
||||||
PROGRESS_TOKEN(current);
|
PROGRESS_TOKEN(current);
|
||||||
Identifier defineTo;
|
Identifier defineTo;
|
||||||
if (!ParseIdentifier(defineTo, current)) {
|
if (!ParseIdentifier(defineTo, current)) {
|
||||||
logError(Diagnostics::DiagnosticType::UnexpectedToken, current->GetSpan());
|
logError(DiagnosticType::UnexpectedToken, current->GetSpan());
|
||||||
}
|
}
|
||||||
PROGRESS_TOKEN(current);
|
PROGRESS_TOKEN(current);
|
||||||
EXPECT_TOKEN(current, SemicolonSymbol);
|
EXPECT_TOKEN(current, SemicolonSymbol);
|
||||||
@ -158,7 +160,7 @@ namespace MalachScript::Parser {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
bool Parser::ParseNamespace(ScopedPtr<const ParsedStatement>& out, const LexToken*& currentToken,
|
bool Parser::ParseNamespace(ScopedPtr<const ParsedStatement>& out, const LexToken*& currentToken,
|
||||||
const error_log_func& logError) {
|
const log_func& log) {
|
||||||
const auto* current = currentToken;
|
const auto* current = currentToken;
|
||||||
if (current->GetKind() != LexTokenKind::NamespaceKeyword) {
|
if (current->GetKind() != LexTokenKind::NamespaceKeyword) {
|
||||||
return false;
|
return false;
|
||||||
@ -167,17 +169,16 @@ namespace MalachScript::Parser {
|
|||||||
PROGRESS_TOKEN(current);
|
PROGRESS_TOKEN(current);
|
||||||
Identifier identifier;
|
Identifier identifier;
|
||||||
if (!ParseIdentifier(identifier, current)) {
|
if (!ParseIdentifier(identifier, current)) {
|
||||||
logError(Diagnostics::DiagnosticType::UnexpectedToken, current->GetSpan());
|
logError(DiagnosticType::UnexpectedToken, current->GetSpan());
|
||||||
}
|
}
|
||||||
const auto* script = ParseScript(current, logError);
|
const auto* script = ParseScript(current, log);
|
||||||
auto end = current->GetSpan().GetEnd();
|
auto end = current->GetSpan().GetEnd();
|
||||||
PROGRESS_TOKEN(current);
|
PROGRESS_TOKEN(current);
|
||||||
out = new ParsedNamespaceStatement(TextSpan(start, end), identifier, script);
|
out = new ParsedNamespaceStatement(TextSpan(start, end), identifier, script);
|
||||||
currentToken = current;
|
currentToken = current;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
bool Parser::ParseFunc(ScopedPtr<const ParsedStatement>& out, const LexToken*& currentToken,
|
bool Parser::ParseFunc(ScopedPtr<const ParsedStatement>& out, const LexToken*& currentToken, const log_func& log) {
|
||||||
const error_log_func& logError) {
|
|
||||||
const auto* current = currentToken;
|
const auto* current = currentToken;
|
||||||
auto start = current->GetSpan().GetStart();
|
auto start = current->GetSpan().GetStart();
|
||||||
bool isShared = false;
|
bool isShared = false;
|
||||||
@ -209,7 +210,7 @@ namespace MalachScript::Parser {
|
|||||||
if (current->GetKind() == LexTokenKind::TildeSymbol) {
|
if (current->GetKind() == LexTokenKind::TildeSymbol) {
|
||||||
// TODO: Handle destructor
|
// TODO: Handle destructor
|
||||||
throw std::logic_error("not implemented");
|
throw std::logic_error("not implemented");
|
||||||
} else if (ParseType(typeStatement, current, logError)) {
|
} else if (ParseType(typeStatement, current, log)) {
|
||||||
if (current->GetKind() == LexTokenKind::AmpersandSymbol) {
|
if (current->GetKind() == LexTokenKind::AmpersandSymbol) {
|
||||||
returnsReference = true;
|
returnsReference = true;
|
||||||
PROGRESS_TOKEN(current);
|
PROGRESS_TOKEN(current);
|
||||||
@ -221,7 +222,7 @@ namespace MalachScript::Parser {
|
|||||||
}
|
}
|
||||||
PROGRESS_TOKEN(current);
|
PROGRESS_TOKEN(current);
|
||||||
ScopedPtr<const ParsedStatement> paramList = nullptr;
|
ScopedPtr<const ParsedStatement> paramList = nullptr;
|
||||||
if (!ParseParamList(paramList, current, logError)) {
|
if (!ParseParamList(paramList, current, log)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
bool isConst = false;
|
bool isConst = false;
|
||||||
@ -230,11 +231,11 @@ namespace MalachScript::Parser {
|
|||||||
PROGRESS_TOKEN(current);
|
PROGRESS_TOKEN(current);
|
||||||
}
|
}
|
||||||
FuncAttr funcAttr = FuncAttr::None;
|
FuncAttr funcAttr = FuncAttr::None;
|
||||||
ParseFuncAttr(funcAttr, current, logError);
|
ParseFuncAttr(funcAttr, current, log);
|
||||||
ScopedPtr<const ParsedStatement> statblock = nullptr;
|
ScopedPtr<const ParsedStatement> statblock = nullptr;
|
||||||
if (current->GetKind() != LexTokenKind::SemicolonSymbol) {
|
if (current->GetKind() != LexTokenKind::SemicolonSymbol) {
|
||||||
if (!ParseStatBlock(statblock, current, logError)) {
|
if (!ParseStatBlock(statblock, current, log)) {
|
||||||
logError(Diagnostics::DiagnosticType::UnexpectedToken, current->GetSpan());
|
logError(DiagnosticType::UnexpectedToken, current->GetSpan());
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
PROGRESS_TOKEN(current);
|
PROGRESS_TOKEN(current);
|
||||||
@ -246,8 +247,7 @@ namespace MalachScript::Parser {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Parser::ParseType(ScopedPtr<const ParsedStatement>& out, const LexToken*& currentToken,
|
bool Parser::ParseType(ScopedPtr<const ParsedStatement>& out, const LexToken*& currentToken, const log_func& log) {
|
||||||
const error_log_func& logError) {
|
|
||||||
const auto* token = currentToken;
|
const auto* token = currentToken;
|
||||||
auto start = token->GetSpan().GetStart();
|
auto start = token->GetSpan().GetStart();
|
||||||
bool isConst = false;
|
bool isConst = false;
|
||||||
@ -258,15 +258,15 @@ namespace MalachScript::Parser {
|
|||||||
PROGRESS_TOKEN(token);
|
PROGRESS_TOKEN(token);
|
||||||
}
|
}
|
||||||
ScopedIdentifier scopedIdentifier;
|
ScopedIdentifier scopedIdentifier;
|
||||||
ParseScope(scopedIdentifier.GetScope(), token, logError);
|
ParseScope(scopedIdentifier.GetScope(), token, log);
|
||||||
if (!ParseDataType(scopedIdentifier.GetIdentifier(), token, logError)) {
|
if (!ParseDataType(scopedIdentifier.GetIdentifier(), token, log)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
// TODO: Generics.
|
// TODO: Generics.
|
||||||
if (token->GetKind() == LexTokenKind::OpenBlockParenthesisSymbol) {
|
if (token->GetKind() == LexTokenKind::OpenBlockParenthesisSymbol) {
|
||||||
PROGRESS_TOKEN(token);
|
PROGRESS_TOKEN(token);
|
||||||
if (token->GetKind() != LexTokenKind::CloseBlockParenthesisSymbol) {
|
if (token->GetKind() != LexTokenKind::CloseBlockParenthesisSymbol) {
|
||||||
logError(Diagnostics::DiagnosticType::UnexpectedToken, token->GetSpan());
|
logError(DiagnosticType::UnexpectedToken, token->GetSpan());
|
||||||
} else {
|
} else {
|
||||||
PROGRESS_TOKEN(token);
|
PROGRESS_TOKEN(token);
|
||||||
isArray = true;
|
isArray = true;
|
||||||
@ -284,8 +284,7 @@ namespace MalachScript::Parser {
|
|||||||
out = new ParsedTypeStatement(TextSpan(start, end), isConst, isArray, isHandle, scopedIdentifier);
|
out = new ParsedTypeStatement(TextSpan(start, end), isConst, isArray, isHandle, scopedIdentifier);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
bool Parser::ParseScope(std::vector<Identifier>& scope, const LexToken*& currentToken,
|
bool Parser::ParseScope(std::vector<Identifier>& scope, const LexToken*& currentToken, const log_func& log) {
|
||||||
const error_log_func& logError) {
|
|
||||||
const auto* current = currentToken;
|
const auto* current = currentToken;
|
||||||
if (current->GetKind() == LexTokenKind::ColonColonSymbol) {
|
if (current->GetKind() == LexTokenKind::ColonColonSymbol) {
|
||||||
scope.emplace_back();
|
scope.emplace_back();
|
||||||
@ -315,7 +314,7 @@ namespace MalachScript::Parser {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
logError(Diagnostics::DiagnosticType::UnexpectedToken, currentToken->GetSpan());
|
logError(DiagnosticType::UnexpectedToken, currentToken->GetSpan());
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -324,8 +323,7 @@ namespace MalachScript::Parser {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Parser::ParseFuncAttr(FuncAttr& out, const LexToken*& currentToken,
|
bool Parser::ParseFuncAttr(FuncAttr& out, const LexToken*& currentToken, [[maybe_unused]] const log_func& log) {
|
||||||
[[maybe_unused]] const error_log_func& logError) {
|
|
||||||
bool lookingForFuncAttr = true;
|
bool lookingForFuncAttr = true;
|
||||||
const auto* current = currentToken;
|
const auto* current = currentToken;
|
||||||
while (lookingForFuncAttr) {
|
while (lookingForFuncAttr) {
|
||||||
@ -354,7 +352,7 @@ namespace MalachScript::Parser {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool Parser::ParseParamList(ScopedPtr<const ParsedStatement>& out, const LexToken*& currentToken,
|
bool Parser::ParseParamList(ScopedPtr<const ParsedStatement>& out, const LexToken*& currentToken,
|
||||||
const error_log_func& logError) {
|
const log_func& log) {
|
||||||
if (currentToken->GetKind() != LexTokenKind::OpenParenthesisSymbol) {
|
if (currentToken->GetKind() != LexTokenKind::OpenParenthesisSymbol) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -365,7 +363,7 @@ namespace MalachScript::Parser {
|
|||||||
if (currentToken->GetKind() == LexTokenKind::VoidKeyword) {
|
if (currentToken->GetKind() == LexTokenKind::VoidKeyword) {
|
||||||
PROGRESS_TOKEN(currentToken);
|
PROGRESS_TOKEN(currentToken);
|
||||||
if (currentToken->GetKind() != LexTokenKind::CloseParenthesisSymbol) {
|
if (currentToken->GetKind() != LexTokenKind::CloseParenthesisSymbol) {
|
||||||
logError(Diagnostics::DiagnosticType::UnexpectedToken, currentToken->GetSpan());
|
logError(DiagnosticType::UnexpectedToken, currentToken->GetSpan());
|
||||||
}
|
}
|
||||||
PROGRESS_TOKEN(currentToken);
|
PROGRESS_TOKEN(currentToken);
|
||||||
out = new ParsedParamListStatement(TextSpan(start, currentToken->GetSpan().GetEnd()), parameters);
|
out = new ParsedParamListStatement(TextSpan(start, currentToken->GetSpan().GetEnd()), parameters);
|
||||||
@ -382,10 +380,10 @@ namespace MalachScript::Parser {
|
|||||||
Identifier identifier;
|
Identifier identifier;
|
||||||
const ParsedStatement* defaultExpression = nullptr;
|
const ParsedStatement* defaultExpression = nullptr;
|
||||||
|
|
||||||
if (!ParseType(typeStatement, currentToken, logError)) {
|
if (!ParseType(typeStatement, currentToken, log)) {
|
||||||
logError(Diagnostics::DiagnosticType::UnexpectedToken, currentToken->GetSpan());
|
logError(DiagnosticType::UnexpectedToken, currentToken->GetSpan());
|
||||||
}
|
}
|
||||||
ParseTypeMod(typeMod, currentToken, logError);
|
ParseTypeMod(typeMod, currentToken, log);
|
||||||
ParseIdentifier(identifier, currentToken);
|
ParseIdentifier(identifier, currentToken);
|
||||||
PROGRESS_TOKEN(currentToken);
|
PROGRESS_TOKEN(currentToken);
|
||||||
// TODO: Default expression
|
// TODO: Default expression
|
||||||
@ -400,7 +398,7 @@ namespace MalachScript::Parser {
|
|||||||
PROGRESS_TOKEN(currentToken);
|
PROGRESS_TOKEN(currentToken);
|
||||||
}
|
}
|
||||||
while (currentToken->GetKind() != LexTokenKind::CloseParenthesisSymbol) {
|
while (currentToken->GetKind() != LexTokenKind::CloseParenthesisSymbol) {
|
||||||
logError(Diagnostics::DiagnosticType::UnexpectedToken, currentToken->GetSpan());
|
logError(DiagnosticType::UnexpectedToken, currentToken->GetSpan());
|
||||||
if (currentToken->GetKind() == LexTokenKind::EndOfFile) {
|
if (currentToken->GetKind() == LexTokenKind::EndOfFile) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -416,8 +414,7 @@ namespace MalachScript::Parser {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Parser::ParseDataType(Identifier& out, const LexToken*& currentToken,
|
bool Parser::ParseDataType(Identifier& out, const LexToken*& currentToken, [[maybe_unused]] const log_func& log) {
|
||||||
[[maybe_unused]] const error_log_func& logError) {
|
|
||||||
switch (currentToken->GetKind()) {
|
switch (currentToken->GetKind()) {
|
||||||
case LexTokenKind::Identifier:
|
case LexTokenKind::Identifier:
|
||||||
out = static_cast<const IdentifierToken*>(currentToken)->GetValue();
|
out = static_cast<const IdentifierToken*>(currentToken)->GetValue();
|
||||||
@ -428,7 +425,7 @@ namespace MalachScript::Parser {
|
|||||||
PROGRESS_TOKEN(currentToken);
|
PROGRESS_TOKEN(currentToken);
|
||||||
return true;
|
return true;
|
||||||
default:
|
default:
|
||||||
if (ParsePrimType(out, currentToken, logError)) {
|
if (ParsePrimType(out, currentToken, log)) {
|
||||||
PROGRESS_TOKEN(currentToken);
|
PROGRESS_TOKEN(currentToken);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -437,7 +434,7 @@ namespace MalachScript::Parser {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool Parser::ParseVirtProp([[maybe_unused]] ScopedPtr<const ParsedStatement>& out, const LexToken*& currentToken,
|
bool Parser::ParseVirtProp([[maybe_unused]] ScopedPtr<const ParsedStatement>& out, const LexToken*& currentToken,
|
||||||
const error_log_func& logError) {
|
const log_func& log) {
|
||||||
const auto* current = currentToken;
|
const auto* current = currentToken;
|
||||||
AccessModifier access = AccessModifier::Public;
|
AccessModifier access = AccessModifier::Public;
|
||||||
if (current->GetKind() == LexTokenKind::PrivateKeyword) {
|
if (current->GetKind() == LexTokenKind::PrivateKeyword) {
|
||||||
@ -448,7 +445,7 @@ namespace MalachScript::Parser {
|
|||||||
PROGRESS_TOKEN(current);
|
PROGRESS_TOKEN(current);
|
||||||
}
|
}
|
||||||
ScopedPtr<const ParsedStatement> typeStatement = nullptr;
|
ScopedPtr<const ParsedStatement> typeStatement = nullptr;
|
||||||
if (!ParseType(typeStatement, current, logError)) {
|
if (!ParseType(typeStatement, current, log)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
bool ref = false;
|
bool ref = false;
|
||||||
@ -481,17 +478,17 @@ namespace MalachScript::Parser {
|
|||||||
getConst = true;
|
getConst = true;
|
||||||
PROGRESS_TOKEN(current);
|
PROGRESS_TOKEN(current);
|
||||||
}
|
}
|
||||||
ParseFuncAttr(getAttr, current, logError);
|
ParseFuncAttr(getAttr, current, log);
|
||||||
if (current->GetKind() != LexTokenKind::SemicolonSymbol) {
|
if (current->GetKind() != LexTokenKind::SemicolonSymbol) {
|
||||||
if (!ParseStatBlock(getStatement, current, logError)) {
|
if (!ParseStatBlock(getStatement, current, log)) {
|
||||||
logError(Diagnostics::DiagnosticType::UnexpectedToken, current->GetSpan());
|
logError(DiagnosticType::UnexpectedToken, current->GetSpan());
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
PROGRESS_TOKEN(current);
|
PROGRESS_TOKEN(current);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (hasGet) {
|
if (hasGet) {
|
||||||
logError(Diagnostics::DiagnosticType::DoubleProperty, TextSpan(start, current->GetSpan().GetEnd()));
|
logError(DiagnosticType::DoubleProperty, TextSpan(start, current->GetSpan().GetEnd()));
|
||||||
}
|
}
|
||||||
hasGet = true;
|
hasGet = true;
|
||||||
} else if (current->GetKind() == LexTokenKind::SetKeyword) {
|
} else if (current->GetKind() == LexTokenKind::SetKeyword) {
|
||||||
@ -500,17 +497,17 @@ namespace MalachScript::Parser {
|
|||||||
setConst = true;
|
setConst = true;
|
||||||
PROGRESS_TOKEN(current);
|
PROGRESS_TOKEN(current);
|
||||||
}
|
}
|
||||||
ParseFuncAttr(setAttr, current, logError);
|
ParseFuncAttr(setAttr, current, log);
|
||||||
if (current->GetKind() != LexTokenKind::SemicolonSymbol) {
|
if (current->GetKind() != LexTokenKind::SemicolonSymbol) {
|
||||||
if (!ParseStatBlock(setStatement, current, logError)) {
|
if (!ParseStatBlock(setStatement, current, log)) {
|
||||||
logError(Diagnostics::DiagnosticType::UnexpectedToken, current->GetSpan());
|
logError(DiagnosticType::UnexpectedToken, current->GetSpan());
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
PROGRESS_TOKEN(current);
|
PROGRESS_TOKEN(current);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (hasSet) {
|
if (hasSet) {
|
||||||
logError(Diagnostics::DiagnosticType::DoubleProperty, TextSpan(start, current->GetSpan().GetEnd()));
|
logError(DiagnosticType::DoubleProperty, TextSpan(start, current->GetSpan().GetEnd()));
|
||||||
}
|
}
|
||||||
hasSet = true;
|
hasSet = true;
|
||||||
} else {
|
} else {
|
||||||
@ -518,7 +515,7 @@ namespace MalachScript::Parser {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (current->GetKind() != LexTokenKind::CloseCurlyParenthesisSymbol) {
|
if (current->GetKind() != LexTokenKind::CloseCurlyParenthesisSymbol) {
|
||||||
logError(Diagnostics::DiagnosticType::UnexpectedToken, current->GetSpan());
|
logError(DiagnosticType::UnexpectedToken, current->GetSpan());
|
||||||
} else {
|
} else {
|
||||||
PROGRESS_TOKEN(current);
|
PROGRESS_TOKEN(current);
|
||||||
}
|
}
|
||||||
@ -532,7 +529,7 @@ namespace MalachScript::Parser {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool Parser::ParseIfStatement([[maybe_unused]] ScopedPtr<const ParsedStatement>& out, const LexToken*& currentToken,
|
bool Parser::ParseIfStatement([[maybe_unused]] ScopedPtr<const ParsedStatement>& out, const LexToken*& currentToken,
|
||||||
const error_log_func& logError) {
|
const log_func& log) {
|
||||||
const auto* current = currentToken;
|
const auto* current = currentToken;
|
||||||
if (current->GetKind() != LexTokenKind::IfKeyword) {
|
if (current->GetKind() != LexTokenKind::IfKeyword) {
|
||||||
return false;
|
return false;
|
||||||
@ -540,21 +537,21 @@ namespace MalachScript::Parser {
|
|||||||
PROGRESS_TOKEN(current);
|
PROGRESS_TOKEN(current);
|
||||||
EXPECT_TOKEN(current, OpenParenthesisSymbol);
|
EXPECT_TOKEN(current, OpenParenthesisSymbol);
|
||||||
ScopedPtr<const ParsedStatement> condition = nullptr;
|
ScopedPtr<const ParsedStatement> condition = nullptr;
|
||||||
if (!ParseAssign(condition, current, logError)) {
|
if (!ParseAssign(condition, current, log)) {
|
||||||
logError(Diagnostics::DiagnosticType::UnexpectedToken, current->GetSpan());
|
logError(DiagnosticType::UnexpectedToken, current->GetSpan());
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
EXPECT_TOKEN(current, CloseParenthesisSymbol);
|
EXPECT_TOKEN(current, CloseParenthesisSymbol);
|
||||||
ScopedPtr<const ParsedStatement> body = nullptr;
|
ScopedPtr<const ParsedStatement> body = nullptr;
|
||||||
if (!ParseStatement(body, current, logError)) {
|
if (!ParseStatement(body, current, log)) {
|
||||||
logError(Diagnostics::DiagnosticType::UnexpectedToken, current->GetSpan());
|
logError(DiagnosticType::UnexpectedToken, current->GetSpan());
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
ScopedPtr<const ParsedStatement> elseStatement = nullptr;
|
ScopedPtr<const ParsedStatement> elseStatement = nullptr;
|
||||||
if (current->GetKind() == LexTokenKind::ElseKeyword) {
|
if (current->GetKind() == LexTokenKind::ElseKeyword) {
|
||||||
PROGRESS_TOKEN(current);
|
PROGRESS_TOKEN(current);
|
||||||
if (!ParseStatement(elseStatement, current, logError)) {
|
if (!ParseStatement(elseStatement, current, log)) {
|
||||||
logError(Diagnostics::DiagnosticType::UnexpectedToken, current->GetSpan());
|
logError(DiagnosticType::UnexpectedToken, current->GetSpan());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
out = new ParsedIfStatement(TextSpan(currentToken->GetSpan().GetStart(), current->GetSpan().GetEnd()),
|
out = new ParsedIfStatement(TextSpan(currentToken->GetSpan().GetStart(), current->GetSpan().GetEnd()),
|
||||||
@ -564,23 +561,23 @@ namespace MalachScript::Parser {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool Parser::ParseStatement(ScopedPtr<const ParsedStatement>& out, const LexToken*& currentToken,
|
bool Parser::ParseStatement(ScopedPtr<const ParsedStatement>& out, const LexToken*& currentToken,
|
||||||
const error_log_func& logError) {
|
const log_func& log) {
|
||||||
// TODO: All the other statements. (switch | try );
|
// TODO: All the other statements. (switch | try );
|
||||||
switch (currentToken->GetKind()) {
|
switch (currentToken->GetKind()) {
|
||||||
case LexTokenKind::IfKeyword: return ParseIfStatement(out, currentToken, logError);
|
case LexTokenKind::IfKeyword: return ParseIfStatement(out, currentToken, log);
|
||||||
case LexTokenKind::ForKeyword: return ParseForStatement(out, currentToken, logError);
|
case LexTokenKind::ForKeyword: return ParseForStatement(out, currentToken, log);
|
||||||
case LexTokenKind::WhileKeyword: return ParseWhileStatement(out, currentToken, logError);
|
case LexTokenKind::WhileKeyword: return ParseWhileStatement(out, currentToken, log);
|
||||||
case LexTokenKind::ReturnKeyword: return ParseReturn(out, currentToken, logError);
|
case LexTokenKind::ReturnKeyword: return ParseReturn(out, currentToken, log);
|
||||||
case LexTokenKind::BreakKeyword: return ParseBreak(out, currentToken, logError);
|
case LexTokenKind::BreakKeyword: return ParseBreak(out, currentToken, log);
|
||||||
case LexTokenKind::ContinueKeyword: return ParseContinue(out, currentToken, logError);
|
case LexTokenKind::ContinueKeyword: return ParseContinue(out, currentToken, log);
|
||||||
case LexTokenKind::DoKeyword: return ParseDoWhileStatement(out, currentToken, logError);
|
case LexTokenKind::DoKeyword: return ParseDoWhileStatement(out, currentToken, log);
|
||||||
default: return ParseStatBlock(out, currentToken, logError) || ParseExprStat(out, currentToken, logError);
|
default: return ParseStatBlock(out, currentToken, log) || ParseExprStat(out, currentToken, log);
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Parser::ParseVar([[maybe_unused]] ScopedPtr<const ParsedStatement>& out, const LexToken*& currentToken,
|
bool Parser::ParseVar([[maybe_unused]] ScopedPtr<const ParsedStatement>& out, const LexToken*& currentToken,
|
||||||
const error_log_func& logError) {
|
const log_func& log) {
|
||||||
const auto* current = currentToken;
|
const auto* current = currentToken;
|
||||||
AccessModifier access = AccessModifier::Public;
|
AccessModifier access = AccessModifier::Public;
|
||||||
if (current->GetKind() == LexTokenKind::PrivateKeyword) {
|
if (current->GetKind() == LexTokenKind::PrivateKeyword) {
|
||||||
@ -591,7 +588,7 @@ namespace MalachScript::Parser {
|
|||||||
PROGRESS_TOKEN(current);
|
PROGRESS_TOKEN(current);
|
||||||
}
|
}
|
||||||
ScopedPtr<const ParsedStatement> typeStatement = nullptr;
|
ScopedPtr<const ParsedStatement> typeStatement = nullptr;
|
||||||
if (!ParseType(typeStatement, current, logError)) {
|
if (!ParseType(typeStatement, current, log)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
Identifier identifier;
|
Identifier identifier;
|
||||||
@ -609,7 +606,7 @@ namespace MalachScript::Parser {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool Parser::ParseStatBlock(ScopedPtr<const ParsedStatement>& out, const LexToken*& currentToken,
|
bool Parser::ParseStatBlock(ScopedPtr<const ParsedStatement>& out, const LexToken*& currentToken,
|
||||||
const error_log_func& logError) {
|
const log_func& log) {
|
||||||
const auto* current = currentToken;
|
const auto* current = currentToken;
|
||||||
if (current->GetKind() != LexTokenKind::OpenCurlyParenthesisSymbol) {
|
if (current->GetKind() != LexTokenKind::OpenCurlyParenthesisSymbol) {
|
||||||
return false;
|
return false;
|
||||||
@ -621,7 +618,7 @@ namespace MalachScript::Parser {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
ScopedPtr<const ParsedStatement> stat = nullptr;
|
ScopedPtr<const ParsedStatement> stat = nullptr;
|
||||||
if (ParseVar(stat, current, logError) || ParseStatement(stat, current, logError)) {
|
if (ParseVar(stat, current, log) || ParseStatement(stat, current, log)) {
|
||||||
statements.push_back(stat.TakeOwnership());
|
statements.push_back(stat.TakeOwnership());
|
||||||
} else {
|
} else {
|
||||||
break;
|
break;
|
||||||
@ -630,7 +627,7 @@ namespace MalachScript::Parser {
|
|||||||
if (current->GetKind() == LexTokenKind::CloseCurlyParenthesisSymbol) {
|
if (current->GetKind() == LexTokenKind::CloseCurlyParenthesisSymbol) {
|
||||||
PROGRESS_TOKEN(current);
|
PROGRESS_TOKEN(current);
|
||||||
} else {
|
} else {
|
||||||
logError(Diagnostics::DiagnosticType::UnexpectedToken, current->GetSpan());
|
logError(DiagnosticType::UnexpectedToken, current->GetSpan());
|
||||||
}
|
}
|
||||||
|
|
||||||
out = new ParsedStatBlockStatement(TextSpan(currentToken->GetSpan().GetStart(), current->GetSpan().GetEnd()),
|
out = new ParsedStatBlockStatement(TextSpan(currentToken->GetSpan().GetStart(), current->GetSpan().GetEnd()),
|
||||||
@ -640,13 +637,11 @@ namespace MalachScript::Parser {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool Parser::ParseFuncDef([[maybe_unused]] ScopedPtr<const ParsedStatement>& out,
|
bool Parser::ParseFuncDef([[maybe_unused]] ScopedPtr<const ParsedStatement>& out,
|
||||||
[[maybe_unused]] const LexToken*& currentToken,
|
[[maybe_unused]] const LexToken*& currentToken, [[maybe_unused]] const log_func& log) {
|
||||||
[[maybe_unused]] const error_log_func& logError) {
|
|
||||||
// TODO
|
// TODO
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
bool Parser::ParsePrimType(Identifier& out, const LexToken*& token,
|
bool Parser::ParsePrimType(Identifier& out, const LexToken*& token, [[maybe_unused]] const log_func& log) {
|
||||||
[[maybe_unused]] const error_log_func& logError) {
|
|
||||||
switch (token->GetKind()) {
|
switch (token->GetKind()) {
|
||||||
case LexTokenKind::VoidKeyword: out = PrimitiveTypes::VoidName(); return true;
|
case LexTokenKind::VoidKeyword: out = PrimitiveTypes::VoidName(); return true;
|
||||||
case LexTokenKind::IntKeyword: out = PrimitiveTypes::IntName(); return true;
|
case LexTokenKind::IntKeyword: out = PrimitiveTypes::IntName(); return true;
|
||||||
@ -665,8 +660,7 @@ namespace MalachScript::Parser {
|
|||||||
default: return false;
|
default: return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
bool Parser::ParseTypeMod(TypeMod& typeMod, const LexToken*& currentToken,
|
bool Parser::ParseTypeMod(TypeMod& typeMod, const LexToken*& currentToken, [[maybe_unused]] const log_func& log) {
|
||||||
[[maybe_unused]] const error_log_func& logError) {
|
|
||||||
if (currentToken->GetKind() != LexTokenKind::AmpersandSymbol) {
|
if (currentToken->GetKind() != LexTokenKind::AmpersandSymbol) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -688,10 +682,10 @@ namespace MalachScript::Parser {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
bool Parser::ParseAssign(ScopedPtr<const ParsedStatement>& out, const LexToken*& currentToken,
|
bool Parser::ParseAssign(ScopedPtr<const ParsedStatement>& out, const LexToken*& currentToken,
|
||||||
const error_log_func& logError) {
|
const log_func& log) {
|
||||||
const auto* current = currentToken;
|
const auto* current = currentToken;
|
||||||
ScopedPtr<const ParsedStatement> leftHand = nullptr;
|
ScopedPtr<const ParsedStatement> leftHand = nullptr;
|
||||||
if (!ParseTernary(leftHand, current, logError)) {
|
if (!ParseTernary(leftHand, current, log)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
AssignmentOperator op;
|
AssignmentOperator op;
|
||||||
@ -702,8 +696,8 @@ namespace MalachScript::Parser {
|
|||||||
}
|
}
|
||||||
PROGRESS_TOKEN(current);
|
PROGRESS_TOKEN(current);
|
||||||
ScopedPtr<const ParsedStatement> rightHand = nullptr;
|
ScopedPtr<const ParsedStatement> rightHand = nullptr;
|
||||||
if (!ParseAssign(rightHand, current, logError)) {
|
if (!ParseAssign(rightHand, current, log)) {
|
||||||
logError(Diagnostics::DiagnosticType::UnexpectedToken, current->GetSpan());
|
logError(DiagnosticType::UnexpectedToken, current->GetSpan());
|
||||||
out = leftHand.TakeOwnership();
|
out = leftHand.TakeOwnership();
|
||||||
currentToken = current;
|
currentToken = current;
|
||||||
return true;
|
return true;
|
||||||
@ -716,9 +710,9 @@ namespace MalachScript::Parser {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool Parser::ParseTernary(ScopedPtr<const ParsedStatement>& out, const LexToken*& currentToken,
|
bool Parser::ParseTernary(ScopedPtr<const ParsedStatement>& out, const LexToken*& currentToken,
|
||||||
const error_log_func& logError) {
|
const log_func& log) {
|
||||||
// TODO: implement ternary.
|
// TODO: implement ternary.
|
||||||
return ParseExpr(out, currentToken, logError);
|
return ParseExpr(out, currentToken, log);
|
||||||
}
|
}
|
||||||
|
|
||||||
#define EXPR_PARSER(operator, name, func) \
|
#define EXPR_PARSER(operator, name, func) \
|
||||||
@ -726,8 +720,8 @@ namespace MalachScript::Parser {
|
|||||||
if (func(name, current)) { \
|
if (func(name, current)) { \
|
||||||
PROGRESS_TOKEN(current); \
|
PROGRESS_TOKEN(current); \
|
||||||
ScopedPtr<const ParsedStatement> rightHand = nullptr; \
|
ScopedPtr<const ParsedStatement> rightHand = nullptr; \
|
||||||
if (!ParseExprTerm(rightHand, current, logError)) { \
|
if (!ParseExprTerm(rightHand, current, log)) { \
|
||||||
logError(Diagnostics::DiagnosticType::UnexpectedToken, current->GetSpan()); \
|
logError(DiagnosticType::UnexpectedToken, current->GetSpan()); \
|
||||||
out = leftHand.TakeOwnership(); \
|
out = leftHand.TakeOwnership(); \
|
||||||
currentToken = current; \
|
currentToken = current; \
|
||||||
return true; \
|
return true; \
|
||||||
@ -739,11 +733,10 @@ namespace MalachScript::Parser {
|
|||||||
return true; \
|
return true; \
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Parser::ParseExpr(ScopedPtr<const ParsedStatement>& out, const LexToken*& currentToken,
|
bool Parser::ParseExpr(ScopedPtr<const ParsedStatement>& out, const LexToken*& currentToken, const log_func& log) {
|
||||||
const error_log_func& logError) {
|
|
||||||
const auto* current = currentToken;
|
const auto* current = currentToken;
|
||||||
ScopedPtr<const ParsedStatement> leftHand = nullptr;
|
ScopedPtr<const ParsedStatement> leftHand = nullptr;
|
||||||
if (!ParseExprTerm(leftHand, current, logError)) {
|
if (!ParseExprTerm(leftHand, current, log)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
EXPR_PARSER(MathOperator, mathOp, ParseMathOp);
|
EXPR_PARSER(MathOperator, mathOp, ParseMathOp);
|
||||||
@ -757,17 +750,17 @@ namespace MalachScript::Parser {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool Parser::ParseExprTerm(ScopedPtr<const ParsedStatement>& out, const LexToken*& currentToken,
|
bool Parser::ParseExprTerm(ScopedPtr<const ParsedStatement>& out, const LexToken*& currentToken,
|
||||||
const error_log_func& logError) {
|
const log_func& log) {
|
||||||
const auto* current = currentToken;
|
const auto* current = currentToken;
|
||||||
// TODO ([type '='] initlist)
|
// TODO ([type '='] initlist)
|
||||||
|
|
||||||
PreOperator preOperator;
|
PreOperator preOperator;
|
||||||
bool hasPreOp = ParsePreOp(preOperator, currentToken, logError);
|
bool hasPreOp = ParsePreOp(preOperator, currentToken, log);
|
||||||
if (hasPreOp) {
|
if (hasPreOp) {
|
||||||
PROGRESS_TOKEN(current);
|
PROGRESS_TOKEN(current);
|
||||||
}
|
}
|
||||||
ScopedPtr<const ParsedStatement> operand = nullptr;
|
ScopedPtr<const ParsedStatement> operand = nullptr;
|
||||||
if (!ParseExprValue(operand, current, logError)) {
|
if (!ParseExprValue(operand, current, log)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -790,7 +783,7 @@ namespace MalachScript::Parser {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
bool Parser::ParseExprValue(ScopedPtr<const ParsedStatement>& out, const LexToken*& currentToken,
|
bool Parser::ParseExprValue(ScopedPtr<const ParsedStatement>& out, const LexToken*& currentToken,
|
||||||
const error_log_func& logError) {
|
const log_func& log) {
|
||||||
const auto* current = currentToken;
|
const auto* current = currentToken;
|
||||||
if (current->GetKind() == LexTokenKind::VoidKeyword) {
|
if (current->GetKind() == LexTokenKind::VoidKeyword) {
|
||||||
PROGRESS_TOKEN(current);
|
PROGRESS_TOKEN(current);
|
||||||
@ -801,19 +794,19 @@ namespace MalachScript::Parser {
|
|||||||
}
|
}
|
||||||
// TODO: constructcall
|
// TODO: constructcall
|
||||||
// TODO: funccall
|
// TODO: funccall
|
||||||
if (ParseVarAccess(out, current, logError)) {
|
if (ParseVarAccess(out, current, log)) {
|
||||||
currentToken = current;
|
currentToken = current;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
// TODO: cast
|
// TODO: cast
|
||||||
if (ParseLiteral(out, current, logError)) {
|
if (ParseLiteral(out, current, log)) {
|
||||||
currentToken = current;
|
currentToken = current;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (current->GetKind() == LexTokenKind::OpenParenthesisSymbol) {
|
if (current->GetKind() == LexTokenKind::OpenParenthesisSymbol) {
|
||||||
PROGRESS_TOKEN(current);
|
PROGRESS_TOKEN(current);
|
||||||
if (!ParseAssign(out, current, logError)) {
|
if (!ParseAssign(out, current, log)) {
|
||||||
logError(Diagnostics::DiagnosticType::UnexpectedToken, current->GetSpan());
|
logError(DiagnosticType::UnexpectedToken, current->GetSpan());
|
||||||
}
|
}
|
||||||
EXPECT_TOKEN(current, CloseParenthesisSymbol);
|
EXPECT_TOKEN(current, CloseParenthesisSymbol);
|
||||||
return true;
|
return true;
|
||||||
@ -823,7 +816,7 @@ namespace MalachScript::Parser {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
bool Parser::ParseLiteral(ScopedPtr<const ParsedStatement>& out, const LexToken*& currentToken,
|
bool Parser::ParseLiteral(ScopedPtr<const ParsedStatement>& out, const LexToken*& currentToken,
|
||||||
[[maybe_unused]] const error_log_func& logError) {
|
[[maybe_unused]] const log_func& log) {
|
||||||
switch (currentToken->GetKind()) {
|
switch (currentToken->GetKind()) {
|
||||||
case LexTokenKind::IntegerLiteral:
|
case LexTokenKind::IntegerLiteral:
|
||||||
out = new ParsedLiteralStatement<ParseInt>(
|
out = new ParsedLiteralStatement<ParseInt>(
|
||||||
@ -856,31 +849,31 @@ namespace MalachScript::Parser {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
bool Parser::ParseReturn(ScopedPtr<const ParsedStatement>& out, const LexToken*& currentToken,
|
bool Parser::ParseReturn(ScopedPtr<const ParsedStatement>& out, const LexToken*& currentToken,
|
||||||
const error_log_func& logError) {
|
const log_func& log) {
|
||||||
auto start = currentToken->GetSpan().GetStart();
|
auto start = currentToken->GetSpan().GetStart();
|
||||||
if (currentToken->GetKind() != LexTokenKind::ReturnKeyword) {
|
if (currentToken->GetKind() != LexTokenKind::ReturnKeyword) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
PROGRESS_TOKEN(currentToken);
|
PROGRESS_TOKEN(currentToken);
|
||||||
ScopedPtr<const ParsedStatement> returnBody;
|
ScopedPtr<const ParsedStatement> returnBody;
|
||||||
ParseAssign(returnBody, currentToken, logError);
|
ParseAssign(returnBody, currentToken, log);
|
||||||
EXPECT_TOKEN(currentToken, SemicolonSymbol);
|
EXPECT_TOKEN(currentToken, SemicolonSymbol);
|
||||||
out = new ParsedReturnStatement(TextSpan(start, currentToken->GetSpan().GetEnd()), returnBody.TakeOwnership());
|
out = new ParsedReturnStatement(TextSpan(start, currentToken->GetSpan().GetEnd()), returnBody.TakeOwnership());
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
bool Parser::ParseExprStat(ScopedPtr<const ParsedStatement>& out, const LexToken*& currentToken,
|
bool Parser::ParseExprStat(ScopedPtr<const ParsedStatement>& out, const LexToken*& currentToken,
|
||||||
const error_log_func& logError) {
|
const log_func& log) {
|
||||||
if (!ParseAssign(out, currentToken, logError)) {
|
if (!ParseAssign(out, currentToken, log)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
EXPECT_TOKEN(currentToken, SemicolonSymbol);
|
EXPECT_TOKEN(currentToken, SemicolonSymbol);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
bool Parser::ParseVarAccess(ScopedPtr<const ParsedStatement>& out, const LexToken*& currentToken,
|
bool Parser::ParseVarAccess(ScopedPtr<const ParsedStatement>& out, const LexToken*& currentToken,
|
||||||
const error_log_func& logError) {
|
const log_func& log) {
|
||||||
std::vector<Identifier> scope;
|
std::vector<Identifier> scope;
|
||||||
auto start = currentToken->GetSpan().GetStart();
|
auto start = currentToken->GetSpan().GetStart();
|
||||||
if (ParseScope(scope, currentToken, logError)) {
|
if (ParseScope(scope, currentToken, log)) {
|
||||||
out = new ParsedVarAccessStatement(TextSpan(start, currentToken->GetSpan().GetEnd()), scope);
|
out = new ParsedVarAccessStatement(TextSpan(start, currentToken->GetSpan().GetEnd()), scope);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -895,7 +888,7 @@ namespace MalachScript::Parser {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
bool Parser::ParseContinue(ScopedPtr<const ParsedStatement>& out, const LexToken*& currentToken,
|
bool Parser::ParseContinue(ScopedPtr<const ParsedStatement>& out, const LexToken*& currentToken,
|
||||||
[[maybe_unused]] const error_log_func& logError) {
|
[[maybe_unused]] const log_func& log) {
|
||||||
if (currentToken->GetKind() != LexTokenKind::ContinueKeyword) {
|
if (currentToken->GetKind() != LexTokenKind::ContinueKeyword) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -906,7 +899,7 @@ namespace MalachScript::Parser {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
bool Parser::ParseBreak(ScopedPtr<const ParsedStatement>& out, const LexToken*& currentToken,
|
bool Parser::ParseBreak(ScopedPtr<const ParsedStatement>& out, const LexToken*& currentToken,
|
||||||
[[maybe_unused]] const error_log_func& logError) {
|
[[maybe_unused]] const log_func& log) {
|
||||||
if (currentToken->GetKind() != LexTokenKind::BreakKeyword) {
|
if (currentToken->GetKind() != LexTokenKind::BreakKeyword) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -917,7 +910,7 @@ namespace MalachScript::Parser {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
bool Parser::ParseForStatement(ScopedPtr<const ParsedStatement>& out, const LexToken*& currentToken,
|
bool Parser::ParseForStatement(ScopedPtr<const ParsedStatement>& out, const LexToken*& currentToken,
|
||||||
const error_log_func& logError) {
|
const log_func& log) {
|
||||||
if (currentToken->GetKind() != LexTokenKind::ForKeyword) {
|
if (currentToken->GetKind() != LexTokenKind::ForKeyword) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -925,19 +918,19 @@ namespace MalachScript::Parser {
|
|||||||
PROGRESS_TOKEN(current);
|
PROGRESS_TOKEN(current);
|
||||||
EXPECT_TOKEN(current, OpenParenthesisSymbol);
|
EXPECT_TOKEN(current, OpenParenthesisSymbol);
|
||||||
ScopedPtr<const ParsedStatement> init;
|
ScopedPtr<const ParsedStatement> init;
|
||||||
if (!ParseVar(init, current, logError) && !ParseExprStat(init, current, logError)) {
|
if (!ParseVar(init, current, log) && !ParseExprStat(init, current, log)) {
|
||||||
logError(Diagnostics::DiagnosticType::UnexpectedToken, current->GetSpan());
|
logError(DiagnosticType::UnexpectedToken, current->GetSpan());
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
ScopedPtr<const ParsedStatement> condition;
|
ScopedPtr<const ParsedStatement> condition;
|
||||||
if (!ParseExprStat(condition, current, logError)) {
|
if (!ParseExprStat(condition, current, log)) {
|
||||||
logError(Diagnostics::DiagnosticType::UnexpectedToken, current->GetSpan());
|
logError(DiagnosticType::UnexpectedToken, current->GetSpan());
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
std::vector<const ParsedStatement*> increment;
|
std::vector<const ParsedStatement*> increment;
|
||||||
while (true) {
|
while (true) {
|
||||||
ScopedPtr<const ParsedStatement> element;
|
ScopedPtr<const ParsedStatement> element;
|
||||||
if (ParseAssign(element, current, logError)) {
|
if (ParseAssign(element, current, log)) {
|
||||||
increment.push_back(element.TakeOwnership());
|
increment.push_back(element.TakeOwnership());
|
||||||
}
|
}
|
||||||
if (current->GetKind() != LexTokenKind::CommaSymbol) {
|
if (current->GetKind() != LexTokenKind::CommaSymbol) {
|
||||||
@ -946,8 +939,8 @@ namespace MalachScript::Parser {
|
|||||||
}
|
}
|
||||||
EXPECT_TOKEN(current, CloseParenthesisSymbol);
|
EXPECT_TOKEN(current, CloseParenthesisSymbol);
|
||||||
ScopedPtr<const ParsedStatement> statementBlock;
|
ScopedPtr<const ParsedStatement> statementBlock;
|
||||||
if (!ParseStatement(statementBlock, current, logError)) {
|
if (!ParseStatement(statementBlock, current, log)) {
|
||||||
logError(Diagnostics::DiagnosticType::UnexpectedToken, current->GetSpan());
|
logError(DiagnosticType::UnexpectedToken, current->GetSpan());
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -959,7 +952,7 @@ namespace MalachScript::Parser {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool Parser::ParseWhileStatement(ScopedPtr<const ParsedStatement>& out, const LexToken*& currentToken,
|
bool Parser::ParseWhileStatement(ScopedPtr<const ParsedStatement>& out, const LexToken*& currentToken,
|
||||||
const error_log_func& logError) {
|
const log_func& log) {
|
||||||
const auto* current = currentToken;
|
const auto* current = currentToken;
|
||||||
if (current->GetKind() != LexTokenKind::WhileKeyword) {
|
if (current->GetKind() != LexTokenKind::WhileKeyword) {
|
||||||
return false;
|
return false;
|
||||||
@ -967,14 +960,14 @@ namespace MalachScript::Parser {
|
|||||||
PROGRESS_TOKEN(current);
|
PROGRESS_TOKEN(current);
|
||||||
EXPECT_TOKEN(current, OpenParenthesisSymbol);
|
EXPECT_TOKEN(current, OpenParenthesisSymbol);
|
||||||
ScopedPtr<const ParsedStatement> condition = nullptr;
|
ScopedPtr<const ParsedStatement> condition = nullptr;
|
||||||
if (!ParseAssign(condition, current, logError)) {
|
if (!ParseAssign(condition, current, log)) {
|
||||||
logError(Diagnostics::DiagnosticType::UnexpectedToken, current->GetSpan());
|
logError(DiagnosticType::UnexpectedToken, current->GetSpan());
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
EXPECT_TOKEN(current, CloseParenthesisSymbol);
|
EXPECT_TOKEN(current, CloseParenthesisSymbol);
|
||||||
ScopedPtr<const ParsedStatement> body = nullptr;
|
ScopedPtr<const ParsedStatement> body = nullptr;
|
||||||
if (!ParseStatement(body, current, logError)) {
|
if (!ParseStatement(body, current, log)) {
|
||||||
logError(Diagnostics::DiagnosticType::UnexpectedToken, current->GetSpan());
|
logError(DiagnosticType::UnexpectedToken, current->GetSpan());
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
out = new ParsedWhileStatement(TextSpan(currentToken->GetSpan().GetStart(), current->GetSpan().GetEnd()),
|
out = new ParsedWhileStatement(TextSpan(currentToken->GetSpan().GetStart(), current->GetSpan().GetEnd()),
|
||||||
@ -983,21 +976,21 @@ namespace MalachScript::Parser {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
bool Parser::ParseDoWhileStatement(ScopedPtr<const ParsedStatement>& out, const LexToken*& currentToken,
|
bool Parser::ParseDoWhileStatement(ScopedPtr<const ParsedStatement>& out, const LexToken*& currentToken,
|
||||||
const error_log_func& logError) {
|
const log_func& log) {
|
||||||
const auto* current = currentToken;
|
const auto* current = currentToken;
|
||||||
if (current->GetKind() != LexTokenKind::DoKeyword) {
|
if (current->GetKind() != LexTokenKind::DoKeyword) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
ScopedPtr<const ParsedStatement> body = nullptr;
|
ScopedPtr<const ParsedStatement> body = nullptr;
|
||||||
if (!ParseStatement(body, current, logError)) {
|
if (!ParseStatement(body, current, log)) {
|
||||||
logError(Diagnostics::DiagnosticType::UnexpectedToken, current->GetSpan());
|
logError(DiagnosticType::UnexpectedToken, current->GetSpan());
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
EXPECT_TOKEN(current, WhileKeyword);
|
EXPECT_TOKEN(current, WhileKeyword);
|
||||||
EXPECT_TOKEN(current, OpenParenthesisSymbol);
|
EXPECT_TOKEN(current, OpenParenthesisSymbol);
|
||||||
ScopedPtr<const ParsedStatement> condition = nullptr;
|
ScopedPtr<const ParsedStatement> condition = nullptr;
|
||||||
if (!ParseAssign(condition, current, logError)) {
|
if (!ParseAssign(condition, current, log)) {
|
||||||
logError(Diagnostics::DiagnosticType::UnexpectedToken, current->GetSpan());
|
logError(DiagnosticType::UnexpectedToken, current->GetSpan());
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
EXPECT_TOKEN(current, CloseParenthesisSymbol);
|
EXPECT_TOKEN(current, CloseParenthesisSymbol);
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
|
|
||||||
#include <functional>
|
#include <functional>
|
||||||
#include "../CoreData/Operators.hpp"
|
#include "../CoreData/Operators.hpp"
|
||||||
#include "../Diagnostics/Diagnostics.hpp"
|
#include "../Diagnostics/Logger.hpp"
|
||||||
#include "../Utils/ScopedPtr.hpp"
|
#include "../Utils/ScopedPtr.hpp"
|
||||||
#include "Lexer/LexToken.hpp"
|
#include "Lexer/LexToken.hpp"
|
||||||
#include "Statements/ParsedStatement.hpp"
|
#include "Statements/ParsedStatement.hpp"
|
||||||
@ -12,10 +12,11 @@ namespace MalachScript::Parser {
|
|||||||
class Parser {
|
class Parser {
|
||||||
public:
|
public:
|
||||||
static const ParsedScriptStatement* Parse(const LexToken* firstToken, std::u8string_view scriptName,
|
static const ParsedScriptStatement* Parse(const LexToken* firstToken, std::u8string_view scriptName,
|
||||||
Diagnostics::Diagnostics* diagnostics);
|
Diagnostics::Logger* diagnostics);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
typedef const std::function<void(Diagnostics::DiagnosticType, const TextSpan&)> error_log_func;
|
using log_func =
|
||||||
|
const std::function<void(Diagnostics::DiagnosticLevel level, Diagnostics::DiagnosticType, const TextSpan&)>;
|
||||||
|
|
||||||
/////////////////////////////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////////////////////////////
|
||||||
// Underlying functions are laid out in the order they are defined in the grammar.ebnf //
|
// Underlying functions are laid out in the order they are defined in the grammar.ebnf //
|
||||||
@ -106,15 +107,13 @@ namespace MalachScript::Parser {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool ParsePrimType(Identifier& out, const LexToken*& currentToken, const error_log_func&);
|
static bool ParsePrimType(Identifier& out, const LexToken*& currentToken, const log_func&);
|
||||||
static bool ParseDataType(Identifier& out, const LexToken*& currentToken, const error_log_func&);
|
static bool ParseDataType(Identifier& out, const LexToken*& currentToken, const log_func&);
|
||||||
static bool ParseScope(std::vector<Identifier>& out, const LexToken*& currentToken, const error_log_func&);
|
static bool ParseScope(std::vector<Identifier>& out, const LexToken*& currentToken, const log_func&);
|
||||||
static bool ParseType(ScopedPtr<const ParsedStatement>& out, const LexToken*& currentToken,
|
static bool ParseType(ScopedPtr<const ParsedStatement>& out, const LexToken*& currentToken, const log_func&);
|
||||||
const error_log_func&);
|
static bool ParseAssign(ScopedPtr<const ParsedStatement>& out, const LexToken*& currentToken, const log_func&);
|
||||||
static bool ParseAssign(ScopedPtr<const ParsedStatement>& out, const LexToken*& currentToken,
|
|
||||||
const error_log_func&);
|
|
||||||
// InitList
|
// InitList
|
||||||
inline static bool ParsePreOp(PreOperator& op, const LexToken*& token, const error_log_func&) {
|
inline static bool ParsePreOp(PreOperator& op, const LexToken*& token, const log_func&) {
|
||||||
switch (token->GetKind()) {
|
switch (token->GetKind()) {
|
||||||
case LexTokenKind::MinusSymbol: op = PreOperator::Negation; return true;
|
case LexTokenKind::MinusSymbol: op = PreOperator::Negation; return true;
|
||||||
case LexTokenKind::PlusSymbol: op = PreOperator::Identity; return true;
|
case LexTokenKind::PlusSymbol: op = PreOperator::Identity; return true;
|
||||||
@ -130,75 +129,65 @@ namespace MalachScript::Parser {
|
|||||||
// FuncCall
|
// FuncCall
|
||||||
// ConstructCall
|
// ConstructCall
|
||||||
static bool ParseVarAccess(ScopedPtr<const ParsedStatement>& out, const LexToken*& currentToken,
|
static bool ParseVarAccess(ScopedPtr<const ParsedStatement>& out, const LexToken*& currentToken,
|
||||||
const error_log_func&);
|
const log_func&);
|
||||||
// Cast
|
// Cast
|
||||||
static bool ParseLiteral(ScopedPtr<const ParsedStatement>& out, const LexToken*& currentToken,
|
static bool ParseLiteral(ScopedPtr<const ParsedStatement>& out, const LexToken*& currentToken, const log_func&);
|
||||||
const error_log_func&);
|
static bool ParseTypeMod(TypeMod& typeMod, const LexToken*& currentToken, const log_func&);
|
||||||
static bool ParseTypeMod(TypeMod& typeMod, const LexToken*& currentToken, const error_log_func&);
|
|
||||||
// Lambda
|
// Lambda
|
||||||
|
|
||||||
static bool ParseExprValue(ScopedPtr<const ParsedStatement>& out, const LexToken*& currentToken,
|
static bool ParseExprValue(ScopedPtr<const ParsedStatement>& out, const LexToken*& currentToken,
|
||||||
const error_log_func&);
|
const log_func&);
|
||||||
// ExprPostOp
|
// ExprPostOp
|
||||||
static bool ParseExprTerm(ScopedPtr<const ParsedStatement>& out, const LexToken*& currentToken,
|
static bool ParseExprTerm(ScopedPtr<const ParsedStatement>& out, const LexToken*& currentToken,
|
||||||
const error_log_func&);
|
const log_func&);
|
||||||
static bool ParseExpr(ScopedPtr<const ParsedStatement>& out, const LexToken*& currentToken,
|
static bool ParseExpr(ScopedPtr<const ParsedStatement>& out, const LexToken*& currentToken, const log_func&);
|
||||||
const error_log_func&);
|
static bool ParseTernary(ScopedPtr<const ParsedStatement>& out, const LexToken*& currentToken, const log_func&);
|
||||||
static bool ParseTernary(ScopedPtr<const ParsedStatement>& out, const LexToken*& currentToken,
|
|
||||||
const error_log_func&);
|
|
||||||
|
|
||||||
static bool ParseReturn(ScopedPtr<const ParsedStatement>& out, const LexToken*& currentToken,
|
static bool ParseReturn(ScopedPtr<const ParsedStatement>& out, const LexToken*& currentToken, const log_func&);
|
||||||
const error_log_func&);
|
|
||||||
static bool ParseExprStat(ScopedPtr<const ParsedStatement>& out, const LexToken*& currentToken,
|
static bool ParseExprStat(ScopedPtr<const ParsedStatement>& out, const LexToken*& currentToken,
|
||||||
const error_log_func&);
|
const log_func&);
|
||||||
static bool ParseContinue(ScopedPtr<const ParsedStatement>& out, const LexToken*& currentToken,
|
static bool ParseContinue(ScopedPtr<const ParsedStatement>& out, const LexToken*& currentToken,
|
||||||
const error_log_func&);
|
const log_func&);
|
||||||
static bool ParseBreak(ScopedPtr<const ParsedStatement>& out, const LexToken*& currentToken,
|
static bool ParseBreak(ScopedPtr<const ParsedStatement>& out, const LexToken*& currentToken, const log_func&);
|
||||||
const error_log_func&);
|
|
||||||
|
|
||||||
static bool ParseIfStatement(ScopedPtr<const ParsedStatement>& out, const LexToken*& currentToken,
|
static bool ParseIfStatement(ScopedPtr<const ParsedStatement>& out, const LexToken*& currentToken,
|
||||||
const error_log_func&);
|
const log_func&);
|
||||||
static bool ParseForStatement(ScopedPtr<const ParsedStatement>& out, const LexToken*& currentToken,
|
static bool ParseForStatement(ScopedPtr<const ParsedStatement>& out, const LexToken*& currentToken,
|
||||||
const error_log_func&);
|
const log_func&);
|
||||||
static bool ParseWhileStatement(ScopedPtr<const ParsedStatement>& out, const LexToken*& currentToken,
|
static bool ParseWhileStatement(ScopedPtr<const ParsedStatement>& out, const LexToken*& currentToken,
|
||||||
const error_log_func&);
|
const log_func&);
|
||||||
static bool ParseDoWhileStatement(ScopedPtr<const ParsedStatement>& out, const LexToken*& currentToken,
|
static bool ParseDoWhileStatement(ScopedPtr<const ParsedStatement>& out, const LexToken*& currentToken,
|
||||||
const error_log_func&);
|
const log_func&);
|
||||||
// Try
|
// Try
|
||||||
// Case
|
// Case
|
||||||
// Switch
|
// Switch
|
||||||
|
|
||||||
static bool ParseStatement(ScopedPtr<const ParsedStatement>& out, const LexToken*& currentToken,
|
static bool ParseStatement(ScopedPtr<const ParsedStatement>& out, const LexToken*& currentToken,
|
||||||
const error_log_func&);
|
const log_func&);
|
||||||
static bool ParseVar(ScopedPtr<const ParsedStatement>& out, const LexToken*& currentToken,
|
static bool ParseVar(ScopedPtr<const ParsedStatement>& out, const LexToken*& currentToken, const log_func&);
|
||||||
const error_log_func&);
|
|
||||||
static bool ParseStatBlock(ScopedPtr<const ParsedStatement>& out, const LexToken*& currentToken,
|
static bool ParseStatBlock(ScopedPtr<const ParsedStatement>& out, const LexToken*& currentToken,
|
||||||
const error_log_func&);
|
const log_func&);
|
||||||
|
|
||||||
static bool ParseFuncAttr(FuncAttr& out, const LexToken*& currentToken, const error_log_func&);
|
static bool ParseFuncAttr(FuncAttr& out, const LexToken*& currentToken, const log_func&);
|
||||||
static bool ParseParamList(ScopedPtr<const ParsedStatement>& out, const LexToken*& currentToken,
|
static bool ParseParamList(ScopedPtr<const ParsedStatement>& out, const LexToken*& currentToken,
|
||||||
const error_log_func&);
|
const log_func&);
|
||||||
|
|
||||||
static bool ParseVirtProp(ScopedPtr<const ParsedStatement>& out, const LexToken*& currentToken,
|
static bool ParseVirtProp(ScopedPtr<const ParsedStatement>& out, const LexToken*& currentToken,
|
||||||
const error_log_func&);
|
const log_func&);
|
||||||
static bool ParseFunc(ScopedPtr<const ParsedStatement>& out, const LexToken*& currentToken,
|
static bool ParseFunc(ScopedPtr<const ParsedStatement>& out, const LexToken*& currentToken, const log_func&);
|
||||||
const error_log_func&);
|
static bool ParseFuncDef(ScopedPtr<const ParsedStatement>& out, const LexToken*& currentToken, const log_func&);
|
||||||
static bool ParseFuncDef(ScopedPtr<const ParsedStatement>& out, const LexToken*& currentToken,
|
static bool ParseClass(ScopedPtr<const ParsedStatement>& out, const LexToken*& currentToken, const log_func&);
|
||||||
const error_log_func&);
|
|
||||||
static bool ParseClass(ScopedPtr<const ParsedStatement>& out, const LexToken*& currentToken,
|
|
||||||
const error_log_func&);
|
|
||||||
|
|
||||||
// Mixin
|
// Mixin
|
||||||
// Enum
|
// Enum
|
||||||
// Import
|
// Import
|
||||||
static bool ParseTypeDef(ScopedPtr<const ParsedStatement>& out, const LexToken*& currentToken,
|
static bool ParseTypeDef(ScopedPtr<const ParsedStatement>& out, const LexToken*& currentToken, const log_func&);
|
||||||
const error_log_func&);
|
|
||||||
|
|
||||||
// InterfaceMethod
|
// InterfaceMethod
|
||||||
// Interface
|
// Interface
|
||||||
static bool ParseNamespace(ScopedPtr<const ParsedStatement>& out, const LexToken*& currentToken,
|
static bool ParseNamespace(ScopedPtr<const ParsedStatement>& out, const LexToken*& currentToken,
|
||||||
const error_log_func&);
|
const log_func&);
|
||||||
static const ParsedScriptStatement* ParseScript(const LexToken* firstToken, const error_log_func&);
|
static const ParsedScriptStatement* ParseScript(const LexToken* firstToken, const log_func&);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5,7 +5,7 @@ using namespace MalachScript::Parser;
|
|||||||
|
|
||||||
#define KEYWORD_TEST(script, symbol) \
|
#define KEYWORD_TEST(script, symbol) \
|
||||||
TEST_CASE("Lex " script) { \
|
TEST_CASE("Lex " script) { \
|
||||||
MalachScript::Diagnostics::Diagnostics diag; \
|
MalachScript::Diagnostics::Logger diag; \
|
||||||
auto lexer = Lexer(u8##script, u8##script, &diag); \
|
auto lexer = Lexer(u8##script, u8##script, &diag); \
|
||||||
const auto* token = lexer.Lex(); \
|
const auto* token = lexer.Lex(); \
|
||||||
CHECK(diag.GetMessages().empty()); \
|
CHECK(diag.GetMessages().empty()); \
|
||||||
@ -92,7 +92,7 @@ namespace doctest {
|
|||||||
|
|
||||||
#define IDENTIFIER_TEST(identifier) \
|
#define IDENTIFIER_TEST(identifier) \
|
||||||
TEST_CASE("Lex identifier " identifier) { \
|
TEST_CASE("Lex identifier " identifier) { \
|
||||||
MalachScript::Diagnostics::Diagnostics diag; \
|
MalachScript::Diagnostics::Logger diag; \
|
||||||
auto lexer = Lexer(u8##identifier, u8##identifier, &diag); \
|
auto lexer = Lexer(u8##identifier, u8##identifier, &diag); \
|
||||||
const auto* token = lexer.Lex(); \
|
const auto* token = lexer.Lex(); \
|
||||||
CHECK(diag.GetMessages().empty()); \
|
CHECK(diag.GetMessages().empty()); \
|
||||||
|
@ -5,7 +5,7 @@ using namespace MalachScript::Parser;
|
|||||||
|
|
||||||
#define LEX_TEST(script, ...) \
|
#define LEX_TEST(script, ...) \
|
||||||
TEST_CASE("Lex: " script) { \
|
TEST_CASE("Lex: " script) { \
|
||||||
MalachScript::Diagnostics::Diagnostics diag; \
|
MalachScript::Diagnostics::Logger diag; \
|
||||||
auto lexer = Lexer(u8##script, u8##script, &diag); \
|
auto lexer = Lexer(u8##script, u8##script, &diag); \
|
||||||
const auto* token = lexer.Lex(); \
|
const auto* token = lexer.Lex(); \
|
||||||
CHECK(diag.GetMessages().empty()); \
|
CHECK(diag.GetMessages().empty()); \
|
||||||
|
@ -5,7 +5,7 @@ using namespace MalachScript::Parser;
|
|||||||
|
|
||||||
#define INTEGER_TEST(script, expected) \
|
#define INTEGER_TEST(script, expected) \
|
||||||
TEST_CASE("Lex " script) { \
|
TEST_CASE("Lex " script) { \
|
||||||
MalachScript::Diagnostics::Diagnostics diag; \
|
MalachScript::Diagnostics::Logger diag; \
|
||||||
auto lexer = Lexer(u8##script, u8##script, &diag); \
|
auto lexer = Lexer(u8##script, u8##script, &diag); \
|
||||||
const auto* token = lexer.Lex(); \
|
const auto* token = lexer.Lex(); \
|
||||||
CHECK(diag.GetMessages().empty()); \
|
CHECK(diag.GetMessages().empty()); \
|
||||||
@ -17,7 +17,7 @@ using namespace MalachScript::Parser;
|
|||||||
|
|
||||||
#define FLOAT_TEST(script, expected) \
|
#define FLOAT_TEST(script, expected) \
|
||||||
TEST_CASE("Lex " script) { \
|
TEST_CASE("Lex " script) { \
|
||||||
MalachScript::Diagnostics::Diagnostics diag; \
|
MalachScript::Diagnostics::Logger diag; \
|
||||||
auto lexer = Lexer(u8##script, u8##script, &diag); \
|
auto lexer = Lexer(u8##script, u8##script, &diag); \
|
||||||
const auto* token = lexer.Lex(); \
|
const auto* token = lexer.Lex(); \
|
||||||
CHECK(diag.GetMessages().empty()); \
|
CHECK(diag.GetMessages().empty()); \
|
||||||
@ -72,7 +72,7 @@ INTEGER_TEST("0B110011", 51);
|
|||||||
#undef FLOAT_TEST
|
#undef FLOAT_TEST
|
||||||
|
|
||||||
TEST_CASE("Lex invalid numerical base") {
|
TEST_CASE("Lex invalid numerical base") {
|
||||||
MalachScript::Diagnostics::Diagnostics diag;
|
MalachScript::Diagnostics::Logger diag;
|
||||||
auto lexer = Lexer(u8"bad base", u8"0f553", &diag);
|
auto lexer = Lexer(u8"bad base", u8"0f553", &diag);
|
||||||
lexer.Lex();
|
lexer.Lex();
|
||||||
const auto& messages = diag.GetMessages();
|
const auto& messages = diag.GetMessages();
|
||||||
|
@ -5,7 +5,7 @@ using namespace MalachScript::Parser;
|
|||||||
|
|
||||||
#define STRING_TEST(str, constraint) \
|
#define STRING_TEST(str, constraint) \
|
||||||
TEST_CASE("Lex string " constraint str constraint) { \
|
TEST_CASE("Lex string " constraint str constraint) { \
|
||||||
MalachScript::Diagnostics::Diagnostics diag; \
|
MalachScript::Diagnostics::Logger diag; \
|
||||||
auto lexer = Lexer(u8##str, u8##constraint str constraint, &diag); \
|
auto lexer = Lexer(u8##str, u8##constraint str constraint, &diag); \
|
||||||
const auto* token = lexer.Lex(); \
|
const auto* token = lexer.Lex(); \
|
||||||
CHECK(diag.GetMessages().empty()); \
|
CHECK(diag.GetMessages().empty()); \
|
||||||
@ -22,7 +22,7 @@ STRING_TEST("\"foo bar\"", "\"\"\"");
|
|||||||
STRING_TEST("\"\"foo bar\"\"", "\"\"\"");
|
STRING_TEST("\"\"foo bar\"\"", "\"\"\"");
|
||||||
|
|
||||||
TEST_CASE("Lex multiline string") {
|
TEST_CASE("Lex multiline string") {
|
||||||
MalachScript::Diagnostics::Diagnostics diag;
|
MalachScript::Diagnostics::Logger diag;
|
||||||
auto lexer = Lexer(u8"multiline", u8R"("""foo
|
auto lexer = Lexer(u8"multiline", u8R"("""foo
|
||||||
bar""")",
|
bar""")",
|
||||||
&diag);
|
&diag);
|
||||||
|
@ -6,7 +6,7 @@ using namespace MalachScript::Parser;
|
|||||||
|
|
||||||
#define SYMBOL_TEST(script, symbol) \
|
#define SYMBOL_TEST(script, symbol) \
|
||||||
TEST_CASE("Lex " script) { \
|
TEST_CASE("Lex " script) { \
|
||||||
MalachScript::Diagnostics::Diagnostics diag; \
|
MalachScript::Diagnostics::Logger diag; \
|
||||||
auto lexer = Lexer(u8##script, u8##script, &diag); \
|
auto lexer = Lexer(u8##script, u8##script, &diag); \
|
||||||
const auto* token = lexer.Lex(); \
|
const auto* token = lexer.Lex(); \
|
||||||
CHECK(diag.GetMessages().empty()); \
|
CHECK(diag.GetMessages().empty()); \
|
||||||
@ -73,7 +73,7 @@ SYMBOL_TEST(" ", Whitespace)
|
|||||||
TEST_CASE("Lex whitespace") {
|
TEST_CASE("Lex whitespace") {
|
||||||
auto whitespace = {u8" ", u8"\t", u8"\n", u8"\r", u8"\xef\xbb\xbf"};
|
auto whitespace = {u8" ", u8"\t", u8"\n", u8"\r", u8"\xef\xbb\xbf"};
|
||||||
for (const auto* v : whitespace) {
|
for (const auto* v : whitespace) {
|
||||||
MalachScript::Diagnostics::Diagnostics diag;
|
MalachScript::Diagnostics::Logger diag;
|
||||||
auto lexer = Lexer(u8"whitespace", v, &diag);
|
auto lexer = Lexer(u8"whitespace", v, &diag);
|
||||||
const auto* token = lexer.Lex();
|
const auto* token = lexer.Lex();
|
||||||
CHECK(diag.GetMessages().empty());
|
CHECK(diag.GetMessages().empty());
|
||||||
|
@ -12,7 +12,7 @@ using namespace MalachScript;
|
|||||||
for (size_t i = 0; i < vec.size() - 1; i++) { \
|
for (size_t i = 0; i < vec.size() - 1; i++) { \
|
||||||
vec[i]->SetNext(vec[i + 1]); \
|
vec[i]->SetNext(vec[i + 1]); \
|
||||||
} \
|
} \
|
||||||
Diagnostics::Diagnostics diags; \
|
Diagnostics::Logger diags; \
|
||||||
auto* script = Parser::Parser::Parse(vec.front(), u8"scriptname", &diags); \
|
auto* script = Parser::Parser::Parse(vec.front(), u8"scriptname", &diags); \
|
||||||
REQUIRE(diags.GetMessages().empty()); \
|
REQUIRE(diags.GetMessages().empty()); \
|
||||||
asserts; \
|
asserts; \
|
||||||
|
@ -12,7 +12,7 @@ using namespace MalachScript;
|
|||||||
for (size_t i = 0; i < vec.size() - 1; i++) { \
|
for (size_t i = 0; i < vec.size() - 1; i++) { \
|
||||||
vec[i]->SetNext(vec[i + 1]); \
|
vec[i]->SetNext(vec[i + 1]); \
|
||||||
} \
|
} \
|
||||||
Diagnostics::Diagnostics diags; \
|
Diagnostics::Logger diags; \
|
||||||
auto* script = Parser::Parser::Parse(vec.front(), u8"scriptname", &diags); \
|
auto* script = Parser::Parser::Parse(vec.front(), u8"scriptname", &diags); \
|
||||||
REQUIRE(diags.GetMessages().empty()); \
|
REQUIRE(diags.GetMessages().empty()); \
|
||||||
asserts; \
|
asserts; \
|
||||||
|
@ -6,7 +6,7 @@ using namespace MalachScript;
|
|||||||
|
|
||||||
#define PARSE_TEST(name, scriptText, asserts) \
|
#define PARSE_TEST(name, scriptText, asserts) \
|
||||||
TEST_CASE(name) { \
|
TEST_CASE(name) { \
|
||||||
Diagnostics::Diagnostics diags; \
|
Diagnostics::Logger diags; \
|
||||||
auto lexer = Parser::Lexer(u8##name, u8##scriptText, &diags); \
|
auto lexer = Parser::Lexer(u8##name, u8##scriptText, &diags); \
|
||||||
auto token = lexer.Lex(); \
|
auto token = lexer.Lex(); \
|
||||||
auto script = Parser::Parser::Parse(token, u8##name, &diags); \
|
auto script = Parser::Parser::Parse(token, u8##name, &diags); \
|
||||||
|
@ -12,7 +12,7 @@ using namespace MalachScript;
|
|||||||
for (size_t i = 0; i < vec.size() - 1; i++) { \
|
for (size_t i = 0; i < vec.size() - 1; i++) { \
|
||||||
vec[i]->SetNext(vec[i + 1]); \
|
vec[i]->SetNext(vec[i + 1]); \
|
||||||
} \
|
} \
|
||||||
Diagnostics::Diagnostics diags; \
|
Diagnostics::Logger diags; \
|
||||||
auto* script = Parser::Parser::Parse(vec.front(), u8"scriptname", &diags); \
|
auto* script = Parser::Parser::Parse(vec.front(), u8"scriptname", &diags); \
|
||||||
REQUIRE(diags.GetMessages().empty()); \
|
REQUIRE(diags.GetMessages().empty()); \
|
||||||
asserts; \
|
asserts; \
|
||||||
|
Loading…
x
Reference in New Issue
Block a user