parent
a626fcb86a
commit
e76b7139ff
71
ell.c
71
ell.c
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue