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