diff --git a/core-parser/inc/ast.h b/core-parser/inc/ast.h index 2041290..2b9db07 100644 --- a/core-parser/inc/ast.h +++ b/core-parser/inc/ast.h @@ -115,7 +115,7 @@ pac_ast_status_e pac_ast_handle_invalid_reference_name_token pac_ast_status_e pac_ast_handle_missing_reference_close_tag (pac_ast_builder_s *builder); pac_ast_status_e pac_ast_handle_missing_rule_header_closing_sign (pac_ast_builder_s *builder); pac_ast_status_e pac_ast_handle_reference_with_equals_sign (pac_ast_builder_s *builder); -pac_ast_status_e pac_ast_handle_missing_item_delimiter (pac_ast_builder_s *builder, char *rule_name, usz_t variant_index, usz_t item_index); +pac_ast_status_e pac_ast_handle_missing_item_separator (pac_ast_builder_s *builder, char *rule_name, usz_t variant_index, usz_t item_index); pac_ast_status_e pac_ast_handle_missing_equals_sign_after_rule_header (pac_ast_builder_s *builder); pac_ast_status_e pac_ast_handle_unknown_item_type (pac_ast_builder_s *builder, char *rule_name, usz_t variant_index, usz_t item_index); diff --git a/core-parser/inc/logger.h b/core-parser/inc/logger.h index a04f395..0f251d8 100644 --- a/core-parser/inc/logger.h +++ b/core-parser/inc/logger.h @@ -6,6 +6,7 @@ typedef enum { + PAC_UNKNOWN_ERROR_TYPE = 0, PAC_SYNTAX_ERROR, PAC_NAMING_ERROR, PAC_VALIDATION_ERROR, @@ -20,7 +21,8 @@ typedef enum PAC_SYNTAX_ERROR_MISSING_TOKEN, PAC_SYNTAX_ERROR_ODD_TOKEN, - PAC_SYNTAX_ERROR_INVALID_ITEM + PAC_SYNTAX_ERROR_INVALID_ITEM, + PAC_SYNTAX_ERROR_MISSING_ITEM_SEPARATOR } pac_syntax_error_e; @@ -216,6 +218,8 @@ typedef struct pac_logger pac_logger_s pac_create_logger (); void pac_delete_logger (pac_logger_s logger); +void pac_display_log (pac_logger_s *logger); + void pac_log_syntax_error (pac_logger_s *logger, pac_syntax_error_s error); void pac_log_naming_error (pac_logger_s *logger, pac_naming_error_s error); void pac_log_validation_error (pac_logger_s *logger, pac_validation_error_s error); diff --git a/core-parser/inc/parcel.h b/core-parser/inc/parcel.h index 6d289ed..ea55489 100644 --- a/core-parser/inc/parcel.h +++ b/core-parser/inc/parcel.h @@ -82,7 +82,7 @@ struct pac_grammar pac_grammar_s pac_convert_grammar (char *source, usz_t len_source); void pac_delete_grammar (pac_grammar_s grammar); -void pac_display_log (pac_grammar_s grammar); +void pac_display_log (pac_logger_s *logger); void pac_display_grammar (pac_grammar_s grammar); #endif // PARCEL_H diff --git a/core-parser/src/ast.c b/core-parser/src/ast.c index 6f345a5..4e0eab5 100644 --- a/core-parser/src/ast.c +++ b/core-parser/src/ast.c @@ -134,12 +134,12 @@ pac_ast_status_e pac_build_ast_variant(pac_ast_builder_s *builder, pac_ast_varia return PAC_AST_STATUS_SUCCESS; } - // Test if there is no delimiter and, if three is none, handle the error. + // Test if there is no separator and, if there is none, handle the error. if( (CURRENT_TOKEN.type != PAC_TOKEN_SIGN_COMMA) && (CURRENT_TOKEN.type != PAC_TOKEN_SIGN_HYPHEN) ) { - status = pac_ast_handle_missing_item_delimiter(builder, rule_name, variant_index, variant->num_items); + status = pac_ast_handle_missing_item_separator(builder, rule_name, variant_index, variant->num_items); if(status != PAC_AST_STATUS_ERROR_HANDLED) return status; continue; } @@ -228,10 +228,13 @@ pac_ast_status_e pac_build_ast_rule(pac_ast_builder_s *builder, pac_ast_rule_s * break; case PAC_AST_STATUS_NOT_RECOVERABLE: - case PAC_AST_STATUS_CONTINUE_AFTER_FINDING_NEXT_RULE: case PAC_AST_STATUS_UNEXPECTED_FILE_END: + free(rule->name); return status; + case PAC_AST_STATUS_CONTINUE_AFTER_FINDING_NEXT_RULE: + return PAC_AST_STATUS_CONTINUE_AFTER_FINDING_NEXT_RULE; + case PAC_AST_STATUS_STOP_ESCALATING_IN_RULE_PARSER: { while(!END_REACHED) @@ -246,7 +249,7 @@ pac_ast_status_e pac_build_ast_rule(pac_ast_builder_s *builder, pac_ast_rule_s * SKIP_TOKEN; } - } return PAC_AST_STATUS_UNEXPECTED_FILE_END; + } break; default: pac_internal_error_s error; @@ -256,9 +259,9 @@ pac_ast_status_e pac_build_ast_rule(pac_ast_builder_s *builder, pac_ast_rule_s * error.specifics.invalid_returned_status.value = pac_ast_stringify_status(status); pac_log_internal_error(builder->logger, error); + free(rule->name); return PAC_AST_STATUS_NOT_RECOVERABLE; } - // It only goes here in the case of PAC_AST_STATUS_SUCCESS if(CURRENT_TOKEN.type == PAC_TOKEN_SIGN_SEMICOLON) { @@ -268,10 +271,12 @@ pac_ast_status_e pac_build_ast_rule(pac_ast_builder_s *builder, pac_ast_rule_s * if(CURRENT_TOKEN.type != PAC_TOKEN_SIGN_VERTICAL_BAR) { + free(rule->name); return PAC_AST_STATUS_NOT_RECOVERABLE; } SKIP_TOKEN; } + free(rule->name); return PAC_AST_STATUS_UNEXPECTED_FILE_END; } @@ -314,8 +319,10 @@ pac_ast_s pac_build_ast(pac_tlist_s tokens, pac_logger_s *logger) pac_ast_status_e status = pac_build_ast_rule(&builder, &ast.rules[ast.num_rules]); if(status == PAC_AST_STATUS_CONTINUE_AFTER_FINDING_NEXT_RULE) + { + ++ast.num_rules; pac_ast_skip_to_next_rule(&builder); - + } if(status == PAC_AST_STATUS_UNEXPECTED_FILE_END) break; diff --git a/core-parser/src/ast_errors.c b/core-parser/src/ast_errors.c index ede87e8..9edaf01 100644 --- a/core-parser/src/ast_errors.c +++ b/core-parser/src/ast_errors.c @@ -92,14 +92,14 @@ pac_ast_status_e pac_ast_handle_invalid_reference_name_token(pac_ast_builder_s * { len_reference_name = ((CURRENT_TOKEN.offset + CURRENT_TOKEN.length) - open_tag_src_offset); } - char *given_rule_name = pac_log_alloc(&builder->logger, len_reference_name + 1); - pac_memory_copy(given_rule_name, &builder->token_list->source[open_tag_src_offset], len_reference_name); + char *given_rule_name = pac_log_alloc(builder->logger, len_reference_name + 1); + pac_memory_copy(given_rule_name, builder->token_list->source[open_tag_src_offset], len_reference_name); pac_naming_error_s error; error.type = PAC_NAMING_ERROR_INVALID_REFERENCE_NAME; error.line = CURRENT_TOKEN.line; error.column = CURRENT_TOKEN.column; error.specifics.invalid_rule_name.given_rule_name = given_rule_name; - pac_log_naming_error(&builder->logger, error); + pac_log_naming_error(builder->logger, error); builder->failed = TRUE; @@ -120,7 +120,7 @@ pac_ast_status_e pac_ast_handle_missing_reference_close_tag(pac_ast_builder_s *b error.location.column = CURRENT_TOKEN.column; error.specifics.missing_token.hint = NULL; error.specifics.missing_token.wanted_token = "Tag Closer (>)"; - pac_log_syntax_error(&builder->logger, error); + pac_log_syntax_error(builder->logger, error); return PAC_AST_STATUS_STOP_ESCALATING_IN_VARIANT_PARSER; } @@ -134,26 +134,26 @@ pac_ast_status_e pac_ast_handle_reference_with_equals_sign(pac_ast_builder_s *bu error.specifics.odd_token.hint = "There might be a semicolon missing 4 tokens ago."; error.specifics.odd_token.num_valid_options = 1; error.specifics.odd_token.valid_options[0] = "Any Rule Item"; - pac_log_syntax_error(&builder->logger, error); + pac_log_syntax_error(builder->logger, error); builder->failed = TRUE; return PAC_AST_STATUS_STOP_ESCALATING_IN_RULE_PARSER; } -pac_ast_status_e pac_ast_handle_missing_item_delimiter(pac_ast_builder_s *builder, char *rule_name, usz_t variant_index, usz_t item_index) +pac_ast_status_e pac_ast_handle_missing_item_separator(pac_ast_builder_s *builder, char *rule_name, usz_t variant_index, usz_t item_index) { builder->failed = TRUE; pac_syntax_error_s error; - error.type = PAC_SYNTAX_ERROR_ODD_TOKEN; + error.type = PAC_SYNTAX_ERROR_MISSING_ITEM_SEPARATOR; error.location.line = CURRENT_TOKEN.line; error.location.column = CURRENT_TOKEN.column; error.specifics.odd_token.present_token = pac_stringify_token_type(CURRENT_TOKEN.type); error.specifics.odd_token.num_valid_options = 2; error.specifics.odd_token.valid_options[0] = pac_stringify_token_type(PAC_TOKEN_SIGN_COMMA); error.specifics.odd_token.valid_options[1] = pac_stringify_token_type(PAC_TOKEN_SIGN_HYPHEN); - pac_log_syntax_error(&builder->logger, error); + pac_log_syntax_error(builder->logger, error); return PAC_AST_STATUS_ERROR_HANDLED; } @@ -174,12 +174,12 @@ pac_ast_status_e pac_ast_handle_missing_equals_sign_after_rule_header(pac_ast_bu if(!pac_ast_builder_forward_seek_item_start(builder, 2)) { error.specifics.odd_token.hint = "Missing equals sign after rule header. Continuing at next rule."; - pac_log_syntax_error(&builder->logger, error); + pac_log_syntax_error(builder->logger, error); return PAC_AST_STATUS_CONTINUE_AFTER_FINDING_NEXT_RULE; } error.specifics.odd_token.hint = "Missing equals sign after rule header. Continuing at next item."; - pac_log_syntax_error(&builder->logger, error); + pac_log_syntax_error(builder->logger, error); return PAC_AST_STATUS_ERROR_HANDLED; } @@ -199,12 +199,12 @@ pac_ast_status_e pac_ast_handle_invalid_rule_name(pac_ast_builder_s *builder) if(!pac_ast_builder_forward_seek_token_type(builder, PAC_TOKEN_SIGN_EQUALS, 3)) { error.specifics.odd_token.hint = "Invalid rule name. Continuing at next rule due to missing equals sign."; - pac_log_syntax_error(&builder->logger, error); + pac_log_syntax_error(builder->logger, error); return PAC_AST_STATUS_CONTINUE_AFTER_FINDING_NEXT_RULE; } error.specifics.odd_token.hint = "Invalid rule name. Continuing after the equals sign."; - pac_log_syntax_error(&builder->logger, error); + pac_log_syntax_error(builder->logger, error); return PAC_AST_STATUS_ERROR_HANDLED; } diff --git a/core-parser/src/linker.c b/core-parser/src/linker.c index 5f47c92..8bfaa5f 100644 --- a/core-parser/src/linker.c +++ b/core-parser/src/linker.c @@ -103,6 +103,4 @@ void pac_link_grammar(pac_grammar_s *grammar, pac_ast_s ast) pac_copy_empty_rules_from_ast_to_grammar(grammar, &ast); pac_copy_variants_and_link_references(grammar, &ast); - - return grammar; } diff --git a/core-parser/src/logger.c b/core-parser/src/logger.c index bb4c609..03444e4 100644 --- a/core-parser/src/logger.c +++ b/core-parser/src/logger.c @@ -1,6 +1,7 @@ #include #include +#include pac_logger_s pac_create_logger() { @@ -19,6 +20,113 @@ void pac_delete_logger(pac_logger_s logger) pac_delete_arena(logger.string_arena); } + + +void pac_display_syntax_error_stray(pac_logger_s *logger, pac_syntax_error_s *error) +{ + printf(">> [SYNTAX ERROR] @ %-2lu:%-3lu in '%s': Stray Sign\n", error->location.line, error->location.column, error->location.file); + printf(" | Found a sign character not known to Parcel: '%c'!\n", error->specifics.stray.sign); +} + +void pac_display_syntax_error_missing_token(pac_logger_s *logger, pac_syntax_error_s *error) +{ + printf(">> [SYNTAX ERROR] @ %-2lu:%-3lu in '%s': Missing a Token\n", error->location.line, error->location.column, error->location.file); + printf(" | Couldn't find %s where it should have been.\n", error->specifics.missing_token.wanted_token); +} + +void pac_display_syntax_error_odd_token(pac_logger_s *logger, pac_syntax_error_s *error) +{ + printf(">> [SYNTAX ERROR] @ %-2lu:%-3lu in '%s': Odd Token\n", error->location.line, error->location.column, error->location.file); + printf(" | Misplaced token '%s', wanted one of:\n", error->specifics.odd_token.present_token); + for(usz_t index = 0; index < error->specifics.odd_token.num_valid_options; ++index) + printf(" | %-2d: %s\n", index, error->specifics.odd_token.valid_options[index]); +} + +void pac_display_syntax_error_invalid_item(pac_logger_s *logger, pac_syntax_error_s *error) +{ + printf(">> [SYNTAX ERROR] @ %-2lu:%-3lu in '%s': Invalid Item Type\n", error->location.line, error->location.column, error->location.file); + // TODO +} + +void pac_display_syntax_error_missing_item_separator(pac_logger_s *logger, pac_syntax_error_s *error) +{ + printf(">> [SYNTAX ERROR] @ %-2lu:%-3lu in '%s': Missing Item Separator\n", error->location.line, error->location.column, error->location.file); + printf(" | There must be one of [ ',' | '-' ] between all items. "); +} + +void pac_display_syntax_error(pac_logger_s *logger, pac_syntax_error_s *error) +{ + switch(error->type) + { + case PAC_SYNTAX_ERROR_STRAY: + pac_display_syntax_error_stray(logger, error); + break; + + case PAC_SYNTAX_ERROR_MISSING_TOKEN: + pac_display_syntax_error_missing_token(logger, error); + break; + + case PAC_SYNTAX_ERROR_ODD_TOKEN: + pac_display_syntax_error_odd_token(logger, error); + break; + + case PAC_SYNTAX_ERROR_INVALID_ITEM: + pac_display_syntax_error_invalid_item(logger, error); + break; + + case PAC_SYNTAX_ERROR_MISSING_ITEM_SEPARATOR: + pac_display_syntax_error_missing_item_separator(logger, error); + break; + } +} + +void pac_display_naming_error(pac_logger_s *logger, pac_naming_error_s *error) +{ + +} + +void pac_display_validation_error(pac_logger_s *logger, pac_validation_error_s *error) +{ + +} + +void pac_display_internal_error(pac_logger_s *logger, pac_internal_error_s *error) +{ + +} + +void pac_display_error(pac_logger_s *logger, pac_error_s *error) +{ + switch(error->type) + { + case PAC_SYNTAX_ERROR: + pac_display_syntax_error(logger, &error->specifics.syntax_error); + break; + + case PAC_NAMING_ERROR: + pac_display_naming_error(logger, &error->specifics.naming_error); + break; + + case PAC_VALIDATION_ERROR: + pac_display_validation_error(logger, &error->specifics.validation_error); + break; + + case PAC_INTERNAL_ERROR: + pac_display_internal_error(logger, &error->specifics.internal_error); + break; + } +} + +void pac_display_log(pac_logger_s *logger) +{ + for(usz_t error_index = 0; logger->num_errors; ++error_index) + { + pac_display_error(logger, &logger->errors[error_index]); + } +} + + + void pac_resize_log_if_needed(pac_logger_s *logger) { if(logger->num_errors >= logger->allocated_errors) @@ -32,7 +140,7 @@ void pac_resize_log_if_needed(pac_logger_s *logger) void pac_log_syntax_error(pac_logger_s *logger, pac_syntax_error_s error) { pac_resize_log_if_needed(logger); - logger->errors[logger->num_errors].type = PAC_SYNTAX_ERROR; + logger->errors[logger->num_errors].type = PAC_SYNTAX_ERROR; logger->errors[logger->num_errors].specifics.syntax_error = error; ++logger->num_errors; } diff --git a/samples/sample_ast_02.parcel b/samples/sample_ast_02.parcel new file mode 100644 index 0000000..698e65e --- /dev/null +++ b/samples/sample_ast_02.parcel @@ -0,0 +1,6 @@ + +## Sample for testing if the AST parser can handle errors. + +# There's an item separator missing after . + = "{", "test", | ; + = "}"