编译原理比较复杂的词法分析器 含代码Word格式文档下载.docx
《编译原理比较复杂的词法分析器 含代码Word格式文档下载.docx》由会员分享,可在线阅读,更多相关《编译原理比较复杂的词法分析器 含代码Word格式文档下载.docx(17页珍藏版)》请在冰豆网上搜索。
![编译原理比较复杂的词法分析器 含代码Word格式文档下载.docx](https://file1.bdocx.com/fileroot1/2023-2/1/67b5f5f7-b2d9-49ed-988b-8be930715e1e/67b5f5f7-b2d9-49ed-988b-8be930715e1e1.gif)
#
{
}
注:
#为结束标志符,详见◤程序框架◢
(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
*
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<
stdio.h>
string.h>
math.h>
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!
='
#'
//输入以#号键结束
scanner();
//扫描,单词
switch(syn)
{
case11:
if(isDecimal==0)
//加了1个强制类型转换
(%d,%d)"
syn,(int)sum);
break;
}
elseif(isExp==1)
(%d,%e)"
syn,sum);
isExp=0;
elseif(isDecimal==1)
(%d,%f)"
case-1:
printf("
输入错误:
"
\n"
default:
(%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=='
'
)//跳过空字符(无效输入)
if(((ch>
a'
)&
&
(ch<
z'
))||((ch>
A'
Z'
)))//ch是字母字符
while(((ch>
0'
9'
)))
token[m++]=ch;
//ch=>
token
//读下一个字符
token[m++]='
\0'
p--;
//回退一格
syn=10;
//如果是"
标识符中的一个
9;
if(strcmp(token,rwtab[n])==0)
syn=n+1;
elseif((ch>
))
IsNum:
if(isSignal==1)
//token[m++]='
-'
while((ch>
sum=sum*10+ch-'
//ch中数字本身是当做字符存放的
if(ch=='
.'
)
isDecimal=1;
//之前忘了清零,123.123+123.123#两个浮点数就无法识别
//pow(x,y)计算x的y次幂
temp=(ch-'
)*pow(0.1,++count);
decimal=decimal+temp;
//AddToDec();
sum=sum+decimal;
e'
||ch=='
E'
isExp=1;
isNegative=1;
//指数
index=index*10+ch-'
//10的幂
//123e3代表123*10(3)
//sum=sum*pow(10,index);
是错误的
if(isNegative)
sum=sum*pow(0.1,index);
else
sum=sum*pow(10,index);
sum=-sum;
isSignal=0;
syn=11;
elseswitch(ch)
case'
'
:
syn=22;
syn=20;
syn=24;
syn=23;
syn=17;
token[m++]=ch;
+'
temp2=prog[p];
if((temp2>
(temp2<
(repeat==1))
isSignal=2;
//isSignal正数
gotoIsNum;
if(((temp2=='
)||(temp2=='
))&
(repeat==0))//如果重复出现符号,才将后边的+,-视为正负号
repeat=1;
//ch=prog[p++];
syn=13;
isSignal=1;
//读“-”下一个字符
//转到数字的识别
//预言会重复
syn=14;
*'
syn=15;
/'
syn=16;
syn=18;
syn=26;
('
syn=27;
{'
syn=12;
case'
}'
syn=19;
)'
syn=28;
case'
syn=0;
syn=-1;
五、测试结果
1)字符串输入测试:
2)小数输入测试:
六、设计体会与收获
通过此次试验,使我对词法分析器有了更加深入的了解,也使我对编译原理这门课程产生了浓厚的兴趣,虽然在实验过程中遇到了不少的困难,但是在同学以及老师共同的帮助下,都基本一一解决,使我懂得了团队精神的重要性。
同时通过本次的实验,使我重新学习了C语言编程方法,知识也得到了相应的扩展,思考问题的方式也能够变得多样化和灵活化。
总的来说,本学期编译原理课程的实验让我受益匪浅。