global Intern_String keyword_s64; global Intern_String keyword_u64; global Intern_String keyword_void; global Intern_String keyword_sizeu; global Intern_String keyword_sizeof; global Intern_String keyword_enum; global Intern_String keyword_typedef; global Intern_String keyword_struct; global Intern_String keyword_union; global Intern_String keyword_function; global Intern_String keyword_global; function void parser_init(Parser *p){ p->interns_count = 4096; p->interns = arena_push_array(&p->intern_table_arena, Intern_String, p->interns_count); memory_zero(p->interns, sizeof(Intern_String)*p->interns_count); p->symbols_count = 4096; p->symbols = arena_push_array(&p->intern_table_arena, Intern_String, p->symbols_count); memory_zero(p->symbols, sizeof(Intern_String)*p->symbols_count); keyword_s64 = intern_string(p, lit("S64")); keyword_u64 = intern_string(p, lit("U64")); keyword_void = intern_string(p, lit("void")); keyword_sizeu = intern_string(p, lit("SizeU")); keyword_sizeof = intern_string(p, lit("sizeof")); keyword_struct = intern_string(p, lit("struct")); keyword_enum = intern_string(p, lit("enum")); keyword_typedef = intern_string(p, lit("typedef")); keyword_union = intern_string(p, lit("union")); keyword_function = intern_string(p, lit("function")); keyword_global = intern_string(p, lit("global")); p->first_keyword = keyword_s64.s.str; p->last_keyword = keyword_global.s.str; type_insert(p, type_s64, keyword_s64); type_insert(p, type_u64, keyword_u64); type_insert(p, type_sizeu, keyword_sizeu); type_insert(p, type_void, keyword_void); } function B32 intern_is_keyword(Parser *p, Intern_String intern){ if(intern.s.str >= p->first_keyword && intern.s.str <= p->last_keyword) return true; return false; } function void parser_push_error(Parser *p, Token *token, char *str, ...){ String string; { va_list args1, args2; va_start(args1, str); va_copy(args2, args1); string.len = vsnprintf(0, 0, str, args2); va_end(args2); string.str = arena_push_size(&p->main_arena, string.len + 1); vsnprintf((char*)string.str, string.len + 1, str, args1); va_end(args1); } Parser_Error *error = arena_push_struct(&p->main_arena, Parser_Error); error->message = string; error->next = 0; error->token = token; SLLQueuePush(p->first_error, p->last_error, error); } //----------------------------------------------------------------------------- // //----------------------------------------------------------------------------- typedef struct Table_Index{ U64 hash; U64 index; U64 iter; U64 max_size; }Table_Index; function Table_Index table_index_from_hash(U64 hash, U64 max_size){ Table_Index result = {0}; result.hash = hash; result.index = result.hash % max_size; result.iter = result.index; result.max_size = max_size; return result; } function Table_Index table_index_from_string(String string, U64 max_size){ U64 hash = hash_fnv(string); Table_Index result = table_index_from_hash(hash, max_size); return result; } function B32 table_index_advance(Table_Index *index){ index->iter = wrap_around_pow2(index->iter + 1, index->max_size); B32 result = index->iter == index->index; return result; } function Intern_String intern_string(Parser *p, String string){ Intern_String result = {}; Table_Index index = table_index_from_string(string, p->interns_count); for(;;){ Intern_String *intern = p->interns + index.iter; if(intern->s.str == 0){ result.s = arena_push_string_copy(&p->main_arena, string); *intern = result; break; } else if(string_compare(intern->s, string)){ result = *intern; break; } if (table_index_advance(&index)) break; } return result; } function void intern_tokens(Parser *p){ for(S64 i = 0; i < p->tokens.len; i++){ Token *t = p->tokens.tokens + i; if(t->kind == TK_Identifier){ t->intern_val = intern_string(p, t->string); if(intern_is_keyword(p, t->intern_val)){ t->kind = TK_Keyword; } } } } function void symbol_insert(Parser *p, Symbol symbol){ String string = symbol.string.s; Table_Index index = table_index_from_string(string, p->symbols_count); for(;;){ Symbol *slot = p->symbols + index.iter; if(slot->string.s.str == 0){ *slot = symbol; break; } else if(slot->string.s.str == string.str){ invalid_codepath; break; } if (table_index_advance(&index)) break; } } function Symbol * symbol_get(Parser *p, Intern_String string){ Table_Index index = table_index_from_string(string.s, p->symbols_count); for(;;){ Symbol *slot = p->symbols + index.iter; if(slot->string.s.str == string.s.str){ return slot; } if (table_index_advance(&index)) break; } return 0; } function void type_insert(Parser *p, Type *type, Intern_String string){ Symbol symbol = {.kind=SK_Type, .string=string, .type=type}; symbol_insert(p, symbol); } function Type * type_get(Parser *p, Token *token){ Type *result = 0; if(token->kind == TK_Identifier || token->kind == TK_Keyword){ Symbol *symbol = symbol_get(p, token->intern_val); if(symbol){ if(symbol->kind == SK_Type){ result = symbol->type; } else { parser_push_error(p, token, "Symbol is not a type"); } } else{ parser_push_error(p, token, "Undefined type"); } } else { parser_push_error(p, token, "Trying to lookup a type with token of wrong kind"); } if(!result){ result = type_undefined; } return result; }