编译原理第二次上机实验报告软工李U172xxWord文件下载.docx
《编译原理第二次上机实验报告软工李U172xxWord文件下载.docx》由会员分享,可在线阅读,更多相关《编译原理第二次上机实验报告软工李U172xxWord文件下载.docx(26页珍藏版)》请在冰豆网上搜索。
内部字符串
(+|-|ε)dd*(.dd*|ε)(e(+|-|ε)dd*|ε)
20
二进制数值表示
=
21
+
22
-
23
*
24
/
25
(
26
)
27
{
28
}
29
30
;
31
>
32
33
<
34
35
==
36
!
37
#
(2)语法结构定义
表达式>
:
:
=<
项>
{+<
|-<
因子>
{*<
|/<
=ID|num|(<
num:
=(+|-|ε)数字数字*(.数字数字*|ε)(e(+|-|ε)数字数字*|ε)
ID:
=字母(字母|数字)*
字母:
=a|b|c…|z|A|B|C…|Z
数字:
=0|1|2…|9
(3)语法分析器功能及基本要求
处理用户提交的符合上述文法的源代码序列,进行语法分析,并给出语法是否正确的结论。
(1)总体设计思想
利用自上而下的分析方法;
本实验所采用的是LL
(1)分析法即预测分析法;
每次通过词法分析模块读入一个完整的单词,在语法分析中判断正确性,最终将结果输出。
(2)详细算法设计
语法分析
用字母替代后写成如下:
E→T{+T|-T}
T→F{*F|/F}
F→i|n|(E)
将该扩充文法还原
EE+T|E-T|T
TT*F|T/F|F
F(E)|i|n
消除非终结符E、T的直接左递归后,文法变为
ETE’
E’+TE’|-TE’|ε
TFT’
T’*FT’|/FT’|ε
此文法是LL
(1)文法
求出该文法的预测分析表
i
n
-
*
/
$
E
ETE’
E’(e)
E’+TE’
E’TE’
E’ε
T
TFT’
TF’
T’(t)
T’ε
T’*FT’
T’/FT’
F
Fi
Fn
F(E)
根据预测分析表、分析栈和一个总控程序来判断一个语句是否正确;
(3)流程框图
(4)函数相关说明
charinput[300];
//存放输入的字符串
chartoken[20];
//存放符合C语言词法规则的单词
charch;
//单个字符
charprevious;
//ch的前一个字符
charlatter;
//ch的后一个字符
charch1,ch2;
//当处理注释的时候使用
inttypenum;
//表示单词的种别码
intp,m,n,cx;
doubledecimal;
//记录小数
doublesum;
//存放数字
intindex;
//存放指数
intisNum;
//是否是数字
intisDecimal;
//记录是否为小数
intisExp;
//记录是否为指数
intisNegative;
//是否带负号(对于指数)
intisNegative1;
//是否为负数
charX,a;
charstack[200];
voidscanner();
char*rwtab[11]={"
main"
"
int"
float"
double"
char"
if"
else"
while"
do"
end"
};
//记录预测分析表,0表示没有产生式,其他数字表示产生式的序号
intList[5][9]={
{1,2,0,0,0,0,3,0,0},
{0,0,4,5,0,0,0,6,7},
{8,9,0,0,0,0,10,0,0},
{0,0,11,12,13,14,0,15,16},
{17,18,0,0,0,0,19,0,0}
};
charreturnResult()函数返回n、i、e、+、-、*、/、(、);
voidscanner()扫描函数判断种别码
boolisVT(charx)判断是否为终结符
boolcheckList(intx,inty)查询是否在分析表中
intgetX()、intgetY()获取要查询数组M[X,a]元素的下标
voidmakeTop()把栈顶放入X中
voidpush(intxy)将y1y2...yn逆序放入S栈中
intmain()主函数
(5)输入与输出(包括出错处理)
输入以$结束回车即可运行程序
输出success!
或者unsuccess!
或者error!
unsuccess!
出错分为两种情况
1.词法错误:
error!
2.词法正确但语法错误:
unsuccess!
(6)程序运行结果(屏幕截图)
(7)词法分析器使用说明
打开编译器VS或者VC++;
文件新建项目;
将代码复制粘贴,编译运行,按照提示输入即可使用;
(8)心得与体会
加强了自己对于LL
(1)分析法的理解与记忆;
第二次试验难度要大于第一次;
主要难在求预测分析表;
开始由于预测分析表求错误导致程序运行一直出错也不知道到底bug出在哪里,后来才发现自己预测分析表求错了;
对于词法分析实验一已经给出,预测分析总控制程序算法书本上已经给出;
所以最大的难点就是求预测分析表;
这需要足够的耐心和细心才能保证FIRSE集和FOLLOW集不多一个,也不漏掉其中一个;
后期需要加强练习;
(9)源程序清单
//语法编译器01.cpp:
定义控制台应用程序的入口点。
//
#include"
stdafx.h"
#include<
stdio.h>
string.h>
math.h>
charreturnResult()
scanner();
switch(typenum)
{
case20:
return'
n'
//表示返回一个数字number
case10:
i'
//表示返回id
case22:
+'
case23:
-'
case24:
*'
case25:
/'
case26:
('
case27:
)'
case0:
$'
default:
e'
//表示error!
}
voidscanner()
cx=0;
//用来记录小数点后面的位数
m=0;
sum=0;
decimal=0;
index=0;
isDecimal=0;
isNegative=0;
isNegative1=0;
isExp=0;
for(n=0;
n<
8;
n++)
token[n]='
\0'
ch=input[p++];
//处理回车换行空格
while((ch=='
'
)||(ch==9)||(ch==10))
{
ch=input[p++];
}
//处理注释
if(ch=='
ch1=input[p];
if(ch1=='
do
{
ch=input[p++];
ch2=input[p];
}while((ch!
='
)||(ch2!
));
p=p+1;
ch=input[p++];
if(((ch>
a'
)&
&
(ch<
z'
))||((ch>
A'
Z'
)))//如果当前ch为字母
while(((ch>
0'
9'
)))
token[m++]=ch;
token[m++]='
typenum=10;
//10表示l(l|d)*
p=p-1;
//回退一步
for(n=0;
n<
10;
if(strcmp(rwtab[n],token)==0)
typenum=n+1;
break;
elseif((ch>
))
isNum:
while((ch>
sum=sum*10+(ch-'
);
if(ch=='
.'
isDecimal=1;
while(ch>
&
ch<
cx=cx+1;
decimal=decimal*10+(ch-'
}
if(ch=='
typenum=-1;
return;
for(inta=0;
a<
cx;
a++)
decimal=decimal*0.1;
sum=sum+decimal;
if((ch=='
)||(ch=='
E'
isExp=1;
isNegative=1;
//表示指数为负数
isNegative=0;
//表示指数为正
while((ch>
index=index*10+(ch-'
if(isNegative==1)//如果指数为负数
for(intk=0;
k<
index;
k++)
sum=sum*0.1;
else
sum=sum*10;
if(isNegative1==1)
sum=sum*(-1);
p--;
typenum=20;
//表示为数字
//运算符、界运算符
else{
switch(ch)
case'
='
typenum=21;
case'
previous=input[p-2];
latter=input[p];
//当+号前面为空或者(或者=并且后面为数字时,+表示正负号;
if(((previous=='
)||(previous=='
))&
((latter>
(latter<
isNegative1=0;
//表示此+号为正负号
gotoisNum;
//当+号前面为+、-、*、/号且后面为数字时,-号表示正负号;
elseif(((previous=='
//如果+号后面是+、-号,则表示为加减号
elseif((latter=='
)||(latter=='
typenum=22;
token[m++]=ch;
break;
//如果+号后面是字母;
elseif(((latter>
))||((latter>
elseif((((previous>
(previous<
))||((previous>
)))&
=0)||(latter<
//当-号前面为空或者(或者=并且后面为数字时,-表示正负号;
isNegative1=1;
//当-号前面为+、-、*、/号且后面为数字时,-号表示正负号;
//如果-号后面是+、-号,则表示为加减号
typenum=23;
//如果-号后面是字母;
//如果前面为字母或者数字且后面为数字,则表示-号
typenum=24;
typenum=25;
'
typenum=33;
typenum=32;
p--;
typenum=35;
typenum=34;
typenum=26;
typenum=27;
{'
typenum=28;
}'
typenum=29;
typenum=30;
typen