编译原理 实验一 词法分析程序开发.docx
《编译原理 实验一 词法分析程序开发.docx》由会员分享,可在线阅读,更多相关《编译原理 实验一 词法分析程序开发.docx(16页珍藏版)》请在冰豆网上搜索。
编译原理实验一词法分析程序开发
集美大学计算机工程学院实验报告
课程名称:
编译原理
指导教师:
付永钢
实验成绩:
实验编号:
实验一
实验名称:
词法分析程序开发
班级:
计算1214
姓名:
学号:
上机实践日期:
2014.11
上机实践时间:
4学时
一、实验目的
1、深入理解有限自动机及其应用;
2、掌握词法分析程序的开发。
;
3、掌握根据语言的词法规则构造识别其单词的有限自动机的方法;
4、深入理解词法分析程序自动生成原理。
二、实验环境
Windows7x64、VC6.0
三、实验原理
词法分析是编译过程的第一阶段。
它的任务就是对输入的字符串形式的源程序按顺序进行扫描,根据源程序的词法规则识别具有独立意义的单词(符号),并输出与其等价的Token序列。
有限自动机是描述程序设计语言单词构成的工具,而状态转换图是有限自动机的比较直观的描述方法。
我们使用确定的有限状态自动机,简记为DFA。
PL/0的语言的词法分析器将要完成以下工作:
(1)跳过分隔符(如空格,回车,制表符);
(2)识别诸如begin,end,if,while等保留字;
(3)识别非保留字的一般标识符,此标识符值(字符序列)赋给全局量id,而全局量sym赋值为SYM_IDENTIFIER。
(4)识别数字序列,当前值赋给全局量NUM,sym则置为SYM_NUMBER;
(5)识别:
=,<=,>=之类的特殊符号,全局量sym则分别被赋值SYM_BECOMES,SYM_LEQ,SYM_GEQ等。
相关过程(函数)有getsym(),getch(),其中getch()为获取单个字符的过程,除此之外,它还完成:
(1)识别且跳过行结束符;
(2)将输入源文件复写到输出文件;
(3)产生一份程序列表,输出相应行号或指令计数器的值。
下面给出能够识别PL0语言中各类单词的DFA:
根据语言的词法规则构造出识别其单词的确定有限自动机DFA,仅仅是词法分析程序的一个形式模型,距离词法分析程序的真正实现还有一定的距离。
状态转换图的程序实现通常是采用直接转向法。
直接转向法又称为程序中心法,是把状态转换图看成一个流程图,从状态转换图的初态开始,对它的每一个状态结点都编写一段相应的程序。
四、实验步骤
1、用自动生成工具LEX生成上述给定DFA所对应的PL0语言的词法分析程序
①在txt文档中编写lex文件test1.l
②在命令行下执行命令flex解析test.l文件,自动生成lex.yy.c文件
③在C环境编译lex.yy.c,生成可执行文件lex.yy.exe对测试用例进行测试
2、根据DFA在C环境下构造词法分析器对测试用例进行测试
五、实验结果
测试程序:
proceduredivide;
varw;
begin
r:
=x;q:
=0;w:
=y;
end
1、自动生成工具LEX测试:
2、C环境分析器测试:
六、实验小结
1、通过本次实验,对有限自动机及其应用有了进一步的了解,对词法分析程序的开发有了一定的认识;
2、第一次使用自动生成工具LEX,对LEX语法不熟悉,通过查阅网上资料,词法分析程序自动生成原理有了一定的认识,能够基本完成本实验的需求,同时对本课程的实际意义也有了全面的理解;
3、在通过C语言编写词法分析器的过程中,用二维数组构造分析表,但是不断出现栈溢出问题,后将分析表缩小,仅存保留字,对其他符号逐一判断,实现本实验要求词法分析器;
4、利用C语言构造词法分析器,考虑到分隔符问题,在本次实验中,仅考虑了‘\n’、‘\t’、空格、以及‘;’,凡不以这四个字符结束的串都被视为错误。
程序代码:
1、LEX:
digit[0-9]
letter[A-Za-z]
id({letter}|[_])({letter}|{digit}|[_])*
%%
[|\t|\n]+
"var"{printf("21,\"%s\"\n",yytext);}
"if"{printf("22,\"%s\"\n",yytext);}
"then"{printf("23,\"%s\"\n",yytext);}
"else"{printf("24,\"%s\"\n",yytext);}
"while"{printf("25,\"%s\"\n",yytext);}
"for"{printf("26,\"%s\"\n",yytext);}
"begin"{printf("27,\"%s\"\n",yytext);}
"writeln"{printf("28,\"%s\"\n",yytext);}
"procedure"{printf("29,\"%s\"\n",yytext);}
"end"{printf("30,\"%s\"\n",yytext);}
{id}{printf("1,\"%s\"\n",yytext);}
{digit}+{printf("2,\"%s\"\n",yytext);}
"+"{printf("3,\"%s\"\n",yytext);}
"-"{printf("4,\"%s\"\n",yytext);}
"*"{printf("5,\"%s\"\n",yytext);}
"/"{printf("6,\"%s\"\n",yytext);}
"="{printf("7,\"%s\"\n",yytext);}
">"{printf("8,\"%s\"\n",yytext);}
"<"{printf("9,\"%s\"\n",yytext);}
"<>"{printf("10,\"%s\"\n",yytext);}
"<="{printf("11,\"%s\"\n",yytext);}
">="{printf("12,\"%s\"\n",yytext);}
"("{printf("13,\"%s\"\n",yytext);}
")"{printf("14,\"%s\"\n",yytext);}
"{"{printf("15,\"%s\"\n",yytext);}
"}"{printf("16,\"%s\"\n",yytext);}
";"{printf("17,\"%s\"\n",yytext);}
","{printf("18,\"%s\"\n",yytext);}
"\""{printf("19,\"%s\"\n",yytext);}
":
="{printf("20,\"%s\"\n",yytext);}
%%
#include
intmain(){
yylex();
return0;
}
yywrap(){
return1;
}
2、C程序
#include"stdio.h"
#include"conio.h"
#include"string.h"
voidmain()
{
inti=0,j;
intk1=0,k2=0;
chartable[10][10]={"var","if","then","else","while","for","begin","writeln","procedure","end"};
charc;
chart[20]={"\0"};//缓冲,用于存放临时串
freopen("D:
\\学习相关\\编译原理\\第一部分实验内容\\C\\in.txt","r",stdin);
c=getchar();
while(c!
=EOF){
if(c==''||c=='\n'||c=='\t'){
c=getchar();
}
elseif((c>='a'&&c<='z')||(c>='A'&&c<='Z')){
t[i++]=c;
c=getchar();
while((c>='a'&&c<='z')||(c>='A'&&c<='Z')||(c>='0'&&c<='9')){
t[i++]=c;
c=getchar();
}
if(c==''||c=='\n'||c=='\t'||c==';'){
for(j=0;j<10;j++){
if(strcmp(t,table[j])==0){
printf("%d,\"%s\"\n",j+21,t);
k1=1;//不是保留字标志
break;
}
}
if(k1==0)
printf("1,\"%s\"\n",t);//标识符
if(c==';')
printf("17,\";\"\n");
c=getchar();
}
else
printf("100,error\n");
for(j=0;j<=i;j++)
t[j]='\0';
k1=0;
i=0;
}
elseif(c>='0'&&c<='9'){
t[i++]=c;
c=getchar();
while((c>='0'&&c<='9')){
t[i++]=c;
c=getchar();
}
if(c==''||c=='\n'||c=='\t'||c==';'){
printf("2,\"%s\"\n",t);
}
if(c==';')
printf("17,\";\"\n");
for(j=0;j<=i;j++)
t[j]='\0';
i=0;
}
elseif(c=='>'){
c=getchar();
if(c==''||c=='\n'||c=='\t'){
printf("8,\">\"\n");
}
elseif(c=='='){
c=getchar();
if(c==''||c=='\n'||c=='\t')
printf("12,\">=\"\n");
else
printf("100,error\n");
}
else{
printf("100,error\n");
}
}
elseif(c=='<'){
c=getchar();
if(c==''||c=='\n'||c=='\t'){
printf("9,\"<\"\n");
}
elseif(c=='>'||c=='='){
if(c=='=')
k2=1;
c=getchar();
if(c==''||c=='\n'||c=='\t'){
if(k1==0)
printf("10,\"<>\"\n");
else
printf("11,\"<=\"\n");
}
else
printf("100,error\n");
}
else{
printf("100,error\n");
}
}
elseif(c=='+'){
c=getchar();
if(c==''||c=='\n'||c=='\t'){
printf("3,\"+\"\n");
}
else{
printf("100,error\n");
}
}
elseif(c=='-'){
c=getchar();
if(c==''||c=='\n'||c=='\t'){
printf("4,\"-\"\n");
}
else{
printf("100,error\n");
}
}
elseif(c=='*'){
c=getchar();
if(c==''||c=='\n'||c=='\t'){
printf("5,\"*\"\n");
}
else{
printf("100,error\n");
}
}
elseif(c=='/'){
c=getchar();
if(c==''||c=='\n'||c=='\t'){
printf("6,\"/\"\n");
}
else{
printf("100,error\n");
}
}
elseif(c=='='){
c=getchar();
if(c==''||c=='\n'||c=='\t'){
printf("7,\"=\"\n");
}
else{
printf("100,error\n");
}
}
elseif(c=='('){
c=getchar();
if(c==''||c=='\n'||c=='\t'){
printf("13,\"(\"\n");
}
else{
printf("100,error\n");
}
}
elseif(c==')'){
c=getchar();
if(c==''||c=='\n'||c=='\t'){
printf("14,\")\"\n");
}
else{
printf("100,error\n");
}
}
elseif(c=='{'){
c=getchar();
if(c==''||c=='\n'||c=='\t'){
printf("15,\"{\"\n");
}
else{
printf("100,error\n");
}
}
elseif(c=='}'){
c=getchar();
if(c==''||c=='\n'||c=='\t'){
printf("16,\"}\"\n");
}
else{
printf("100,error\n");
}
}
elseif(c==';'){
c=getchar();
if(c==''||c=='\n'||c=='\t'){
printf("17,\";\"\n");
}
else{
printf("100,error\n");
}
}
elseif(c=='\''){
c=getchar();
if(c==''||c=='\n'||c=='\t'){
printf("18,\"\'\"\n");
}
else{
printf("100,error\n");
}
}
elseif(c=='\"'){
c=getchar();
if(c==''||c=='\n'||c=='\t'){
printf("19,\"\"\"\n");
}
else{
printf("100,error\n");
}
}
elseif(c==':
'){
c=getchar();
if(c=='='){
c=getchar();
if(c==''||c=='\n'||c=='\t')
printf("20,\":
=\"\n");
else
printf("100,error\n");
}
else{
printf("100,error\n");
}
}
else{
printf("100,error\n");
c=getchar();
}
}
fclose(stdin);//关闭文件
}