250 lines
6.6 KiB
C
250 lines
6.6 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;
|
|
|
|
global AST_Node *type_s64;
|
|
global AST_Node *type_u64;
|
|
global AST_Node *type_void;
|
|
global AST_Node *type_sizeu;
|
|
|
|
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->symbol_table_arena, AST_Node, 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;
|
|
|
|
parser_push_scope(p); // Global scope
|
|
type_s64 = symbol_register_basic_type(p, keyword_s64, sizeof(S64));
|
|
type_u64 = symbol_register_basic_type(p, keyword_u64, sizeof(U64));
|
|
type_sizeu = symbol_register_basic_type(p, keyword_sizeu, sizeof(SizeU));
|
|
type_void = symbol_register_basic_type(p, keyword_void, sizeof(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
|
|
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
|
|
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;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Symbols
|
|
//-----------------------------------------------------------------------------
|
|
function AST_Node *
|
|
symbol_alloc_slot(Parser *p, Intern_String string, B32 is_global){
|
|
Table_Index index = table_index_from_string(string.s, p->symbols_count);
|
|
for(;;){
|
|
AST_Node *symbol = p->symbols + index.iter;
|
|
|
|
if(symbol->name.s.str == 0){
|
|
/* @Note(Krzosa): Push on scope */ {
|
|
if(is_global){
|
|
SLLQueuePush(p->scope_stack->first, p->scope_stack->last, symbol);
|
|
}
|
|
else{
|
|
SLLQueuePush(p->global_scope->first, p->global_scope->last, symbol);
|
|
}
|
|
}
|
|
symbol->name = string;
|
|
p->symbols_inserted++;
|
|
|
|
return symbol;
|
|
}
|
|
else if(intern_compare(symbol->name, string)){
|
|
return symbol;
|
|
}
|
|
|
|
if (table_index_advance(&index))
|
|
break;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
function AST_Node *
|
|
symbol_lookup(Parser *p, Intern_String string){
|
|
Table_Index index = table_index_from_string(string.s, p->symbols_count);
|
|
for(;;){
|
|
AST_Node *symbol = p->symbols + index.iter;
|
|
|
|
if(symbol->name.s.str == 0){
|
|
return 0;
|
|
}
|
|
else if(intern_compare(symbol->name, string)){
|
|
return symbol;
|
|
}
|
|
|
|
if (table_index_advance(&index))
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
function AST_Node *
|
|
symbol_register_basic_type(Parser *p, Intern_String string, SizeU size){
|
|
AST_Node *node = symbol_alloc_slot(p, string, true);
|
|
node->kind = AK_BaseType;
|
|
node->base_type_size = size;
|
|
return node;
|
|
}
|
|
|
|
function AST_Node *
|
|
symbol_lookup_type(Parser *p, Intern_String string){
|
|
AST_Node *node = symbol_lookup(p, string);
|
|
if(node){
|
|
if(ast_is_type(node)){
|
|
return node;
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
function void
|
|
parser_push_scope(Parser *p){
|
|
Scope *scope = 0;
|
|
SLLStackPop(p->scope_free_list, scope);
|
|
if(!scope){
|
|
scope = arena_push_struct(&p->main_arena, Scope);
|
|
}
|
|
SLLStackPush(p->scope_stack, scope);
|
|
if(p->global_scope == 0){
|
|
p->global_scope = scope;
|
|
}
|
|
}
|
|
|
|
function void
|
|
parser_pop_scope(Parser *p){
|
|
Scope *scope = 0;
|
|
SLLStackPop(p->scope_stack, scope);
|
|
assert(scope);
|
|
|
|
for(AST_Node *s = scope->first; s; s=s->scope_next){
|
|
memory_zero(s, sizeof(AST_Node));
|
|
p->symbols_inserted--;
|
|
}
|
|
memory_zero(scope, sizeof(Scope));
|
|
SLLStackPush(p->scope_free_list, scope);
|
|
}
|