commit e3b7a7ae5df4853ff4cf7e96ee070b12e96a6450
parent fdc2e9cd2d9896f9139b04d12489a69cceb9354d
Author: thing1 <thing1@seacrossedlovers.xyz>
Date: Thu, 18 Dec 2025 20:48:11 +0000
added better error msgs
Diffstat:
7 files changed, 71 insertions(+), 27 deletions(-)
diff --git a/TODO.md b/TODO.md
@@ -0,0 +1,8 @@
+IMPORTANT
+=========
+
+- make casts into real code, should check at the parser level to achieve this
+- add support for structs and other user aliased types
+- add arrays, along side the start of the rt lib
+- add tupples to allow for multiple return types
+- .............................
diff --git a/lexer.c b/lexer.c
@@ -6,6 +6,25 @@
#include "lexer.h"
+loc
+findloc(lex l) {
+ int lines = 1;
+ int col = 1;
+ for (char *c = l.input; c != l.ptr; c++, col++) {
+ if (*c == '\n') {
+ col = 0;
+ lines++;
+ }
+ }
+
+ return (loc){lines, col};
+}
+
+loc
+findloctok(tok t) {
+ return findloc(t.l);
+}
+
void
lexErr(lex *l) {
fprintf(stderr, "unexpected token '%c'\n", *l->ptr);
@@ -49,6 +68,7 @@ tok
next(lex *l) {
l->prev = l->ptr;
tok t = {0};
+ t.l = *l;
switch (*l->ptr) {
case 0:
t.op = LEOF;
diff --git a/lexer.h b/lexer.h
@@ -34,8 +34,13 @@ enum lex_ops {
DEREF,
};
+typedef struct lex {
+ char *input, *ptr, *prev, *name;
+} lex;
+
typedef struct tok {
enum lex_ops op;
+ lex l;
union {
int64_t n;
double f;
@@ -43,10 +48,12 @@ typedef struct tok {
};
} tok;
-typedef struct lex {
- char *input, *ptr, *prev;
-} lex;
+typedef struct loc {
+ int line, col;
+} loc;
+loc findloc(lex l);
+loc findloctok(tok t);
void lexErr(lex *l);
char *unlex(lex *l);
tok next(lex *l);
diff --git a/parse.c b/parse.c
@@ -36,8 +36,15 @@ char *builtinfns[] = {
int funcargs = false;
void
-parserErr(const char *msg) {
- fprintf(stderr, "%s\n", msg);
+parserErr(const char *msg, lex l) {
+ loc lo = findloc(l);
+ fprintf(stderr, "%s:%d:%d: %s\n", l.name, lo.line, lo.col, msg);
+}
+
+void
+parserErrtok(const char *msg, tok t) {
+ loc lo = findloctok(t);
+ fprintf(stderr, "%s:%d:%d: %s\n", t.l.name, lo.line, lo.col, msg);
}
int
@@ -78,13 +85,13 @@ findend(tok *start, tok *end) {
tok *t;
if (start->op != OBRACE) {
- parserErr("Expected a '('");
+ parserErrtok("expected a '('", *start);
return NULL;
}
for (t = &start[1]; d != 0; t = &t[1]) {
if (end->op != CBRACE && t == end) {
- parserErr("unclosed brace");
+ parserErrtok("unclosed brace", *t);
return NULL;
}
@@ -172,7 +179,7 @@ parsefcall(tok *start, tok *end, mctx *ctx) {
* mark it as so, to allow for the comp step to fix everything up */
if (!(f = isbuiltin(start->name, ctx))) {
if (!(f = (fn *)lookupmap(funcs, start->name))) {
- parserErr("no such function");
+ parserErrtok("no such function", *start);
return NULL;
}
builtin = 0;
@@ -203,7 +210,7 @@ another:
if (!builtin) {
if (!isequaltype(e->args[e->argc - 1].type, &f->args[e->argc - 1])) {
- parserErr("type missmatch");
+ parserErrtok("type missmatch", *start);
return NULL;
}
}
@@ -237,7 +244,7 @@ parsesimple(tok *start, tok *end, tok *lowest, mctx *ctx) {
case INT:
case FLOAT:
if (start != end) {
- parserErr("Trailing expression");
+ parserErrtok("trailing expression", *start);
return NULL;
}
e = alloczctx(ctx, sizeof(rexpr));
@@ -259,7 +266,7 @@ parsesimple(tok *start, tok *end, tok *lowest, mctx *ctx) {
break;
case NAME:
if (!(v = (var *)lookupmap(vars, lowest->name))) {
- parserErr("var is not declared");
+ parserErrtok("var is not declared", *start);
return NULL;
}
e->type = v->type;
@@ -291,7 +298,7 @@ parsesimple(tok *start, tok *end, tok *lowest, mctx *ctx) {
e->type = e->e->type->nested;
break;
default:
- parserErr("Unexpected token type");
+ parserErrtok("unexpected token type", *start);
return NULL;
}
@@ -303,7 +310,7 @@ parsebin(tok *start, tok *end, tok *lowest, mctx *ctx) {
rexpr *e = alloczctx(ctx, sizeof(rexpr));
if (!isop(*lowest)) {
- parserErr("Expected op");
+ parserErrtok("expected op", *lowest);
return NULL;
}
@@ -312,7 +319,7 @@ parsebin(tok *start, tok *end, tok *lowest, mctx *ctx) {
e->expr[1] = parserexpr(&lowest[1], end, ctx);
if (!isequaltype(e->expr[0]->type, e->expr[1]->type)) {
- parserErr("Type missmatch");
+ parserErrtok("type missmatch", *start);
return NULL;
}
@@ -360,7 +367,7 @@ parsetype(lex *l, mctx *ctx) {
}
if (!isbasictype(t.name)) {
- parserErr("not a known type!");
+ parserErr("not a known type!", *l);
RESTORE(l);
return NULL;
}
@@ -413,7 +420,7 @@ parseassign(lex *l, tok name, mctx *ctx) {
shortdec:
if (lookupmap(vars, name.name)) {
- parserErr("redeclaration of var");
+ parserErr("redeclaration of var", *l);
RESTORE(l);
return NULL;
}
@@ -426,7 +433,7 @@ shortdec:
le->rexpr = r;
if (r && !isequaltype(ty, r->type)) {
- parserErr("type missmatch");
+ parserErr("type missmatch", *l);
RESTORE(l);
return NULL;
}
@@ -449,12 +456,12 @@ parsefunc(lex *l, mctx *ctx) {
int argc = 0;
if ((name = next(l)).op != NAME) {
- parserErr("function has no name");
+ parserErr("function has no name", *l);
RESTORE(l);
return NULL;
}
if (next(l).op != OBRACE) {
- parserErr("expected '('");
+ parserErr("expected '('", *l);
RESTORE(l);
return NULL;
}
@@ -464,7 +471,7 @@ parsefunc(lex *l, mctx *ctx) {
case NAME:
funcargs = 1;
if (!(arg = parseassign(l, t, ctx))) {
- parserErr("malformed function arg");
+ parserErr("malformed function arg", *l);
RESTORE(l);
return NULL;
}
@@ -477,7 +484,7 @@ parsefunc(lex *l, mctx *ctx) {
case CBRACE:
goto done;
default:
- parserErr("unexpected token");
+ parserErr("unexpected token", *l);
RESTORE(l);
return NULL;
}
@@ -489,7 +496,7 @@ done:
}
if (!(ty = parsetype(l, ctx))) {
- parserErr("function has no type");
+ parserErr("function has no type", *l);
RESTORE(l);
return NULL;
}
@@ -497,7 +504,7 @@ done:
if ((t = next(l)).op == ';')
goto prototype;
else if (t.op != '{') {
- parserErr("expected function body, or ';'");
+ parserErr("expected function body, or ';'", *l);
RESTORE(l);
return NULL;
}
@@ -607,7 +614,7 @@ parselexpr(lex *l, mctx *ctx) {
f->args[i] = *le->args[i].type;
}
if (lookupmap(funcs, f->name)) {
- parserErr("function already exists");
+ parserErr("function already exists", *l);
RESTORE(l);
haserrored = 1;
return NULL;
@@ -630,7 +637,7 @@ parselexpr(lex *l, mctx *ctx) {
case LEOF:
return NULL;
default:
- parserErr("unexpected tok type");
+ parserErr("unexpected tok type", *l);
haserrored = 1;
}
if (!le) {
diff --git a/parse.h b/parse.h
@@ -4,6 +4,7 @@
#include "lexer.h"
#include "util.h"
+
enum lexpr_ops {
LEXPR_ASSIGN,
LEXPR_FUNC,
@@ -69,7 +70,7 @@ typedef struct lexpr {
extern int haserrored;
-void parserErr(const char *msg);
+void parserErr(const char *msg, lex l);
int getpres(tok t);
int isop(tok t);
tok *findend(tok *start, tok *end);
diff --git a/spl.c b/spl.c
@@ -19,6 +19,7 @@ main(int argc, char **argv) {
fclose(f);
lex l = mklexer(file);
+ l.name = argv[1];
mctx *ctx = newctx();
lexpr *xs = NULL, *x;
diff --git a/test.spl b/test.spl
@@ -3,6 +3,6 @@ func foo(c *i32) i32 {
}
func main() i32 {
- a i32 = i16(5);
+ a i32 = 5 + 5.4;
b i32 = foo(&a);
}