编译原理实验一:词法分析工具Flex
实验要求
根据cminux-f的词法补全[lexical_analyer.l](../../src/lexer/lexical_analyzer.l)文件,完成词法分析器,能够输出识别出的token,type ,line(刚出现的行数),pos_start(该行开始位置),pos_end(结束的位置,不包含)。如:
文本输入:
int a;
则识别结果应为:
int 280 1 2 5
a 285 1 6 7
; 270 1 7 8
实验难点
1.Flex的使用
将词素转换为词法单元有两种方式:第一种是手动用代码实现(需要画状态转移图辅助),另一种是使用词法分析器生成工具(需要使用正则表达式描述出词素的模式)。而Flex就是一个词法分析器生成工具。词法分析器工具的工作过程如下:
Lex源程序----->Lex编译器----->lex.yy.c
lex.yy.c-----> C编译器 ----->a.out
输入流 -----> a.out ----->词法单元的序列
而Lex源程序的格式如下:
声明部分:变量的定义和声明,会直接复制到lex.yy.c中。
%%
转换规则:形式为:模式{
动作},模式为正则表达式,动作则是代码片段。
%%
辅助函数:各个动作需要的辅助函数。用户自定义,直接复制到lex.yy.c末尾。
Lex中还有一些变量和函数,以下只给出了实验涉及的一部分:
-
yyin:FILE*,指向正在解析的文件。
-
yyout:FILE*,指向记录lexer输出的位置,缺省时yyin和yyout都指向标准输入和输出流。
-
yytext:char*,存储匹配模式的文本。
-
yylex():这一函数开始词法分析,由Lex自动生成。
-
yywrap():这一函数在文件或输入的末尾调用,返回值是1则停止解析。可以通过改变yyin指针指向不同文件,进行多文件的解析。
本实验主要是需要完成转换规则部分,给出cminux-f中词法单元的正则表达式和动作。
2.识别到词法单元的动作
运算符,符号,关键字,ID和NUM类型的词法单元在识别后,需要确定出现的行数,开始位置,结束的位置。出现的行数可以在识别到换行符时lines++实现,开始的位置为上一个识别的词法单元结束的位置,结束的位置为开始位置加上词素长度。最后返回token值结束完成一个词素的识别。因此识别到词法单元的动作如下:
RE {
pos_start=pos_end;pos_end=pos_start+strlen(yytext);return token}
对于运算符,符号和关键字,长度是确定的,可以直接加上长度,不需要调用sterlen。
3.识别到特殊词法单元的动作
对于注释,空格,换行符,只需要进行识别,不需要输出到分析结果中。这些token与程序运行无关。其中空格对接下来的词法单元无影响,与一般词法单元的动作相同;识别到换行符需要将lines++,并将开始位置置1;识别到注释时,由于注释中内容全部都与程序无关,需要判断注释中是否含有换行符,并将lines加上换行符的个数。因此在识别到这些词法单元时,处理如下:
int len;
while(token = yylex()){
switch(token){
case COMMENT:
len = strlen(yytext);
for(int i=0;i<len;i++){
if(yytext[i]=='\n') {
lines++;
pos_end = 1; //pos_start由pos_end得到,这里就不需要置1了
}
else pos_end++;
}
break;
case BLANK:
break;
case EOL:
lines++;
pos_end = 1

本文介绍如何使用词法分析工具Flex完成词法分析器的搭建,重点讲解词法单元的正则表达式及动作设置,并针对注释的处理进行了详细说明。通过实验设计与测试验证,展示了词法分析器的有效性和正确性。

2万+

被折叠的 条评论
为什么被折叠?



