1
0
mirror of https://github.com/janet-lang/janet synced 2024-11-28 19:19:53 +00:00

Add better error message on unexpected eos.

Show innermost open delimiter
This commit is contained in:
Calvin Rose 2020-04-13 23:18:27 -05:00
parent 93fc11ea21
commit a09112404d
3 changed files with 53 additions and 15 deletions

View File

@ -26,6 +26,9 @@
#include "util.h" #include "util.h"
#endif #endif
#define JANET_PARSER_DEAD 0x1
#define JANET_PARSER_GENERATED_ERROR 0x2
/* Check if a character is whitespace */ /* Check if a character is whitespace */
static int is_whitespace(uint8_t c) { static int is_whitespace(uint8_t c) {
return c == ' ' return c == ' '
@ -637,11 +640,30 @@ void janet_parser_eof(JanetParser *parser) {
size_t oldline = parser->line; size_t oldline = parser->line;
janet_parser_consume(parser, '\n'); janet_parser_consume(parser, '\n');
if (parser->statecount > 1) { if (parser->statecount > 1) {
parser->error = "unexpected end of source"; JanetParseState *s = parser->states + (parser->statecount - 1);
JanetBuffer *buffer = janet_buffer(40);
janet_buffer_push_cstring(buffer, "unexpected end of source: ");
if (s->flags & PFLAG_PARENS) {
janet_buffer_push_u8(buffer, '(');
} else if (s->flags & PFLAG_SQRBRACKETS) {
janet_buffer_push_u8(buffer, '[');
} else if (s->flags & PFLAG_CURLYBRACKETS) {
janet_buffer_push_u8(buffer, '{');
} else if (s->flags & PFLAG_STRING) {
janet_buffer_push_u8(buffer, '"');
} else if (s->flags & PFLAG_LONGSTRING) {
int32_t i;
for (i = 0; i < s->argn; i++) {
janet_buffer_push_u8(buffer, '`');
}
}
janet_formatbb(buffer, " opened at line %d, column %d", s->line, s->column);
parser->error = (const char *) janet_string(buffer->data, buffer->count);
parser->flag |= JANET_PARSER_GENERATED_ERROR;
} }
parser->line = oldline; parser->line = oldline;
parser->column = oldcolumn; parser->column = oldcolumn;
parser->flag = 1; parser->flag |= JANET_PARSER_DEAD;
} }
enum JanetParserStatus janet_parser_status(JanetParser *parser) { enum JanetParserStatus janet_parser_status(JanetParser *parser) {
@ -663,6 +685,7 @@ const char *janet_parser_error(JanetParser *parser) {
if (status == JANET_PARSE_ERROR) { if (status == JANET_PARSE_ERROR) {
const char *e = parser->error; const char *e = parser->error;
parser->error = NULL; parser->error = NULL;
parser->flag &= ~JANET_PARSER_GENERATED_ERROR;
janet_parser_flush(parser); janet_parser_flush(parser);
return e; return e;
} }
@ -766,6 +789,9 @@ static int parsermark(void *p, size_t size) {
for (i = 0; i < parser->argcount; i++) { for (i = 0; i < parser->argcount; i++) {
janet_mark(parser->args[i]); janet_mark(parser->args[i]);
} }
if (parser->flag & JANET_PARSER_GENERATED_ERROR) {
janet_mark(janet_wrap_string(parser->error));
}
return 0; return 0;
} }
@ -900,7 +926,11 @@ static Janet cfun_parse_error(int32_t argc, Janet *argv) {
janet_fixarity(argc, 1); janet_fixarity(argc, 1);
JanetParser *p = janet_getabstract(argv, 0, &janet_parser_type); JanetParser *p = janet_getabstract(argv, 0, &janet_parser_type);
const char *err = janet_parser_error(p); const char *err = janet_parser_error(p);
if (err) return janet_cstringv(err); if (err) {
return (p->flag & JANET_PARSER_GENERATED_ERROR)
? janet_wrap_string(err)
: janet_cstringv(err);
}
return janet_wrap_nil(); return janet_wrap_nil();
} }
@ -999,31 +1029,30 @@ struct ParserStateGetter {
}; };
static Janet parser_state_delimiters(const JanetParser *_p) { static Janet parser_state_delimiters(const JanetParser *_p) {
JanetParser *clone = janet_abstract(&janet_parser_type, sizeof(JanetParser)); JanetParser *p = (JanetParser *)_p;
janet_parser_clone(_p, clone);
size_t i; size_t i;
const uint8_t *str; const uint8_t *str;
size_t oldcount; size_t oldcount;
oldcount = clone->bufcount; oldcount = p->bufcount;
for (i = 0; i < clone->statecount; i++) { for (i = 0; i < p->statecount; i++) {
JanetParseState *s = clone->states + i; JanetParseState *s = p->states + i;
if (s->flags & PFLAG_PARENS) { if (s->flags & PFLAG_PARENS) {
push_buf(clone, '('); push_buf(p, '(');
} else if (s->flags & PFLAG_SQRBRACKETS) { } else if (s->flags & PFLAG_SQRBRACKETS) {
push_buf(clone, '['); push_buf(p, '[');
} else if (s->flags & PFLAG_CURLYBRACKETS) { } else if (s->flags & PFLAG_CURLYBRACKETS) {
push_buf(clone, '{'); push_buf(p, '{');
} else if (s->flags & PFLAG_STRING) { } else if (s->flags & PFLAG_STRING) {
push_buf(clone, '"'); push_buf(p, '"');
} else if (s->flags & PFLAG_LONGSTRING) { } else if (s->flags & PFLAG_LONGSTRING) {
int32_t i; int32_t i;
for (i = 0; i < s->argn; i++) { for (i = 0; i < s->argn; i++) {
push_buf(clone, '`'); push_buf(p, '`');
} }
} }
} }
str = janet_string(clone->buf + oldcount, (int32_t)(clone->bufcount - oldcount)); str = janet_string(p->buf + oldcount, (int32_t)(p->bufcount - oldcount));
clone->bufcount = oldcount; p->bufcount = oldcount;
return janet_wrap_string(str); return janet_wrap_string(str);
} }

View File

@ -863,6 +863,14 @@ const uint8_t *janet_formatc(const char *format, ...) {
return ret; return ret;
} }
JanetBuffer *janet_formatbb(JanetBuffer *buffer, const char *format, ...) {
va_list args;
va_start(args, format);
janet_formatb(buffer, format, args);
va_end(args);
return buffer;
}
/* Shared implementation between string/format and /* Shared implementation between string/format and
* buffer/format */ * buffer/format */
void janet_buffer_format( void janet_buffer_format(

View File

@ -1239,6 +1239,7 @@ JANET_API void janet_description_b(JanetBuffer *buffer, Janet x);
#define janet_stringv(str, len) janet_wrap_string(janet_string((str), (len))) #define janet_stringv(str, len) janet_wrap_string(janet_string((str), (len)))
JANET_API JanetString janet_formatc(const char *format, ...); JANET_API JanetString janet_formatc(const char *format, ...);
JANET_API void janet_formatb(JanetBuffer *bufp, const char *format, va_list args); JANET_API void janet_formatb(JanetBuffer *bufp, const char *format, va_list args);
JANET_API JanetBuffer *janet_formatbb(JanetBuffer *bufp, const char *format, ...);
/* Symbol functions */ /* Symbol functions */
JANET_API JanetSymbol janet_symbol(const uint8_t *str, int32_t len); JANET_API JanetSymbol janet_symbol(const uint8_t *str, int32_t len);