Implements parsing switch case statements.
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
85e3a6db43
commit
de15173b0b
@ -575,6 +575,7 @@ namespace MalachScript::Parser {
|
|||||||
case LexTokenKind::ContinueKeyword: return ParseContinue(out, currentToken, log);
|
case LexTokenKind::ContinueKeyword: return ParseContinue(out, currentToken, log);
|
||||||
case LexTokenKind::DoKeyword: return ParseDoWhileStatement(out, currentToken, log);
|
case LexTokenKind::DoKeyword: return ParseDoWhileStatement(out, currentToken, log);
|
||||||
case LexTokenKind::TryKeyword: return ParseTryStatement(out, currentToken, log);
|
case LexTokenKind::TryKeyword: return ParseTryStatement(out, currentToken, log);
|
||||||
|
case LexTokenKind::SwitchKeyword: return ParseSwitchStatement(out, currentToken, log);
|
||||||
default: return ParseStatBlock(out, currentToken, log) || ParseExprStat(out, currentToken, log);
|
default: return ParseStatBlock(out, currentToken, log) || ParseExprStat(out, currentToken, log);
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
@ -1030,4 +1031,90 @@ namespace MalachScript::Parser {
|
|||||||
currentToken = current;
|
currentToken = current;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
bool Parser::ParseSwitchStatement(ScopedPtr<const ParsedStatement>& out, const LexToken*& currentToken,
|
||||||
|
const Parser::log_func& log) {
|
||||||
|
const auto* current = currentToken;
|
||||||
|
if (current->GetKind() != LexTokenKind::SwitchKeyword) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
PROGRESS_TOKEN(current);
|
||||||
|
EXPECT_TOKEN(currentToken, OpenParenthesisSymbol);
|
||||||
|
ScopedPtr<const ParsedStatement> expression = nullptr;
|
||||||
|
if (!ParseExpr(expression, current, log)) {
|
||||||
|
logError(DiagnosticType::UnexpectedToken, current->GetSpan());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
EXPECT_TOKEN(currentToken, CloseParenthesisSymbol);
|
||||||
|
EXPECT_TOKEN(currentToken, OpenCurlyParenthesisSymbol);
|
||||||
|
std::vector<const ParsedStatement*> caseStatements;
|
||||||
|
while (true) {
|
||||||
|
if (current->GetKind() == LexTokenKind::CloseCurlyParenthesisSymbol) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (current->GetKind() == LexTokenKind::CaseKeyword ||
|
||||||
|
currentToken->GetKind() == LexTokenKind::DefaultKeyword) {
|
||||||
|
ScopedPtr<const ParsedStatement> stat = nullptr;
|
||||||
|
if (!ParseCaseStatement(stat, current, log)) {
|
||||||
|
for (const auto* s : caseStatements) {
|
||||||
|
delete s;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
caseStatements.push_back(stat.TakeOwnership());
|
||||||
|
} else {
|
||||||
|
logError(DiagnosticType::UnexpectedToken, current->GetSpan());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Consume }
|
||||||
|
PROGRESS_TOKEN(current);
|
||||||
|
|
||||||
|
out = new ParsedSwitchStatement(TextSpan(currentToken->GetSpan().GetStart(), current->GetSpan().GetEnd()),
|
||||||
|
expression.TakeOwnership(), caseStatements);
|
||||||
|
currentToken = current;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Parser::ParseCaseStatement(ScopedPtr<const ParsedStatement>& out, const LexToken*& currentToken,
|
||||||
|
const Parser::log_func& log) {
|
||||||
|
const auto* current = currentToken;
|
||||||
|
|
||||||
|
if (current->GetKind() != LexTokenKind::CaseKeyword && current->GetKind() != LexTokenKind::DefaultKeyword) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
bool isDefault = current->GetKind() == LexTokenKind::DefaultKeyword;
|
||||||
|
PROGRESS_TOKEN(current);
|
||||||
|
|
||||||
|
ScopedPtr<const ParsedStatement> expression = nullptr;
|
||||||
|
if (!isDefault) {
|
||||||
|
if (!ParseExpr(expression, current, log)) {
|
||||||
|
logError(DiagnosticType::UnexpectedToken, current->GetSpan());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
EXPECT_TOKEN(current, ColonSymbol);
|
||||||
|
|
||||||
|
std::vector<const ParsedStatement*> statements;
|
||||||
|
while (true) {
|
||||||
|
// Minor optimization, if we encounter a case/default keyword we know the upcoming statement is another case
|
||||||
|
// so not part of the current case. Similarly, if we find a close curly parenthesis we know we're at the end
|
||||||
|
// of the current switch statement, so we don't need to continue parsing.
|
||||||
|
if (current->GetKind() == LexTokenKind::CaseKeyword || current->GetKind() == LexTokenKind::DefaultKeyword ||
|
||||||
|
current->GetKind() == LexTokenKind::CloseCurlyParenthesisSymbol) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
ScopedPtr<const ParsedStatement> stat = nullptr;
|
||||||
|
if (ParseStatement(stat, current, log)) {
|
||||||
|
statements.push_back(stat.TakeOwnership());
|
||||||
|
} else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
out = new ParsedCaseStatement(TextSpan(currentToken->GetSpan().GetStart(), current->GetSpan().GetEnd()),
|
||||||
|
expression.TakeOwnership(), statements);
|
||||||
|
currentToken = current;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
@ -160,8 +160,10 @@ namespace MalachScript::Parser {
|
|||||||
const log_func&);
|
const log_func&);
|
||||||
static bool ParseTryStatement(ScopedPtr<const ParsedStatement>& out, const LexToken*& currentToken,
|
static bool ParseTryStatement(ScopedPtr<const ParsedStatement>& out, const LexToken*& currentToken,
|
||||||
const log_func&);
|
const log_func&);
|
||||||
// Case
|
static bool ParseCaseStatement(ScopedPtr<const ParsedStatement>& out, const LexToken*& currentToken,
|
||||||
// Switch
|
const log_func&);
|
||||||
|
static bool ParseSwitchStatement(ScopedPtr<const ParsedStatement>& out, const LexToken*& currentToken,
|
||||||
|
const log_func&);
|
||||||
|
|
||||||
static bool ParseStatement(ScopedPtr<const ParsedStatement>& out, const LexToken*& currentToken,
|
static bool ParseStatement(ScopedPtr<const ParsedStatement>& out, const LexToken*& currentToken,
|
||||||
const log_func&);
|
const log_func&);
|
||||||
|
@ -429,6 +429,36 @@ namespace MalachScript::Parser {
|
|||||||
std::unique_ptr<const ParsedStatement> _catchStatement;
|
std::unique_ptr<const ParsedStatement> _catchStatement;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class ParsedSwitchStatement : public ParsedStatementImpl<ParsedStatementKind::Switch> {
|
||||||
|
public:
|
||||||
|
ParsedSwitchStatement(const TextSpan& span, const ParsedStatement* expression,
|
||||||
|
const std::vector<const ParsedStatement*>& cases)
|
||||||
|
: ParsedStatementImpl(span), _expression(expression), _cases(cases.size()) {
|
||||||
|
for (size_t i = 0; i < cases.size(); i++) {
|
||||||
|
_cases[i] = std::unique_ptr<const ParsedStatement>(cases[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::unique_ptr<const ParsedStatement> _expression;
|
||||||
|
std::vector<std::unique_ptr<const ParsedStatement>> _cases;
|
||||||
|
};
|
||||||
|
|
||||||
|
class ParsedCaseStatement : public ParsedStatementImpl<ParsedStatementKind::Case> {
|
||||||
|
public:
|
||||||
|
ParsedCaseStatement(const TextSpan& span, const ParsedStatement* expression,
|
||||||
|
const std::vector<const ParsedStatement*>& statements)
|
||||||
|
: ParsedStatementImpl(span), _expression(expression), _statements(statements.size()) {
|
||||||
|
for (size_t i = 0; i < statements.size(); i++) {
|
||||||
|
_statements[i] = std::unique_ptr<const ParsedStatement>(statements[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::unique_ptr<const ParsedStatement> _expression;
|
||||||
|
std::vector<std::unique_ptr<const ParsedStatement>> _statements;
|
||||||
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // MALACHSCRIPT_PARSEDSTATEMENT_HPP
|
#endif // MALACHSCRIPT_PARSEDSTATEMENT_HPP
|
||||||
|
@ -27,7 +27,9 @@ namespace MalachScript::Parser {
|
|||||||
For,
|
For,
|
||||||
While,
|
While,
|
||||||
DoWhile,
|
DoWhile,
|
||||||
Try
|
Try,
|
||||||
|
Switch,
|
||||||
|
Case,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user