c4为实现编译器自举 ,不使用结构体而使用指针存放表,对于标识符的检测主要有下边
enum { Tk, Hash, Name, Class, Type, Val, HClass, HType, HVal, Idsz };
token:唯一标识(id)
hash:hash 值 用于在strcmp前置的检索,提高标识符的检索速度
name:这个标识符的字符串
class:类型 (局部变量/全局变量/
type:类型(int/char/
value: 值
后三个H: 当全局变量和局部变量冲突时候,用于保存全局变量的属性
Idsz:长度 不为表内容 用于添加值 即数字9 一个标识符空间为9*sizeof(int)
其中定义全局变量
int *symbols_tab,*cur_id;
int token_val;
else if((token>='a'&&token<='z')||(token>='A'&&token<="Z")||token=='_') //标识符开头;
{
st_pos=src-1;
while((*src>='a'&&*src<='z')||(*src>='A'&&*src<="Z")||*src=='_'||(*src>= '0' && *src<= '9'))
{hash=token*147+*src;//hash fun
src++;
}
en_pos=src-1;
cur_id=symbols_tab;
while (cur_id[Token]) { //遍历符号表
if (cur_id[Hash] == hash && !memcmp((char *)cur_id[Name], st_pos, en_pos-st_pos+1)) {
token = cur_id[Token]; //如果是已经存在的字符
return;
}
else cur_id=cur_id+IdSize; //++
}
//如果没有return(跳出) ,下面这段相当于往表中push一个新的symbol
cur_id[Name]=(int)st_pos;
cur_id[Hash]=hash;
token=cur_id[Token]=Id;
return;
}
在进行语法分析前提前初始化
enum { CHAR, INT, PTR };
int *idmain; //main函数
c4的方法
// 用词法分析器先把这些关键词放进符号表
p = "char else enum if int return sizeof while "
"open read close printf malloc memset memcmp exit void main";
// 把关键词加进去,id[Tk]修改为和Enum一致
i = Char; while (i <= While) { next(); id[Tk] = i++; } // add keywords to symbol table
//把[库]里定义的符号(系统函数等) 加进去 Class 赋值为Sys
i = OPEN; while (i <= EXIT) { next(); id[Class] = Sys; id[Type] = INT; id[Val] = i++; } // add library to symbol table
// void 认为是char
next(); id[Tk] = Char; // handle void type
// 记录main函数的符号id
next(); idmain = id; // keep track of main
相对容易
字符串识别容易了
数字的识别需要注意一下进制
符号的识别就是将token转换为以下枚举变量
enum {
Num = 128, Fun, Sys, Glo, Loc, Id,
Char, Else, Enum, If, Int, Return, Sizeof, While,
Assign, Cond, Lor, Lan, Or, Xor, And, Eq, Ne, Lt, Gt, Le, Ge, Shl, Shr, Add, Sub, Mul, Div, Mod, Inc, Dec, Brak
};