init basic
This commit is contained in:
		
							
								
								
									
										53
									
								
								ccompiler/frontend/parser/symtab/hashmap.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										53
									
								
								ccompiler/frontend/parser/symtab/hashmap.c
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,53 @@
 | 
			
		||||
// hashmap.c
 | 
			
		||||
#include "hashmap.h"
 | 
			
		||||
#include <stdlib.h>
 | 
			
		||||
#include <string.h>
 | 
			
		||||
 | 
			
		||||
// DJB2哈希算法
 | 
			
		||||
static unsigned long hash(const char* str) {
 | 
			
		||||
    unsigned long hash = 5381;
 | 
			
		||||
    int c;
 | 
			
		||||
    while ((c = *str++))
 | 
			
		||||
        hash = ((hash << 5) + hash) + c; /* hash * 33 + c */
 | 
			
		||||
    return hash % HMAP_SIZE;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void hmap_init(HashMap* map) {
 | 
			
		||||
    memset(map->buckets, 0, sizeof(map->buckets));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void hmap_put(HashMap* map, const char* key, void* value) {
 | 
			
		||||
    unsigned long idx = hash(key);
 | 
			
		||||
    HashMapEntry* entry = malloc(sizeof(HashMapEntry));
 | 
			
		||||
    entry->key = strdup(key);
 | 
			
		||||
    entry->value = value;
 | 
			
		||||
    entry->next = map->buckets[idx];
 | 
			
		||||
    map->buckets[idx] = entry;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void* hmap_get(HashMap* map, const char* key) {
 | 
			
		||||
    unsigned long idx = hash(key);
 | 
			
		||||
    HashMapEntry* entry = map->buckets[idx];
 | 
			
		||||
    while (entry) {
 | 
			
		||||
        if (strcmp(entry->key, key) == 0) 
 | 
			
		||||
            return entry->value;
 | 
			
		||||
        entry = entry->next;
 | 
			
		||||
    }
 | 
			
		||||
    return NULL;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int hmap_contains(HashMap* map, const char* key) {
 | 
			
		||||
    return hmap_get(map, key) != NULL;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void hmap_destroy(HashMap* map) {
 | 
			
		||||
    for (int i = 0; i < HMAP_SIZE; i++) {
 | 
			
		||||
        HashMapEntry* entry = map->buckets[i];
 | 
			
		||||
        while (entry) {
 | 
			
		||||
            HashMapEntry* next = entry->next;
 | 
			
		||||
            free(entry->key);
 | 
			
		||||
            free(entry);
 | 
			
		||||
            entry = next;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										31
									
								
								ccompiler/frontend/parser/symtab/hashmap.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										31
									
								
								ccompiler/frontend/parser/symtab/hashmap.h
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,31 @@
 | 
			
		||||
#ifndef HASHMAP_H
 | 
			
		||||
#define HASHMAP_H
 | 
			
		||||
 | 
			
		||||
#define HMAP_SIZE 64
 | 
			
		||||
 | 
			
		||||
typedef struct HashMapEntry {
 | 
			
		||||
    char* key;
 | 
			
		||||
    void* value;
 | 
			
		||||
    struct HashMapEntry* next;
 | 
			
		||||
} HashMapEntry;
 | 
			
		||||
 | 
			
		||||
typedef struct {
 | 
			
		||||
    HashMapEntry* buckets[HMAP_SIZE];
 | 
			
		||||
} HashMap;
 | 
			
		||||
 | 
			
		||||
// 初始化哈希表
 | 
			
		||||
void hmap_init(HashMap* map);
 | 
			
		||||
 | 
			
		||||
// 插入键值对
 | 
			
		||||
void hmap_put(HashMap* map, const char* key, void* value);
 | 
			
		||||
 | 
			
		||||
// 查找键值
 | 
			
		||||
void* hmap_get(HashMap* map, const char* key);
 | 
			
		||||
 | 
			
		||||
// 检查键是否存在
 | 
			
		||||
int hmap_contains(HashMap* map, const char* key);
 | 
			
		||||
 | 
			
		||||
// 释放哈希表内存(不释放value)
 | 
			
		||||
void hmap_destroy(HashMap* map);
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
							
								
								
									
										43
									
								
								ccompiler/frontend/parser/symtab/scope.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										43
									
								
								ccompiler/frontend/parser/symtab/scope.c
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,43 @@
 | 
			
		||||
// scope.c
 | 
			
		||||
#include "scope.h"
 | 
			
		||||
#include <stdio.h>
 | 
			
		||||
#include <stdlib.h>
 | 
			
		||||
 | 
			
		||||
typedef struct Scope Scope;
 | 
			
		||||
 | 
			
		||||
Scope* scope_create(Scope* parent) {
 | 
			
		||||
    Scope* scope = malloc(sizeof(Scope));
 | 
			
		||||
    hmap_init(&scope->symbols);
 | 
			
		||||
    scope->parent = parent;
 | 
			
		||||
    scope->base_offset = 0;
 | 
			
		||||
    scope->cur_offset = 0;
 | 
			
		||||
    return scope;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void scope_destroy(Scope* scope) {
 | 
			
		||||
    hmap_destroy(&scope->symbols);
 | 
			
		||||
    free(scope);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void scope_insert(Scope* scope, const char* name, void* symbol) {
 | 
			
		||||
    if (hmap_contains(&scope->symbols, name)) {
 | 
			
		||||
        // 处理重复定义错误
 | 
			
		||||
        fprintf(stderr, "Error: Symbol '%s' already defined\n", name);
 | 
			
		||||
        exit(EXIT_FAILURE);
 | 
			
		||||
    }
 | 
			
		||||
    hmap_put(&scope->symbols, name, symbol);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void* scope_lookup(Scope* scope, const char* name) {
 | 
			
		||||
    void* symbol = NULL;
 | 
			
		||||
    while (scope) {
 | 
			
		||||
        symbol = hmap_get(&scope->symbols, name);
 | 
			
		||||
        if (symbol) break;
 | 
			
		||||
        scope = scope->parent;
 | 
			
		||||
    }
 | 
			
		||||
    return symbol;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void* scope_lookup_current(Scope* scope, const char* name) {
 | 
			
		||||
    return hmap_get(&scope->symbols, name);
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										28
									
								
								ccompiler/frontend/parser/symtab/scope.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										28
									
								
								ccompiler/frontend/parser/symtab/scope.h
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,28 @@
 | 
			
		||||
#ifndef SCOPE_H
 | 
			
		||||
#define SCOPE_H
 | 
			
		||||
 | 
			
		||||
#include "hashmap.h"
 | 
			
		||||
 | 
			
		||||
struct Scope {
 | 
			
		||||
    HashMap symbols;      // 当前作用域符号表
 | 
			
		||||
    struct Scope* parent; // 上层作用域
 | 
			
		||||
    int base_offset;
 | 
			
		||||
    int cur_offset;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
// 创建新作用域(父作用域可为NULL)
 | 
			
		||||
struct Scope* scope_create(struct Scope* parent);
 | 
			
		||||
 | 
			
		||||
// 销毁作用域
 | 
			
		||||
void scope_destroy(struct Scope* scope);
 | 
			
		||||
 | 
			
		||||
// 在当前作用域插入符号
 | 
			
		||||
void scope_insert(struct Scope* scope, const char* name, void* symbol);
 | 
			
		||||
 | 
			
		||||
// 逐级查找符号
 | 
			
		||||
void* scope_lookup(struct Scope* scope, const char* name);
 | 
			
		||||
 | 
			
		||||
// 仅在当前作用域查找
 | 
			
		||||
void* scope_lookup_current(struct Scope* scope, const char* name);
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
							
								
								
									
										45
									
								
								ccompiler/frontend/parser/symtab/symtab.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										45
									
								
								ccompiler/frontend/parser/symtab/symtab.c
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,45 @@
 | 
			
		||||
// symtab.c
 | 
			
		||||
#include "../../frontend.h"
 | 
			
		||||
#include "scope.h"
 | 
			
		||||
#include "symtab.h"
 | 
			
		||||
 | 
			
		||||
typedef struct SymbolTable SymbolTable;
 | 
			
		||||
typedef struct Scope Scope;
 | 
			
		||||
 | 
			
		||||
void init_symtab(SymbolTable* symtab) {
 | 
			
		||||
    symtab->global_scope = scope_create(NULL);
 | 
			
		||||
    symtab->cur_scope = symtab->global_scope;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void del_symtab(SymbolTable* symtab) {
 | 
			
		||||
    scope_destroy(symtab->global_scope);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void symtab_enter_scope(SymbolTable* symtab) {
 | 
			
		||||
    struct Scope* scope = scope_create(symtab->cur_scope);
 | 
			
		||||
    scope->base_offset = symtab->cur_scope->base_offset + symtab->cur_scope->cur_offset;
 | 
			
		||||
    symtab->cur_scope = scope;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void symtab_leave_scope(SymbolTable* symtab) {
 | 
			
		||||
    Scope * scope = symtab->cur_scope;
 | 
			
		||||
    if (scope == NULL) {
 | 
			
		||||
        error("cannot leave NULL scope or global scope");
 | 
			
		||||
    }
 | 
			
		||||
    symtab->cur_scope = symtab->cur_scope->parent;
 | 
			
		||||
    scope_destroy(scope);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void symtab_add_symbol(SymbolTable* symtab, const char* name, void* ast_node) {
 | 
			
		||||
    struct Scope* scope = symtab->cur_scope;
 | 
			
		||||
    if (scope_lookup_current(scope, name) != NULL) {
 | 
			
		||||
        // TODO WARNING
 | 
			
		||||
        // return NULL;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    scope_insert(scope, name, ast_node);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void* symtab_lookup_symbol(SymbolTable* symtab, const char* name) {
 | 
			
		||||
    return scope_lookup(symtab->cur_scope, name);
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										18
									
								
								ccompiler/frontend/parser/symtab/symtab.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										18
									
								
								ccompiler/frontend/parser/symtab/symtab.h
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,18 @@
 | 
			
		||||
// symtab.h
 | 
			
		||||
#ifndef __SYMTAB_H__
 | 
			
		||||
#define __SYMTAB_H__
 | 
			
		||||
 | 
			
		||||
struct SymbolTable {
 | 
			
		||||
    struct Scope* cur_scope;
 | 
			
		||||
    struct Scope* global_scope;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
void init_symtab(struct SymbolTable* symtab);
 | 
			
		||||
void del_symtab(struct SymbolTable* symtab);
 | 
			
		||||
 | 
			
		||||
void symtab_enter_scope(struct SymbolTable* symtab);
 | 
			
		||||
void symtab_leave_scope(struct SymbolTable* symtab);
 | 
			
		||||
void symtab_add_symbol(struct SymbolTable* symtab, const char* name, void* ast_node);
 | 
			
		||||
void* symtab_lookup_symbol(struct SymbolTable* symtab, const char* name);
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
		Reference in New Issue
	
	Block a user