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

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); 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 printer;
printer.address = true; printer.address = true;
printer.print(st, outfile);
printer.print(st, stderr); printer.print(st, stderr);
outfile.close();
#if _XOPEN_SOURCE >= 700 || _POSIX_C_SOURCE >= 200809L #if _XOPEN_SOURCE >= 700 || _POSIX_C_SOURCE >= 200809L
psiginfo(info, nullptr); psiginfo(info, nullptr);

View File

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

View File

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