编译原理词法分析课程设计报告Word格式.docx
- 文档编号:22457466
- 上传时间:2023-02-04
- 格式:DOCX
- 页数:24
- 大小:307.99KB
编译原理词法分析课程设计报告Word格式.docx
《编译原理词法分析课程设计报告Word格式.docx》由会员分享,可在线阅读,更多相关《编译原理词法分析课程设计报告Word格式.docx(24页珍藏版)》请在冰豆网上搜索。
(三)、对于此题,我使用Lex编程来自动生成词法分析器。
使用Lex编程的重点与难点是正则式的定义,对于容易产生二义性的正则表达式,我们要借助与辅助函数来解决。
以下为一个二义性的解决;
plus({Int}|{Float}|{id}){blank}?
\+//加号的正则定义
{plus}{install(yytext,PLUS);
}//转换规则里的模式{动作}
需要说明的是:
当‘+’左边为一个标示符(id)或数字(num)时,我们才认为它是加号;
否则为正号。
但匹配到plus正则式时,我们调用intinstall()辅助函数,intinstall()函数再把“+”前面的标示符(id)或数字(num)与“+”分离开来,其余三个容易产生歧义的符号,也采用同种处理方法,install()辅助函数的定义,将在本报告的第四部分<
程序说明>
中给出。
四、程序说明
Lex是一种生成扫描器的工具,我们可以通过编写Lex文件来实现识别文本中的词汇模式的程序。
一个Lex程序可具有如下形式:
声明、定义部分
%%
转换规则
%%
辅助函数
1、声明部分包括变量和明示常量(被声明的表示一个常数标示符,如一个此法单元的名字)的声明,本程序声明部分包括:
C语言的头文件,及为每个关键字定义一个宏常量,为避免与ASCII冲突,数值从257开始。
定义部分同时给出了正则表达式。
第一段的部分如下,详细见附件二
声明部分
%{
#include<
stdio.h>
#include<
string.h>
ctype.h>
intyywrap();
#defineLB257
#defineLP258
….
#defineREAL_LITERAL367
#defineSTRING368
#defineCHARACTER369
#defineNUM370
%}
正则表达式
blank\0
delim[\t\n]
ws{delim}+
FloatE?
{digit}+(\.{digit}+)+(e{E}?
{digit}+)?
[Ff]
id{letter}({letter}|{digit})*
incom(\/\*[^*]*\*+([^/*]*\*+)*\/)|(\/\/(.)*)
mul({Int}|{Float}|{id}){blank}?
\*//乘号的正则定义
Bit({Int}|{Float}|{id}){blank}?
\&
//按位与的正则定义
sub({Int}|{Float}|{id}){blank}?
\-//减号的正则定义
2.LEX程序的每个转换规则具有如下形式:
模式{动作}
其中,每个模式是一个正则表达式,我的程序的正则表达式的定义全部在声明部分给出。
动作部分是代码片段。
以下为转换规则部分
}
{sub}{install(yytext,MINUS);
{mul}{install(yytext,MULT);
"
+="
{printf("
<
%s,%d>
\n"
yytext,PLUSA);
-="
yytext,MINUSA);
*="
yytext,MULA);
/="
yytext,DIVA);
Lex机器经过此法扫描。
通过模式匹配产生一个动作,其形式为<
词素,属性值>
,其中词素为当前匹配到的最长字符串,属性值为该词素对应的属性值,这里我们通过lex程序的声明部分的宏声明,给出每个词素对应的属性值,每个词素的属性值是唯一的。
3.Lex程序的第三个部分包括各个动作需要的所有辅助函数,其中int yywrap() 函数,这里作者定义了一个用于消除“+、—、*、&
”二义性的辅助函数
intinstall(constchar*y,intb)
{
intlen=strlen(y);
charid[len];
inti;
for(i=0;
i<
len-1;
++i)
id[i]=*(y+i);
id[len-1]='
\0'
;
if(!
sdigit(id))printf("
%s,%d>
id,IDENTIFIER);
elseprintf("
id,NUM);
printf("
%c,%d>
y[len-1],b);
return0;
};
五、程序运行结果
在lunix中用vi编辑器,编辑一个名叫lex.l的lex程序文件;
lex编译器产生lex.yy.c文件:
(如下图)
用gcclex.yy.c–ll命令产生a.out文件:
执行a.out文件,其中goods.c为要进行词法分析的C程序源文件,
使用:
./a.outgoods.c>
goods.tok通过命令行传递文件,并把分析器产生的词素通过重定向符‘>
’输入goods.tok文件中(操作如下图)
通过分屏操作符more打开goods.tok文件(如下图)
其中good.c文件的部分如下图:
六、测试报告
1、现在用写好的lex程序,用来扫描一个li.c文件,程序的重点在于二义性的处理,简单起见,我的li.c文件的内容不会太多,具体如下图:
图
(一)
2、我们用命令./a.outli.c>
li.tok对li.c文件进行词法分析,得到的结果输入到li.tok文件中,我们打开li.tok文件,其结果如下图:
图
(二)
在lex程序的声明部分我们定义了如下宏:
#definePLUS261//“+”为加号
#defineMINUS262//“-”为减号
#defineMULT263//“*”为乘号
#defineBITAND276//“&
”为按位与操作
#defineUNARYMINUS297//“-”为正号
#defineUNARYPLUS298//“+”为负号
#defineDEREFERECE299//“*”为指针号
#defineADDRESS300//“&
”为引用符号
#defineIDENTIFIER303
我们由第一部可知a、b、c都为标示符(id),所以a、b、c其属性指都是303,第一个表达式a+b,扫描结果理论为<
+,261>
表示其为加号,由图二可知此法扫描实际结果与理论匹配;
第二表达式+a中的“+”理论上是正号,对应的是<
+,298>
图二中的实际结果也是<
,其他表达式,同理也可分析出。
七、存在问题及分析
词法分析的正则表达式编写有些不是很全面简洁,比如说char和income的正则式。
宏定义部分显得冗余,没有把握住词法分析的程序关键要处理的词素,
识别某些词法记号的正则表达式编写的不是很严谨,比如说在识别C语言预处理定义语句的正则表达式仅仅只能识别出预处理语句,而无法进行预处理包含的头文件的词法分析。
程序存在一个瑕疵,在处理”+、—、*、&
”时,扫描id+id、id*id、id-id、id&
id,时,把这四个符号当成加、减、乘、与符号,但当扫描遇到num+、num*、num&
、num-时,分不出mun是int还是float类型,只是笼统的把它归为数字。
这个问题是在设计辅助函数,及在正则式定义是出现的最大漏洞。
对Lex编程还不是很了解,对词法分析器的作用以及工作原理的理解还有待提高
八、总结及体会
在拿到本次课程设计题目后,对是用C/C++还是lex进行了分析,用C/C++语言直接编写词法分析程序从思路上来说会比较容易些,但在写代码的过程中,慢慢地就暴露出直接编写词法分析程序的一些问题,比如说代码里充斥着大量的if…switch…语句,也频繁些读写语句,极大地增加了代码的复杂度,从而促使我选择使用unix下的Lex编程来自动生成词法分析器的方案。
使用Lex编程就简化了代码的编写,但是Lex编程的重点是正则表达式的定义。
本次课程设计也暴露了我在编译原理学习中的一些不足,比如对正规式的含义和编写还有一些疑问,对辅助函数的编写显得不严谨,对词法分析器的作用和工作原理理解的不是很清等等,通过课程设计很好的复习了编译原理课程中的词法分析部分,对自己理解词法分析有很大的帮助
参考文献
AlfredV.AhoMonicaS.LamRaviSethiJeffreyD.Ullman《编译原理》,机械工程出版社
附录:
附录一
C语言词法记号及其含义表
MINUS
“-”
MULT
“*”
DIV
“/”
MOD
“%”
PLUSA
“+=”
MINUSA
“-=”
MULA
“*=”
DIVA
“/=”
MODA
“%=”
LS
“<
”
RS
“>
>
LSA
=”
RSA
NOT
“!
BITAND
&
BITOR
|"
XOR
^"
COMPL
~"
AND
“&
OR
“||”
LT
LE
GT
GE
EQ
“==”
NE
ASSIGN
“=”
DOT
“.”
MS
->
LA
["
RA
]"
POSINC
++"
POSDEC
--"
PREINC
PREDEC
UNARYMINUS
-"
附件二程序源代码:
%{
/****************************************************************************
Filename:
lex.l
ProductLexfileinunix
Author:
蒋阳斌学号:
2402090206
**************************************************************************/
#defineRB259
#defineRP260
#definePLUS261
#defineMINUS262
#defineMULT263
#defineDIV264
#defineMOD265
#definePLUSA266
#defineMINUSA267
#defineMULA268
#defineDIVA269
#defineMODA270
#defineLS271
#defineRS272
#defineLSA273
#defineRSA274
#defineNOT275
#defineBITAND276
#defineBITOR277
#defineXOR278
#defineCOMPL279
#defineAND280
#defineOR281
#defineLT282
#defineLE283
#defineGT284
#defineGE285
#defineEQ286
#defineNE287
#defineASSIGN288
#defineDOT289
#defineMS290
#defineLA291
#defineRA292
#definePOSINC293
#definePOSDEC294
#definePREINC295
#definePREDEC296
#defineUNARYMINUS297
#defineUNARYPLUS298
#defineDEREFERECE299
#defineADDRESS300
#defineCOMMA301
#defineSC302
#defineASM304
#defineAUTO305
#defineBOOL306
#defineBREAK307
#defineCASE308
#defineCATCH309
#defineCHAR310
#defineCLASS311
#defineCONST312
#defineCONST_CAST313
#defineCONTINUE314
#defineDEFAULT315
#defineDELETE316
#defineDO317
#defineDOUBLE318
#defineDYNAMIC_CAST319
#defineELSE320
#defineENUM321
#defineEXPLICIT322
#defineEXTERN323
#defineFALSE324
#defineFLOAT325
#defineFOR326
#defineFRIEND327
#defineGOTO328
#defineIF329
#defineINLINE330
#defineINT331
#defineLOG332
#defineLONG333
#defineMUTABLE334
#defineNAMESPACE335
#defineNEW336
#defineOPERATOR337
#definePRIVATE338
#definePROTECTED339
#definePUBLIC340
#defineREGISTER341
#defineREINTERPRET_CAST342
#defineRETURN343
#defineSHORT344
#defineSIGNED345
#defineSIZEOF346
#defineSTATIC347
#defineSTATIC_CAST348
#defineSTRUCT349
#defineTEMPLATE350
#defineTHIS351
#defineTHROW352
#defineTRUE353
#defineTRY354
#defineTYPEDEF355
#defineTYPRID356
#defineTYPENAME357
#defineUNION358
#defineUNSIGNED359
#defineUSING360
#defineVIRTUAL361
#defineVOID362
#defineVOLATITLE363
#defineWCHAR_T364
#defineWHILE365
#defineINTEGER_LITERAL366
/*正则式的定义*/
letter[A-Za-z]
digit[0-9]
E[+-]
Int{E}?
{digit}+
Float{E}?
{digit}+(\.{digit}+)[Ff]
Oct0(E?
)[0-7]+
UNSIGN[0-9]+[uU]
HEX0[xX](E?
)[a-fA-F0-9]+
string\"
[^"
]*\"
char(\\(([ntbrf\\'
])|([0-7]{1,3})|([xX][A-Fa-f0-9]{1,2})))|\'
[^'
]\'
headfile#include\<
[A-Za-z]+(.h)?
\>
\*
Bit({id}|{Int}|{Float}){blank}?
plus({id}|{Int}|{Float}){blank}?
\+
sub({id}|{Int}|{Float}){blank}?
\-
/*转换规则*/
{ws}{/*noaction*/}
{"
{printf("
yytext,LB);
("
yytext,LP);
}"
yytext,RB);
)"
yytext,RP);
{plus}{install(PLUS);
}//匹配加号
{sub}{install(MINUS);
}//匹配减号
{mul}{install(MULT);
}//匹配乘号
{Bit}{install(BITAND);
}//匹配按位与操作符
/"
yytext,DIV);
%"
yytext,MOD);
%="
yytext,MODA);
yytext,LS);
yytext,RS);
="
yytext,LSA);
yytext,RSA);
!
yytext,NOT);
yytext,COMPL);
yytext,AND);
||"
yytext,OR);
yytext,LT);
yytext,LE);
yytext,GT);
yytext,GE);
=="
yytext,EQ);
yytext,NE);
yytext,ASSIGN);
."
yytext,DOT);
yytext,MS);
yytext,LA);
yytext,RA);
yytext,POSINC);
yytext,POSDEC);
yytext,UNARYMINUS);
}//匹配符号
+"
yytext
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 编译 原理 词法 分析 课程设计 报告