diff --git a/src/lexer/lexer.cpp b/src/lexer/lexer.cpp index 4622411..5b568e4 100644 --- a/src/lexer/lexer.cpp +++ b/src/lexer/lexer.cpp @@ -68,7 +68,13 @@ const std::vector Lexer::makeTokens() { } else if (currentChar == ']') { tokens.emplace_back(new Token(TokenType::RSQRBRACKET, line, column)); } else if (currentChar == '=') { - tokens.emplace_back(new Token(TokenType::EQUALS, line, column)); + advance(); + if (idx >= expr->size() || currentChar != '=') { + tokens.emplace_back(new Token(TokenType::EQUALS, line, column)); + continue; + } else { + throw PSC::LexerError(line, column - 1, "Invalid token '=='\nIf you want to check for equality, use single '=' instead"); + } } else if (currentChar == ':') { tokens.emplace_back(new Token(TokenType::COLON, line, column)); } else if (currentChar == ',') { diff --git a/src/nodes/functions/function.cpp b/src/nodes/functions/function.cpp index 3fb5efe..15ed111 100644 --- a/src/nodes/functions/function.cpp +++ b/src/nodes/functions/function.cpp @@ -30,7 +30,7 @@ std::unique_ptr FunctionNode::evaluate(PSC::Context &ctx) { PSC::DataType returnDataType = ctx.getType(returnType); if (returnDataType == PSC::DataType::NONE) - throw PSC::NotDefinedError(returnType, ctx, "Type '" + returnType.value + "'"); + throw PSC::TypeNotDefinedError(returnType, ctx, returnType.value); size_t parametersSize = parameterNames.size(); std::vector parameters; @@ -39,7 +39,7 @@ std::unique_ptr FunctionNode::evaluate(PSC::Context &ctx) { const Token *typeToken = parameterTypes[i]; PSC::DataType type = ctx.getType(*typeToken); if (type == PSC::DataType::NONE) - throw PSC::NotDefinedError(*typeToken, ctx, "Type '" + typeToken->value + "'"); + throw PSC::TypeNotDefinedError(*typeToken, ctx, typeToken->value); parameters.emplace_back(parameterNames[i], type, parameterPassTypes[i]); } diff --git a/src/nodes/functions/procedure.cpp b/src/nodes/functions/procedure.cpp index f1b4b18..e84dc65 100644 --- a/src/nodes/functions/procedure.cpp +++ b/src/nodes/functions/procedure.cpp @@ -33,7 +33,7 @@ std::unique_ptr ProcedureNode::evaluate(PSC::Context &ctx) { const Token *typeToken = parameterTypes[i]; PSC::DataType type = ctx.getType(*typeToken); if (type == PSC::DataType::NONE) - throw PSC::NotDefinedError(*typeToken, ctx, "Type '" + typeToken->value + "'"); + throw PSC::TypeNotDefinedError(*typeToken, ctx, typeToken->value); parameters.emplace_back(parameterNames[i], type, parameterPassTypes[i]); } diff --git a/src/nodes/variable/array.cpp b/src/nodes/variable/array.cpp index 51d3c60..8a6cce5 100644 --- a/src/nodes/variable/array.cpp +++ b/src/nodes/variable/array.cpp @@ -42,7 +42,7 @@ std::unique_ptr ArrayDeclareNode::evaluate(PSC::Context &ctx) { for (auto identifier : identifiers) { PSC::DataType dataType = ctx.getType(type); if (dataType.type == PSC::DataType::NONE) - throw PSC::NotDefinedError(token, ctx, "Type '" + type.value + "'"); + throw PSC::TypeNotDefinedError(token, ctx, type.value); auto array = std::make_unique(identifier->value, dataType, dimensions); array->init(ctx); diff --git a/src/nodes/variable/pointer.cpp b/src/nodes/variable/pointer.cpp index 93e51d6..10a1694 100644 --- a/src/nodes/variable/pointer.cpp +++ b/src/nodes/variable/pointer.cpp @@ -10,7 +10,7 @@ PointerDefineNode::PointerDefineNode(const Token &token, const Token &name, cons std::unique_ptr PointerDefineNode::evaluate(PSC::Context &ctx) { PSC::DataType pointerType = ctx.getType(type); if (pointerType == PSC::DataType::NONE) - throw PSC::NotDefinedError(token, ctx, "Type '" + type.value + "'"); + throw PSC::TypeNotDefinedError(token, ctx, type.value); if (ctx.isIdentifierType(name, false)) throw PSC::RedefinitionError(token, ctx, name.value); diff --git a/src/nodes/variable/variable.cpp b/src/nodes/variable/variable.cpp index e5f8e58..b287444 100644 --- a/src/nodes/variable/variable.cpp +++ b/src/nodes/variable/variable.cpp @@ -19,7 +19,7 @@ std::unique_ptr DeclareNode::evaluate(PSC::Context &ctx) { PSC::DataType dataType = ctx.getType(type); if (dataType == PSC::DataType::NONE) - throw PSC::NotDefinedError(token, ctx, "Type '" + type.value + "'"); + throw PSC::TypeNotDefinedError(token, ctx, type.value); ctx.addVariable(new PSC::Variable(identifier->value, dataType, false, &ctx)); } diff --git a/src/psc/error.cpp b/src/psc/error.cpp index ed00127..acdb67d 100644 --- a/src/psc/error.cpp +++ b/src/psc/error.cpp @@ -107,8 +107,29 @@ ConstAssignError::ConstAssignError(const Token &token, const Context &context, c : RuntimeError(token, context, "Assignment to constant '" + constant + "'") {} -NotDefinedError::NotDefinedError(const Token &token, const Context &context, const std::string &identifier) - : RuntimeError(token, context, identifier + " is not defined") +NotDefinedError::NotDefinedError(const Token &token, const Context &context, const std::string &identifier, const std::string &hint) + : RuntimeError(token, context, identifier + " is not defined" + hint) +{} + +inline std::string getTypeHint(const std::string &s) { + std::string hint = ""; + + if (s == "INT") + hint = "\nDid you mean 'INTEGER'?"; + else if (s == "FLOAT") + hint = "\nDid you mean 'REAL'?"; + else if (s == "CHARACTER") + hint = "\nDid you mean 'CHAR'?"; + else if (s == "BOOL") + hint = "\nDid you mean 'BOOLEAN'?"; + else if (s == "STR") + hint = "\nDid you mean 'STRING'?"; + + return hint; +} + +TypeNotDefinedError::TypeNotDefinedError(const Token &token, const Context &context, const std::string &type) + : NotDefinedError(token, context, "Type '" + type + "'", getTypeHint(type)) {} ArrayDirectAccessError::ArrayDirectAccessError(const Token &token, const Context &context) diff --git a/src/psc/error.h b/src/psc/error.h index 23d3bef..115c821 100644 --- a/src/psc/error.h +++ b/src/psc/error.h @@ -97,7 +97,12 @@ namespace PSC { class NotDefinedError : public RuntimeError { public: - NotDefinedError(const Token &token, const Context &context, const std::string &identifier); + NotDefinedError(const Token &token, const Context &context, const std::string &identifier, const std::string &hint = ""); + }; + + class TypeNotDefinedError : public NotDefinedError { + public: + TypeNotDefinedError(const Token &token, const Context &context, const std::string &type); }; class ArrayDirectAccessError : public RuntimeError {