Implements parsing switch case statements.
continuous-integration/drone/push Build is passing
Details
continuous-integration/drone/push Build is passing
Details
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::DoKeyword: return ParseDoWhileStatement(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);
|
||||
}
|
||||
return false;
|
||||
|
@ -1030,4 +1031,90 @@ namespace MalachScript::Parser {
|
|||
currentToken = current;
|
||||
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&);
|
||||
static bool ParseTryStatement(ScopedPtr<const ParsedStatement>& out, const LexToken*& currentToken,
|
||||
const log_func&);
|
||||
// Case
|
||||
// Switch
|
||||
static bool ParseCaseStatement(ScopedPtr<const ParsedStatement>& out, const LexToken*& currentToken,
|
||||
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,
|
||||
const log_func&);
|
||||
|
|
|
@ -429,6 +429,36 @@ namespace MalachScript::Parser {
|
|||
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
|
||||
|
|
|
@ -27,7 +27,9 @@ namespace MalachScript::Parser {
|
|||
For,
|
||||
While,
|
||||
DoWhile,
|
||||
Try
|
||||
Try,
|
||||
Switch,
|
||||
Case,
|
||||
};
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue