-
词法分析的功能
词法分析是编译器处理流程中的第一步,它顺序扫描文件内的字符,通过硬编码方式解析器进行匹配,产生各式各样的词法记号。
-
扫描器
扫描器读取源文件年,按序返回文件内的字符,直到文件结束。为了节省IO开销,解释用缓冲区结构。
#define BUFFEN 100 //缓冲区大小
int len_data = 0; //缓冲区数据长度
int readIndex = -1; //读取位置下标
char buffer[BUFFEN]; //缓冲区
int rowlNum = 0; //行号
int colNum = 0; //列号 设置行号和列号的原因为了报错信息
char priorchar ; //上一个字符
char scan(FILE *file)
{
if(!file) //如果文件不存在
return -1;
if(readIndex==len_data-1) //缓冲区数据已经读取完毕或者为空
{
len_data = fread(buffer,1,BUFFEN,file); //加载新的数据
if(len_data==0) //源文件已经读取完毕
{
len_data=1; //设置数据长度为一,因为文件结束标记占一位
buffer[0]=-1; //文件结束标记
}
readIndex=-1; //恢复初始读取位置
}
readIndex++; //读取下一个字符
char ch = buffer[readIndex];
if(priorchar=='\n') //读取新行
{
rowNum++: //行号加一
colNum=0; //列号清零
}
if(ch==-1) //文件结束
{
fclose(file);
file=NULL;
}
else if(chh!='\n')
colNum++; //列号加一
priorchar = ch;
return ch;
}
- 词法记号
词法记号通常可以分为标识符、关键字、常量、界符四大类。
我们使用一个枚举类型记录所有的词法记号标签,为后面的代码提供符好定义。
enum Tag
{
ERROR, //错误异常
END, //文件结束标记
ID, //标示符
NUM,CHAR,STR, //常量
KW_INT,KW_CHAR,KW_VOID, //数据类型
KW_EXTERN, //extern
NOT,LEA, //单目运算符
ADD,SUB,MUL,DIV,MOD, //算法运算符
INC,DEC, //自加自减
GT,GE,LE,LE,EQU,NEQU, //比较运算符
AND,OR, //逻辑运算符
LPAREU,RPAREN, //()
LBRACK,RBRACK, //[]
LBRACE,RBRACE, //{}
COMMA,COLON,SEMICON, //逗号,冒号,分号
ASSIGN, //赋值
KW_IF,KW_ELSE, //if else
KW_SWITCH,KW_CASE,KW_DEFAULT,
KW_WHILE,KW_DO,KW_FOR, //循环
KW_BREAK,KW_CONTINUE,KW_RETURN //break,continue,return
};
词法记号标签只是区分了不同的词法记号,对于标示符、常量等特殊词法记号除了需要保存词法记号标签信息外,还要保存标示符名称、常量值等信息,以用来构造符号表。
基类Token表示一般的词法记号,它只包含一个公有字段tag,用于记录词法记号的标签,Token有四个派生类Id、Num、Char、Str,分别对应标示符、数字常量、字符常量、字符串常量。Id公有字段name记录标识符的名称,Num的公有字段val记录了数字常量的值&#