实验一、flex词法分析
具体flex使用方法,可参考编译原理-词法分析实践(flex)
1. %option yylineno
使得yylineno自动更新,返回所在行的行号。
2. 定义段
该段直接拷贝到c代码中运行,定义为flex中的全局变量。
%{
#include "stdio.h"
#include "string.h"
%}
id [A-Za-z][A-Za-z0-9]*
intconst [0-9]+
3. 规则段
%%
[ \r\t\n] {}
{intconst} {printf("(51,%s) ",yytext);}
"+" {printf("(60,-) ");}
"-" {printf("(61,-) ");}
"*" {printf("(62,-) ");}
"/" {printf("(63,-) ");}
"=" {printf("(64,-) ");}
"<" {printf("(65,-) ");}
">" {printf("(67,-) ");}
"{" {printf("(71,-) ");}
"}" {printf("(72,-) ");}
"(" {printf("(73,-) ");}
")" {printf("(74,-) ");}
"," {printf("(75,-) ");}
";" {printf("(76,-) ");}
"int" {printf("(1,-) ");}
"while" {printf("(2,-) ");}
"if" {printf("(3,-) ");}
"else" {printf("(4,-) ");}
"return" {printf("(5,-) ");}
{id} {printf("(50,\"%s\") ",yytext);}
. {printf("\n<error character \'%s\' in line %d> ",yytext,yylineno);}
"<=" {printf("(66,-) ");}
">=" {printf("(68,-) ");}
"==" {printf("(69,-) ");}
"!=" {printf("(70,-) ");}
<<EOF>> { return 0; }
%%
在规则段中注意,如若有两个同等长度的符号匹配,则优先匹配前方的符号。
例如“+”,“”都可匹配符号“+”,则优先匹配写在前方的符号,因此必须将单符号,单字母,写在之前。同理,必须将关键字写在ID匹配之前。
对于特定字符,使用“”括起来匹配,对于正则表达式,直接使用正则表达式,或用{}括起来正则表达式的标识符,例如{id}使用。
<>表示匹配文件末尾标识符。
yytest为flex自带全局变量,保存当前正在匹配的字符串。
4. 用户子程序段
int main(int argc,char *argv[])
{
yylineno=1; //行序号变量,每次遇到\n后会自动加1
yyin=fopen(argv[1],"r");
if (!yyin) return 0;
while (yylex());
return 0;
}
int yywrap() { return 1;}
初始化yylineno,读入文件,while循环yylex,yylex调用规则段匹配程序。
5.编译运行
环境:将flex.exe所在文件的目录保存在用户系统变量中。
在test.l文件下运行cmd。
输入:flex test.l
编译文件,生成C文件lex.yy.c
输入:gcc lex.yy.c
编译c文件,生成可执行文件a.exe
输入:a.exe <需要编译的文件名称>
得到运行结果
实验二、词法分析(确定有穷自动机)
1. 文件的打开
FILE *fp;
fp=fopen(argv[1],"r");
if (!fp) {printf("Fail Open\n");return 0;}
2. 文件的读入
char c = fgetc(fp);
3. 文件的指针修改
fseek(fp,-1,SEEK_CUR);//从当前指针向后退一个字符。
4. 实现有穷自动机的方法:
- 1)使用函数分割不同状态
- 2)使用switch case来分割不同的状态
5. 有穷自动机
- 首输入为数字时,转入数字状态。
- 当首输入为字母时,转入关键字/ID状态。
- 当首输入为特殊符号时,转入相对应的符号状态
- 当首输入为回车、空格、制表符,跳过。
- 数字状态下,匹配数字,直到遇到非数字字符时,退回输入字符,并返回匹配的数字。
- 关键字/ID状态下,匹配字母、数字、下划线。遇到非法字符时,退回输入字符,并首先匹配关键字,如若没有匹配,则匹配ID。
- 特殊符号状态下,判断是否有双字符运算符,如若有,尝试匹配第二个字符。
实验总结:
掌握了flex的使用方法,flex词法构造,有穷自动机的构造等。
理解了编译器的词法部分的实现过程。