From a28874145cce8e2863f3e9f67dc1452d536dab91 Mon Sep 17 00:00:00 2001 From: Max Wash Date: Thu, 8 May 2025 20:31:55 +0100 Subject: [PATCH] lang: lex: add diagnostic support --- lang/include/ivy/lang/lex.h | 2 ++ lang/lex.c | 32 ++++++++++++++++++++++++++++++++ lang/lex.h | 1 + 3 files changed, 35 insertions(+) diff --git a/lang/include/ivy/lang/lex.h b/lang/include/ivy/lang/lex.h index f12f095..2f8cca3 100644 --- a/lang/include/ivy/lang/lex.h +++ b/lang/include/ivy/lang/lex.h @@ -136,12 +136,14 @@ struct ivy_token { struct ivy_lexer_symbol_node; struct ivy_lexer_state; struct ivy_lexer; +struct ivy_diag_ctx; IVY_API enum ivy_status ivy_lexer_create(struct ivy_lexer **lex); IVY_API void ivy_lexer_destroy(struct ivy_lexer *lex); IVY_API void ivy_lexer_set_source( struct ivy_lexer *lex, struct ivy_line_source *src); +IVY_API void ivy_lexer_set_diag_ctx(struct ivy_lexer *lex, struct ivy_diag_ctx *ctx); IVY_API enum ivy_status ivy_lexer_get_status(struct ivy_lexer *lex); IVY_API struct ivy_token *ivy_lexer_peek(struct ivy_lexer *lex); diff --git a/lang/lex.c b/lang/lex.c index 925929d..a5b4d77 100644 --- a/lang/lex.c +++ b/lang/lex.c @@ -6,6 +6,8 @@ #include #include #include +#include +#include #include #include #include @@ -338,6 +340,11 @@ void ivy_lexer_set_source(struct ivy_lexer *lex, struct ivy_line_source *src) lex->lex_source = src; } +void ivy_lexer_set_diag_ctx(struct ivy_lexer *lex, struct ivy_diag_ctx *ctx) +{ + lex->lex_diag_ctx = ctx; +} + enum ivy_status ivy_lexer_get_status(struct ivy_lexer *lex) { return lex->lex_status; @@ -728,6 +735,11 @@ static enum ivy_status read_atom(struct ivy_lexer *lex) advance(lex); } + if (b_string_get_size(str, B_STRLEN_NORMAL) == 0) { + /* TODO report empty atom error */ + return IVY_ERR_BAD_SYNTAX; + } + char *s = b_string_steal(str); return push_atom(lex, s); } @@ -998,6 +1010,25 @@ static enum ivy_status read_ident(struct ivy_lexer *lex) return push_token(lex, tok); } +static void report_unrecognised_char(struct ivy_lexer *lex, int c) +{ + struct ivy_diag *diag = ivy_diag_ctx_create_diag( + lex->lex_diag_ctx, IVY_LANG_E_UNRECOGNISED_SYMBOL); + + ivy_diag_set_location(diag, lex->lex_cursor_row, lex->lex_cursor_col); + ivy_diag_push_msg(diag, IVY_LANG_MSG_UNKNOWN_SYMBOL_ENCOUNTERED); + + const struct ivy_diag_highlight hl[] = { + IVY_DIAG_HL( + ERROR, lex->lex_cursor_row, lex->lex_cursor_col, + lex->lex_cursor_row, lex->lex_cursor_col), + }; + const size_t nr_hl = sizeof hl / sizeof hl[0]; + + ivy_diag_push_snippet( + diag, lex->lex_cursor_row, lex->lex_cursor_row, NULL, 0, hl, nr_hl); +} + static enum ivy_status pump_tokens(struct ivy_lexer *lex) { struct lexer_state *state = get_lexer_state(lex); @@ -1059,6 +1090,7 @@ static enum ivy_status pump_tokens(struct ivy_lexer *lex) return read_number(lex); } + report_unrecognised_char(lex, c); return IVY_ERR_BAD_SYNTAX; } diff --git a/lang/lex.h b/lang/lex.h index 0a91498..3aa951a 100644 --- a/lang/lex.h +++ b/lang/lex.h @@ -10,6 +10,7 @@ struct ivy_lexer { struct ivy_lexer_symbol_node *lex_sym_tree; + struct ivy_diag_ctx *lex_diag_ctx; struct ivy_line_source *lex_source; b_dict *lex_keywords; enum ivy_status lex_status;