From 1af27136faac16ff9f9d48519c6d3ccde7f4e5df Mon Sep 17 00:00:00 2001 From: Christoffer Lerno Date: Sat, 17 Jul 2021 15:20:13 +0200 Subject: [PATCH] Improved error messages on incorrect module name. Issue #209 --- src/compiler/parse_global.c | 22 ++++++++++++++++++- src/compiler/parser_internal.h | 21 +++++++++++++++++- .../module/module_bad_path_ident.c3 | 1 + .../module/module_bad_path_invalid.c3 | 1 + .../module/module_bad_path_keyword.c3 | 1 + .../module/module_start_bad_ident.c3 | 1 + .../test_suite/module/module_start_invalid.c3 | 1 + .../test_suite/module/module_start_keyword.c3 | 1 + 8 files changed, 47 insertions(+), 2 deletions(-) create mode 100644 test/test_suite/module/module_bad_path_ident.c3 create mode 100644 test/test_suite/module/module_bad_path_invalid.c3 create mode 100644 test/test_suite/module/module_bad_path_keyword.c3 create mode 100644 test/test_suite/module/module_start_bad_ident.c3 create mode 100644 test/test_suite/module/module_start_invalid.c3 create mode 100644 test/test_suite/module/module_start_keyword.c3 diff --git a/src/compiler/parse_global.c b/src/compiler/parse_global.c index 4ffaf7651..b09fc14a2 100644 --- a/src/compiler/parse_global.c +++ b/src/compiler/parse_global.c @@ -241,6 +241,16 @@ static inline Path *parse_module_path(Context *context) const char *string = TOKSTR(context->tok); if (!try_consume(context, TOKEN_IDENT)) { + if (token_is_keyword(context->tok.type)) + { + SEMA_TOKEN_ERROR(context->tok, "The module path cannot contain a reserved keyword, try another name."); + return false; + } + if (token_is_some_ident(context->tok.type)) + { + SEMA_TOKEN_ERROR(context->tok, "The elements of a module path must consist of only lower case letters, 0-9 and '_'."); + return false; + } SEMA_TOKEN_ERROR(context->tok, "Each '::' must be followed by a regular lower case sub module name."); return NULL; } @@ -338,7 +348,17 @@ bool parse_module(Context *context) if (!TOKEN_IS(TOKEN_IDENT)) { - SEMA_TOKEN_ERROR(context->tok, "Module statement should be followed by the name of the module."); + if (token_is_keyword(context->tok.type)) + { + SEMA_TOKEN_ERROR(context->tok, "The module name cannot contain a reserved keyword, try another name."); + return false; + } + if (token_is_some_ident(context->tok.type)) + { + SEMA_TOKEN_ERROR(context->tok, "The module name must consist of only lower case letters, 0-9 and '_'."); + return false; + } + SEMA_TOKEN_ERROR(context->tok, "'module' should be followed by a module name."); return false; } diff --git a/src/compiler/parser_internal.h b/src/compiler/parser_internal.h index fa14583e6..2ac32b4f9 100644 --- a/src/compiler/parser_internal.h +++ b/src/compiler/parser_internal.h @@ -19,7 +19,6 @@ #define CHECK_EXPR(_expr) do { if (!expr_ok(_expr)) return _expr; } while(0) - #define COMMA_RPAREN_OR(_res) \ do { if (!try_consume(context, TOKEN_COMMA) && !TOKEN_IS(TOKEN_RPAREN)) { \ SEMA_TOKEN_ERROR(context->tok, "Expected ',' or ')'"); return _res; } } while(0) @@ -80,6 +79,26 @@ static inline bool expect(Context *context, TokenType token_type) return false; } +static inline bool token_is_some_ident(TokenType token_type) +{ + switch (token_type) + { + case TOKEN_TYPE_IDENT: + case TOKEN_IDENT: + case TOKEN_CONST_IDENT: + return true; + default: + return false; + } +} + +static inline bool token_is_keyword(TokenType token_type) +{ + if (token_type >= TOKEN_VOID && token_type <= TOKEN_TYPEID) return true; + if (token_type >= TOKEN_ALIAS && token_type <= TOKEN_WHILE) return true; + return false; +} + static inline bool expect_ident(Context *context, const char* name) { switch (context->tok.type) diff --git a/test/test_suite/module/module_bad_path_ident.c3 b/test/test_suite/module/module_bad_path_ident.c3 new file mode 100644 index 000000000..3897c998c --- /dev/null +++ b/test/test_suite/module/module_bad_path_ident.c3 @@ -0,0 +1 @@ +module big::MONEY; // #error: The elements of a module path must consist of only lower \ No newline at end of file diff --git a/test/test_suite/module/module_bad_path_invalid.c3 b/test/test_suite/module/module_bad_path_invalid.c3 new file mode 100644 index 000000000..1554c001d --- /dev/null +++ b/test/test_suite/module/module_bad_path_invalid.c3 @@ -0,0 +1 @@ +module abc::&&; // #error: Each '::' must be followed by a regular lower case sub module name \ No newline at end of file diff --git a/test/test_suite/module/module_bad_path_keyword.c3 b/test/test_suite/module/module_bad_path_keyword.c3 new file mode 100644 index 000000000..918aa7389 --- /dev/null +++ b/test/test_suite/module/module_bad_path_keyword.c3 @@ -0,0 +1 @@ +module abc::if::while; // #error: The module path cannot contain a reserved keyword, try another name \ No newline at end of file diff --git a/test/test_suite/module/module_start_bad_ident.c3 b/test/test_suite/module/module_start_bad_ident.c3 new file mode 100644 index 000000000..3502724ba --- /dev/null +++ b/test/test_suite/module/module_start_bad_ident.c3 @@ -0,0 +1 @@ +module BIG::MONEY; // #error: The module name must consist of only lower case letters \ No newline at end of file diff --git a/test/test_suite/module/module_start_invalid.c3 b/test/test_suite/module/module_start_invalid.c3 new file mode 100644 index 000000000..1c8e68bb9 --- /dev/null +++ b/test/test_suite/module/module_start_invalid.c3 @@ -0,0 +1 @@ +module &&; // #error: 'module' should be followed by a module name \ No newline at end of file diff --git a/test/test_suite/module/module_start_keyword.c3 b/test/test_suite/module/module_start_keyword.c3 new file mode 100644 index 000000000..84ff3d77c --- /dev/null +++ b/test/test_suite/module/module_start_keyword.c3 @@ -0,0 +1 @@ +module if::hello; // #error: The module name cannot contain a reserved keyword \ No newline at end of file