summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorWormHeamer2025-08-02 03:54:21 -0400
committerWormHeamer2025-08-02 03:54:21 -0400
commitdbfb6ab16c6ff83291b9401a0432d814f9c6fda0 (patch)
tree0ce6272b4b4749f7b94e74fd08950ba9bbb250e4
parent70e5f31e4d5fa050447bb81b64f9573d421187e0 (diff)
bunch of stuff to make error messages look more like gcc lol
-rw-r--r--lex.c33
-rw-r--r--lex.h1
-rw-r--r--main.c17
-rw-r--r--test.lang2
4 files changed, 25 insertions, 28 deletions
diff --git a/lex.c b/lex.c
index a254e7b..7cfc1ec 100644
--- a/lex.c
+++ b/lex.c
@@ -48,13 +48,13 @@ void lex_expect_not(Lexer *l, TokMask t) {
void lex_expected(Lexer *l, TokMask t) {
if (!(TMASK(l->tok) & t)) {
- lex_error(l, LE_ERROR, str_fmt(&l->arena, "Expected %S but got %s", lex_mask_str(l, t), lex_tok_str[l->tok]));
+ lex_error(l, LE_ERROR, str_fmt(&l->arena, "expected %S but got %s", lex_mask_str(l, t), lex_tok_str[l->tok]));
}
}
void lex_expected_not(Lexer *l, TokMask t) {
if (TMASK(l->tok) & t) {
- lex_error(l, LE_ERROR, str_fmt(&l->arena, "Unexpected %s", lex_tok_str[l->tok]));
+ lex_error(l, LE_ERROR, str_fmt(&l->arena, "unexpected %s", lex_tok_str[l->tok]));
}
}
@@ -81,14 +81,20 @@ void lex_error(Lexer *l, LexErr e, Str msg) {
lex_error_at(l, l->pos, e, msg);
}
+void lex_err_color(LexErr e) {
+ fprintf(stderr, "%s", e == LE_NONE ? "\x1b[0m" : (e == LE_ERROR ? "\x1b[1;31m" : "\x1b[1;33m"));
+}
+
void lex_error_at(Lexer *l, LexSpan pos, LexErr e, Str msg) {
int line, col;
lex_pos(l, pos.ofs, &line, &col);
- fprintf(stderr, "%s", e == LE_ERROR ? "\x1b[1;31m" : "\x1b[1;33m");
- fprintf(stderr, "%.*s:%d:%d: %.*s\n\n",
- (int)l->filename.n, l->filename.s, line + 1, col + 1, (int)msg.n, msg.s);
+ fprintf(stderr, "\x1b[1m%.*s:%d:%d:\x1b[0m ", (int)l->filename.n, l->filename.s, line + 1, col + 1);
+ lex_err_color(e);
+ if (e != LE_NONE) fprintf(stderr, "%s", e == LE_ERROR ? "error" : "warn");
+ lex_err_color(LE_NONE);
+ fprintf(stderr, ": %.*s\n\n", (int)msg.n, msg.s);
{
int ofs = pos.ofs;
@@ -96,13 +102,16 @@ void lex_error_at(Lexer *l, LexSpan pos, LexErr e, Str msg) {
while (line_start > 0 && l->buf.s[line_start - 1] != '\n') line_start--;
int line_end = line_start;
while (line_end < l->buf.n && l->buf.s[line_end] != '\n') line_end++;
+ lex_err_color(e);
fprintf(stderr, "%.*s\n", line_end - line_start, &l->buf.s[line_start]);
for (int i = 0; i < col; i++) fputc(' ', stderr);
- for (int i = ofs; i < ofs + pos.n && i < line_end; i++) fputc('^', stderr);
- putchar('\n');
+ fputc('^', stderr);
+ for (int i = ofs + 1; i < ofs + pos.n && i < line_end; i++) fputc('~', stderr);
+ lex_err_color(LE_NONE);
+ fputc('\n', stderr);
}
- fprintf(stderr, "\x1b[0m\n");
+ fputc('\n', stderr);
if (e == LE_ERROR) {
exit(1);
@@ -170,15 +179,15 @@ recurse:
T(TOK_LIT_CHAR);
if (i < l->buf.n && l->buf.s[i] == '\\') i += 2;
else i++;
- if (i >= l->buf.n) lex_error(l, LE_ERROR, S("Unterminated character literal"));
- if (l->buf.s[i] != '\'') lex_error(l, LE_ERROR, S("Overlong character literal"));
+ if (i >= l->buf.n) lex_error(l, LE_ERROR, S("unterminated character literal"));
+ if (l->buf.s[i] != '\'') lex_error(l, LE_ERROR, S("overlong character literal"));
i++;
break;
case '"':
T(TOK_LIT_STR);
for (;;) {
if (i >= l->buf.n) {
- lex_error(l, LE_ERROR, S("Unterminated string literal"));
+ lex_error(l, LE_ERROR, S("unterminated string literal"));
}
if (l->buf.s[i] == '\\') {
i += 2;
@@ -190,7 +199,7 @@ recurse:
}
}
if (l->tok == TOK_MAX) {
- lex_error(l, LE_ERROR, S("Invalid token"));
+ lex_error(l, LE_ERROR, S("parse error"));
}
l->ident.n = i - start_ofs;
l->pos.n = i - start_ofs;
diff --git a/lex.h b/lex.h
index 9c38208..66de6d5 100644
--- a/lex.h
+++ b/lex.h
@@ -83,6 +83,7 @@ typedef struct {
} Lexer;
typedef enum {
+ LE_NONE,
LE_WARN,
LE_ERROR
} LexErr;
diff --git a/main.c b/main.c
index 3ffd6cb..64d3cf2 100644
--- a/main.c
+++ b/main.c
@@ -227,7 +227,6 @@ static inline int node_op_communative(NodeType t) {
/* needs lexer for error reporting */
Node *node_peephole(Node *n, Proc *p, Lexer *l) {
- return n;
/*
* Is there a method to convey these transformations a little more nicely?
*
@@ -253,7 +252,7 @@ Node *node_peephole(Node *n, Proc *p, Lexer *l) {
case N_OP_MUL: r = node_new_lit_i64(p, in[0]->lit.i * in[1]->lit.i); break;
case N_OP_DIV:
if (in[1]->lit.i == 0) {
- lex_error_at(l, n->src_pos, LE_ERROR, S("Division by zero"));
+ lex_error_at(l, in[1]->src_pos, LE_ERROR, S("divisor always evaluates to zero"));
}
r = node_new_lit_i64(p, in[0]->lit.i / in[1]->lit.i);
break;
@@ -364,21 +363,9 @@ Node *parse_term(Lexer *l, Proc *p) {
return node_peephole(node, p, l);
}
+/* TODO: operator precedence would be kinda nice actually, sad to say */
Node *parse_expr(Lexer *l, Proc *p) {
Node *lhs = parse_term(l, p);
- if (l->tok == TOK_LPAREN) {
- lex_next(l);
- puts("args_start");
- for (;;) {
- parse_expr(l, p);
- lex_expected(l, TM_COMMA | TM_RPAREN);
- if (l->tok == TOK_RPAREN) break;
- lex_next(l);
- }
- lex_next(l);
- puts("args_end");
- puts("func_call");
- }
if (TMASK(l->tok) & (TM_PLUS | TM_MINUS | TM_ASTERISK | TM_SLASH | TM_NOT | TM_AND | TM_XOR | TM_OR)) {
Token t = l->tok;
lex_next(l);
diff --git a/test.lang b/test.lang
index 4ce371a..45cd53e 100644
--- a/test.lang
+++ b/test.lang
@@ -7,5 +7,5 @@
*/
proc main {
- return ((1 & 3) * 1 + 4 / (81237 & 37)) - 23 + -3 + 4
+ return (3 * 5612 * -2) / (1 * (32 ^ 32) + (512 ^ 512) & 3131)
}