Added new sample and fixed memory bugs found with new sample.

This commit is contained in:
Eric-Paul Ickhorn 2023-11-29 18:27:46 +01:00
parent 3251632dbe
commit 5b4c28a350
8 changed files with 147 additions and 24 deletions

View File

@ -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_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_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_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_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); 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);

View File

@ -6,6 +6,7 @@
typedef enum typedef enum
{ {
PAC_UNKNOWN_ERROR_TYPE = 0,
PAC_SYNTAX_ERROR, PAC_SYNTAX_ERROR,
PAC_NAMING_ERROR, PAC_NAMING_ERROR,
PAC_VALIDATION_ERROR, PAC_VALIDATION_ERROR,
@ -20,7 +21,8 @@ typedef enum
PAC_SYNTAX_ERROR_MISSING_TOKEN, PAC_SYNTAX_ERROR_MISSING_TOKEN,
PAC_SYNTAX_ERROR_ODD_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; } pac_syntax_error_e;
@ -216,6 +218,8 @@ typedef struct pac_logger
pac_logger_s pac_create_logger (); pac_logger_s pac_create_logger ();
void pac_delete_logger (pac_logger_s 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_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_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); void pac_log_validation_error (pac_logger_s *logger, pac_validation_error_s error);

View File

@ -82,7 +82,7 @@ struct pac_grammar
pac_grammar_s pac_convert_grammar (char *source, usz_t len_source); pac_grammar_s pac_convert_grammar (char *source, usz_t len_source);
void pac_delete_grammar (pac_grammar_s grammar); 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); void pac_display_grammar (pac_grammar_s grammar);
#endif // PARCEL_H #endif // PARCEL_H

View File

@ -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; 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( if(
(CURRENT_TOKEN.type != PAC_TOKEN_SIGN_COMMA) (CURRENT_TOKEN.type != PAC_TOKEN_SIGN_COMMA)
&& (CURRENT_TOKEN.type != PAC_TOKEN_SIGN_HYPHEN) && (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; if(status != PAC_AST_STATUS_ERROR_HANDLED) return status;
continue; continue;
} }
@ -228,10 +228,13 @@ pac_ast_status_e pac_build_ast_rule(pac_ast_builder_s *builder, pac_ast_rule_s *
break; break;
case PAC_AST_STATUS_NOT_RECOVERABLE: case PAC_AST_STATUS_NOT_RECOVERABLE:
case PAC_AST_STATUS_CONTINUE_AFTER_FINDING_NEXT_RULE:
case PAC_AST_STATUS_UNEXPECTED_FILE_END: case PAC_AST_STATUS_UNEXPECTED_FILE_END:
free(rule->name);
return status; 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: case PAC_AST_STATUS_STOP_ESCALATING_IN_RULE_PARSER:
{ {
while(!END_REACHED) 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; SKIP_TOKEN;
} }
} return PAC_AST_STATUS_UNEXPECTED_FILE_END; } break;
default: default:
pac_internal_error_s error; 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); error.specifics.invalid_returned_status.value = pac_ast_stringify_status(status);
pac_log_internal_error(builder->logger, error); pac_log_internal_error(builder->logger, error);
free(rule->name);
return PAC_AST_STATUS_NOT_RECOVERABLE; 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) 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) if(CURRENT_TOKEN.type != PAC_TOKEN_SIGN_VERTICAL_BAR)
{ {
free(rule->name);
return PAC_AST_STATUS_NOT_RECOVERABLE; return PAC_AST_STATUS_NOT_RECOVERABLE;
} }
SKIP_TOKEN; SKIP_TOKEN;
} }
free(rule->name);
return PAC_AST_STATUS_UNEXPECTED_FILE_END; 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]); 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) if(status == PAC_AST_STATUS_CONTINUE_AFTER_FINDING_NEXT_RULE)
{
++ast.num_rules;
pac_ast_skip_to_next_rule(&builder); pac_ast_skip_to_next_rule(&builder);
}
if(status == PAC_AST_STATUS_UNEXPECTED_FILE_END) if(status == PAC_AST_STATUS_UNEXPECTED_FILE_END)
break; break;

View File

@ -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); 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); 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_memory_copy(given_rule_name, builder->token_list->source[open_tag_src_offset], len_reference_name);
pac_naming_error_s error; pac_naming_error_s error;
error.type = PAC_NAMING_ERROR_INVALID_REFERENCE_NAME; error.type = PAC_NAMING_ERROR_INVALID_REFERENCE_NAME;
error.line = CURRENT_TOKEN.line; error.line = CURRENT_TOKEN.line;
error.column = CURRENT_TOKEN.column; error.column = CURRENT_TOKEN.column;
error.specifics.invalid_rule_name.given_rule_name = given_rule_name; 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; 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.location.column = CURRENT_TOKEN.column;
error.specifics.missing_token.hint = NULL; error.specifics.missing_token.hint = NULL;
error.specifics.missing_token.wanted_token = "Tag Closer (>)"; 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; 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.hint = "There might be a semicolon missing 4 tokens ago.";
error.specifics.odd_token.num_valid_options = 1; error.specifics.odd_token.num_valid_options = 1;
error.specifics.odd_token.valid_options[0] = "Any Rule Item"; 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; builder->failed = TRUE;
return PAC_AST_STATUS_STOP_ESCALATING_IN_RULE_PARSER; 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; builder->failed = TRUE;
pac_syntax_error_s error; 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.line = CURRENT_TOKEN.line;
error.location.column = CURRENT_TOKEN.column; error.location.column = CURRENT_TOKEN.column;
error.specifics.odd_token.present_token = pac_stringify_token_type(CURRENT_TOKEN.type); 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.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[0] = pac_stringify_token_type(PAC_TOKEN_SIGN_COMMA);
error.specifics.odd_token.valid_options[1] = pac_stringify_token_type(PAC_TOKEN_SIGN_HYPHEN); 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; 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)) 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."; 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; return PAC_AST_STATUS_CONTINUE_AFTER_FINDING_NEXT_RULE;
} }
error.specifics.odd_token.hint = "Missing equals sign after rule header. Continuing at next item."; 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; 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)) 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."; 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; return PAC_AST_STATUS_CONTINUE_AFTER_FINDING_NEXT_RULE;
} }
error.specifics.odd_token.hint = "Invalid rule name. Continuing after the equals sign."; 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; return PAC_AST_STATUS_ERROR_HANDLED;
} }

View File

@ -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_empty_rules_from_ast_to_grammar(grammar, &ast);
pac_copy_variants_and_link_references(grammar, &ast); pac_copy_variants_and_link_references(grammar, &ast);
return grammar;
} }

View File

@ -1,6 +1,7 @@
#include <logger.h> #include <logger.h>
#include <stdlib.h> #include <stdlib.h>
#include <stdio.h>
pac_logger_s pac_create_logger() pac_logger_s pac_create_logger()
{ {
@ -19,6 +20,113 @@ void pac_delete_logger(pac_logger_s logger)
pac_delete_arena(logger.string_arena); 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) void pac_resize_log_if_needed(pac_logger_s *logger)
{ {
if(logger->num_errors >= logger->allocated_errors) 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) void pac_log_syntax_error(pac_logger_s *logger, pac_syntax_error_s error)
{ {
pac_resize_log_if_needed(logger); 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->errors[logger->num_errors].specifics.syntax_error = error;
++logger->num_errors; ++logger->num_errors;
} }

View File

@ -0,0 +1,6 @@
## Sample for testing if the AST parser can handle errors.
# There's an item separator missing after <string>.
<root> = "{", <string> "test", <leaf> | <leaf>;
<leaf> = "}"