Initial work on parsing.
This commit is contained in:
@@ -1,15 +1,28 @@
|
||||
#include "Parser.hpp"
|
||||
#include <iostream>
|
||||
|
||||
#define PROGRESS_TOKEN(token) \
|
||||
token = token->GetNext().get(); \
|
||||
while (token->GetKind() == LexTokenKind::Whitespace) { \
|
||||
token = token->GetNext().get(); \
|
||||
}
|
||||
|
||||
namespace MalachScript::Parser {
|
||||
ParsedScriptStatement* Parser::Parse() {
|
||||
std::vector<const ParsedStatement*> statements(32);
|
||||
std::vector<const ParsedStatement*> statements;
|
||||
statements.reserve(32);
|
||||
size_t current = 0;
|
||||
while (true) {
|
||||
auto next = this->Consume();
|
||||
if (next->GetKind() == LexTokenKind::EndOfFile) {
|
||||
while (_currentToken->GetKind() == LexTokenKind::Whitespace) {
|
||||
_currentToken = _currentToken->GetNext().get();
|
||||
}
|
||||
if (_currentToken->GetKind() == LexTokenKind::EndOfFile) {
|
||||
break;
|
||||
}
|
||||
statements[current] = this->ParseStatement(next);
|
||||
const ParsedStatement* statement;
|
||||
if (ParseClass(statement)) {
|
||||
}
|
||||
statements.push_back(statement);
|
||||
current++;
|
||||
}
|
||||
statements.resize(current);
|
||||
@@ -17,10 +30,84 @@ namespace MalachScript::Parser {
|
||||
if (current > 0) {
|
||||
end = statements.back()->GetSpan().GetEnd();
|
||||
}
|
||||
const auto* block = new ParsedBlockStatement(TextSpan(0, end), statements);
|
||||
return new ParsedScriptStatement(block);
|
||||
return new ParsedScriptStatement(TextSpan(0, end), statements);
|
||||
}
|
||||
const ParsedStatement* Parser::ParseStatement(const LexToken* token) {
|
||||
// If modifier (shared, external, private, protected, etc) push to buffer, continue
|
||||
bool Parser::ParseClass(const ParsedStatement*& out) {
|
||||
const auto* current = _currentToken;
|
||||
auto start = current->GetSpan().GetStart();
|
||||
bool lookingForClass = true;
|
||||
bool encounteredError = false;
|
||||
while (lookingForClass) {
|
||||
switch (current->GetKind()) {
|
||||
case LexTokenKind::SharedKeyword: break;
|
||||
case LexTokenKind::AbstractKeyword: break;
|
||||
case LexTokenKind::FinalKeyword: break;
|
||||
case LexTokenKind::ExternalKeyword: break;
|
||||
case LexTokenKind::ClassKeyword: lookingForClass = false; break;
|
||||
default: return false;
|
||||
}
|
||||
PROGRESS_TOKEN(current);
|
||||
}
|
||||
std::u8string_view identifier;
|
||||
// After class keyword, an identifier should always follow, if it doesn't, log an error.
|
||||
identifier = ParseIdentifier(current, encounteredError);
|
||||
PROGRESS_TOKEN(current);
|
||||
std::vector<std::u8string_view> inherits;
|
||||
std::vector<const ParsedStatement*> body;
|
||||
body.reserve(16);
|
||||
|
||||
switch (current->GetKind()) {
|
||||
case LexTokenKind::SemicolonSymbol: {
|
||||
PROGRESS_TOKEN(current);
|
||||
break;
|
||||
}
|
||||
case LexTokenKind::ColonSymbol: {
|
||||
PROGRESS_TOKEN(current);
|
||||
auto id = ParseIdentifier(current, encounteredError);
|
||||
inherits.push_back(id);
|
||||
while (current->GetKind() == LexTokenKind::CommaSymbol) {
|
||||
PROGRESS_TOKEN(current);
|
||||
id = ParseIdentifier(current, encounteredError);
|
||||
inherits.push_back(id);
|
||||
PROGRESS_TOKEN(current);
|
||||
}
|
||||
if (!encounteredError && current->GetKind() != LexTokenKind::OpenCurlyParenthesisSymbol)
|
||||
{
|
||||
encounteredError = true;
|
||||
LogError(Diagnostics::DiagnosticType::UnexpectedToken, current->GetSpan());
|
||||
}
|
||||
// Intentionally don't break so we continue into the inner body statement.
|
||||
}
|
||||
case LexTokenKind::OpenCurlyParenthesisSymbol: {
|
||||
PROGRESS_TOKEN(current);
|
||||
while (true) {
|
||||
// Cheapest operation, check first
|
||||
if (current->GetKind() == LexTokenKind::CloseCurlyParenthesisSymbol) {
|
||||
PROGRESS_TOKEN(current);
|
||||
break;
|
||||
}
|
||||
const ParsedStatement* statement;
|
||||
// TODO: Sort by
|
||||
if (!ParseVirtProp(statement) &&
|
||||
!ParseFunc(statement) &&
|
||||
!ParseVar(statement) &&
|
||||
!ParseFuncDef(statement)){
|
||||
LogError(Diagnostics::DiagnosticType::UnexpectedToken, current->GetSpan());
|
||||
} else{
|
||||
body.push_back(statement);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
default: throw;
|
||||
}
|
||||
out = new ParsedClassStatement(TextSpan(start, current->GetSpan().GetEnd()), identifier,
|
||||
inherits, body);
|
||||
_currentToken = current;
|
||||
return true;
|
||||
}
|
||||
bool Parser::ParseVirtProp([[maybe_unused]]const ParsedStatement*& out) { return false; }
|
||||
bool Parser::ParseFunc([[maybe_unused]]const ParsedStatement*& out) { return false; }
|
||||
bool Parser::ParseVar([[maybe_unused]]const ParsedStatement*& out) { return false; }
|
||||
bool Parser::ParseFuncDef([[maybe_unused]]const ParsedStatement*& out) { return false; }
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user