编译原理比较复杂的词法分析器 含代码.docx
- 文档编号:8805129
- 上传时间:2023-02-01
- 格式:DOCX
- 页数:17
- 大小:110.97KB
编译原理比较复杂的词法分析器 含代码.docx
《编译原理比较复杂的词法分析器 含代码.docx》由会员分享,可在线阅读,更多相关《编译原理比较复杂的词法分析器 含代码.docx(17页珍藏版)》请在冰豆网上搜索。
编译原理比较复杂的词法分析器含代码
实验报告二
词法分析
一、总体设计思想
1)实验目的:
设计编制并调试一个词法分析程序,加深对构造词法分析器的原理和技术的理解与应用。
2)实验具体要求:
针对计算机高级程序语言——C语言子语言,运用恰当的词法分析技术线路,设计和实现C语言子语言的词法分析器。
Ø编程语言:
C语言/JAVA语言
Ø平台选择:
Linux/Windows
Ø技术线路(任选其一)
⏹正规式→NFA→DFA→minDFA→程序设计
⏹正规文法→NFA→DFA→minDFA→程序设计
Ø词法分析器程序输出形式,参见◤输出形式设计◢
Ø具有出错处理功能
C语言子语言词法描述——涉及的单词类如下:
(1)关键字
mainifelsewhiledoforintvoidchar
(2)运算符和界符
=
+
-
*
/
<
<=
>
>=
!
=
==
;
(
)
:
#
{
}
注:
#为结束标志符,详见◤程序框架◢
(3)标识符
正规式:
ID=letter(letter|digit)*
(4)整型常数
正规式:
NUM=digit(digit)*
3)词法分析器构造原理:
词法分析器就是根据语言的此法规则构造出识别其单词的有限自动机,它是一个数学模型,先给出识别各类单词的状态转换图,再将各类单词的状态转换图的初始状态合并成一个唯一的初状态;然后化简并调整冲突的状态编号;最后再将有限自动机变成一个可行的词法分析器。
二、种别码表设计及其在计算机中存放表示
1)单词种别码设计:
单词种别码对照表
单词符号
种别码
单词符号
种别码
main
1
/
16
if
2
:
17
else
3
=
18
while
4
}
19
do
5
<
20
for
6
!
=
21
int
7
<=
22
char
8
>
23
void
9
>=
24
标识符
10
==
25
整型常数
11
;
26
{
12
(
27
+
13
)
28
-
14
#
0
*
15
2)输出形式设计:
词法分析器的输入是源程序字符串,输出是对应的单词串。
每个单词按照二元组(种别码,单词符号本身)格式输出。
例如:
假设源程序为
main()
{
x=9;
y=4;
if(x>0)
x=2*x+1/3;
}#
则词法分析器对应输出的结果是:
(1,main)(27,()(28,))(12,{)(10,x)(18,=)(11,9)(26,;)(10,y)(18,=)
(11,4)(26,;)(2,if)(27,()(10,x)(23,>)(11,0)(10,x)(18,=)(11,2)
(15,*)(10,x)(13,+)(11,1)(16,/)(11,3)(26,;)(19,})(0,#)
三、词法分析程序详细设计
1)算法构造思想:
依据建立的识别单词的DFA,设计算法,其框架如下。
其中,
1syn存放单词的种别码;
2token存放符合C语言子语言词法规则的单词;
3sum存放整型常量的单词。
4Prog存放所有输入的字符。
5isSignal判断是否带正负号(0不带,1负号,2正号)。
6isDecimal判断是否是小数。
7isExp判断是否是指数。
2)主要模块算法的框图描述:
四、 主要代码
#include
#include
#include
charprog[80];//存放所有输入字符
chartoken[32];//②token存放符合C语言子语言词法规则的单词;
charch;//单个字符
intsyn,p,m,n;//①syn存放单词的种别码
doublesum;//③sum存放整型常量的单词。
intcount;
intisSignal;//是否带正负号(0不带,1负号,2正号)
intisDecimal;//是否是小数
doubledecimal;//小数
intisExp;//是否是指数
intindex;//指数幂
intisNegative;//是否带负号
doubletemp;
inttemp2;
intrepeat;
voidscanner();
char*rwtab[9]={"main","if","else","while","do","for","int","char","void"};
voidmain()
{
p=0;
count=0;
isDecimal=0;
index=0;
repeat=0;
printf("\npleaseinputarangeofdata,withtheendof#:
\n");
do{
ch=getchar();
prog[p++]=ch;
}while(ch!
='#');//输入以#号键结束
p=0;
do{
scanner();//扫描,单词
switch(syn)
{
case11:
if(isDecimal==0)
{
//加了1个强制类型转换
printf("(%d,%d)",syn,(int)sum);
break;
}
elseif(isExp==1)
{
printf("(%d,%e)",syn,sum);
isExp=0;
isDecimal=0;
break;
}
elseif(isDecimal==1)
{
printf("(%d,%f)",syn,sum);
isDecimal=0;
break;
}
case-1:
printf("输入错误:
")
printf("\n");
break;
default:
printf("(%d,%s)",syn,token);
}
}while(syn!
=0);
getchar();
}
voidscanner()
{
sum=0;
decimal=0;
m=0;
for(n=0;n<8;n++)
token[n]=NULL;
ch=prog[p++];//从prog中读出一个字符到ch中
while(ch=='')//跳过空字符(无效输入)
ch=prog[p++];
if(((ch>='a')&&(ch<='z'))||((ch>='A')&&(ch<='Z')))//ch是字母字符
{
while(((ch>='a')&&(ch<='z'))||((ch>='A')&&(ch<='Z'))||((ch>='0')&&(ch<='9')))
{
token[m++]=ch;//ch=>token
ch=prog[p++];//读下一个字符
}
token[m++]='\0';
p--;//回退一格
syn=10;
//如果是"main","if","else","while","do","for","int","char","void"标识符中的一个
for(n=0;n<9;n++)
if(strcmp(token,rwtab[n])==0)
{
syn=n+1;
break;
}
}
elseif((ch>='0')&&(ch<='9'))
{
IsNum:
if(isSignal==1)
{
//token[m++]='-';
}
while((ch>='0')&&(ch<='9'))
{
sum=sum*10+ch-'0';//ch中数字本身是当做字符存放的
ch=prog[p++];
}
if(ch=='.')
{
isDecimal=1;
ch=prog[p++];
count=0;//之前忘了清零,123.123+123.123#两个浮点数就无法识别
while((ch>='0')&&(ch<='9'))
{
//pow(x,y)计算x的y次幂
temp=(ch-'0')*pow(0.1,++count);
decimal=decimal+temp;
//AddToDec();
ch=prog[p++];
}
sum=sum+decimal;
}
if(ch=='e'||ch=='E')
{
isExp=1;
ch=prog[p++];
if(ch=='-')
{
isNegative=1;
ch=prog[p++];
}
while((ch>='0')&&(ch<='9'))
{
//指数
index=index*10+ch-'0';
ch=prog[p++];
}
//10的幂
//123e3代表123*10(3)
//sum=sum*pow(10,index);是错误的
if(isNegative)
sum=sum*pow(0.1,index);
else
sum=sum*pow(10,index);
}
if(isSignal==1)
{
sum=-sum;
isSignal=0;
}
p--;
syn=11;
}
elseswitch(ch)
{
case'<':
m=0;
token[m++]=ch;
ch=prog[p++];
if(ch=='=')
{
syn=22;
token[m++]=ch;
}
else
{
syn=20;
p--;
}
break;
case'>':
m=0;
token[m++]=ch;
ch=prog[p++];
if(ch=='=')
{
syn=24;
token[m++]=ch;
}
else
{
syn=23;
p--;
}
break;
case':
':
syn=17;
token[m++]=ch;
break;
case'+':
temp2=prog[p];
token[m++]=ch;
if((temp2>='0')&&(temp2<='9')&&(repeat==1))
{
isSignal=2;//isSignal正数
ch=prog[p++];
repeat=0;
gotoIsNum;
}
if(((temp2=='+')||(temp2=='-'))&&(repeat==0))//如果重复出现符号,才将后边的+,-视为正负号
{
repeat=1;
//ch=prog[p++];
}
syn=13;
break;
case'-':
temp2=prog[p];
token[m++]=ch;
if((temp2>='0')&&(temp2<='9')&&(repeat==1))
{
isSignal=1;
ch=prog[p++];//读“-”下一个字符
repeat=0;
gotoIsNum;//转到数字的识别
}
if(((temp2=='+')||(temp2=='-'))&&(repeat==0))//如果重复出现符号,才将后边的+,-视为正负号
{
repeat=1;//预言会重复
//ch=prog[p++];//读下一个字符
}
syn=14;
break;
case'*':
temp2=prog[p];
token[m++]=ch;
syn=15;
break;
case'/':
syn=16;
token[m++]=ch;
break;
case'=':
syn=18;
token[m++]=ch;
break;
case';':
syn=26;
token[m++]=ch;
break;
case'(':
temp2=prog[p];
token[m++]=ch;
syn=27;
break;
case'{':
temp2=prog[p];
token[m++]=ch;
syn=12;
break;
case'}':
temp2=prog[p];
token[m++]=ch;
syn=19;
break;
case')':
syn=28;
token[m++]=ch;
break;
case'#':
syn=0;
token[m++]=ch;
break;
default:
syn=-1;
}
}
五、测试结果
1)字符串输入测试:
2)小数输入测试:
六、设计体会与收获
通过此次试验,使我对词法分析器有了更加深入的了解,也使我对编译原理这门课程产生了浓厚的兴趣,虽然在实验过程中遇到了不少的困难,但是在同学以及老师共同的帮助下,都基本一一解决,使我懂得了团队精神的重要性。
同时通过本次的实验,使我重新学习了C语言编程方法,知识也得到了相应的扩展,思考问题的方式也能够变得多样化和灵活化。
总的来说,本学期编译原理课程的实验让我受益匪浅。
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 编译原理比较复杂的词法分析器 含代码 编译 原理 比较 复杂 词法 分析器 代码