diff --git a/src/errors.cc b/src/errors.cc index f04b275..67426cc 100644 --- a/src/errors.cc +++ b/src/errors.cc @@ -106,16 +106,17 @@ void assert(bool condition, std::string message, Location loc) std::ostream& operator<<(std::ostream& os, Error const& err) { std::string_view short_description = visit(Overloaded { - [](errors::Expected_Keyword const&) { return "Expected keyword"; }, - [](errors::Failed_Numeric_Parsing const&) { return "Failed to parse a number"; }, - [](errors::Music_Literal_Used_As_Identifier const&) { return "Music literal in place of identifier"; }, - [](errors::Not_Callable const&) { return "Value not callable"; }, - [](errors::Undefined_Identifier const&) { return "Undefined identifier"; }, - [](errors::Undefined_Operator const&) { return "Undefined operator"; }, - [](errors::Unexpected_Empty_Source const&) { return "Unexpected end of file"; }, - [](errors::Unexpected_Keyword const&) { return "Unexpected keyword"; }, - [](errors::Unrecognized_Character const&) { return "Unrecognized character"; }, - [](errors::internal::Unexpected_Token const&) { return "Unexpected token"; } + [](errors::Expected_Keyword const&) { return "Expected keyword"; }, + [](errors::Failed_Numeric_Parsing const&) { return "Failed to parse a number"; }, + [](errors::Music_Literal_Used_As_Identifier const&) { return "Music literal in place of identifier"; }, + [](errors::Not_Callable const&) { return "Value not callable"; }, + [](errors::Undefined_Identifier const&) { return "Undefined identifier"; }, + [](errors::Undefined_Operator const&) { return "Undefined operator"; }, + [](errors::Unexpected_Empty_Source const&) { return "Unexpected end of file"; }, + [](errors::Unexpected_Keyword const&) { return "Unexpected keyword"; }, + [](errors::Unrecognized_Character const&) { return "Unrecognized character"; }, + [](errors::internal::Unexpected_Token const&) { return "Unexpected token"; }, + [](errors::Expected_Expression_Separator_Before const&) { return "Missing semicolon"; } }, err.details); error_heading(os, err.location, Error_Level::Error, short_description); @@ -148,13 +149,22 @@ std::ostream& operator<<(std::ostream& os, Error const& err) encourage_contact(os); }, - [&os](errors::Expected_Keyword const&) {}, - [&os](errors::Music_Literal_Used_As_Identifier const&) {}, - [&os](errors::Not_Callable const&) {}, - [&os](errors::Undefined_Identifier const&) {}, - [&os](errors::Undefined_Operator const&) {}, - [&os](errors::Unexpected_Keyword const&) {}, - [&os](errors::Unexpected_Empty_Source const&) {} + [&os](errors::Expected_Expression_Separator_Before const& err) { + os << "I failed to parse following code, due to missing semicolon before it!\n"; + + if (err.what == "var") { + os << "\nIf you want to create variable inside expression try wrapping them inside parentheses like this:\n"; + os << " 10 + (var i = 20)\n"; + } + }, + + [&os](errors::Expected_Keyword const&) { unimplemented(); }, + [&os](errors::Music_Literal_Used_As_Identifier const&) { unimplemented(); }, + [&os](errors::Not_Callable const&) { unimplemented(); }, + [&os](errors::Undefined_Identifier const&) { unimplemented(); }, + [&os](errors::Undefined_Operator const&) { unimplemented(); }, + [&os](errors::Unexpected_Keyword const&) { unimplemented(); }, + [&os](errors::Unexpected_Empty_Source const&) { unimplemented(); } }, err.details); return os; diff --git a/src/musique.hh b/src/musique.hh index 09bfb7d..b7b1c44 100644 --- a/src/musique.hh +++ b/src/musique.hh @@ -69,6 +69,11 @@ namespace errors std::string_view received_type = {}; }; + struct Expected_Expression_Separator_Before + { + std::string_view what; + }; + struct Unexpected_Keyword { std::string_view keyword; @@ -109,6 +114,7 @@ namespace errors } using Details = std::variant< + Expected_Expression_Separator_Before, Expected_Keyword, Failed_Numeric_Parsing, Music_Literal_Used_As_Identifier, diff --git a/src/parser.cc b/src/parser.cc index e13fe97..971eb2b 100644 --- a/src/parser.cc +++ b/src/parser.cc @@ -40,6 +40,12 @@ Result Parser::parse(std::string_view source, std::string_view filename) auto const result = parser.parse_sequence(); if (parser.token_id < parser.tokens.size()) { + if (parser.expect(Token::Type::Keyword, "var")) { + return Error { + .details = errors::Expected_Expression_Separator_Before { .what = "var" }, + .location = parser.peek()->location + }; + } errors::all_tokens_were_not_parsed(std::span(parser.tokens).subspan(parser.token_id)); } @@ -54,10 +60,10 @@ Result Parser::parse_sequence() Result Parser::parse_expression() { - auto var = parse_variable_declaration(); - if (!var.has_value()) - return parse_infix_expression(); - return var; + if (expect(Token::Type::Keyword, "var")) { + return parse_variable_declaration(); + } + return parse_infix_expression(); } Result Parser::parse_variable_declaration()