Skip to content

Commit

Permalink
Detect and report some allocation errors.
Browse files Browse the repository at this point in the history
See #45.
  • Loading branch information
ianh committed Jan 8, 2025
1 parent dba6335 commit ae33e64
Show file tree
Hide file tree
Showing 3 changed files with 18 additions and 1 deletion.
1 change: 1 addition & 0 deletions doc/generated-parser.md
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,7 @@ There are a few kinds of errors that can happen while creating a tree (see the t
| `ERROR_INVALID_TOKEN` | Part of the text didn't match any valid token. | A range that begins with the first unrecognized character. |
| `ERROR_UNEXPECTED_TOKEN` | The parser encountered an out-of-place token that didn't fit the grammar. | The range of the unexpected token. |
| `ERROR_MORE_INPUT_NEEDED` | The input is valid so far, but incomplete; more tokens are necessary to complete it. | A range positioned at the end of the input. |
| `ERROR_ALLOCATION_FAILURE` | A call to a system allocator returned NULL. Note that not all allocation failures are currently detected. | None. |

To handle the error yourself, you can use `owl_tree_get_error`. The `range` parameter is optional; if you pass a non-null pointer, it will be filled with a byte range as described in the table above.

Expand Down
11 changes: 11 additions & 0 deletions src/6a-generate.c
Original file line number Diff line number Diff line change
Expand Up @@ -282,6 +282,9 @@ void generate(struct generator *gen)
output_line(out, " // The input is valid so far, but incomplete; more tokens could be added to");
output_line(out, " // complete it.");
output_line(out, " ERROR_MORE_INPUT_NEEDED,");
output_line(out, "");
output_line(out, " // A call to a system allocator returned NULL.");
output_line(out, " ERROR_ALLOCATION_FAILURE,");
output_line(out, "};");
output_line(out, "// Returns an error code, or ERROR_NONE if there wasn't an error.");
output_line(out, "// The error_range parameter can be null.");
Expand Down Expand Up @@ -656,6 +659,9 @@ void generate(struct generator *gen)
output_line(out, " case ERROR_MORE_INPUT_NEEDED:");
output_line(out, " fprintf(stderr, \"more input needed\\n\");");
output_line(out, " break;");
output_line(out, " case ERROR_ALLOCATION_FAILURE:");
output_line(out, " fprintf(stderr, \"allocation failure\\n\");");
output_line(out, " break;");
output_line(out, " default:");
output_line(out, " break;");
output_line(out, " }");
Expand Down Expand Up @@ -1176,6 +1182,11 @@ void generate(struct generator *gen)
output_line(out, " }");
output_line(out, " struct fill_run_state top = c.stack[c.top_index];");
output_line(out, " free(c.stack);");
output_line(out, " if (tokenizer.allocation_failed) {");
output_line(out, " tree->error = ERROR_ALLOCATION_FAILURE;");
output_line(out, " free_token_runs(&token_run);");
output_line(out, " return;");
output_line(out, " }");
output_line(out, " if (string[tokenizer.offset] != '\\0') {");
output_line(out, " tree->error = ERROR_INVALID_TOKEN;");
output_line(out, " estimate_next_token_range(&tokenizer, &tree->error_range.start, &tree->error_range.end);");
Expand Down
7 changes: 6 additions & 1 deletion src/x-tokenize.h
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,9 @@ struct owl_default_tokenizer {

// The `info` pointer is passed to READ_KEYWORD_TOKEN.
void *info;

// Communicate allocation failures to the caller.
bool allocation_failed;
};

static bool char_is_whitespace(char c)
Expand Down Expand Up @@ -241,8 +244,10 @@ owl_default_tokenizer_advance(struct owl_default_tokenizer *tokenizer,
if (tokenizer->text[tokenizer->offset] == '\0')
return false;
struct owl_token_run *run = malloc(sizeof(struct owl_token_run));
if (!run)
if (!run) {
tokenizer->allocation_failed = true;
return false;
}
uint16_t number_of_tokens = 0;
uint16_t lengths_size = 0;
const char *text = tokenizer->text;
Expand Down

0 comments on commit ae33e64

Please sign in to comment.