Move memory allocation out of the lexer

Mostly.
This commit is contained in:
Přemysl Eric Janouch 2017-05-19 09:39:57 +02:00
parent a626fcb86a
commit e76b7139ff
Signed by: p
GPG Key ID: B715679E3A361BE6
1 changed files with 41 additions and 30 deletions

71
ell.c
View File

@ -277,24 +277,9 @@ lexer_advance (struct lexer *self) {
return c; return c;
} }
static bool lexer_error (struct lexer *self, char **e, const char *fmt, ...) static inline bool
ATTRIBUTE_PRINTF (3, 4); lexer_error (const char **e, const char *message) {
*e = message;
static bool
lexer_error (struct lexer *self, char **e, const char *fmt, ...) {
va_list ap;
va_start (ap, fmt);
char *description = vformat (fmt, ap);
va_end (ap);
*e = format ("near line %u, column %u: %s",
self->line + 1, self->column + 1, description);
// TODO: see "script", we can just use error constants to avoid allocation
if (!*e)
abort ();
free (description);
return false; return false;
} }
@ -323,9 +308,10 @@ lexer_hexa_escape (struct lexer *self, struct buffer *output) {
} }
static bool static bool
lexer_escape_sequence (struct lexer *self, struct buffer *output, char **e) { lexer_escape_sequence (struct lexer *self, struct buffer *output,
const char **e) {
if (!self->len) if (!self->len)
return lexer_error (self, e, "premature end of escape sequence"); return lexer_error (e, "premature end of escape sequence");
unsigned char c = *self->p; unsigned char c = *self->p;
switch (c) { switch (c) {
@ -344,11 +330,10 @@ lexer_escape_sequence (struct lexer *self, struct buffer *output, char **e) {
lexer_advance (self); lexer_advance (self);
if (lexer_hexa_escape (self, output)) if (lexer_hexa_escape (self, output))
return true; return true;
return lexer_error (e, "invalid hexadecimal escape");
return lexer_error (self, e, "invalid hexadecimal escape");
default: default:
return lexer_error (self, e, "unknown escape sequence"); return lexer_error (e, "unknown escape sequence");
} }
buffer_append_c (output, c); buffer_append_c (output, c);
@ -357,7 +342,7 @@ lexer_escape_sequence (struct lexer *self, struct buffer *output, char **e) {
} }
static bool static bool
lexer_string (struct lexer *self, struct buffer *output, char **e) { lexer_string (struct lexer *self, struct buffer *output, const char **e) {
unsigned char c; unsigned char c;
while (self->len) { while (self->len) {
if ((c = lexer_advance (self)) == '\'') if ((c = lexer_advance (self)) == '\'')
@ -367,11 +352,11 @@ lexer_string (struct lexer *self, struct buffer *output, char **e) {
else if (!lexer_escape_sequence (self, output, e)) else if (!lexer_escape_sequence (self, output, e))
return false; return false;
} }
return lexer_error (self, e, "premature end of string"); return lexer_error (e, "premature end of string");
} }
static enum token static enum token
lexer_next (struct lexer *self, char **e) { lexer_next (struct lexer *self, const char **e) {
// Skip over any whitespace between tokens // Skip over any whitespace between tokens
while (self->len && lexer_is_ignored (*self->p)) while (self->len && lexer_is_ignored (*self->p))
lexer_advance (self); lexer_advance (self);
@ -412,6 +397,25 @@ lexer_next (struct lexer *self, char **e) {
return T_STRING; return T_STRING;
} }
static char *lexer_errorf (struct lexer *self, const char *fmt, ...)
ATTRIBUTE_PRINTF (2, 3);
static char *
lexer_errorf (struct lexer *self, const char *fmt, ...) {
va_list ap;
va_start (ap, fmt);
char *description = vformat (fmt, ap);
va_end (ap);
if (!description)
return NULL;
char *e = format ("near line %u, column %u: %s",
self->line + 1, self->column + 1, description);
free (description);
return e;
}
// --- Parsing ----------------------------------------------------------------- // --- Parsing -----------------------------------------------------------------
// FIXME: the parser generally ignores memory allocation errors // FIXME: the parser generally ignores memory allocation errors
@ -479,9 +483,14 @@ parser_free (struct parser *self) {
static enum token static enum token
parser_peek (struct parser *self, jmp_buf out) { parser_peek (struct parser *self, jmp_buf out) {
if (self->replace_token) { if (self->replace_token) {
self->token = lexer_next (&self->lexer, &self->error); const char *e = NULL;
if (self->error) self->token = lexer_next (&self->lexer, &e);
if (e) {
// TODO: check memory error
self->error = lexer_errorf (&self->lexer, "%s", e);
longjmp (out, 1); longjmp (out, 1);
}
// TODO: with T_STRING check for memory error within
self->replace_token = false; self->replace_token = false;
} }
return self->token; return self->token;
@ -497,7 +506,8 @@ parser_expect (struct parser *self, enum token token, jmp_buf out) {
if (parser_accept (self, token, out)) if (parser_accept (self, token, out))
return; return;
lexer_error (&self->lexer, &self->error, "unexpected `%s', expected `%s'", // TODO: check memory error
self->error = lexer_errorf (&self->lexer, "unexpected `%s', expected `%s'",
token_name (self->token), token_name (self->token),
token_name (token)); token_name (token));
longjmp (out, 1); longjmp (out, 1);
@ -564,7 +574,8 @@ parse_item (struct parser *self, jmp_buf out) {
return parse_prefix_list (new_list (result), "quote"); return parse_prefix_list (new_list (result), "quote");
} }
lexer_error (&self->lexer, &self->error, // TODO: check memory error
self->error = lexer_errorf (&self->lexer,
"unexpected `%s', expected a value", token_name (self->token)); "unexpected `%s', expected a value", token_name (self->token));
longjmp (out, 1); longjmp (out, 1);
} }