From da82819fffcd938d5d5cd1df684aa7aea091532f Mon Sep 17 00:00:00 2001 From: Deukhoofd Date: Wed, 6 Jan 2021 13:32:06 +0100 Subject: [PATCH] More work on better parser logging. --- extern/format.hpp | 20 +- src/Diagnostics/DiagnosticTypeEN_US.hpp | 9 +- src/Parser/Lexer/LexTokenKind.hpp | 242 ++++++++++++------------ src/Parser/Parser.cpp | 126 ++++++------ 4 files changed, 217 insertions(+), 180 deletions(-) diff --git a/extern/format.hpp b/extern/format.hpp index b1566cb..44c58f6 100644 --- a/extern/format.hpp +++ b/extern/format.hpp @@ -41,9 +41,12 @@ namespace util { char* endptr = nullptr; index = strtol(&item[0], &endptr, 10); - if (index < 0 || index >= (int)args.size()) { + if (index >= (int)args.size()) { return; } + if (index < 0) { + index = args.size() + index; + } if (*endptr == ',') { alignment = strtol(endptr + 1, &endptr, 10); @@ -57,8 +60,21 @@ namespace util { if (*endptr == ':') { fmt = endptr + 1; } + if (*endptr == '.' && *(endptr + 1) == '.') { + auto endIndex = strtol(endptr + 2, &endptr, 10); + if (endIndex < 0) { + endIndex = args.size() + endIndex + 1; + } - args[index]->Format(ss, fmt); + for (; index < endIndex; index++) { + args[index]->Format(ss, fmt); + if (index != endIndex - 1) { + ss << ", "; + } + } + } else { + args[index]->Format(ss, fmt); + } return; } diff --git a/src/Diagnostics/DiagnosticTypeEN_US.hpp b/src/Diagnostics/DiagnosticTypeEN_US.hpp index bf7e95f..dc2f3bd 100644 --- a/src/Diagnostics/DiagnosticTypeEN_US.hpp +++ b/src/Diagnostics/DiagnosticTypeEN_US.hpp @@ -14,7 +14,14 @@ namespace MalachScript::Diagnostics { case DiagnosticType::ExpectedEndOfString: return util::Format("Expected end of string, found {0}", diag->GetFormats()); case DiagnosticType::UnexpectedToken: - return util::Format("Unexpected Token. Expected any of: {0}, but found {1}", diag->GetFormats()); + if (diag->GetFormats().size() == 1) { + return util::Format("Unexpected Token: '{0}'", diag->GetFormats()); + } else if (diag->GetFormats().size() == 2) { + return util::Format("Unexpected Token. Expected: '{0}', but found '{-1}'", diag->GetFormats()); + } else if (diag->GetFormats().size() > 2) { + return util::Format("Unexpected Token. Expected any of: '{0..-2}', but found '{-1}'", + diag->GetFormats()); + } case DiagnosticType::DoubleProperty: return "Property block found twice."; } return std::to_string((uint8_t)diag->GetType()); diff --git a/src/Parser/Lexer/LexTokenKind.hpp b/src/Parser/Lexer/LexTokenKind.hpp index e05bc6f..c6eb8fc 100644 --- a/src/Parser/Lexer/LexTokenKind.hpp +++ b/src/Parser/Lexer/LexTokenKind.hpp @@ -144,127 +144,127 @@ namespace MalachScript::Parser { case LexTokenKind::Unknown: return "Unknown"; case LexTokenKind::EndOfFile: return "EndOfFile"; - case LexTokenKind::Whitespace: break; - case LexTokenKind::StarSymbol: break; - case LexTokenKind::StarStarSymbol: break; - case LexTokenKind::SlashSymbol: break; - case LexTokenKind::PercentSymbol: break; - case LexTokenKind::PlusSymbol: break; - case LexTokenKind::MinusSymbol: break; - case LexTokenKind::LessThanEqualsSymbol: break; - case LexTokenKind::LessThanSymbol: break; - case LexTokenKind::GreaterThanEqualsSymbol: break; - case LexTokenKind::GreaterThanSymbol: break; - case LexTokenKind::OpenParenthesisSymbol: break; - case LexTokenKind::CloseParenthesisSymbol: break; - case LexTokenKind::EqualsEqualsSymbol: break; - case LexTokenKind::ExclamationMarkEqualsSymbol: break; - case LexTokenKind::QuestionMarkSymbol: break; - case LexTokenKind::ColonSymbol: break; - case LexTokenKind::EqualsSymbol: break; - case LexTokenKind::PlusEqualsSymbol: break; - case LexTokenKind::MinusEqualsSymbol: break; - case LexTokenKind::StarEqualsSymbol: break; - case LexTokenKind::SlashEqualsSymbol: break; - case LexTokenKind::PercentEqualsSymbol: break; - case LexTokenKind::StarStarEqualsSymbol: break; - case LexTokenKind::PlusPlusSymbol: break; - case LexTokenKind::MinusMinusSymbol: break; - case LexTokenKind::AmpersandSymbol: break; - case LexTokenKind::CommaSymbol: break; - case LexTokenKind::OpenCurlyParenthesisSymbol: break; - case LexTokenKind::CloseCurlyParenthesisSymbol: break; - case LexTokenKind::SemicolonSymbol: break; - case LexTokenKind::VerticalLineSymbol: break; - case LexTokenKind::CaretSymbol: break; - case LexTokenKind::TildeSymbol: break; - case LexTokenKind::LessThanLessThanSymbol: break; - case LexTokenKind::GreaterThanGreaterThanSymbol: break; - case LexTokenKind::GreaterThanGreaterThanGreaterThanSymbol: break; - case LexTokenKind::AmpersandEqualsSymbol: break; - case LexTokenKind::VerticalLineEqualsSymbol: break; - case LexTokenKind::CaretEqualsSymbol: break; - case LexTokenKind::LessThanLessThanEqualsSymbol: break; - case LexTokenKind::GreaterThanGreaterThanEqualsSymbol: break; - case LexTokenKind::GreaterThanGreaterThanGreaterThanEqualsSymbol: break; - case LexTokenKind::DotSymbol: break; - case LexTokenKind::AmpersandAmpersandSymbol: break; - case LexTokenKind::VerticalLineVerticalLineSymbol: break; - case LexTokenKind::ExclamationMarkSymbol: break; - case LexTokenKind::OpenBlockParenthesisSymbol: break; - case LexTokenKind::CloseBlockParenthesisSymbol: break; - case LexTokenKind::CaretCaretSymbol: break; - case LexTokenKind::AtSymbol: break; - case LexTokenKind::ExclamationMarkIsSymbol: break; - case LexTokenKind::ColonColonSymbol: break; - case LexTokenKind::AndKeyword: break; - case LexTokenKind::AbstractKeyword: break; - case LexTokenKind::AutoKeyword: break; - case LexTokenKind::BoolKeyword: break; - case LexTokenKind::BreakKeyword: break; - case LexTokenKind::CaseKeyword: break; - case LexTokenKind::CastKeyword: break; - case LexTokenKind::CatchKeyword: break; - case LexTokenKind::ClassKeyword: break; - case LexTokenKind::ConstKeyword: break; - case LexTokenKind::ContinueKeyword: break; - case LexTokenKind::DefaultKeyword: break; - case LexTokenKind::DoKeyword: break; - case LexTokenKind::DoubleKeyword: break; - case LexTokenKind::ElseKeyword: break; - case LexTokenKind::EnumKeyword: break; - case LexTokenKind::ExplicitKeyword: break; - case LexTokenKind::ExternalKeyword: break; - case LexTokenKind::FalseKeyword: break; - case LexTokenKind::FinalKeyword: break; - case LexTokenKind::FloatKeyword: break; - case LexTokenKind::ForKeyword: break; - case LexTokenKind::FromKeyword: break; - case LexTokenKind::FuncdefKeyword: break; - case LexTokenKind::FunctionKeyword: break; - case LexTokenKind::GetKeyword: break; - case LexTokenKind::IfKeyword: break; - case LexTokenKind::ImportKeyword: break; - case LexTokenKind::InKeyword: break; - case LexTokenKind::InoutKeyword: break; - case LexTokenKind::IntKeyword: break; - case LexTokenKind::InterfaceKeyword: break; - case LexTokenKind::Int8Keyword: break; - case LexTokenKind::Int16Keyword: break; - case LexTokenKind::Int32Keyword: break; - case LexTokenKind::Int64Keyword: break; - case LexTokenKind::IsKeyword: break; - case LexTokenKind::MixinKeyword: break; - case LexTokenKind::NamespaceKeyword: break; - case LexTokenKind::NotKeyword: break; - case LexTokenKind::NullKeyword: break; - case LexTokenKind::OrKeyword: break; - case LexTokenKind::OutKeyword: break; - case LexTokenKind::OverrideKeyword: break; - case LexTokenKind::PrivateKeyword: break; - case LexTokenKind::PropertyKeyword: break; - case LexTokenKind::ProtectedKeyword: break; - case LexTokenKind::ReturnKeyword: break; - case LexTokenKind::SetKeyword: break; - case LexTokenKind::SharedKeyword: break; - case LexTokenKind::SuperKeyword: break; - case LexTokenKind::SwitchKeyword: break; - case LexTokenKind::ThisKeyword: break; - case LexTokenKind::TrueKeyword: break; - case LexTokenKind::TryKeyword: break; - case LexTokenKind::TypedefKeyword: break; - case LexTokenKind::UintKeyword: break; - case LexTokenKind::Uint8Keyword: break; - case LexTokenKind::Uint16Keyword: break; - case LexTokenKind::Uint32Keyword: break; - case LexTokenKind::Uint64Keyword: break; - case LexTokenKind::VoidKeyword: break; - case LexTokenKind::WhileKeyword: break; - case LexTokenKind::XorKeyword: break; - case LexTokenKind::FloatLiteral: break; - case LexTokenKind::IntegerLiteral: break; - case LexTokenKind::StringLiteral: break; - case LexTokenKind::Identifier: break; + case LexTokenKind::Whitespace: return "Whitespace"; + case LexTokenKind::StarSymbol: return "*"; + case LexTokenKind::StarStarSymbol: return "**"; + case LexTokenKind::SlashSymbol: return "/"; + case LexTokenKind::PercentSymbol: return "%"; + case LexTokenKind::PlusSymbol: return "+"; + case LexTokenKind::MinusSymbol: return "-"; + case LexTokenKind::LessThanEqualsSymbol: return "<="; + case LexTokenKind::LessThanSymbol: return "<"; + case LexTokenKind::GreaterThanEqualsSymbol: return ">="; + case LexTokenKind::GreaterThanSymbol: return ">"; + case LexTokenKind::OpenParenthesisSymbol: return "("; + case LexTokenKind::CloseParenthesisSymbol: return ")"; + case LexTokenKind::EqualsEqualsSymbol: return "=="; + case LexTokenKind::ExclamationMarkEqualsSymbol: return "!="; + case LexTokenKind::QuestionMarkSymbol: return "?"; + case LexTokenKind::ColonSymbol: return ":"; + case LexTokenKind::EqualsSymbol: return "="; + case LexTokenKind::PlusEqualsSymbol: return "+="; + case LexTokenKind::MinusEqualsSymbol: return "-="; + case LexTokenKind::StarEqualsSymbol: return "*="; + case LexTokenKind::SlashEqualsSymbol: return "/="; + case LexTokenKind::PercentEqualsSymbol: return "%="; + case LexTokenKind::StarStarEqualsSymbol: return "**="; + case LexTokenKind::PlusPlusSymbol: return "++"; + case LexTokenKind::MinusMinusSymbol: return "--"; + case LexTokenKind::AmpersandSymbol: return "&"; + case LexTokenKind::CommaSymbol: return ","; + case LexTokenKind::OpenCurlyParenthesisSymbol: return "{"; + case LexTokenKind::CloseCurlyParenthesisSymbol: return "}"; + case LexTokenKind::SemicolonSymbol: return ";"; + case LexTokenKind::VerticalLineSymbol: return "|"; + case LexTokenKind::CaretSymbol: return "^"; + case LexTokenKind::TildeSymbol: return "~"; + case LexTokenKind::LessThanLessThanSymbol: return "<<"; + case LexTokenKind::GreaterThanGreaterThanSymbol: return ">>"; + case LexTokenKind::GreaterThanGreaterThanGreaterThanSymbol: return ">>>"; + case LexTokenKind::AmpersandEqualsSymbol: return "&="; + case LexTokenKind::VerticalLineEqualsSymbol: return "|="; + case LexTokenKind::CaretEqualsSymbol: return "^="; + case LexTokenKind::LessThanLessThanEqualsSymbol: return "<<="; + case LexTokenKind::GreaterThanGreaterThanEqualsSymbol: return ">>="; + case LexTokenKind::GreaterThanGreaterThanGreaterThanEqualsSymbol: return ">>>="; + case LexTokenKind::DotSymbol: return "."; + case LexTokenKind::AmpersandAmpersandSymbol: return "&"; + case LexTokenKind::VerticalLineVerticalLineSymbol: return "||"; + case LexTokenKind::ExclamationMarkSymbol: return "!"; + case LexTokenKind::OpenBlockParenthesisSymbol: return "["; + case LexTokenKind::CloseBlockParenthesisSymbol: return "]"; + case LexTokenKind::CaretCaretSymbol: return "^^"; + case LexTokenKind::AtSymbol: return "@"; + case LexTokenKind::ExclamationMarkIsSymbol: return "!="; + case LexTokenKind::ColonColonSymbol: return "::"; + case LexTokenKind::AndKeyword: return "and"; + case LexTokenKind::AbstractKeyword: return "abstract"; + case LexTokenKind::AutoKeyword: return "auto"; + case LexTokenKind::BoolKeyword: return "bool"; + case LexTokenKind::BreakKeyword: return "break"; + case LexTokenKind::CaseKeyword: return "case"; + case LexTokenKind::CastKeyword: return "cast"; + case LexTokenKind::CatchKeyword: return "catch"; + case LexTokenKind::ClassKeyword: return "class"; + case LexTokenKind::ConstKeyword: return "const"; + case LexTokenKind::ContinueKeyword: return "continue"; + case LexTokenKind::DefaultKeyword: return "default"; + case LexTokenKind::DoKeyword: return "do"; + case LexTokenKind::DoubleKeyword: return "double"; + case LexTokenKind::ElseKeyword: return "else"; + case LexTokenKind::EnumKeyword: return "enum"; + case LexTokenKind::ExplicitKeyword: return "explicit"; + case LexTokenKind::ExternalKeyword: return "external"; + case LexTokenKind::FalseKeyword: return "false"; + case LexTokenKind::FinalKeyword: return "final"; + case LexTokenKind::FloatKeyword: return "float"; + case LexTokenKind::ForKeyword: return "for"; + case LexTokenKind::FromKeyword: return "from"; + case LexTokenKind::FuncdefKeyword: return "funcdef"; + case LexTokenKind::FunctionKeyword: return "function"; + case LexTokenKind::GetKeyword: return "get"; + case LexTokenKind::IfKeyword: return "if"; + case LexTokenKind::ImportKeyword: return "import"; + case LexTokenKind::InKeyword: return "in"; + case LexTokenKind::InoutKeyword: return "inout"; + case LexTokenKind::IntKeyword: return "int"; + case LexTokenKind::InterfaceKeyword: return "interface"; + case LexTokenKind::Int8Keyword: return "int8"; + case LexTokenKind::Int16Keyword: return "int16"; + case LexTokenKind::Int32Keyword: return "int32"; + case LexTokenKind::Int64Keyword: return "int64"; + case LexTokenKind::IsKeyword: return "is"; + case LexTokenKind::MixinKeyword: return "mixin"; + case LexTokenKind::NamespaceKeyword: return "namespace"; + case LexTokenKind::NotKeyword: return "not"; + case LexTokenKind::NullKeyword: return "null"; + case LexTokenKind::OrKeyword: return "or"; + case LexTokenKind::OutKeyword: return "out"; + case LexTokenKind::OverrideKeyword: return "override"; + case LexTokenKind::PrivateKeyword: return "private"; + case LexTokenKind::PropertyKeyword: return "property"; + case LexTokenKind::ProtectedKeyword: return "protected"; + case LexTokenKind::ReturnKeyword: return "return"; + case LexTokenKind::SetKeyword: return "set"; + case LexTokenKind::SharedKeyword: return "shared"; + case LexTokenKind::SuperKeyword: return "super"; + case LexTokenKind::SwitchKeyword: return "switch"; + case LexTokenKind::ThisKeyword: return "this"; + case LexTokenKind::TrueKeyword: return "true"; + case LexTokenKind::TryKeyword: return "try"; + case LexTokenKind::TypedefKeyword: return "typedef"; + case LexTokenKind::UintKeyword: return "uint"; + case LexTokenKind::Uint8Keyword: return "uint8"; + case LexTokenKind::Uint16Keyword: return "uint16"; + case LexTokenKind::Uint32Keyword: return "uint32"; + case LexTokenKind::Uint64Keyword: return "uint64"; + case LexTokenKind::VoidKeyword: return "void"; + case LexTokenKind::WhileKeyword: return "while"; + case LexTokenKind::XorKeyword: return "xor"; + case LexTokenKind::FloatLiteral: return "float"; + case LexTokenKind::IntegerLiteral: return "integer"; + case LexTokenKind::StringLiteral: return "string"; + case LexTokenKind::Identifier: return "identifier"; } return "FAIL"; } diff --git a/src/Parser/Parser.cpp b/src/Parser/Parser.cpp index 44af6cb..06f09a3 100644 --- a/src/Parser/Parser.cpp +++ b/src/Parser/Parser.cpp @@ -11,7 +11,7 @@ #define EXPECT_TOKEN(token, kind) \ if ((token)->GetKind() != LexTokenKind::kind) { \ - logError(DiagnosticType::UnexpectedToken, (token)->GetSpan(), {}); \ + logUnexpectedToken(kind, token); \ if ((token)->GetNext() != nullptr && (token)->GetNext()->GetNext() != nullptr && \ (token)->GetNext()->GetKind() == LexTokenKind::kind) { \ (token) = (token)->GetNext()->GetNext().get(); \ @@ -21,6 +21,19 @@ } #define logError(type, span, formats) log(DiagnosticLevel::Error, type, span, formats) +#define logUnexpectedToken(expected, found) \ + log(DiagnosticLevel::Error, DiagnosticType::UnexpectedToken, (found)->GetSpan(), \ + {LexTokenKindHelper::ToString(LexTokenKind::expected), (found)->ToString()}); +#define logUnexpectedTokenWithAnyOf(found, ...) \ + std::vector vars = {__VA_ARGS__}; \ + auto expectedTokens = std::vector(vars.size() + 1); \ + for (size_t i = 0; i < vars.size(); i++) { \ + expectedTokens[i] = LexTokenKindHelper::ToString(vars[i]); \ + } \ + expectedTokens[expectedTokens.size() - 1] = (found)->ToString(); \ + log(DiagnosticLevel::Error, DiagnosticType::UnexpectedToken, (found)->GetSpan(), expectedTokens); +#define logUnexpectedTokenWithoutExpected(found) \ + log(DiagnosticLevel::Error, DiagnosticType::UnexpectedToken, (found)->GetSpan(), {(found)->ToString()}); namespace MalachScript::Parser { using namespace Diagnostics; @@ -64,8 +77,7 @@ namespace MalachScript::Parser { auto result = ParseTypeDef(statement, current, log) || ParseClass(statement, current, log) || ParseFunc(statement, current, log) || ParseNamespace(statement, current, log); if (!result) { - log(DiagnosticLevel::Error, DiagnosticType::UnexpectedToken, current->GetSpan(), - {"", current->ToString()}); + logUnexpectedTokenWithoutExpected(current); PROGRESS_TOKEN(current); continue; } @@ -100,7 +112,7 @@ namespace MalachScript::Parser { // After class keyword, an identifier should always follow, if it doesn't, log an error. Identifier identifier; if (!ParseIdentifier(identifier, current)) { - logError(DiagnosticType::UnexpectedToken, current->GetSpan(), {}); + logUnexpectedToken(Identifier, current); return false; } PROGRESS_TOKEN(current); @@ -116,21 +128,21 @@ namespace MalachScript::Parser { PROGRESS_TOKEN(current); Identifier id; if (!ParseIdentifier(id, current)) { - logError(DiagnosticType::UnexpectedToken, current->GetSpan(), {}); + logUnexpectedToken(Identifier, current); return false; } inherits.push_back(id); while (current->GetKind() == LexTokenKind::CommaSymbol) { PROGRESS_TOKEN(current); if (!ParseIdentifier(id, current)) { - logError(DiagnosticType::UnexpectedToken, current->GetSpan(), {}); + logUnexpectedToken(Identifier, current); return false; } inherits.push_back(id); PROGRESS_TOKEN(current); } if (current->GetKind() != LexTokenKind::OpenCurlyParenthesisSymbol) { - logError(DiagnosticType::UnexpectedToken, current->GetSpan(), {}); + logUnexpectedToken(OpenCurlyParenthesisSymbol, current); return false; } [[fallthrough]]; @@ -148,14 +160,16 @@ namespace MalachScript::Parser { // TODO: Sort by complexity if (!ParseVirtProp(statement, current, log) && !ParseFunc(statement, current, log) && !ParseVar(statement, current, log) && !ParseFuncDef(statement, current, log)) { - logError(DiagnosticType::UnexpectedToken, current->GetSpan(), {}); + logUnexpectedTokenWithoutExpected(current); break; } body.push_back(statement.TakeOwnership()); } break; } - default: logError(DiagnosticType::UnexpectedToken, current->GetSpan(), {}); return false; + default: + logUnexpectedTokenWithAnyOf(current, LexTokenKind::SemicolonSymbol, LexTokenKind::ColonSymbol, + LexTokenKind::OpenCurlyParenthesisSymbol); } out = new ParsedClassStatement(TextSpan(start, current->GetSpan().GetEnd()), classAttr, identifier, inherits, body); @@ -172,13 +186,13 @@ namespace MalachScript::Parser { PROGRESS_TOKEN(current); Identifier defineFrom; if (!ParsePrimType(defineFrom, current, log) && !ParseIdentifier(defineFrom, current)) { - logError(DiagnosticType::UnexpectedToken, current->GetSpan(), {}); + logUnexpectedTokenWithoutExpected(current); } PROGRESS_TOKEN(current); Identifier defineTo; if (!ParseIdentifier(defineTo, current)) { - logError(DiagnosticType::UnexpectedToken, current->GetSpan(), {}); + logUnexpectedToken(Identifier, current); } PROGRESS_TOKEN(current); EXPECT_TOKEN(current, SemicolonSymbol); @@ -195,14 +209,14 @@ namespace MalachScript::Parser { PROGRESS_TOKEN(current); Identifier identifier; if (!ParseIdentifier(identifier, current)) { - logError(DiagnosticType::UnexpectedToken, current->GetSpan(), {}); + logUnexpectedToken(Identifier, current); } else { PROGRESS_TOKEN(current); } EXPECT_TOKEN(current, OpenCurlyParenthesisSymbol); ScopedPtr script = nullptr; if (!ParseScript(script, current, log)) { - logError(DiagnosticType::UnexpectedToken, current->GetSpan(), {}); + logUnexpectedTokenWithoutExpected(current); } auto end = current->GetSpan().GetEnd(); EXPECT_TOKEN(current, CloseCurlyParenthesisSymbol); @@ -268,7 +282,7 @@ namespace MalachScript::Parser { ScopedPtr statblock = nullptr; if (current->GetKind() != LexTokenKind::SemicolonSymbol) { if (!ParseStatBlock(statblock, current, log)) { - logError(DiagnosticType::UnexpectedToken, current->GetSpan(), {}); + logUnexpectedTokenWithoutExpected(current); return false; } } else { @@ -282,39 +296,39 @@ namespace MalachScript::Parser { } bool Parser::ParseType(ScopedPtr& out, const LexToken*& currentToken, const log_func& log) { - const auto* token = currentToken; - auto start = token->GetSpan().GetStart(); + const auto* current = currentToken; + auto start = current->GetSpan().GetStart(); bool isConst = false; bool isArray = false; bool isHandle = false; - if (token->GetKind() == LexTokenKind::ConstKeyword) { + if (current->GetKind() == LexTokenKind::ConstKeyword) { isConst = true; - PROGRESS_TOKEN(token); + PROGRESS_TOKEN(current); } ScopedIdentifier scopedIdentifier; - ParseScope(scopedIdentifier.GetScope(), token, log); - if (!ParseDataType(scopedIdentifier.GetIdentifier(), token, log)) { + ParseScope(scopedIdentifier.GetScope(), current, log); + if (!ParseDataType(scopedIdentifier.GetIdentifier(), current, log)) { return false; } // TODO: Generics. - if (token->GetKind() == LexTokenKind::OpenBlockParenthesisSymbol) { - PROGRESS_TOKEN(token); - if (token->GetKind() != LexTokenKind::CloseBlockParenthesisSymbol) { - logError(DiagnosticType::UnexpectedToken, token->GetSpan(), {}); + if (current->GetKind() == LexTokenKind::OpenBlockParenthesisSymbol) { + PROGRESS_TOKEN(current); + if (current->GetKind() != LexTokenKind::CloseBlockParenthesisSymbol) { + logUnexpectedToken(CloseCurlyParenthesisSymbol, current); } else { - PROGRESS_TOKEN(token); + PROGRESS_TOKEN(current); isArray = true; } - } else if (token->GetKind() == LexTokenKind::AtSymbol) { + } else if (current->GetKind() == LexTokenKind::AtSymbol) { isHandle = true; - PROGRESS_TOKEN(token); - if (token->GetKind() == LexTokenKind::ConstKeyword) { + PROGRESS_TOKEN(current); + if (current->GetKind() == LexTokenKind::ConstKeyword) { isConst = true; - PROGRESS_TOKEN(token); + PROGRESS_TOKEN(current); } } - auto end = token->GetSpan().GetEnd(); - currentToken = token; + auto end = current->GetSpan().GetEnd(); + currentToken = current; out = new ParsedTypeStatement(TextSpan(start, end), isConst, isArray, isHandle, scopedIdentifier); return true; } @@ -348,7 +362,7 @@ namespace MalachScript::Parser { break; } } else { - logError(DiagnosticType::UnexpectedToken, currentToken->GetSpan(), {}); + logUnexpectedToken(Identifier, current); break; } } @@ -412,11 +426,11 @@ namespace MalachScript::Parser { const ParsedStatement* defaultExpression = nullptr; if (!ParseType(typeStatement, currentToken, log)) { - logError(DiagnosticType::UnexpectedToken, currentToken->GetSpan(), {}); + logUnexpectedTokenWithoutExpected(currentToken); } ParseTypeMod(typeMod, currentToken, log); if (!ParseIdentifier(identifier, currentToken)) { - logError(DiagnosticType::UnexpectedToken, currentToken->GetSpan(), {}); + logUnexpectedToken(Identifier, currentToken); } else { PROGRESS_TOKEN(currentToken); } @@ -503,7 +517,7 @@ namespace MalachScript::Parser { ParseFuncAttr(getAttr, current, log); if (current->GetKind() != LexTokenKind::SemicolonSymbol) { if (!ParseStatBlock(getStatement, current, log)) { - logError(DiagnosticType::UnexpectedToken, current->GetSpan(), {}); + logUnexpectedTokenWithoutExpected(current); } } else { PROGRESS_TOKEN(current); @@ -522,7 +536,7 @@ namespace MalachScript::Parser { ParseFuncAttr(setAttr, current, log); if (current->GetKind() != LexTokenKind::SemicolonSymbol) { if (!ParseStatBlock(setStatement, current, log)) { - logError(DiagnosticType::UnexpectedToken, current->GetSpan(), {}); + logUnexpectedTokenWithoutExpected(current); } } else { PROGRESS_TOKEN(current); @@ -537,7 +551,7 @@ namespace MalachScript::Parser { } } if (current->GetKind() != LexTokenKind::CloseCurlyParenthesisSymbol) { - logError(DiagnosticType::UnexpectedToken, current->GetSpan(), {}); + logUnexpectedToken(CloseCurlyParenthesisSymbol, current); } else { PROGRESS_TOKEN(current); } @@ -560,18 +574,18 @@ namespace MalachScript::Parser { EXPECT_TOKEN(current, OpenParenthesisSymbol); ScopedPtr condition = nullptr; if (!ParseAssign(condition, current, log)) { - logError(DiagnosticType::UnexpectedToken, current->GetSpan(), {}); + logUnexpectedTokenWithoutExpected(current); } EXPECT_TOKEN(current, CloseParenthesisSymbol); ScopedPtr body = nullptr; if (!ParseStatement(body, current, log)) { - logError(DiagnosticType::UnexpectedToken, current->GetSpan(), {}); + logUnexpectedTokenWithoutExpected(current); } ScopedPtr elseStatement = nullptr; if (current->GetKind() == LexTokenKind::ElseKeyword) { PROGRESS_TOKEN(current); if (!ParseStatement(elseStatement, current, log)) { - logError(DiagnosticType::UnexpectedToken, current->GetSpan(), {}); + logUnexpectedTokenWithoutExpected(current); } } out = new ParsedIfStatement(TextSpan(currentToken->GetSpan().GetStart(), current->GetSpan().GetEnd()), @@ -649,7 +663,7 @@ namespace MalachScript::Parser { if (current->GetKind() == LexTokenKind::CloseCurlyParenthesisSymbol) { PROGRESS_TOKEN(current); } else { - logError(DiagnosticType::UnexpectedToken, current->GetSpan(), {}); + logUnexpectedToken(CloseCurlyParenthesisSymbol, current); } out = new ParsedStatBlockStatement(TextSpan(currentToken->GetSpan().GetStart(), current->GetSpan().GetEnd()), @@ -719,7 +733,7 @@ namespace MalachScript::Parser { PROGRESS_TOKEN(current); ScopedPtr rightHand = nullptr; if (!ParseAssign(rightHand, current, log)) { - logError(DiagnosticType::UnexpectedToken, current->GetSpan(), {}); + logUnexpectedTokenWithoutExpected(current); out = leftHand.TakeOwnership(); currentToken = current; return true; @@ -743,7 +757,7 @@ namespace MalachScript::Parser { PROGRESS_TOKEN(current); \ ScopedPtr rightHand = nullptr; \ if (!ParseExprTerm(rightHand, current, log)) { \ - logError(DiagnosticType::UnexpectedToken, current->GetSpan(), {}); \ + logUnexpectedTokenWithoutExpected(current); \ out = leftHand.TakeOwnership(); \ currentToken = current; \ return true; \ @@ -828,7 +842,7 @@ namespace MalachScript::Parser { if (current->GetKind() == LexTokenKind::OpenParenthesisSymbol) { PROGRESS_TOKEN(current); if (!ParseAssign(out, current, log)) { - logError(DiagnosticType::UnexpectedToken, current->GetSpan(), {}); + logUnexpectedTokenWithoutExpected(current); } EXPECT_TOKEN(current, CloseParenthesisSymbol); currentToken = current; @@ -942,12 +956,12 @@ namespace MalachScript::Parser { EXPECT_TOKEN(current, OpenParenthesisSymbol); ScopedPtr init; if (!ParseVar(init, current, log) && !ParseExprStat(init, current, log)) { - logError(DiagnosticType::UnexpectedToken, current->GetSpan(), {}); + logUnexpectedTokenWithoutExpected(current); return false; } ScopedPtr condition; if (!ParseExprStat(condition, current, log)) { - logError(DiagnosticType::UnexpectedToken, current->GetSpan(), {}); + logUnexpectedTokenWithoutExpected(current); return false; } std::vector increment; @@ -963,7 +977,7 @@ namespace MalachScript::Parser { EXPECT_TOKEN(current, CloseParenthesisSymbol); ScopedPtr statementBlock; if (!ParseStatement(statementBlock, current, log)) { - logError(DiagnosticType::UnexpectedToken, current->GetSpan(), {}); + logUnexpectedTokenWithoutExpected(current); return false; } @@ -984,13 +998,13 @@ namespace MalachScript::Parser { EXPECT_TOKEN(current, OpenParenthesisSymbol); ScopedPtr condition = nullptr; if (!ParseAssign(condition, current, log)) { - logError(DiagnosticType::UnexpectedToken, current->GetSpan(), {}); + logUnexpectedTokenWithoutExpected(current); return false; } EXPECT_TOKEN(current, CloseParenthesisSymbol); ScopedPtr body = nullptr; if (!ParseStatement(body, current, log)) { - logError(DiagnosticType::UnexpectedToken, current->GetSpan(), {}); + logUnexpectedTokenWithoutExpected(current); return false; } out = new ParsedWhileStatement(TextSpan(currentToken->GetSpan().GetStart(), current->GetSpan().GetEnd()), @@ -1007,14 +1021,14 @@ namespace MalachScript::Parser { PROGRESS_TOKEN(current); ScopedPtr body = nullptr; if (!ParseStatement(body, current, log)) { - logError(DiagnosticType::UnexpectedToken, current->GetSpan(), {}); + logUnexpectedTokenWithoutExpected(current); return false; } EXPECT_TOKEN(current, WhileKeyword); EXPECT_TOKEN(current, OpenParenthesisSymbol); ScopedPtr condition = nullptr; if (!ParseAssign(condition, current, log)) { - logError(DiagnosticType::UnexpectedToken, current->GetSpan(), {}); + logUnexpectedTokenWithoutExpected(current); return false; } EXPECT_TOKEN(current, CloseParenthesisSymbol); @@ -1034,13 +1048,13 @@ namespace MalachScript::Parser { ScopedPtr tryStatement = nullptr; if (!ParseStatBlock(tryStatement, current, log)) { - logError(DiagnosticType::UnexpectedToken, current->GetSpan(), {}); + logUnexpectedTokenWithoutExpected(current); return false; } EXPECT_TOKEN(current, CatchKeyword); ScopedPtr catchStatement = nullptr; if (!ParseStatBlock(catchStatement, current, log)) { - logError(DiagnosticType::UnexpectedToken, current->GetSpan(), {}); + logUnexpectedTokenWithoutExpected(current); return false; } @@ -1059,7 +1073,7 @@ namespace MalachScript::Parser { EXPECT_TOKEN(currentToken, OpenParenthesisSymbol); ScopedPtr expression = nullptr; if (!ParseExpr(expression, current, log)) { - logError(DiagnosticType::UnexpectedToken, current->GetSpan(), {}); + logUnexpectedTokenWithoutExpected(current); return false; } EXPECT_TOKEN(currentToken, CloseParenthesisSymbol); @@ -1080,7 +1094,7 @@ namespace MalachScript::Parser { } caseStatements.push_back(stat.TakeOwnership()); } else { - logError(DiagnosticType::UnexpectedToken, current->GetSpan(), {}); + logUnexpectedToken(CaseKeyword, current); return false; } } @@ -1106,7 +1120,7 @@ namespace MalachScript::Parser { ScopedPtr expression = nullptr; if (!isDefault) { if (!ParseExpr(expression, current, log)) { - logError(DiagnosticType::UnexpectedToken, current->GetSpan(), {}); + logUnexpectedTokenWithoutExpected(current); return false; } }