Make parser class static, to reduce required state.
continuous-integration/drone/push Build is passing
Details
continuous-integration/drone/push Build is passing
Details
This commit is contained in:
parent
dd2722d485
commit
5ac627a9b3
|
@ -10,19 +10,27 @@
|
|||
|
||||
#define EXPECT_TOKEN(token, kind) \
|
||||
if (token->GetKind() != LexTokenKind::kind) { \
|
||||
LogError(Diagnostics::DiagnosticType::UnexpectedToken, token->GetSpan()); \
|
||||
logError(Diagnostics::DiagnosticType::UnexpectedToken, token->GetSpan()); \
|
||||
} else { \
|
||||
PROGRESS_TOKEN(token); \
|
||||
}
|
||||
|
||||
namespace MalachScript::Parser {
|
||||
const ParsedScriptStatement* Parser::Parse() { return ParseScript(); }
|
||||
const ParsedScriptStatement* Parser::Parse(const LexToken* firstToken, std::u8string_view scriptName,
|
||||
Diagnostics::Diagnostics* diagnostics) {
|
||||
const error_log_func& errorLog = [diagnostics, scriptName](Diagnostics::DiagnosticType type,
|
||||
const TextSpan& span) {
|
||||
diagnostics->LogError(type, scriptName, span);
|
||||
};
|
||||
|
||||
const ParsedScriptStatement* Parser::ParseScript() {
|
||||
return ParseScript(firstToken, errorLog);
|
||||
}
|
||||
|
||||
const ParsedScriptStatement* Parser::ParseScript(const LexToken* firstToken, const error_log_func& logError) {
|
||||
std::vector<const ParsedStatement*> statements;
|
||||
statements.reserve(32);
|
||||
size_t current = 0;
|
||||
const auto* currentToken = _firstToken;
|
||||
const auto* currentToken = firstToken;
|
||||
while (true) {
|
||||
while (currentToken->GetKind() == LexTokenKind::Whitespace) {
|
||||
currentToken = currentToken->GetNext().get();
|
||||
|
@ -31,8 +39,9 @@ namespace MalachScript::Parser {
|
|||
break;
|
||||
}
|
||||
ScopedPtr<const ParsedStatement> statement;
|
||||
auto result = ParseClass(statement, currentToken) || ParseFunc(statement, currentToken) ||
|
||||
ParseNamespace(statement, currentToken);
|
||||
auto result = ParseClass(statement, currentToken, logError) ||
|
||||
ParseFunc(statement, currentToken, logError) ||
|
||||
ParseNamespace(statement, currentToken, logError);
|
||||
if (!result) {
|
||||
// TODO: Log error
|
||||
PROGRESS_TOKEN(currentToken);
|
||||
|
@ -48,7 +57,8 @@ namespace MalachScript::Parser {
|
|||
}
|
||||
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 error_log_func& logError) {
|
||||
const auto* current = currentToken;
|
||||
auto start = current->GetSpan().GetStart();
|
||||
bool lookingForClass = true;
|
||||
|
@ -66,7 +76,7 @@ namespace MalachScript::Parser {
|
|||
// After class keyword, an identifier should always follow, if it doesn't, log an error.
|
||||
Identifier identifier;
|
||||
if (!ParseIdentifier(identifier, current)) {
|
||||
LogError(Diagnostics::DiagnosticType::UnexpectedToken, current->GetSpan());
|
||||
logError(Diagnostics::DiagnosticType::UnexpectedToken, current->GetSpan());
|
||||
}
|
||||
PROGRESS_TOKEN(current);
|
||||
std::vector<Identifier> inherits;
|
||||
|
@ -82,19 +92,19 @@ namespace MalachScript::Parser {
|
|||
PROGRESS_TOKEN(current);
|
||||
Identifier id;
|
||||
if (!ParseIdentifier(id, current)) {
|
||||
LogError(Diagnostics::DiagnosticType::UnexpectedToken, current->GetSpan());
|
||||
logError(Diagnostics::DiagnosticType::UnexpectedToken, current->GetSpan());
|
||||
}
|
||||
inherits.push_back(id);
|
||||
while (current->GetKind() == LexTokenKind::CommaSymbol) {
|
||||
PROGRESS_TOKEN(current);
|
||||
if (!ParseIdentifier(id, current)) {
|
||||
LogError(Diagnostics::DiagnosticType::UnexpectedToken, current->GetSpan());
|
||||
logError(Diagnostics::DiagnosticType::UnexpectedToken, current->GetSpan());
|
||||
}
|
||||
inherits.push_back(id);
|
||||
PROGRESS_TOKEN(current);
|
||||
}
|
||||
if (current->GetKind() != LexTokenKind::OpenCurlyParenthesisSymbol) {
|
||||
LogError(Diagnostics::DiagnosticType::UnexpectedToken, current->GetSpan());
|
||||
logError(Diagnostics::DiagnosticType::UnexpectedToken, current->GetSpan());
|
||||
}
|
||||
[[fallthrough]];
|
||||
// Intentionally don't break so we continue into the inner body statement.
|
||||
|
@ -109,9 +119,9 @@ namespace MalachScript::Parser {
|
|||
}
|
||||
ScopedPtr<const ParsedStatement> statement = nullptr;
|
||||
// TODO: Sort by complexity
|
||||
if (!ParseVirtProp(statement, current) && !ParseFunc(statement, current) &&
|
||||
!ParseVar(statement, current) && !ParseFuncDef(statement, current)) {
|
||||
LogError(Diagnostics::DiagnosticType::UnexpectedToken, current->GetSpan());
|
||||
if (!ParseVirtProp(statement, current, logError) && !ParseFunc(statement, current, logError) &&
|
||||
!ParseVar(statement, current, logError) && !ParseFuncDef(statement, current, logError)) {
|
||||
logError(Diagnostics::DiagnosticType::UnexpectedToken, current->GetSpan());
|
||||
break;
|
||||
}
|
||||
body.push_back(statement.TakeOwnership());
|
||||
|
@ -124,7 +134,8 @@ namespace MalachScript::Parser {
|
|||
currentToken = current;
|
||||
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 auto* current = currentToken;
|
||||
if (current->GetKind() != LexTokenKind::TypedefKeyword) {
|
||||
return false;
|
||||
|
@ -132,21 +143,22 @@ namespace MalachScript::Parser {
|
|||
auto start = current->GetSpan().GetStart();
|
||||
PROGRESS_TOKEN(current);
|
||||
Identifier defineFrom;
|
||||
if (!ParsePrimType(defineFrom, current) && !ParseIdentifier(defineFrom, current)) {
|
||||
LogError(Diagnostics::DiagnosticType::UnexpectedToken, current->GetSpan());
|
||||
if (!ParsePrimType(defineFrom, current, logError) && !ParseIdentifier(defineFrom, current)) {
|
||||
logError(Diagnostics::DiagnosticType::UnexpectedToken, current->GetSpan());
|
||||
}
|
||||
|
||||
PROGRESS_TOKEN(current);
|
||||
Identifier defineTo;
|
||||
if (!ParseIdentifier(defineTo, current)) {
|
||||
LogError(Diagnostics::DiagnosticType::UnexpectedToken, current->GetSpan());
|
||||
logError(Diagnostics::DiagnosticType::UnexpectedToken, current->GetSpan());
|
||||
}
|
||||
PROGRESS_TOKEN(current);
|
||||
EXPECT_TOKEN(current, SemicolonSymbol);
|
||||
out = new ParsedTypeDefStatement(TextSpan(start, current->GetSpan().GetEnd()), defineFrom, defineTo);
|
||||
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 auto* current = currentToken;
|
||||
if (current->GetKind() != LexTokenKind::NamespaceKeyword) {
|
||||
return false;
|
||||
|
@ -155,16 +167,17 @@ namespace MalachScript::Parser {
|
|||
PROGRESS_TOKEN(current);
|
||||
Identifier identifier;
|
||||
if (!ParseIdentifier(identifier, current)) {
|
||||
LogError(Diagnostics::DiagnosticType::UnexpectedToken, current->GetSpan());
|
||||
logError(Diagnostics::DiagnosticType::UnexpectedToken, current->GetSpan());
|
||||
}
|
||||
const auto* script = ParseScript();
|
||||
const auto* script = ParseScript(current, logError);
|
||||
auto end = current->GetSpan().GetEnd();
|
||||
PROGRESS_TOKEN(current);
|
||||
out = new ParsedNamespaceStatement(TextSpan(start, end), identifier, script);
|
||||
currentToken = current;
|
||||
return true;
|
||||
}
|
||||
bool Parser::ParseFunc(ScopedPtr<const ParsedStatement>& out, const LexToken*& currentToken) {
|
||||
bool Parser::ParseFunc(ScopedPtr<const ParsedStatement>& out, const LexToken*& currentToken,
|
||||
const error_log_func& logError) {
|
||||
const auto* current = currentToken;
|
||||
auto start = current->GetSpan().GetStart();
|
||||
bool isShared = false;
|
||||
|
@ -196,7 +209,7 @@ namespace MalachScript::Parser {
|
|||
if (current->GetKind() == LexTokenKind::TildeSymbol) {
|
||||
// TODO: Handle destructor
|
||||
throw std::logic_error("not implemented");
|
||||
} else if (ParseType(typeStatement, current)) {
|
||||
} else if (ParseType(typeStatement, current, logError)) {
|
||||
if (current->GetKind() == LexTokenKind::AmpersandSymbol) {
|
||||
returnsReference = true;
|
||||
PROGRESS_TOKEN(current);
|
||||
|
@ -208,7 +221,7 @@ namespace MalachScript::Parser {
|
|||
}
|
||||
PROGRESS_TOKEN(current);
|
||||
ScopedPtr<const ParsedStatement> paramList = nullptr;
|
||||
if (!ParseParamList(paramList, current)) {
|
||||
if (!ParseParamList(paramList, current, logError)) {
|
||||
return false;
|
||||
}
|
||||
bool isConst = false;
|
||||
|
@ -217,11 +230,11 @@ namespace MalachScript::Parser {
|
|||
PROGRESS_TOKEN(current);
|
||||
}
|
||||
FuncAttr funcAttr = FuncAttr::None;
|
||||
ParseFuncAttr(funcAttr, current);
|
||||
ParseFuncAttr(funcAttr, current, logError);
|
||||
ScopedPtr<const ParsedStatement> statblock = nullptr;
|
||||
if (current->GetKind() != LexTokenKind::SemicolonSymbol) {
|
||||
if (!ParseStatBlock(statblock, current)) {
|
||||
LogError(Diagnostics::DiagnosticType::UnexpectedToken, current->GetSpan());
|
||||
if (!ParseStatBlock(statblock, current, logError)) {
|
||||
logError(Diagnostics::DiagnosticType::UnexpectedToken, current->GetSpan());
|
||||
}
|
||||
} else {
|
||||
PROGRESS_TOKEN(current);
|
||||
|
@ -233,7 +246,8 @@ namespace MalachScript::Parser {
|
|||
return true;
|
||||
}
|
||||
|
||||
bool Parser::ParseType(ScopedPtr<const ParsedStatement>& out, const LexToken*& currentToken) {
|
||||
bool Parser::ParseType(ScopedPtr<const ParsedStatement>& out, const LexToken*& currentToken,
|
||||
const error_log_func& logError) {
|
||||
const auto* token = currentToken;
|
||||
auto start = token->GetSpan().GetStart();
|
||||
bool isConst = false;
|
||||
|
@ -244,15 +258,15 @@ namespace MalachScript::Parser {
|
|||
PROGRESS_TOKEN(token);
|
||||
}
|
||||
ScopedIdentifier scopedIdentifier;
|
||||
ParseScope(scopedIdentifier.GetScope(), token);
|
||||
if (!ParseDataType(scopedIdentifier.GetIdentifier(), token)) {
|
||||
ParseScope(scopedIdentifier.GetScope(), token, logError);
|
||||
if (!ParseDataType(scopedIdentifier.GetIdentifier(), token, logError)) {
|
||||
return false;
|
||||
}
|
||||
// TODO: Generics.
|
||||
if (token->GetKind() == LexTokenKind::OpenBlockParenthesisSymbol) {
|
||||
PROGRESS_TOKEN(token);
|
||||
if (token->GetKind() != LexTokenKind::CloseBlockParenthesisSymbol) {
|
||||
LogError(Diagnostics::DiagnosticType::UnexpectedToken, token->GetSpan());
|
||||
logError(Diagnostics::DiagnosticType::UnexpectedToken, token->GetSpan());
|
||||
} else {
|
||||
PROGRESS_TOKEN(token);
|
||||
isArray = true;
|
||||
|
@ -270,7 +284,8 @@ namespace MalachScript::Parser {
|
|||
out = new ParsedTypeStatement(TextSpan(start, end), isConst, isArray, isHandle, scopedIdentifier);
|
||||
return true;
|
||||
}
|
||||
bool Parser::ParseScope(std::vector<Identifier>& scope, const LexToken*& currentToken) {
|
||||
bool Parser::ParseScope(std::vector<Identifier>& scope, const LexToken*& currentToken,
|
||||
const error_log_func& logError) {
|
||||
const auto* current = currentToken;
|
||||
if (current->GetKind() == LexTokenKind::ColonColonSymbol) {
|
||||
scope.emplace_back();
|
||||
|
@ -300,7 +315,7 @@ namespace MalachScript::Parser {
|
|||
break;
|
||||
}
|
||||
} else {
|
||||
LogError(Diagnostics::DiagnosticType::UnexpectedToken, currentToken->GetSpan());
|
||||
logError(Diagnostics::DiagnosticType::UnexpectedToken, currentToken->GetSpan());
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -309,7 +324,8 @@ namespace MalachScript::Parser {
|
|||
return true;
|
||||
}
|
||||
|
||||
bool Parser::ParseFuncAttr(FuncAttr& out, const LexToken*& currentToken) {
|
||||
bool Parser::ParseFuncAttr(FuncAttr& out, const LexToken*& currentToken,
|
||||
[[maybe_unused]] const error_log_func& logError) {
|
||||
bool lookingForFuncAttr = true;
|
||||
const auto* current = currentToken;
|
||||
while (lookingForFuncAttr) {
|
||||
|
@ -337,7 +353,8 @@ namespace MalachScript::Parser {
|
|||
return true;
|
||||
}
|
||||
|
||||
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) {
|
||||
if (currentToken->GetKind() != LexTokenKind::OpenParenthesisSymbol) {
|
||||
return false;
|
||||
}
|
||||
|
@ -348,7 +365,7 @@ namespace MalachScript::Parser {
|
|||
if (currentToken->GetKind() == LexTokenKind::VoidKeyword) {
|
||||
PROGRESS_TOKEN(currentToken);
|
||||
if (currentToken->GetKind() != LexTokenKind::CloseParenthesisSymbol) {
|
||||
LogError(Diagnostics::DiagnosticType::UnexpectedToken, currentToken->GetSpan());
|
||||
logError(Diagnostics::DiagnosticType::UnexpectedToken, currentToken->GetSpan());
|
||||
}
|
||||
PROGRESS_TOKEN(currentToken);
|
||||
out = new ParsedParamListStatement(TextSpan(start, currentToken->GetSpan().GetEnd()), parameters);
|
||||
|
@ -365,10 +382,10 @@ namespace MalachScript::Parser {
|
|||
Identifier identifier;
|
||||
const ParsedStatement* defaultExpression = nullptr;
|
||||
|
||||
if (!ParseType(typeStatement, currentToken)) {
|
||||
LogError(Diagnostics::DiagnosticType::UnexpectedToken, currentToken->GetSpan());
|
||||
if (!ParseType(typeStatement, currentToken, logError)) {
|
||||
logError(Diagnostics::DiagnosticType::UnexpectedToken, currentToken->GetSpan());
|
||||
}
|
||||
ParseTypeMod(typeMod, currentToken);
|
||||
ParseTypeMod(typeMod, currentToken, logError);
|
||||
ParseIdentifier(identifier, currentToken);
|
||||
PROGRESS_TOKEN(currentToken);
|
||||
// TODO: Default expression
|
||||
|
@ -383,7 +400,7 @@ namespace MalachScript::Parser {
|
|||
PROGRESS_TOKEN(currentToken);
|
||||
}
|
||||
while (currentToken->GetKind() != LexTokenKind::CloseParenthesisSymbol) {
|
||||
LogError(Diagnostics::DiagnosticType::UnexpectedToken, currentToken->GetSpan());
|
||||
logError(Diagnostics::DiagnosticType::UnexpectedToken, currentToken->GetSpan());
|
||||
if (currentToken->GetKind() == LexTokenKind::EndOfFile) {
|
||||
break;
|
||||
}
|
||||
|
@ -399,7 +416,8 @@ namespace MalachScript::Parser {
|
|||
return true;
|
||||
}
|
||||
|
||||
bool Parser::ParseDataType(Identifier& out, const LexToken*& currentToken) {
|
||||
bool Parser::ParseDataType(Identifier& out, const LexToken*& currentToken,
|
||||
[[maybe_unused]] const error_log_func& logError) {
|
||||
switch (currentToken->GetKind()) {
|
||||
case LexTokenKind::Identifier:
|
||||
out = static_cast<const IdentifierToken*>(currentToken)->GetValue();
|
||||
|
@ -410,7 +428,7 @@ namespace MalachScript::Parser {
|
|||
PROGRESS_TOKEN(currentToken);
|
||||
return true;
|
||||
default:
|
||||
if (ParsePrimType(out, currentToken)) {
|
||||
if (ParsePrimType(out, currentToken, logError)) {
|
||||
PROGRESS_TOKEN(currentToken);
|
||||
return true;
|
||||
}
|
||||
|
@ -418,7 +436,8 @@ 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 auto* current = currentToken;
|
||||
AccessModifier access = AccessModifier::Public;
|
||||
if (current->GetKind() == LexTokenKind::PrivateKeyword) {
|
||||
|
@ -429,7 +448,7 @@ namespace MalachScript::Parser {
|
|||
PROGRESS_TOKEN(current);
|
||||
}
|
||||
ScopedPtr<const ParsedStatement> typeStatement = nullptr;
|
||||
if (!ParseType(typeStatement, current)) {
|
||||
if (!ParseType(typeStatement, current, logError)) {
|
||||
return false;
|
||||
}
|
||||
bool ref = false;
|
||||
|
@ -462,18 +481,17 @@ namespace MalachScript::Parser {
|
|||
getConst = true;
|
||||
PROGRESS_TOKEN(current);
|
||||
}
|
||||
ParseFuncAttr(getAttr, current);
|
||||
ParseFuncAttr(getAttr, current, logError);
|
||||
if (current->GetKind() != LexTokenKind::SemicolonSymbol) {
|
||||
if (!ParseStatBlock(getStatement, current)) {
|
||||
this->LogError(Diagnostics::DiagnosticType::UnexpectedToken, current->GetSpan());
|
||||
if (!ParseStatBlock(getStatement, current, logError)) {
|
||||
logError(Diagnostics::DiagnosticType::UnexpectedToken, current->GetSpan());
|
||||
}
|
||||
} else {
|
||||
PROGRESS_TOKEN(current);
|
||||
}
|
||||
|
||||
if (hasGet) {
|
||||
this->LogError(Diagnostics::DiagnosticType::DoubleProperty,
|
||||
TextSpan(start, current->GetSpan().GetEnd()));
|
||||
logError(Diagnostics::DiagnosticType::DoubleProperty, TextSpan(start, current->GetSpan().GetEnd()));
|
||||
}
|
||||
hasGet = true;
|
||||
} else if (current->GetKind() == LexTokenKind::SetKeyword) {
|
||||
|
@ -482,18 +500,17 @@ namespace MalachScript::Parser {
|
|||
setConst = true;
|
||||
PROGRESS_TOKEN(current);
|
||||
}
|
||||
ParseFuncAttr(setAttr, current);
|
||||
ParseFuncAttr(setAttr, current, logError);
|
||||
if (current->GetKind() != LexTokenKind::SemicolonSymbol) {
|
||||
if (!ParseStatBlock(setStatement, current)) {
|
||||
this->LogError(Diagnostics::DiagnosticType::UnexpectedToken, current->GetSpan());
|
||||
if (!ParseStatBlock(setStatement, current, logError)) {
|
||||
logError(Diagnostics::DiagnosticType::UnexpectedToken, current->GetSpan());
|
||||
}
|
||||
} else {
|
||||
PROGRESS_TOKEN(current);
|
||||
}
|
||||
|
||||
if (hasSet) {
|
||||
this->LogError(Diagnostics::DiagnosticType::DoubleProperty,
|
||||
TextSpan(start, current->GetSpan().GetEnd()));
|
||||
logError(Diagnostics::DiagnosticType::DoubleProperty, TextSpan(start, current->GetSpan().GetEnd()));
|
||||
}
|
||||
hasSet = true;
|
||||
} else {
|
||||
|
@ -501,7 +518,7 @@ namespace MalachScript::Parser {
|
|||
}
|
||||
}
|
||||
if (current->GetKind() != LexTokenKind::CloseCurlyParenthesisSymbol) {
|
||||
LogError(Diagnostics::DiagnosticType::UnexpectedToken, current->GetSpan());
|
||||
logError(Diagnostics::DiagnosticType::UnexpectedToken, current->GetSpan());
|
||||
} else {
|
||||
PROGRESS_TOKEN(current);
|
||||
}
|
||||
|
@ -514,8 +531,8 @@ namespace MalachScript::Parser {
|
|||
return true;
|
||||
}
|
||||
|
||||
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 auto* current = currentToken;
|
||||
if (current->GetKind() != LexTokenKind::IfKeyword) {
|
||||
return false;
|
||||
|
@ -523,21 +540,21 @@ namespace MalachScript::Parser {
|
|||
PROGRESS_TOKEN(current);
|
||||
EXPECT_TOKEN(current, OpenParenthesisSymbol);
|
||||
ScopedPtr<const ParsedStatement> condition = nullptr;
|
||||
if (!ParseAssign(condition, current)) {
|
||||
LogError(Diagnostics::DiagnosticType::UnexpectedToken, current->GetSpan());
|
||||
if (!ParseAssign(condition, current, logError)) {
|
||||
logError(Diagnostics::DiagnosticType::UnexpectedToken, current->GetSpan());
|
||||
return false;
|
||||
}
|
||||
EXPECT_TOKEN(current, CloseParenthesisSymbol);
|
||||
ScopedPtr<const ParsedStatement> body = nullptr;
|
||||
if (!ParseStatement(body, current)) {
|
||||
LogError(Diagnostics::DiagnosticType::UnexpectedToken, current->GetSpan());
|
||||
if (!ParseStatement(body, current, logError)) {
|
||||
logError(Diagnostics::DiagnosticType::UnexpectedToken, current->GetSpan());
|
||||
return false;
|
||||
}
|
||||
ScopedPtr<const ParsedStatement> elseStatement = nullptr;
|
||||
if (current->GetKind() == LexTokenKind::ElseKeyword) {
|
||||
PROGRESS_TOKEN(current);
|
||||
if (!ParseStatement(elseStatement, current)) {
|
||||
LogError(Diagnostics::DiagnosticType::UnexpectedToken, current->GetSpan());
|
||||
if (!ParseStatement(elseStatement, current, logError)) {
|
||||
logError(Diagnostics::DiagnosticType::UnexpectedToken, current->GetSpan());
|
||||
}
|
||||
}
|
||||
out = new ParsedIfStatement(TextSpan(currentToken->GetSpan().GetStart(), current->GetSpan().GetEnd()),
|
||||
|
@ -546,22 +563,24 @@ namespace MalachScript::Parser {
|
|||
return true;
|
||||
}
|
||||
|
||||
bool Parser::ParseStatement(ScopedPtr<const ParsedStatement>& out, const LexToken*& currentToken) {
|
||||
// TODO: All the other statements. (dowhile | switch | try );
|
||||
bool Parser::ParseStatement(ScopedPtr<const ParsedStatement>& out, const LexToken*& currentToken,
|
||||
const error_log_func& logError) {
|
||||
// TODO: All the other statements. (switch | try );
|
||||
switch (currentToken->GetKind()) {
|
||||
case LexTokenKind::IfKeyword: return ParseIfStatement(out, currentToken);
|
||||
case LexTokenKind::ForKeyword: return ParseForStatement(out, currentToken);
|
||||
case LexTokenKind::WhileKeyword: return ParseWhileStatement(out, currentToken);
|
||||
case LexTokenKind::ReturnKeyword: return ParseReturn(out, currentToken);
|
||||
case LexTokenKind::BreakKeyword: return ParseBreak(out, currentToken);
|
||||
case LexTokenKind::ContinueKeyword: return ParseContinue(out, currentToken);
|
||||
case LexTokenKind::DoKeyword: return ParseDoWhileStatement(out, currentToken);
|
||||
default: return ParseStatBlock(out, currentToken) || ParseExprStat(out, currentToken);
|
||||
case LexTokenKind::IfKeyword: return ParseIfStatement(out, currentToken, logError);
|
||||
case LexTokenKind::ForKeyword: return ParseForStatement(out, currentToken, logError);
|
||||
case LexTokenKind::WhileKeyword: return ParseWhileStatement(out, currentToken, logError);
|
||||
case LexTokenKind::ReturnKeyword: return ParseReturn(out, currentToken, logError);
|
||||
case LexTokenKind::BreakKeyword: return ParseBreak(out, currentToken, logError);
|
||||
case LexTokenKind::ContinueKeyword: return ParseContinue(out, currentToken, logError);
|
||||
case LexTokenKind::DoKeyword: return ParseDoWhileStatement(out, currentToken, logError);
|
||||
default: return ParseStatBlock(out, currentToken, logError) || ParseExprStat(out, currentToken, logError);
|
||||
}
|
||||
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 auto* current = currentToken;
|
||||
AccessModifier access = AccessModifier::Public;
|
||||
if (current->GetKind() == LexTokenKind::PrivateKeyword) {
|
||||
|
@ -572,7 +591,7 @@ namespace MalachScript::Parser {
|
|||
PROGRESS_TOKEN(current);
|
||||
}
|
||||
ScopedPtr<const ParsedStatement> typeStatement = nullptr;
|
||||
if (!ParseType(typeStatement, current)) {
|
||||
if (!ParseType(typeStatement, current, logError)) {
|
||||
return false;
|
||||
}
|
||||
Identifier identifier;
|
||||
|
@ -589,7 +608,8 @@ namespace MalachScript::Parser {
|
|||
return true;
|
||||
}
|
||||
|
||||
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 auto* current = currentToken;
|
||||
if (current->GetKind() != LexTokenKind::OpenCurlyParenthesisSymbol) {
|
||||
return false;
|
||||
|
@ -601,7 +621,7 @@ namespace MalachScript::Parser {
|
|||
break;
|
||||
}
|
||||
ScopedPtr<const ParsedStatement> stat = nullptr;
|
||||
if (ParseVar(stat, current) || ParseStatement(stat, current)) {
|
||||
if (ParseVar(stat, current, logError) || ParseStatement(stat, current, logError)) {
|
||||
statements.push_back(stat.TakeOwnership());
|
||||
} else {
|
||||
break;
|
||||
|
@ -610,7 +630,7 @@ namespace MalachScript::Parser {
|
|||
if (current->GetKind() == LexTokenKind::CloseCurlyParenthesisSymbol) {
|
||||
PROGRESS_TOKEN(current);
|
||||
} else {
|
||||
LogError(Diagnostics::DiagnosticType::UnexpectedToken, current->GetSpan());
|
||||
logError(Diagnostics::DiagnosticType::UnexpectedToken, current->GetSpan());
|
||||
}
|
||||
|
||||
out = new ParsedStatBlockStatement(TextSpan(currentToken->GetSpan().GetStart(), current->GetSpan().GetEnd()),
|
||||
|
@ -620,10 +640,13 @@ namespace MalachScript::Parser {
|
|||
}
|
||||
|
||||
bool Parser::ParseFuncDef([[maybe_unused]] ScopedPtr<const ParsedStatement>& out,
|
||||
[[maybe_unused]] const LexToken*& currentToken) {
|
||||
[[maybe_unused]] const LexToken*& currentToken,
|
||||
[[maybe_unused]] const error_log_func& logError) {
|
||||
// TODO
|
||||
return false;
|
||||
}
|
||||
bool Parser::ParsePrimType(Identifier& out, const LexToken*& token) {
|
||||
bool Parser::ParsePrimType(Identifier& out, const LexToken*& token,
|
||||
[[maybe_unused]] const error_log_func& logError) {
|
||||
switch (token->GetKind()) {
|
||||
case LexTokenKind::VoidKeyword: out = PrimitiveTypes::VoidName(); return true;
|
||||
case LexTokenKind::IntKeyword: out = PrimitiveTypes::IntName(); return true;
|
||||
|
@ -642,7 +665,8 @@ namespace MalachScript::Parser {
|
|||
default: return false;
|
||||
}
|
||||
}
|
||||
bool Parser::ParseTypeMod(TypeMod& typeMod, const LexToken*& currentToken) {
|
||||
bool Parser::ParseTypeMod(TypeMod& typeMod, const LexToken*& currentToken,
|
||||
[[maybe_unused]] const error_log_func& logError) {
|
||||
if (currentToken->GetKind() != LexTokenKind::AmpersandSymbol) {
|
||||
return false;
|
||||
}
|
||||
|
@ -663,10 +687,11 @@ namespace MalachScript::Parser {
|
|||
default: typeMod = TypeMod::RefInOut; return true;
|
||||
}
|
||||
}
|
||||
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 auto* current = currentToken;
|
||||
ScopedPtr<const ParsedStatement> leftHand = nullptr;
|
||||
if (!ParseTernary(leftHand, current)) {
|
||||
if (!ParseTernary(leftHand, current, logError)) {
|
||||
return false;
|
||||
}
|
||||
AssignmentOperator op;
|
||||
|
@ -677,8 +702,8 @@ namespace MalachScript::Parser {
|
|||
}
|
||||
PROGRESS_TOKEN(current);
|
||||
ScopedPtr<const ParsedStatement> rightHand = nullptr;
|
||||
if (!ParseAssign(rightHand, current)) {
|
||||
LogError(Diagnostics::DiagnosticType::UnexpectedToken, current->GetSpan());
|
||||
if (!ParseAssign(rightHand, current, logError)) {
|
||||
logError(Diagnostics::DiagnosticType::UnexpectedToken, current->GetSpan());
|
||||
out = leftHand.TakeOwnership();
|
||||
currentToken = current;
|
||||
return true;
|
||||
|
@ -690,9 +715,10 @@ namespace MalachScript::Parser {
|
|||
return true;
|
||||
}
|
||||
|
||||
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) {
|
||||
// TODO: implement ternary.
|
||||
return ParseExpr(out, currentToken);
|
||||
return ParseExpr(out, currentToken, logError);
|
||||
}
|
||||
|
||||
#define EXPR_PARSER(operator, name, func) \
|
||||
|
@ -700,8 +726,8 @@ namespace MalachScript::Parser {
|
|||
if (func(name, current)) { \
|
||||
PROGRESS_TOKEN(current); \
|
||||
ScopedPtr<const ParsedStatement> rightHand = nullptr; \
|
||||
if (!ParseExprTerm(rightHand, current)) { \
|
||||
LogError(Diagnostics::DiagnosticType::UnexpectedToken, current->GetSpan()); \
|
||||
if (!ParseExprTerm(rightHand, current, logError)) { \
|
||||
logError(Diagnostics::DiagnosticType::UnexpectedToken, current->GetSpan()); \
|
||||
out = leftHand.TakeOwnership(); \
|
||||
currentToken = current; \
|
||||
return true; \
|
||||
|
@ -713,10 +739,11 @@ namespace MalachScript::Parser {
|
|||
return true; \
|
||||
}
|
||||
|
||||
bool Parser::ParseExpr(ScopedPtr<const ParsedStatement>& out, const LexToken*& currentToken) {
|
||||
bool Parser::ParseExpr(ScopedPtr<const ParsedStatement>& out, const LexToken*& currentToken,
|
||||
const error_log_func& logError) {
|
||||
const auto* current = currentToken;
|
||||
ScopedPtr<const ParsedStatement> leftHand = nullptr;
|
||||
if (!ParseExprTerm(leftHand, current)) {
|
||||
if (!ParseExprTerm(leftHand, current, logError)) {
|
||||
return false;
|
||||
}
|
||||
EXPR_PARSER(MathOperator, mathOp, ParseMathOp);
|
||||
|
@ -729,17 +756,18 @@ namespace MalachScript::Parser {
|
|||
return true;
|
||||
}
|
||||
|
||||
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 auto* current = currentToken;
|
||||
// TODO ([type '='] initlist)
|
||||
|
||||
PreOperator preOperator;
|
||||
bool hasPreOp = ParsePreOp(preOperator, currentToken);
|
||||
bool hasPreOp = ParsePreOp(preOperator, currentToken, logError);
|
||||
if (hasPreOp) {
|
||||
PROGRESS_TOKEN(current);
|
||||
}
|
||||
ScopedPtr<const ParsedStatement> operand = nullptr;
|
||||
if (!ParseExprValue(operand, current)) {
|
||||
if (!ParseExprValue(operand, current, logError)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -761,7 +789,8 @@ namespace MalachScript::Parser {
|
|||
currentToken = current;
|
||||
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 auto* current = currentToken;
|
||||
if (current->GetKind() == LexTokenKind::VoidKeyword) {
|
||||
PROGRESS_TOKEN(current);
|
||||
|
@ -772,19 +801,19 @@ namespace MalachScript::Parser {
|
|||
}
|
||||
// TODO: constructcall
|
||||
// TODO: funccall
|
||||
if (ParseVarAccess(out, current)) {
|
||||
if (ParseVarAccess(out, current, logError)) {
|
||||
currentToken = current;
|
||||
return true;
|
||||
}
|
||||
// TODO: cast
|
||||
if (ParseLiteral(out, current)) {
|
||||
if (ParseLiteral(out, current, logError)) {
|
||||
currentToken = current;
|
||||
return true;
|
||||
}
|
||||
if (current->GetKind() == LexTokenKind::OpenParenthesisSymbol) {
|
||||
PROGRESS_TOKEN(current);
|
||||
if (!ParseAssign(out, current)) {
|
||||
LogError(Diagnostics::DiagnosticType::UnexpectedToken, current->GetSpan());
|
||||
if (!ParseAssign(out, current, logError)) {
|
||||
logError(Diagnostics::DiagnosticType::UnexpectedToken, current->GetSpan());
|
||||
}
|
||||
EXPECT_TOKEN(current, CloseParenthesisSymbol);
|
||||
return true;
|
||||
|
@ -793,7 +822,8 @@ namespace MalachScript::Parser {
|
|||
|
||||
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) {
|
||||
switch (currentToken->GetKind()) {
|
||||
case LexTokenKind::IntegerLiteral:
|
||||
out = new ParsedLiteralStatement<ParseInt>(
|
||||
|
@ -825,29 +855,32 @@ namespace MalachScript::Parser {
|
|||
default: return false;
|
||||
}
|
||||
}
|
||||
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) {
|
||||
auto start = currentToken->GetSpan().GetStart();
|
||||
if (currentToken->GetKind() != LexTokenKind::ReturnKeyword) {
|
||||
return false;
|
||||
}
|
||||
PROGRESS_TOKEN(currentToken);
|
||||
ScopedPtr<const ParsedStatement> returnBody;
|
||||
ParseAssign(returnBody, currentToken);
|
||||
ParseAssign(returnBody, currentToken, logError);
|
||||
EXPECT_TOKEN(currentToken, SemicolonSymbol);
|
||||
out = new ParsedReturnStatement(TextSpan(start, currentToken->GetSpan().GetEnd()), returnBody.TakeOwnership());
|
||||
return true;
|
||||
}
|
||||
bool Parser::ParseExprStat(ScopedPtr<const ParsedStatement>& out, const LexToken*& currentToken) {
|
||||
if (!ParseAssign(out, currentToken)) {
|
||||
bool Parser::ParseExprStat(ScopedPtr<const ParsedStatement>& out, const LexToken*& currentToken,
|
||||
const error_log_func& logError) {
|
||||
if (!ParseAssign(out, currentToken, logError)) {
|
||||
return false;
|
||||
}
|
||||
EXPECT_TOKEN(currentToken, SemicolonSymbol);
|
||||
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) {
|
||||
std::vector<Identifier> scope;
|
||||
auto start = currentToken->GetSpan().GetStart();
|
||||
if (ParseScope(scope, currentToken)) {
|
||||
if (ParseScope(scope, currentToken, logError)) {
|
||||
out = new ParsedVarAccessStatement(TextSpan(start, currentToken->GetSpan().GetEnd()), scope);
|
||||
return true;
|
||||
}
|
||||
|
@ -861,7 +894,8 @@ namespace MalachScript::Parser {
|
|||
}
|
||||
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) {
|
||||
if (currentToken->GetKind() != LexTokenKind::ContinueKeyword) {
|
||||
return false;
|
||||
}
|
||||
|
@ -871,7 +905,8 @@ namespace MalachScript::Parser {
|
|||
out = new ParsedContinueStatement(TextSpan(start, currentToken->GetSpan().GetEnd()));
|
||||
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) {
|
||||
if (currentToken->GetKind() != LexTokenKind::BreakKeyword) {
|
||||
return false;
|
||||
}
|
||||
|
@ -881,7 +916,8 @@ namespace MalachScript::Parser {
|
|||
out = new ParsedBreakStatement(TextSpan(start, currentToken->GetSpan().GetEnd()));
|
||||
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) {
|
||||
if (currentToken->GetKind() != LexTokenKind::ForKeyword) {
|
||||
return false;
|
||||
}
|
||||
|
@ -889,19 +925,19 @@ namespace MalachScript::Parser {
|
|||
PROGRESS_TOKEN(current);
|
||||
EXPECT_TOKEN(current, OpenParenthesisSymbol);
|
||||
ScopedPtr<const ParsedStatement> init;
|
||||
if (!ParseVar(init, current) && !ParseExprStat(init, current)) {
|
||||
LogError(Diagnostics::DiagnosticType::UnexpectedToken, current->GetSpan());
|
||||
if (!ParseVar(init, current, logError) && !ParseExprStat(init, current, logError)) {
|
||||
logError(Diagnostics::DiagnosticType::UnexpectedToken, current->GetSpan());
|
||||
return false;
|
||||
}
|
||||
ScopedPtr<const ParsedStatement> condition;
|
||||
if (!ParseExprStat(condition, current)) {
|
||||
LogError(Diagnostics::DiagnosticType::UnexpectedToken, current->GetSpan());
|
||||
if (!ParseExprStat(condition, current, logError)) {
|
||||
logError(Diagnostics::DiagnosticType::UnexpectedToken, current->GetSpan());
|
||||
return false;
|
||||
}
|
||||
std::vector<const ParsedStatement*> increment;
|
||||
while (true) {
|
||||
ScopedPtr<const ParsedStatement> element;
|
||||
if (ParseAssign(element, current)) {
|
||||
if (ParseAssign(element, current, logError)) {
|
||||
increment.push_back(element.TakeOwnership());
|
||||
}
|
||||
if (current->GetKind() != LexTokenKind::CommaSymbol) {
|
||||
|
@ -910,8 +946,8 @@ namespace MalachScript::Parser {
|
|||
}
|
||||
EXPECT_TOKEN(current, CloseParenthesisSymbol);
|
||||
ScopedPtr<const ParsedStatement> statementBlock;
|
||||
if (!ParseStatement(statementBlock, current)) {
|
||||
LogError(Diagnostics::DiagnosticType::UnexpectedToken, current->GetSpan());
|
||||
if (!ParseStatement(statementBlock, current, logError)) {
|
||||
logError(Diagnostics::DiagnosticType::UnexpectedToken, current->GetSpan());
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -922,7 +958,8 @@ namespace MalachScript::Parser {
|
|||
return true;
|
||||
}
|
||||
|
||||
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 auto* current = currentToken;
|
||||
if (current->GetKind() != LexTokenKind::WhileKeyword) {
|
||||
return false;
|
||||
|
@ -930,14 +967,14 @@ namespace MalachScript::Parser {
|
|||
PROGRESS_TOKEN(current);
|
||||
EXPECT_TOKEN(current, OpenParenthesisSymbol);
|
||||
ScopedPtr<const ParsedStatement> condition = nullptr;
|
||||
if (!ParseAssign(condition, current)) {
|
||||
LogError(Diagnostics::DiagnosticType::UnexpectedToken, current->GetSpan());
|
||||
if (!ParseAssign(condition, current, logError)) {
|
||||
logError(Diagnostics::DiagnosticType::UnexpectedToken, current->GetSpan());
|
||||
return false;
|
||||
}
|
||||
EXPECT_TOKEN(current, CloseParenthesisSymbol);
|
||||
ScopedPtr<const ParsedStatement> body = nullptr;
|
||||
if (!ParseStatement(body, current)) {
|
||||
LogError(Diagnostics::DiagnosticType::UnexpectedToken, current->GetSpan());
|
||||
if (!ParseStatement(body, current, logError)) {
|
||||
logError(Diagnostics::DiagnosticType::UnexpectedToken, current->GetSpan());
|
||||
return false;
|
||||
}
|
||||
out = new ParsedWhileStatement(TextSpan(currentToken->GetSpan().GetStart(), current->GetSpan().GetEnd()),
|
||||
|
@ -945,21 +982,22 @@ namespace MalachScript::Parser {
|
|||
currentToken = current;
|
||||
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 auto* current = currentToken;
|
||||
if (current->GetKind() != LexTokenKind::DoKeyword) {
|
||||
return false;
|
||||
}
|
||||
ScopedPtr<const ParsedStatement> body = nullptr;
|
||||
if (!ParseStatement(body, current)) {
|
||||
LogError(Diagnostics::DiagnosticType::UnexpectedToken, current->GetSpan());
|
||||
if (!ParseStatement(body, current, logError)) {
|
||||
logError(Diagnostics::DiagnosticType::UnexpectedToken, current->GetSpan());
|
||||
return false;
|
||||
}
|
||||
EXPECT_TOKEN(current, WhileKeyword);
|
||||
EXPECT_TOKEN(current, OpenParenthesisSymbol);
|
||||
ScopedPtr<const ParsedStatement> condition = nullptr;
|
||||
if (!ParseAssign(condition, current)) {
|
||||
LogError(Diagnostics::DiagnosticType::UnexpectedToken, current->GetSpan());
|
||||
if (!ParseAssign(condition, current, logError)) {
|
||||
logError(Diagnostics::DiagnosticType::UnexpectedToken, current->GetSpan());
|
||||
return false;
|
||||
}
|
||||
EXPECT_TOKEN(current, CloseParenthesisSymbol);
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
#ifndef MALACHSCRIPT_PARSER_HPP
|
||||
#define MALACHSCRIPT_PARSER_HPP
|
||||
|
||||
#include <functional>
|
||||
#include "../CoreData/Operators.hpp"
|
||||
#include "../Diagnostics/Diagnostics.hpp"
|
||||
#include "../Utils/ScopedPtr.hpp"
|
||||
|
@ -10,18 +11,11 @@
|
|||
namespace MalachScript::Parser {
|
||||
class Parser {
|
||||
public:
|
||||
Parser(std::u8string_view scriptName, const LexToken* firstToken, Diagnostics::Diagnostics* diagnostics)
|
||||
: _scriptName(scriptName), _diagnostics(diagnostics), _firstToken(firstToken) {}
|
||||
const ParsedScriptStatement* Parse();
|
||||
static const ParsedScriptStatement* Parse(const LexToken* firstToken, std::u8string_view scriptName,
|
||||
Diagnostics::Diagnostics* diagnostics);
|
||||
|
||||
private:
|
||||
std::u8string_view _scriptName;
|
||||
Diagnostics::Diagnostics* _diagnostics;
|
||||
const LexToken* _firstToken;
|
||||
|
||||
inline void LogError(Diagnostics::DiagnosticType type, const TextSpan& span) {
|
||||
_diagnostics->LogError(type, _scriptName, span);
|
||||
}
|
||||
typedef const std::function<void(Diagnostics::DiagnosticType, const TextSpan&)> error_log_func;
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Underlying functions are laid out in the order they are defined in the grammar.ebnf //
|
||||
|
@ -112,13 +106,15 @@ namespace MalachScript::Parser {
|
|||
}
|
||||
}
|
||||
|
||||
bool ParsePrimType(Identifier& out, const LexToken*& currentToken);
|
||||
bool ParseDataType(Identifier& out, const LexToken*& currentToken);
|
||||
bool ParseScope(std::vector<Identifier>& out, const LexToken*& currentToken);
|
||||
bool ParseType(ScopedPtr<const ParsedStatement>& out, const LexToken*& currentToken);
|
||||
bool ParseAssign(ScopedPtr<const ParsedStatement>& out, const LexToken*& currentToken);
|
||||
static bool ParsePrimType(Identifier& out, const LexToken*& currentToken, const error_log_func&);
|
||||
static bool ParseDataType(Identifier& out, const LexToken*& currentToken, const error_log_func&);
|
||||
static bool ParseScope(std::vector<Identifier>& out, const LexToken*& currentToken, const error_log_func&);
|
||||
static bool ParseType(ScopedPtr<const ParsedStatement>& out, const LexToken*& currentToken,
|
||||
const error_log_func&);
|
||||
static bool ParseAssign(ScopedPtr<const ParsedStatement>& out, const LexToken*& currentToken,
|
||||
const error_log_func&);
|
||||
// InitList
|
||||
inline static bool ParsePreOp(PreOperator& op, const LexToken*& token) {
|
||||
inline static bool ParsePreOp(PreOperator& op, const LexToken*& token, const error_log_func&) {
|
||||
switch (token->GetKind()) {
|
||||
case LexTokenKind::MinusSymbol: op = PreOperator::Negation; return true;
|
||||
case LexTokenKind::PlusSymbol: op = PreOperator::Identity; return true;
|
||||
|
@ -133,52 +129,76 @@ namespace MalachScript::Parser {
|
|||
// ArgList
|
||||
// FuncCall
|
||||
// ConstructCall
|
||||
bool ParseVarAccess(ScopedPtr<const ParsedStatement>& out, const LexToken*& currentToken);
|
||||
static bool ParseVarAccess(ScopedPtr<const ParsedStatement>& out, const LexToken*& currentToken,
|
||||
const error_log_func&);
|
||||
// Cast
|
||||
bool ParseLiteral(ScopedPtr<const ParsedStatement>& out, const LexToken*& currentToken);
|
||||
bool ParseTypeMod(TypeMod& typeMod, const LexToken*& currentToken);
|
||||
static bool ParseLiteral(ScopedPtr<const ParsedStatement>& out, const LexToken*& currentToken,
|
||||
const error_log_func&);
|
||||
static bool ParseTypeMod(TypeMod& typeMod, const LexToken*& currentToken, const error_log_func&);
|
||||
// Lambda
|
||||
|
||||
bool ParseExprValue(ScopedPtr<const ParsedStatement>& out, const LexToken*& currentToken);
|
||||
static bool ParseExprValue(ScopedPtr<const ParsedStatement>& out, const LexToken*& currentToken,
|
||||
const error_log_func&);
|
||||
// ExprPostOp
|
||||
bool ParseExprTerm(ScopedPtr<const ParsedStatement>& out, const LexToken*& currentToken);
|
||||
bool ParseExpr(ScopedPtr<const ParsedStatement>& out, const LexToken*& currentToken);
|
||||
bool ParseTernary(ScopedPtr<const ParsedStatement>& out, const LexToken*& currentToken);
|
||||
static bool ParseExprTerm(ScopedPtr<const ParsedStatement>& out, const LexToken*& currentToken,
|
||||
const error_log_func&);
|
||||
static bool ParseExpr(ScopedPtr<const ParsedStatement>& out, const LexToken*& currentToken,
|
||||
const error_log_func&);
|
||||
static bool ParseTernary(ScopedPtr<const ParsedStatement>& out, const LexToken*& currentToken,
|
||||
const error_log_func&);
|
||||
|
||||
bool ParseReturn(ScopedPtr<const ParsedStatement>& out, const LexToken*& currentToken);
|
||||
bool ParseExprStat(ScopedPtr<const ParsedStatement>& out, const LexToken*& currentToken);
|
||||
bool ParseContinue(ScopedPtr<const ParsedStatement>& out, const LexToken*& currentToken);
|
||||
bool ParseBreak(ScopedPtr<const ParsedStatement>& out, const LexToken*& currentToken);
|
||||
static bool ParseReturn(ScopedPtr<const ParsedStatement>& out, const LexToken*& currentToken,
|
||||
const error_log_func&);
|
||||
static bool ParseExprStat(ScopedPtr<const ParsedStatement>& out, const LexToken*& currentToken,
|
||||
const error_log_func&);
|
||||
static bool ParseContinue(ScopedPtr<const ParsedStatement>& out, const LexToken*& currentToken,
|
||||
const error_log_func&);
|
||||
static bool ParseBreak(ScopedPtr<const ParsedStatement>& out, const LexToken*& currentToken,
|
||||
const error_log_func&);
|
||||
|
||||
bool ParseIfStatement(ScopedPtr<const ParsedStatement>& out, const LexToken*& currentToken);
|
||||
bool ParseForStatement(ScopedPtr<const ParsedStatement>& out, const LexToken*& currentToken);
|
||||
bool ParseWhileStatement(ScopedPtr<const ParsedStatement>& out, const LexToken*& currentToken);
|
||||
bool ParseDoWhileStatement(ScopedPtr<const ParsedStatement>& out, const LexToken*& currentToken);
|
||||
static bool ParseIfStatement(ScopedPtr<const ParsedStatement>& out, const LexToken*& currentToken,
|
||||
const error_log_func&);
|
||||
static bool ParseForStatement(ScopedPtr<const ParsedStatement>& out, const LexToken*& currentToken,
|
||||
const error_log_func&);
|
||||
static bool ParseWhileStatement(ScopedPtr<const ParsedStatement>& out, const LexToken*& currentToken,
|
||||
const error_log_func&);
|
||||
static bool ParseDoWhileStatement(ScopedPtr<const ParsedStatement>& out, const LexToken*& currentToken,
|
||||
const error_log_func&);
|
||||
// Try
|
||||
// Case
|
||||
// Switch
|
||||
|
||||
bool ParseStatement(ScopedPtr<const ParsedStatement>& out, const LexToken*& currentToken);
|
||||
bool ParseVar(ScopedPtr<const ParsedStatement>& out, const LexToken*& currentToken);
|
||||
bool ParseStatBlock(ScopedPtr<const ParsedStatement>& out, const LexToken*& currentToken);
|
||||
static bool ParseStatement(ScopedPtr<const ParsedStatement>& out, const LexToken*& currentToken,
|
||||
const error_log_func&);
|
||||
static bool ParseVar(ScopedPtr<const ParsedStatement>& out, const LexToken*& currentToken,
|
||||
const error_log_func&);
|
||||
static bool ParseStatBlock(ScopedPtr<const ParsedStatement>& out, const LexToken*& currentToken,
|
||||
const error_log_func&);
|
||||
|
||||
bool ParseFuncAttr(FuncAttr& out, const LexToken*& currentToken);
|
||||
bool ParseParamList(ScopedPtr<const ParsedStatement>& out, const LexToken*& currentToken);
|
||||
static bool ParseFuncAttr(FuncAttr& out, const LexToken*& currentToken, const error_log_func&);
|
||||
static bool ParseParamList(ScopedPtr<const ParsedStatement>& out, const LexToken*& currentToken,
|
||||
const error_log_func&);
|
||||
|
||||
bool ParseVirtProp(ScopedPtr<const ParsedStatement>& out, const LexToken*& currentToken);
|
||||
bool ParseFunc(ScopedPtr<const ParsedStatement>& out, const LexToken*& currentToken);
|
||||
bool ParseFuncDef(ScopedPtr<const ParsedStatement>& out, const LexToken*& currentToken);
|
||||
bool ParseClass(ScopedPtr<const ParsedStatement>& out, const LexToken*& currentToken);
|
||||
static bool ParseVirtProp(ScopedPtr<const ParsedStatement>& out, const LexToken*& currentToken,
|
||||
const error_log_func&);
|
||||
static bool ParseFunc(ScopedPtr<const ParsedStatement>& out, const LexToken*& currentToken,
|
||||
const error_log_func&);
|
||||
static bool ParseFuncDef(ScopedPtr<const ParsedStatement>& out, const LexToken*& currentToken,
|
||||
const error_log_func&);
|
||||
static bool ParseClass(ScopedPtr<const ParsedStatement>& out, const LexToken*& currentToken,
|
||||
const error_log_func&);
|
||||
|
||||
// Mixin
|
||||
// Enum
|
||||
// Import
|
||||
bool ParseTypeDef(ScopedPtr<const ParsedStatement>& out, const LexToken*& currentToken);
|
||||
static bool ParseTypeDef(ScopedPtr<const ParsedStatement>& out, const LexToken*& currentToken,
|
||||
const error_log_func&);
|
||||
|
||||
// InterfaceMethod
|
||||
// Interface
|
||||
bool ParseNamespace(ScopedPtr<const ParsedStatement>& out, const LexToken*& currentToken);
|
||||
const ParsedScriptStatement* ParseScript();
|
||||
static bool ParseNamespace(ScopedPtr<const ParsedStatement>& out, const LexToken*& currentToken,
|
||||
const error_log_func&);
|
||||
static const ParsedScriptStatement* ParseScript(const LexToken* firstToken, const error_log_func&);
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -13,8 +13,7 @@ using namespace MalachScript;
|
|||
vec[i]->SetNext(vec[i + 1]); \
|
||||
} \
|
||||
Diagnostics::Diagnostics diags; \
|
||||
auto parser = Parser::Parser(u8"scriptname", vec.front(), &diags); \
|
||||
auto* script = parser.Parse(); \
|
||||
auto* script = Parser::Parser::Parse(vec.front(), u8"scriptname", &diags); \
|
||||
REQUIRE(diags.GetMessages().empty()); \
|
||||
asserts; \
|
||||
delete vec[0]; \
|
||||
|
|
|
@ -13,8 +13,7 @@ using namespace MalachScript;
|
|||
vec[i]->SetNext(vec[i + 1]); \
|
||||
} \
|
||||
Diagnostics::Diagnostics diags; \
|
||||
auto parser = Parser::Parser(u8"scriptname", vec.front(), &diags); \
|
||||
auto* script = parser.Parse(); \
|
||||
auto* script = Parser::Parser::Parse(vec.front(), u8"scriptname", &diags); \
|
||||
REQUIRE(diags.GetMessages().empty()); \
|
||||
asserts; \
|
||||
delete vec[0]; \
|
||||
|
|
|
@ -9,8 +9,7 @@ using namespace MalachScript;
|
|||
Diagnostics::Diagnostics diags; \
|
||||
auto lexer = Parser::Lexer(u8##name, u8##scriptText, &diags); \
|
||||
auto token = lexer.Lex(); \
|
||||
auto parser = Parser::Parser(u8##name, token, &diags); \
|
||||
auto script = parser.Parse(); \
|
||||
auto script = Parser::Parser::Parse(token, u8##name, &diags); \
|
||||
asserts; \
|
||||
delete script; \
|
||||
}
|
||||
|
|
|
@ -13,8 +13,7 @@ using namespace MalachScript;
|
|||
vec[i]->SetNext(vec[i + 1]); \
|
||||
} \
|
||||
Diagnostics::Diagnostics diags; \
|
||||
auto parser = Parser::Parser(u8"scriptname", vec.front(), &diags); \
|
||||
auto* script = parser.Parse(); \
|
||||
auto* script = Parser::Parser::Parse(vec.front(), u8"scriptname", &diags); \
|
||||
REQUIRE(diags.GetMessages().empty()); \
|
||||
asserts; \
|
||||
delete vec[0]; \
|
||||
|
|
Loading…
Reference in New Issue