Rethink the parse() function

Now the parser should handle memory allocation failures properly.
This commit is contained in:
Přemysl Eric Janouch 2017-05-19 20:35:32 +02:00
parent 5d5042fdec
commit 158b8fffeb
Signed by: p
GPG Key ID: B715679E3A361BE6
1 changed files with 27 additions and 30 deletions

57
ell.c
View File

@ -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 ()