summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author0x221e2026-06-17 00:07:58 +0200
committer0x221e2026-06-17 01:12:23 +0300
commit8a77b4096d9f61b6b6eaefb4c8c8abe7f4793b73 (patch)
tree2a51d4bc47e9add8c4175b6906ca8b1e5921c133
parent9224992817c3faf7d6274681fb5bacc5ad761504 (diff)
lex: pretty error messages and lex_number() checks
Error messages are now pretty (not rlly), and lex_number() now checks improper use of number and binary literals. osal.h now also requires platforms to implement a printv() wrapper.
-rw-r--r--include/lex.h11
-rw-r--r--include/platform/osal.h2
-rw-r--r--lex/lex.c94
-rw-r--r--platform/elf/osal.c5
4 files changed, 106 insertions, 6 deletions
diff --git a/include/lex.h b/include/lex.h
index 634be5f..bdfd32f 100644
--- a/include/lex.h
+++ b/include/lex.h
@@ -33,10 +33,15 @@
const char* lex_get_token_name(int id);
+#define LEX_NUMBER_ERR 0
+#define LEX_HEX_ERR 1
+#define LEX_BINARY_ERR 2
+
+
struct token {
int type;
// size_t line;
-// size_t pos;
+// size_t linepos;
size_t length;
char *lexeme;
};
@@ -45,12 +50,16 @@ struct lex {
size_t pos;
size_t size;
char* buffer;
+ const char* filepath;
size_t line;
+ size_t linepos;
};
char lex_advance(struct lex *l, size_t o);
char lex_seek(struct lex *l, size_t o);
+void lex_error(struct lex *l, int err_code, const char *s, ...);
+
struct token lex_number(struct lex *l);
struct token lex_directive(struct lex *l);
struct token lex_link_unit(struct lex *l);
diff --git a/include/platform/osal.h b/include/platform/osal.h
index b6a35d9..493ce6f 100644
--- a/include/platform/osal.h
+++ b/include/platform/osal.h
@@ -3,6 +3,7 @@
#include <stddef.h>
#include <stdint.h>
+#include <stdarg.h>
void* mem_alloc(size_t s);
void mem_free(void *p);
@@ -19,6 +20,7 @@ struct file {
struct file open_file(const char *path, int flags);
void print(const char *fmt, ...);
+void printv(const char *fmt, va_list l);
void exitc(int c);
#endif
diff --git a/lex/lex.c b/lex/lex.c
index ba49ca3..ea0978e 100644
--- a/lex/lex.c
+++ b/lex/lex.c
@@ -86,11 +86,76 @@ char lex_seek(struct lex *l, size_t o)
return 0;
}
+char lex_advance(struct lex *l, size_t o)
+{
+ assert(l != NULL);
+
+ if (l->buffer[l->pos + o] == 0 ||
+ l->pos + o >= l->size) {
+ l->pos = l->size;
+ return 0;
+ }
+
+ l->pos += o;
+ return lex_seek(l, o);
+}
+
struct token lex_token_create(int tt, char* lexeme, size_t s)
{
return (struct token) {.type = tt, .length = s, .lexeme = lexeme};
}
+void lex_error(struct lex *l, int err_code, const char *s, ...)
+{
+ assert(l != NULL);
+ va_list args;
+ va_start(args, s);
+ print("%s:%d: error: ", l->filepath, l->line);
+ printv(s, args);
+ print("\n");
+
+ int start = 0;
+ int end = 0;
+
+ int pos = 0;
+ int curr_line = 0;
+
+ // inefficient, but safe for now
+
+ while (l->buffer[pos]) {
+ if (l->buffer[pos] == '\n') {
+ curr_line+=1;
+ }
+ pos++;
+
+ if (curr_line == l->line - 1) {
+ start = pos;
+
+ while (l->buffer[pos]) {
+ if (l->buffer[pos] == '\n')
+ break;
+ else
+ pos++;
+ }
+ end = pos;
+ }
+ }
+
+ int size = (int)(end - start);
+
+ print("%d | %.*s\n", l->line, size, &l->buffer[start]);
+
+ print(" |");
+ size_t cursor_loc = (l->pos - start) + 4;
+ for (size_t i = 0; i < cursor_loc; i++) {
+ print(" ");
+ }
+ print("^\n");
+
+ va_end(args);
+ exitc(1);
+}
+
struct token lex_number(struct lex *l)
{
assert(l != NULL);
@@ -121,8 +186,15 @@ struct token lex_number(struct lex *l)
switch (state) {
case 0:
tt = TOKEN_NUMBER;
- while (lex_seek(l, len) && lex_is_digit(lex_seek(l, len)))
- len++;
+ while (lex_seek(l, len)) {
+ if (lex_is_digit(lex_seek(l, len))) {
+ len++;
+ } else if (lex_is_char(lex_seek(l, len))) {
+ lex_error(l, LEX_NUMBER_ERR, "A number literal must not contain any non-digit characters.");
+ } else {
+ break;
+ }
+ }
break;
case 1:
tt = TOKEN_HEX;
@@ -131,15 +203,27 @@ struct token lex_number(struct lex *l)
break;
case 2:
tt = TOKEN_BINARY;
- while (lex_seek(l, len) && (lex_seek(l, len) == '0' || lex_seek(l, len) == '1')) {
- len++;
+ while (lex_seek(l, len)) {
+ char curr = lex_seek(l, len);
+
+ if ((curr == '0') ||
+ (curr == '1')) {
+ len++;
+ continue;
+ } else if (lex_is_digit(curr)) {
+ lex_error(l, LEX_BINARY_ERR, "A binary number should not have digits other than 0 or 1.");
+ } else if (lex_is_char(curr)) {
+ lex_error(l, LEX_BINARY_ERR,"A binary number should not contain alphanumeric characters.");
+ }
+
+ break;
}
break;
default:
return (struct token) {.type = TOKEN_INVALID, .lexeme = "number"};
}
- l->pos += len;
+ lex_advance(l, len);
return lex_token_create(tt, &l->buffer[start], len);
}
diff --git a/platform/elf/osal.c b/platform/elf/osal.c
index 414cd80..2630b97 100644
--- a/platform/elf/osal.c
+++ b/platform/elf/osal.c
@@ -51,6 +51,11 @@ void print(const char *fmt, ...)
va_end(args);
}
+void printv(const char *fmt, va_list l)
+{
+ vprintf(fmt, l);
+}
+
void exitc(int c)
{
exit(c);