编译原理实验之语法分析程序.docx
《编译原理实验之语法分析程序.docx》由会员分享,可在线阅读,更多相关《编译原理实验之语法分析程序.docx(22页珍藏版)》请在冰豆网上搜索。
编译原理实验之语法分析程序
《编译原理》实验报告
——之语法分析程序
姓名:
卢旭
学号:
U200917806
班级:
软工0901班
2011年10月22日
目录
一、实验题目3
一、实验题目
编制一个递归下降分析程序,实现对词法分析程序所提供的单词序列的语法检查和结构分析。
单词符号
单词符号
种别编码
单词值
main
1
int
2
float
3
double
4
char
5
if
6
else
7
do
8
while
9
l(l|d)*
10
内部字符串
(+|-|ε)dd*(.dd*|ε)(e(+|-|ε)dd*|ε)
20
二进制数值表示
=
21
+
22
-
23
*
24
/
25
(
26
)
27
{
28
}
29
30
;
31
>
32
>=
33
<
34
<=
35
==
36
!
=
37
语法结构定义:
<表达式>:
:
=<项>{+<项>|-<项>}
<项>:
:
=<因子>{*<因子>|/<因子>}
<因子>:
:
=ID|num|(<表达式>)
num:
:
=(+|-|ε)数字数字*(.数字数字*|ε)(e(+|-|ε)数字数字*|ε)
ID:
:
=字母(字母|数字)*
字母:
:
=a|b|c…|z|A|B|C…|Z
数字:
:
=0|1|2…|9
二、实验目的
1)练习用C语言来编写语法分析程序
2)加深对编译原理中语法分析流程的理解
三、实验要求
输入单词串,以‘#’结束,如果是文法正确的句子,则输出成功信息,打印“success”,否则输出“error”。
例如:
输入:
begina:
=9;x:
=2*3;b:
=a+xend#
输出success
输入x:
=a+b*cend#
输出error
四、实验设计
基本设计思路
1)关键字表置初值:
char*rwtab[6]={"begin","if","then","while","do","end"};识别出标识符,然后查这个关键字表,给出相应的种别码;
2)识别无符号整数是将数字串转换为无符号整数。
3)设计扫描函数scanner(),扫描程序每次读取1个独立意义的单词符号,并判断单词类型;
4)递归下降分析法是对文法的每个非终结符编制一个递归过程(函数),按规则右部符号串的顺序编写:
若为终结符,则读下一个单词符号;非终结符,调用相应的递归过程(函数)。
流程框图
图C2.1函数E
图C2.2函数T
图C2.3函数F
算法设计
设置全局变量
1)charch字符变量,存放当前读进的源程序字符。
2)chartoken[8]字符数组,存放构成单词符号的字符串。
3)charprog[80]字符数组,存放所有用户输入的字符。
4)intsyn整数,存放当前单词的种别码。
5)doublesum双精度浮点型变量,存放无符号整数,或者浮点数。
6)intisDecimal整数,是否为浮点数。
值为1,则为浮点数。
7)doubledecimal双精度浮点型变量(double),浮点数的小数部分。
8)intisExp整数,是否为指数形式表示的浮点数(即是否存在符号E或者e)。
值为1,则为指数形式。
9)intindex整数,指数形式的幂。
10)intisNegative整数,是否为负数幂。
值为1,则为负数幂。
11)intisSignal;是否带正负号(0不带,1负号,2正号)
12)intrepeat;是否连续出现+,-。
设置函数:
1)scanner()扫描子程序。
2)getchar()从控制台读取一个字符数据。
3)doublepow(doublex,doubley),计算x的y次幂。
4)intstrcmp(char*str1,char#str2),字符串比较。
5)voidE();递归下降分析程序中,为非终结符E编写的函数
6)voidT();递归下降分析程序中,为非终结符T编写的函数
7)voidF();递归下降分析程序中,为非终结符F编写的函数
函数相关说明
voidE()
{
T();
while((syn==22)||(syn==23))
{
scanner();
T();
}
}
voidT()
{
F();
while((syn==24)||(syn==25))
{
scanner();
F();
}
}
voidF()
{
if((syn==20)||(syn==10))
scanner();
elseif(syn==26)
{
scanner();
E();
if(syn==27)
{
scanner();
}
elseisError=1;
}
elseisError=1;
}
输入与输出
输入:
所给文法的源程序字符串。
(字符串以“#”号结束)
输出:
success是文法正确句子
error不是文法正确句子
例如:
输入begina:
=9;x:
=2*3;b:
=a+xend#输出success.
程序运行结果
五、实验实现方式
在windows7下,借助vc6.0++,用C语言实现;
采用递归下降分析法做语法分析;
六、分析器使用说明
1)输入待识别字符串,并以“#”结尾
2)回车后程序自动输出语法分析结果
七、心得与体会
因为之前只是听了课,上机之前木有自己去写过代码,因此上机课还是没有做出来,以至于直接放弃走了,连调试都没有做……这是很失败的地方……以后一定得提前写出代码,然后直接拿到现场去做调试!
这样就能很快的解决问题!
通过这次实验后,基本上掌握了采用递归下降分析法来做语法分析,还是很有自豪感滴~~
八、源程序清单
#include
#include
#include
intisError;
charprog[80];//存放所有输入字符
chartoken[8];//存放词组
charch;//单个字符
intsyn,p,m,n;//syn:
种别编码
doublesum;
intcount;
intisSignal;//是否带正负号(0不带,1负号,2正号)
intisDecimal;//是否是小数
doubledecimal;//小数
intisExp;//是否是指数
intindex;//指数幂
intisNegative;//是否带负号
doubletemp;
inttemp2;
intrepeat;//是否连续出现+,-
voidscanner();
char*rwtab[9]={"main","int","float","double","char","if","else","do","while"};
voidE();
voidT();
voidF();
voidscanner();
voidmain()
{
p=0;
count=0;
isDecimal=0;
index=0;
repeat=0;
printf("\npleaseinputthesourcestring:
\n");
do{
ch=getchar();
prog[p++]=ch;
}while(ch!
='#');
p=0;
isError=0;
scanner();
if((syn==20)||(syn==10)||(syn==26))
{
E();
}
if((ch=='#')&&(isError==0))
printf("success\n");
else
printf("error\n");
}
voidE()
{
T();
while((syn==22)||(syn==23))
{
scanner();
T();
}
}
voidT()
{
F();
while((syn==24)||(syn==25))
{
scanner();
F();
}
}
voidF()
{
if((syn==20)||(syn==10))
scanner();
elseif(syn==26)
{
scanner();
E();
if(syn==27)
{
scanner();
}
elseisError=1;
}
elseisError=1;
}
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;//标识符
//如果是"begin","if","then","while","do","end"标识符中的一个
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=20;
}
elseswitch(ch)
{
case'<':
m=0;
token[m++]=ch;
ch=prog[p++];
if(ch=='=')
{
syn=35;
token[m++]=ch;
}
else
{
syn=34;
p--;
}
break;
case'>':
m=0;
token[m++]=ch;
ch=prog[p++];
if(ch=='=')
{
syn=33;
token[m++]=ch;
}
else
{
syn=32;
p--;
}
break;
case'=':
m=0;
token[m++]=ch;
ch=prog[p++];
if(ch=='=')
{
syn=36;
token[m++]=ch;
}
else
{
syn=21;
p--;
}
break;
case'+':
temp2=prog[p];
token[m++]=ch;
if((temp2>='0')&&(temp2<='9')&&(repeat==1))
{
isSignal=2;
ch=prog[p++];
repeat=0;
gotoIsNum;
}
if(((temp2=='+')||(temp2=='-'))&&(repeat==0))//如果重复出现符号,才将后边的+,-视为正负号
{
repeat=1;
//ch=prog[p++];
}
syn=22;
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=23;
break;
/*
case'*':
syn=24;
token[m++]=ch;
break;
*/
case'*':
temp2=prog[p];
token[m++]=ch;
if(temp2=='+')
{
isSignal=2;
repeat=1;
}
elseif(temp2=='-')
{
isSignal=1;
repeat=1;
}
syn=24;
break;
case'/':
syn=25;
token[m++]=ch;
break;
/*
case'(':
syn=26;
token[m++]=ch;
break;
*/
case'(':
temp2=prog[p];
token[m++]=ch;
if(temp2=='+')
{
isSignal=2;
repeat=1;
}
elseif(temp2=='-')
{
isSignal=1;
repeat=1;
}
syn=26;
break;
case')':
syn=27;
token[m++]=ch;
break;
case'{':
syn=28;
token[m++]=ch;
break;
case'}':
syn=29;
token[m++]=ch;
break;
case',':
syn=30;
token[m++]=ch;
break;
case';':
syn=31;
token[m++]=ch;
break;
case'#':
syn=0;
token[m++]=ch;
break;
default:
syn=-1;
}
}