aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/lex.h11
-rw-r--r--src/lex.c22
-rw-r--r--src/main.c2
-rw-r--r--src/parse.c12
4 files changed, 39 insertions, 8 deletions
diff --git a/include/lex.h b/include/lex.h
index ba1596d..51485a5 100644
--- a/include/lex.h
+++ b/include/lex.h
@@ -103,8 +103,14 @@ struct number {
} value;
};
+struct location {
+ const char *file;
+ int line, column;
+};
+
struct token {
enum lexical_token token;
+ struct location loc;
union {
struct number num;
const char *str;
@@ -117,11 +123,14 @@ struct lexer {
char *buf;
size_t bufsz, buflen;
struct token un;
+ struct location loc;
};
-void lex_init(struct lexer *lexer, FILE *f);
+void lex_init(struct lexer *lexer, FILE *f, const char *filename);
void lex_finish(struct lexer *lexer);
+struct location lex_loc(struct lexer *lexer);
+
enum lexical_token lex(struct lexer *lexer, struct token *out);
void unlex(struct lexer *lexer, const struct token *in);
bool match(struct lexer *lexer, enum lexical_token token);
diff --git a/src/lex.c b/src/lex.c
index 69a92a7..e616160 100644
--- a/src/lex.c
+++ b/src/lex.c
@@ -46,7 +46,7 @@ const char *tokens[] = {
};
void
-lex_init(struct lexer *lexer, FILE *f)
+lex_init(struct lexer *lexer, FILE *f, const char *filename)
{
lexer->in = f;
lexer->c[0] = 0;
@@ -55,6 +55,9 @@ lex_init(struct lexer *lexer, FILE *f)
lexer->bufsz = 2;
lexer->buflen = 0;
lexer->un.token = T_NONE;
+ lexer->loc.file = filename;
+ lexer->loc.line = 1;
+ lexer->loc.column = 0;
}
void
@@ -63,6 +66,15 @@ lex_finish(struct lexer *lexer)
fclose(lexer->in);
}
+struct location
+lex_loc(struct lexer *lexer)
+{
+ if (lexer->un.token != T_NONE) {
+ return lexer->un.loc;
+ }
+ return lexer->loc;
+}
+
static uint32_t next(struct lexer *lexer)
{
if (lexer->c[0]) {
@@ -75,6 +87,13 @@ static uint32_t next(struct lexer *lexer)
return c;
}
+ if (c == '\n') {
+ ++lexer->loc.line;
+ lexer->loc.column = 0;
+ } else {
+ ++lexer->loc.column;
+ }
+
lexer->c[1] = c;
return c;
}
@@ -240,6 +259,7 @@ lex(struct lexer *lexer, struct token *out)
}
uint32_t c = wgetc(lexer);
+ out->loc = lexer->loc;
if (c == C_EOF) {
out->token = T_EOF;
return out->token;
diff --git a/src/main.c b/src/main.c
index c0cee11..f318c52 100644
--- a/src/main.c
+++ b/src/main.c
@@ -41,7 +41,7 @@ main(int argc, char *argv[])
return EXIT_ABNORMAL;
}
- lex_init(&lexer, in);
+ lex_init(&lexer, in, path);
parse(&lexer, &ast);
lex_finish(&lexer);
}
diff --git a/src/parse.c b/src/parse.c
index a047424..2fa3ee4 100644
--- a/src/parse.c
+++ b/src/parse.c
@@ -5,8 +5,10 @@
#include "util.h"
static noreturn void
-error(const char *fmt, ...)
+error(struct location loc, const char *fmt, ...)
{
+ fprintf(stderr, "%s:%d:%d ", loc.file, loc.line, loc.column);
+
va_list ap;
va_start(ap, fmt);
vfprintf(stderr, fmt, ap);
@@ -34,7 +36,7 @@ parse_path(struct lexer *lexer, struct ast_path *out)
struct token name;
if (lex(lexer, &name) != T_NAME) {
- error("syntax error: expected path");
+ error(name.loc, "syntax error: expected path");
}
out->segments = must_calloc(1, sizeof(const char *));
@@ -44,7 +46,7 @@ parse_path(struct lexer *lexer, struct ast_path *out)
while (match(lexer, T_MODDELIM)) {
if (lex(lexer, &name) != T_NAME) {
- error("syntax error: expected name");
+ error(name.loc, "syntax error: expected name");
}
append(out, name.info.str);
}
@@ -60,7 +62,7 @@ parse_import(struct lexer *lexer, struct ast_import *out)
}
if (!parse_path(lexer, &out->path)) {
- error("syntax error: expected import path");
+ error(lex_loc(lexer), "syntax error: expected import path");
}
struct token token;
@@ -72,7 +74,7 @@ parse_import(struct lexer *lexer, struct ast_import *out)
}
if (!match(lexer, T_SEMICOLON)) {
- error("syntax error: expected semicolon");
+ error(lex_loc(lexer), "syntax error: expected semicolon");
}
return true;