diff options
author | Carlos Maniero <carlosmaniero@gmail.com> | 2023-04-20 13:32:36 -0300 |
---|---|---|
committer | Johnny Richard <johnny@johnnyrichard.com> | 2023-04-20 18:31:55 +0200 |
commit | 3ceb85bd93fa87a5be3682ab8995abea82a63ea3 (patch) | |
tree | 9512c4255bd87967dfd42a8ca68abd18e34e7407 /test | |
parent | a47e5ceb6eefdac9c5f5473e1fee0d33a5f4646e (diff) |
parser: Stop exiting on parser error
Previously, when an error occurred during parsing, the application
would exit, making it difficult to test the parser and limiting the
compiler's extensibility. This commit improves the parser's error
handling by allowing for continued execution after an error, enabling
easier testing and increased flexibility.
The parser is prepared to handle multiples errors, although the
current implementation always returns a single error, it may be
useful given multiples functions where we can show errors by context.
Signed-off-by: Carlos Maniero <carlosmaniero@gmail.com>
Reviwed-by: Johnny Richard <johnny@johnnyrichard.com>
Diffstat (limited to 'test')
-rw-r--r-- | test/parser_test.c | 41 |
1 files changed, 40 insertions, 1 deletions
diff --git a/test/parser_test.c b/test/parser_test.c index 30aa285..d0d36ca 100644 --- a/test/parser_test.c +++ b/test/parser_test.c @@ -23,6 +23,7 @@ void make_lexer_from_static_src(lexer_t *lexer, char *src) { + lexer->filepath = "test.pipa"; lexer->srclen = 0; lexer->cur = 0; lexer->row = 0; @@ -31,6 +32,22 @@ make_lexer_from_static_src(lexer_t *lexer, char *src) lexer->srclen = strlen(src); } +void +assert_parser_error(char* src, char* error_msg) { + parser_t parser; + lexer_t lexer; + + make_lexer_from_static_src(&lexer, src); + parser_init(&parser, &lexer); + + ast_node_t *ast_function = ast_node_new(); + + bool parsed = parser_parse_function_declaration(&parser, ast_function); + assert_false(parsed); + assert_int(1, ==, parser.errors_len); + assert_string_equal(error_msg, parser.errors[0].message); +} + static MunitResult test_parse_function(const MunitParameter params[], void *user_data_or_fixture) @@ -41,7 +58,9 @@ test_parse_function(const MunitParameter params[], make_lexer_from_static_src(&lexer, "main(): i32 { return 42; }"); parser_init(&parser, &lexer); ast_node_t *ast_function = ast_node_new(); - parser_parse_function_declaration(&parser, ast_function); + + bool parsed = parser_parse_function_declaration(&parser, ast_function); + assert_true(parsed); char actual[5]; @@ -59,8 +78,28 @@ test_parse_function(const MunitParameter params[], return MUNIT_OK; } +static MunitResult +test_parse_basic_syntax_errors(const MunitParameter params[], + void *user_data_or_fixture) +{ + assert_parser_error("(): i32 { return 42; }" , "expected 'TOKEN_NAME' but got '('"); + assert_parser_error("main): i32 { return 42; }" , "expected '(' but got ')'"); + assert_parser_error("main(: i32 { return 42; }" , "expected ')' but got ':'"); + assert_parser_error("main() i32 { return 42; }" , "expected ':' but got 'TOKEN_NAME'"); + assert_parser_error("main(): { return 42; }" , "expected 'TOKEN_NAME' but got '{'"); + assert_parser_error("main(): i32 return 42; }" , "expected '{' but got 'TOKEN_NAME'"); + assert_parser_error("main(): i32 { 42; }" , "expected 'TOKEN_NAME' but got 'TOKEN_NUMBER'"); + assert_parser_error("main(): i32 { return; }" , "expected 'TOKEN_NUMBER' but got ';'"); + assert_parser_error("main(): i32 { return 42;" , "expected '}' but got end of file"); + assert_parser_error("main(): beff { return 42; }" , "type 'beff' is not defined"); + assert_parser_error("main(): i32 { oxi 42; }" , "expected 'return' keyword but got 'oxi'"); + + return MUNIT_OK; +} + static MunitTest tests[] = { { "/test_parse_function", test_parse_function, NULL, NULL, MUNIT_TEST_OPTION_NONE, NULL }, + { "/test_parse_basic_syntax_errors", test_parse_basic_syntax_errors, NULL, NULL, MUNIT_TEST_OPTION_NONE, NULL }, { NULL, NULL, NULL, NULL, MUNIT_TEST_OPTION_NONE, NULL } }; |