lang: lex: use a dictionary to lookup keywords

This commit is contained in:
2024-11-19 10:49:42 +00:00
parent c5f60c285e
commit 90a32ac1a1

View File

@@ -1,6 +1,8 @@
#include <blue/core/hash.h> #include <blue/core/hash.h>
#include <blue/core/queue.h> #include <blue/core/queue.h>
#include <blue/object/string.h> #include <blue/object/string.h>
#include <blue/object/dict.h>
#include <blue/object/number.h>
#include <ctype.h> #include <ctype.h>
#include <ivy/lang/lex.h> #include <ivy/lang/lex.h>
#include <stdbool.h> #include <stdbool.h>
@@ -18,7 +20,7 @@
struct ivy_lexer { struct ivy_lexer {
struct ivy_lexer_symbol_node *lex_sym_tree; struct ivy_lexer_symbol_node *lex_sym_tree;
struct ivy_line_source *lex_source; struct ivy_line_source *lex_source;
b_dict *lex_keywords;
enum ivy_status lex_status; enum ivy_status lex_status;
struct ivy_token *lex_queue; struct ivy_token *lex_queue;
@@ -303,34 +305,24 @@ static void print_symbol_node(struct ivy_lexer_symbol_node *node, int depth)
} }
} }
static void init_keywords(void) static void init_keywords(b_dict *keyword_dict)
{ {
for (size_t i = 0; i < nr_keywords; i++) { for (size_t i = 0; i < nr_keywords; i++) {
keywords[i].name_hash = b_hash_string(keywords[i].name); struct lex_token_def *keyword = &keywords[i];
b_dict_put(keyword_dict, keyword->name, B_RV_INT(keyword->id));
} }
} }
static enum ivy_keyword find_keyword_by_name(const char *s) static enum ivy_keyword find_keyword_by_name(struct ivy_lexer *lex, const char *s)
{ {
uint64_t s_hash = b_hash_string(s); b_number *id = b_dict_at(lex->lex_keywords, s);
if (!id) {
for (size_t i = 0; i < nr_keywords; i++) {
struct lex_token_def *def = &keywords[i];
if (s_hash != def->name_hash) {
continue;
}
if (strcmp(s, def->name) != 0) {
continue;
}
return def->id;
}
return IVY_KW_NONE; return IVY_KW_NONE;
} }
return b_number_get_int(id);
}
enum ivy_status ivy_lexer_create(struct ivy_lexer **lexp) enum ivy_status ivy_lexer_create(struct ivy_lexer **lexp)
{ {
struct ivy_lexer *lex = malloc(sizeof *lex); struct ivy_lexer *lex = malloc(sizeof *lex);
@@ -359,8 +351,8 @@ enum ivy_status ivy_lexer_create(struct ivy_lexer **lexp)
print_symbol_node(lex->lex_sym_tree, 0); print_symbol_node(lex->lex_sym_tree, 0);
/* TODO only do keyword initialisation once */ lex->lex_keywords = b_dict_create();
init_keywords(); init_keywords(lex->lex_keywords);
*lexp = lex; *lexp = lex;
return IVY_OK; return IVY_OK;
@@ -386,6 +378,10 @@ void ivy_lexer_destroy(struct ivy_lexer *lex)
b_string_release(lex->lex_temp); b_string_release(lex->lex_temp);
} }
if (lex->lex_keywords) {
b_dict_release(lex->lex_keywords);
}
destroy_state_stack(&lex->lex_state); destroy_state_stack(&lex->lex_state);
free(lex); free(lex);
@@ -967,7 +963,7 @@ static enum ivy_status read_ident(struct ivy_lexer *lex)
} }
enum ivy_keyword keyword = IVY_KW_NONE; enum ivy_keyword keyword = IVY_KW_NONE;
if (!label && (keyword = find_keyword_by_name(s)) != IVY_KW_NONE) { if (!label && (keyword = find_keyword_by_name(lex, s)) != IVY_KW_NONE) {
return push_keyword(lex, keyword); return push_keyword(lex, keyword);
} }