Files
corelang/parser.c
2022-04-29 23:28:41 +02:00

252 lines
6.4 KiB
C

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);
p->symbols_count = 4096;
p->symbols = arena_push_array(&p->intern_table_arena, 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);
}
lex_print("Error: %s\n", string.str);// @Todo(Krzosa):
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);
p->interns_in_bytes += string.len;
p->interns_inserted += 1;
*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 Symbol *
symbol_get_slot(Parser *p, Intern_String intern){
String string = intern.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->string = intern;
p->symbols_inserted++;
return slot;
}
else if(slot->string.s.str == string.str){
return slot;
}
if (table_index_advance(&index))
break;
}
parser_push_error(p, token_get(p), "Failed to find a spot for symbol");
return 0;
}
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 B32
symbol_require_empty(Parser *p, Symbol *symbol){
assert(symbol);
B32 result = symbol->kind == SK_None;
if(!result){
// @Todo(Krzosa): Should send symbol name not token
parser_push_error(p, token_get(p), "This symbol name is already registered");
}
return result;
}
function void
const_val_insert(Parser *p, Token *token, Type *type, Intern_String string, Expr *expr){
Symbol *symbol = symbol_get_slot(p, string);
if(symbol_require_empty(p, symbol)){
symbol->kind = SK_Const;
symbol->token = token;
symbol->const_val.type = type;
symbol->const_val.expr = expr;
}
}
function void
variable_insert(Parser *p, Decl *decl){
Symbol *symbol = symbol_get_slot(p, decl->name);
if(symbol_require_empty(p, symbol)){
symbol->kind = SK_Decl;
symbol->decl = decl;
symbol->string = decl->name;
symbol->token = decl->token;
}
}
function void
type_insert(Parser *p, Type *type, Intern_String string){
Symbol *symbol = symbol_get_slot(p, string);
if(symbol_require_empty(p, symbol)){
symbol->kind = SK_Type;
symbol->type = type;
symbol->string = string;
}
}
function Type *
type_get(Parser *p, Intern_String string){
Type *result = 0;
Symbol *symbol = symbol_get(p, string);
if(symbol){
if(symbol->kind == SK_Type){
result = symbol->type;
}
else {
parser_push_error(p, token_get(p), "Symbol is not a type");
}
}
else{
parser_push_error(p, token_get(p), "Undefined type");
}
if(!result){
result = type_undefined;
}
return result;
}