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/queue.h>
#include <blue/object/string.h>
#include <blue/object/dict.h>
#include <blue/object/number.h>
#include <ctype.h>
#include <ivy/lang/lex.h>
#include <stdbool.h>
@@ -18,7 +20,7 @@
struct ivy_lexer {
struct ivy_lexer_symbol_node *lex_sym_tree;
struct ivy_line_source *lex_source;
b_dict *lex_keywords;
enum ivy_status lex_status;
struct ivy_token *lex_queue;
@@ -303,32 +305,22 @@ 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++) {
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);
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;
b_number *id = b_dict_at(lex->lex_keywords, s);
if (!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)
@@ -359,8 +351,8 @@ enum ivy_status ivy_lexer_create(struct ivy_lexer **lexp)
print_symbol_node(lex->lex_sym_tree, 0);
/* TODO only do keyword initialisation once */
init_keywords();
lex->lex_keywords = b_dict_create();
init_keywords(lex->lex_keywords);
*lexp = lex;
return IVY_OK;
@@ -386,6 +378,10 @@ void ivy_lexer_destroy(struct ivy_lexer *lex)
b_string_release(lex->lex_temp);
}
if (lex->lex_keywords) {
b_dict_release(lex->lex_keywords);
}
destroy_state_stack(&lex->lex_state);
free(lex);
@@ -967,7 +963,7 @@ static enum ivy_status read_ident(struct ivy_lexer *lex)
}
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);
}