Tiny语言编译器的符号表还是很简单的,主要的是写了一个简单的哈希表,共有211个桶,采用拉链法,用另外一个链表记录了一个符号所出现的所有行号,源代码如下:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "symtab.h"
#define SHIFT 4
#define SIZE 211
//哈希函数
static int hash(char* key)
{
int temp=0;
int i=0;
while(key[i]!='\0')
{
temp = ((temp<<SHIFT)+key[i])%SIZE;
i++;
}
return temp;
}
//记录符号行号的链表
typedef struct LineListRec
{
int lineno;
struct LineListRec* next;
}*LineList;
//哈希表的桶定义
typedef struct BucketListRect
{
char *name;
LineList lines;
int memloc;
struct BucketListRect *next;
}*BucketList;
//哈希表
static BucketList hashTable[SIZE];
void st_insert(char* name, int lineno, int loc)
{
int h=hash(name);
BucketList l= hashTable[h];
while((l!=NULL) && (strcmp(name, l->name)!=0))
l=l->next;
//如果从未出现过该符号
if(l==NULL)
{
l=(BucketList)malloc(sizeof(struct BucketListRect));
l->name = name;
l->memloc = loc;
l->lines=(LineList)malloc(sizeof(struct LineListRec));
l->lines->lineno = lineno;
l->lines->next=NULL;
l->next = hashTable[h];
hashTable[h]=l;
}
else //已经出现过该符号了,找到相应的桶,只需要再添加一个行号,忽略name和loc
{
LineList t = l->lines;
while(t->next!=NULL) t=t->next;