|
@@ -414,21 +414,27 @@ int is_required(char *path) {
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
-void traverse(char *source, size_t pos, size_t *line, size_t *col) {
|
|
|
+char *traverse(char *source, size_t pos, size_t *line, size_t *col) {
|
|
|
*line = 1;
|
|
|
*col = 1;
|
|
|
|
|
|
+ size_t p = 0;
|
|
|
+
|
|
|
for (size_t i = 0; i < pos; i++) {
|
|
|
if (source[i] == '\n') {
|
|
|
(*line)++;
|
|
|
(*col) = 1;
|
|
|
+
|
|
|
+ p = i;
|
|
|
} else (*col)++;
|
|
|
}
|
|
|
+
|
|
|
+ return &source[p];
|
|
|
}
|
|
|
|
|
|
void format_error(char *filename, char *source, size_t pos, char *fmt, ...) {
|
|
|
size_t line, col;
|
|
|
- traverse(source, pos, &line, &col);
|
|
|
+ char *src = traverse(source, pos, &line, &col);
|
|
|
|
|
|
va_list args;
|
|
|
va_start(args, fmt);
|
|
@@ -438,6 +444,22 @@ void format_error(char *filename, char *source, size_t pos, char *fmt, ...) {
|
|
|
fputc('\n', stderr);
|
|
|
|
|
|
va_end(args);
|
|
|
+
|
|
|
+ if (!*src)
|
|
|
+ return;
|
|
|
+
|
|
|
+ fputc('\t', stderr);
|
|
|
+
|
|
|
+ for (size_t i = 0; src[i] && src[i] != '\n' && i < 64; i++)
|
|
|
+ fputc(src[i], stderr);
|
|
|
+
|
|
|
+ fputc('\n', stderr);
|
|
|
+ fputc('\t', stderr);
|
|
|
+
|
|
|
+ for (size_t i = 0; i < col && i < 64; i++)
|
|
|
+ fputc(' ', stderr);
|
|
|
+
|
|
|
+ fputs("^\n", stderr);
|
|
|
}
|
|
|
|
|
|
#define GETFNAME(fi) ((char *)((list_t *)list_index(FILES, fi))->data[0])
|
|
@@ -1223,7 +1245,15 @@ node_t *parse_primary(list_t *tokens, size_t *pos) {
|
|
|
} else if (MATCH(NUMBER) || MATCH(STRING) || MATCH(FSTRING) || MATCH(NAME))
|
|
|
return NODET(LITERAL, tokens->data[(*pos)-1]);
|
|
|
|
|
|
- PARSE_ERROR("expected expression");
|
|
|
+ if (AT(RPAR)) {
|
|
|
+ PARSE_ERROR("extraneous )");
|
|
|
+ } else if (AT(RSB)) {
|
|
|
+ PARSE_ERROR("extraneous ]");
|
|
|
+ } else if (AT(RCB)) {
|
|
|
+ PARSE_ERROR("extraneous }");
|
|
|
+ } else {
|
|
|
+ PARSE_ERROR("expected expression");
|
|
|
+ }
|
|
|
|
|
|
return NULL;
|
|
|
}
|
|
@@ -3514,7 +3544,6 @@ void compile_node(buffer_t *gbuf, buffer_t *buf, list_t *ctx, table_t *ltab, sta
|
|
|
|
|
|
buffer_t *tbuf = buffer_new();
|
|
|
|
|
|
-
|
|
|
for (size_t i = 0; i < strlen(text); i++) {
|
|
|
char c = text[i];
|
|
|
if (c == '$' && text[i+1] == '$') {
|
|
@@ -3548,7 +3577,14 @@ void compile_node(buffer_t *gbuf, buffer_t *buf, list_t *ctx, table_t *ltab, sta
|
|
|
char *source = buffer_read(tbuf2);
|
|
|
|
|
|
list_t *pair = list_new();
|
|
|
- list_push(pair, "<fstring>");
|
|
|
+
|
|
|
+ buffer_t *fname = buffer_new();
|
|
|
+ size_t line, col;
|
|
|
+ (void)traverse(GETSRC(-1), node->pos, &line, &col);
|
|
|
+
|
|
|
+ buffer_fmt(fname, "<fstring at %s:%zu:%zu>", GETFNAME(-1), line, col);
|
|
|
+
|
|
|
+ list_push(pair, buffer_read(fname));
|
|
|
list_push(pair, source);
|
|
|
|
|
|
list_push(FILES, pair);
|