Make parser be able to skip tokens when encountering an unexpected token.
continuous-integration/drone/push Build is passing Details

This commit is contained in:
Deukhoofd 2021-01-05 13:20:34 +01:00
parent d9d52554e4
commit b73bfe6482
Signed by: Deukhoofd
GPG Key ID: F63E044490819F6F
3 changed files with 33 additions and 27 deletions

5
extern/backward.hpp vendored
View File

@ -3993,9 +3993,14 @@ namespace backward {
st.load_here(32, reinterpret_cast<void*>(uctx), info->si_addr);
}
std::ofstream outfile;
outfile.open("error.log", std::ios::out | std::ios::trunc);
Printer printer;
printer.address = true;
printer.print(st, outfile);
printer.print(st, stderr);
outfile.close();
#if _XOPEN_SOURCE >= 700 || _POSIX_C_SOURCE >= 200809L
psiginfo(info, nullptr);

View File

@ -11,6 +11,10 @@
#define EXPECT_TOKEN(token, kind) \
if ((token)->GetKind() != LexTokenKind::kind) { \
logError(DiagnosticType::UnexpectedToken, (token)->GetSpan()); \
if ((token)->GetNext() != nullptr && (token)->GetNext()->GetNext() != nullptr && \
(token)->GetNext()->GetKind() == LexTokenKind::kind) { \
(token) = (token)->GetNext()->GetNext().get(); \
} \
} else { \
PROGRESS_TOKEN(token); \
}
@ -371,11 +375,7 @@ namespace MalachScript::Parser {
if (currentToken->GetKind() == LexTokenKind::VoidKeyword) {
PROGRESS_TOKEN(currentToken);
if (currentToken->GetKind() != LexTokenKind::CloseParenthesisSymbol) {
logError(DiagnosticType::UnexpectedToken, currentToken->GetSpan());
return false;
}
PROGRESS_TOKEN(currentToken);
EXPECT_TOKEN(currentToken, CloseParenthesisSymbol);
out = new ParsedParamListStatement(TextSpan(start, currentToken->GetSpan().GetEnd()), parameters);
return true;
}
@ -392,14 +392,13 @@ namespace MalachScript::Parser {
if (!ParseType(typeStatement, currentToken, log)) {
logError(DiagnosticType::UnexpectedToken, currentToken->GetSpan());
return false;
}
ParseTypeMod(typeMod, currentToken, log);
if (!ParseIdentifier(identifier, currentToken)) {
logError(DiagnosticType::UnexpectedToken, currentToken->GetSpan());
return false;
} else {
PROGRESS_TOKEN(currentToken);
}
PROGRESS_TOKEN(currentToken);
// TODO: Default expression
parameters.push_back(new ParsedParamListStatement::ParsedParameter(
@ -411,22 +410,8 @@ namespace MalachScript::Parser {
}
PROGRESS_TOKEN(currentToken);
}
while (currentToken->GetKind() != LexTokenKind::CloseParenthesisSymbol) {
logError(DiagnosticType::UnexpectedToken, currentToken->GetSpan());
if (currentToken->GetKind() == LexTokenKind::EndOfFile) {
logError(DiagnosticType::UnexpectedToken, currentToken->GetSpan());
return false;
}
if (currentToken->GetKind() == LexTokenKind::SemicolonSymbol) {
logError(DiagnosticType::UnexpectedToken, currentToken->GetSpan());
return false;
}
PROGRESS_TOKEN(currentToken);
}
EXPECT_TOKEN(currentToken, CloseParenthesisSymbol);
out = new ParsedParamListStatement(TextSpan(start, currentToken->GetSpan().GetEnd()), parameters);
if (currentToken->GetKind() != LexTokenKind::SemicolonSymbol) {
PROGRESS_TOKEN(currentToken);
}
return true;
}
@ -555,13 +540,11 @@ namespace MalachScript::Parser {
ScopedPtr<const ParsedStatement> condition = nullptr;
if (!ParseAssign(condition, current, log)) {
logError(DiagnosticType::UnexpectedToken, current->GetSpan());
return false;
}
EXPECT_TOKEN(current, CloseParenthesisSymbol);
ScopedPtr<const ParsedStatement> body = nullptr;
if (!ParseStatement(body, current, log)) {
logError(DiagnosticType::UnexpectedToken, current->GetSpan());
return false;
}
ScopedPtr<const ParsedStatement> elseStatement = nullptr;
if (current->GetKind() == LexTokenKind::ElseKeyword) {
@ -827,6 +810,7 @@ namespace MalachScript::Parser {
logError(DiagnosticType::UnexpectedToken, current->GetSpan());
}
EXPECT_TOKEN(current, CloseParenthesisSymbol);
currentToken = current;
return true;
}
// TODO: lambda

View File

@ -13,6 +13,10 @@ namespace MalachScript::Parser {
}
static void StringifyType(const ParsedTypeStatement* statement, std::stringstream& stream) {
if (statement == nullptr) {
stream << "NULL";
return;
}
if (statement->IsConst()) {
stream << "const ";
}
@ -46,6 +50,12 @@ namespace MalachScript::Parser {
public:
static void Stringify(const ParsedStatement* statement, std::stringstream& stream, const std::string& prefix,
bool isLast) {
if (statement == nullptr) {
stream << prefix;
stream << (isLast ? "└──" : "├──");
stream << "NULL";
return;
}
DefaultStringify(statement, stream, prefix, isLast);
switch (statement->GetKind()) {
@ -88,8 +98,12 @@ namespace MalachScript::Parser {
case ParsedStatementKind::Func: {
const auto* func = static_cast<const ParsedFuncStatement*>(statement);
stream << " " << func->GetIdentifier();
StringifyParamList(dynamic_cast<const ParsedParamListStatement*>(func->GetParamList().get()),
stream);
if (func->GetParamList() != nullptr) {
StringifyParamList(dynamic_cast<const ParsedParamListStatement*>(func->GetParamList().get()),
stream);
} else {
stream << " NULL";
}
stream << std::endl;
Stringify(func->GetStatBlock().get(), stream, prefix + (isLast ? " " : ""), true);
@ -151,6 +165,9 @@ namespace MalachScript::Parser {
stream << std::endl;
Stringify(s->GetBody().get(), stream,
propPrefix + (s->GetElseStatement() == nullptr ? " " : ""), true);
if (s->GetBody() == nullptr) {
stream << std::endl;
}
if (s->GetElseStatement() != nullptr) {
stream << propPrefix << "└──"
<< "Else";