From 3ceb85bd93fa87a5be3682ab8995abea82a63ea3 Mon Sep 17 00:00:00 2001 From: Carlos Maniero Date: Thu, 20 Apr 2023 13:32:36 -0300 Subject: 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 Reviwed-by: Johnny Richard --- test/parser_test.c | 41 ++++++++++++++++++++++++++++++++++++++++- 1 file changed, 40 insertions(+), 1 deletion(-) (limited to 'test') 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 } }; -- cgit v1.2.3