diff options
| -rw-r--r-- | include/lex.h | 11 | ||||
| -rw-r--r-- | include/platform/osal.h | 2 | ||||
| -rw-r--r-- | lex/lex.c | 94 | ||||
| -rw-r--r-- | platform/elf/osal.c | 5 |
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 @@ -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); |
