spl

a Simple Programming Language
Log | Files | Refs

commit e3b7a7ae5df4853ff4cf7e96ee070b12e96a6450
parent fdc2e9cd2d9896f9139b04d12489a69cceb9354d
Author: thing1 <thing1@seacrossedlovers.xyz>
Date:   Thu, 18 Dec 2025 20:48:11 +0000

added better error msgs

Diffstat:
ATODO.md | 8++++++++
Mlexer.c | 20++++++++++++++++++++
Mlexer.h | 13++++++++++---
Mparse.c | 51+++++++++++++++++++++++++++++----------------------
Mparse.h | 3++-
Mspl.c | 1+
Mtest.spl | 2+-
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); }