Rethink the parse() function
Now the parser should handle memory allocation failures properly.
This commit is contained in:
parent
5d5042fdec
commit
158b8fffeb
57
ell.c
57
ell.c
|
@ -620,35 +620,22 @@ parse_line (struct parser *self, jmp_buf out) {
|
|||
#undef CHECK
|
||||
|
||||
static struct item *
|
||||
parse (const char *s, size_t len, char **e) {
|
||||
struct parser parser;
|
||||
parser_init (&parser, s, len);
|
||||
|
||||
parser_run (struct parser *self, const char **e) {
|
||||
jmp_buf err;
|
||||
struct item *volatile result = NULL, *volatile *tail = &result;
|
||||
if (setjmp (err)) {
|
||||
item_free_list (result);
|
||||
*e = parser.error;
|
||||
lexer_free (&parser.lexer);
|
||||
|
||||
// TODO: figure out how to handle this, since the return value
|
||||
// may be null and we may not be able to allocate an error message
|
||||
if (parser.memory_failure)
|
||||
abort ();
|
||||
|
||||
if (e) {
|
||||
*e = self->error;
|
||||
if (self->memory_failure)
|
||||
*e = "memory allocation failure";
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
while ((*tail = parse_line (&parser, err)))
|
||||
while ((*tail = parse_line (self, err)))
|
||||
tail = &(*tail)->next;
|
||||
parser_expect (&parser, T_ABORT, err);
|
||||
|
||||
parser_free (&parser);
|
||||
#ifndef NDEBUG
|
||||
printf ("\x1b[1m%s\x1b[0m\n", s);
|
||||
print_tree (result, 0);
|
||||
printf ("\n\n");
|
||||
#endif
|
||||
parser_expect (self, T_ABORT, err);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
@ -929,17 +916,18 @@ init_runtime_library_scripts (struct context *ctx) {
|
|||
};
|
||||
|
||||
for (size_t i = 0; i < N_ELEMENTS (functions); i++) {
|
||||
char *e = NULL;
|
||||
struct item *body = parse (functions[i].definition,
|
||||
strlen (functions[i].definition), &e);
|
||||
// TODO: also handle memory allocation errors
|
||||
struct parser parser;
|
||||
parser_init (&parser,
|
||||
functions[i].definition, strlen (functions[i].definition));
|
||||
const char *e = NULL;
|
||||
struct item *body = parser_run (&parser, &e);
|
||||
if (e) {
|
||||
printf ("error parsing internal function `%s': %s\n",
|
||||
functions[i].definition, e);
|
||||
free (e);
|
||||
functions[i].name, e);
|
||||
ok = false;
|
||||
} else
|
||||
ok &= set (ctx, functions[i].name, body);
|
||||
parser_free (&parser);
|
||||
}
|
||||
return ok;
|
||||
}
|
||||
|
@ -1025,15 +1013,24 @@ main (int argc, char *argv[]) {
|
|||
buffer_append_c (&buf, 0);
|
||||
fclose (fp);
|
||||
|
||||
char *e = NULL;
|
||||
struct item *program = parse (buf.s, buf.len, &e);
|
||||
struct parser parser;
|
||||
parser_init (&parser, buf.s, buf.len - 1);
|
||||
const char *e = NULL;
|
||||
struct item *program = parser_run (&parser, &e);
|
||||
free (buf.s);
|
||||
|
||||
if (e) {
|
||||
printf ("%s: %s\n", "parse error", e);
|
||||
free (e);
|
||||
return 1;
|
||||
}
|
||||
|
||||
#ifndef NDEBUG
|
||||
printf ("\x1b[1m%s\x1b[0m\n", buf.s);
|
||||
print_tree (program, 0);
|
||||
printf ("\n\n");
|
||||
#endif
|
||||
parser_free (&parser);
|
||||
|
||||
struct context ctx;
|
||||
context_init (&ctx);
|
||||
if (!init_runtime_library ()
|
||||
|
|
Loading…
Reference in New Issue