编译实验二.docx
《编译实验二.docx》由会员分享,可在线阅读,更多相关《编译实验二.docx(15页珍藏版)》请在冰豆网上搜索。
编译实验二
实验二语法分析程序设计
[实验目的]:
1.了解语法分析的主要任务。
2.熟悉编译程序的编制。
[实验内容]:
根据某文法,构造一基本递归下降语法分析程序。
给出分析过程中所用的产生式序列。
[实验要求]:
1.选择一个文法,进行实验,可选的文法包括以下三个:
P1904.8
P1904.9
P1904.10
2.设计语法分析程序的输出形式(输出应为语法树或推导),一个可以参考的例子,可见图1。
3.编写递归下降语法分析程序(参考P148-149Topdownparsingbyrecursive-descent),实现基本的递归下降分析器,能够分析任给的符号串是否为该文法所定义的合法句子。
实验报告中要说明分析使用的方法。
4.根据所作业题选项e所给出的input,生成并输出分析过程中所用的产生式序列(showtheactionsofparser):
1产生式1
2产生式2
……
5.自已设计一个不合法的句子,作为输出进行分析,给出结果。
[实验步骤]:
1.写出该小语言的的LL
(1)文法。
如
G[E]:
其中
E→TGG为E’
G→+TG|∧∧为ε
T→FSS为T’
S→*FS|∧
F→i|(E)
2.编写递归下降语法分析程序。
3.调试运行程序。
4.结果分析。
5.撰写实验报告。
[实验报告]:
1.写出实现的算法,并画流程图。
此题我的测试用例为(a,1),简单版流程图如下:
2.根据你选择的文法,分析左递归或左因子是否会影响本算法的结果。
会影响,左递归会使分析进入无限循环中,左因子的情况是因为如果左边是一样的,那么程序就无法明确下一步怎么走。
3.列举实验设计过程中出现的问题及解决的方法(至少3条,选择实验中最困扰的问题)。
(1).最主要的问题是我一开始在推导式的代码那边出了很严重的逻辑问题,导致我一输完字符串运行时就开始闪退,后来在同学的建议下,在草稿本上理清楚了我的测试用例的逻辑,再不断修改代码才解决掉这个问题。
(2).因为我是直接在老师给出的代码段的基础上修改的,所以对于源代码中的有些变量的定义不太清楚,主要是经常搞错数组d和数组e的区别,还有数组b的意义也不是很了解,后来经过不断地前后文代码的对比,自己的各种实践终于搞清楚各个变量的含义。
(3).本来我是想直接用0到9的数字,还有a到z,A到Z的字符进行测试,但是我的代码一旦写上ch>='0'&&ch<='9'等写法,就一直运行不出来结果,问了同学也没有办法解决,所以我只能用ch=='1'||ch=='a'的写法直接在代码里写死了我的测试案例。
4.比较作业题和本次实验结果,分析递归下降和LL
(1)算法的异同点。
递归下降是指从文法的开始符出发并寻找出这样一个推导序列,推导出的句子恰为输入符号串,这种方法是不带回溯的,并且只能实现一部分上下文无关语言的分析,这就是LL
(1)文法所产生的语言。
LL
(1)算法是从左到右扫描输入串,同时采用最左推导,且对每次直接推导只需向前看一个输入符号,对实现LL
(1)算法最重要的是first级和follow级。
5.给出程序清单。
#include
#include
#include
#include
//定义相关变量
charshuru[50],b[50],tuidao[200],tuidaoing[10];/*数组shuru存输入串,数组tuidao存推导式,数组tuidaoing存临时用到的推导式*/
charch;//定义字符
intlen,i1=0,flag=1,n=5;//flag=1处理非终结符,flag=0处理终结符,len表示输入串实际长度
inttotal=0;//步骤计数器
intE1();
intlexp();
intatom();
intlist();
intseq();
intseq1();
voidinput();
voidinput1();
voidoutput();
intmain()
{
intf,p,j=0;
charx;
printf("请输入字符串(长度<50,以#号结束)\n");
do
{
scanf("%c",&ch);
shuru[j]=ch;
j++;
}while(ch!
='#');
len=j;/*n1输入串实际长度*/
ch=b[0]=shuru[0];
//判断第一步选择的推导式
if(ch=='1'||ch=='a')
{
tuidao[0]='lexp';
tuidao[1]='=';
tuidao[2]='>';
tuidao[3]='atom';
tuidao[4]='#';
}
if(ch=='(')
{
tuidao[0]='lexp';
tuidao[1]='=';
tuidao[2]='>';
tuidao[3]='list';
tuidao[4]='#';
}
printf("步骤\t文法\t\t分析串\t\t分析字符\t剩余串\n");
f=E1();
if(f==0)
return(0);/*有语法错误,失败退出*/
if(ch=='#')
{printf("accept\n");/*输入串是文法的句子*/
p=0;
x=tuidao[p];
}
else
{printf("error\n");
printf("回车返回\n");
getchar();
getchar();
return0;
}
printf("回车返回\n");
getchar();
getchar();
}
intE1()/*有语法错误函数返回值为0,否则为1*/
{
if(atom())
{
printf("%d\tlexp-->atom\t",total);
total++;
flag=1;//非终结符
input();
input1();
return
(1);
}
elseif(list())
{
printf("%d\tlexp-->list\t",total);
total++;
flag=1;//非终结符
input();
input1();
return
(1);
}
elsereturn(0);
}
intlexp(){
intf,f1;
if(ch=='1'||ch=='a')//如果输入字符是1或者a,则用lexp-->atom推导式。
{
printf("%d\tlexp-->atom\t",total);
total++;
tuidaoing[0]='lexp';
tuidaoing[1]='=';
tuidaoing[2]='>';
tuidaoing[3]='atom';
tuidaoing[4]='#';
output();
flag=1;
input();
input1();
f=atom();
if(f==0)
return(0);
}
elseif(ch=='(')//如果输入字符是(,则用lexp-->list推导式。
{
printf("%d\tlexp-->list\t",total);
total++;
tuidaoing[0]='lexp';
tuidaoing[1]='=';
tuidaoing[2]='>';
tuidaoing[3]='list';
tuidaoing[4]='#';
output();
flag=1;
input();
input1();
f1=list();
if(f==0)
return(0);
}
else
{
//printf("error\n");
return(0);
}
return
(1);
}
intlist(){
intf;
if(ch=='(')
{
b[i1]=ch;
printf("%d\tlist-->(seq)\t",total);
total++;
tuidaoing[0]='list';
tuidaoing[1]='=';
tuidaoing[2]='>';
tuidaoing[3]='(';
tuidaoing[4]='seq';
tuidaoing[5]=')';
tuidaoing[6]='#';
output();
flag=0;
input();
input1();
ch=shuru[++i1];
f=seq();
if(f==0)
return(0);
if(ch==')')
{
b[i1]=ch;
printf("%d\tlist-->(seq)\t",total);
total++;
flag=0;
input();
input1();
ch=shuru[++i1];
}
else
{
//printf("error\n");
return(0);
}
}
return
(1);
}
intseq(){
intf,f1;
printf("%d\tseq--lexpseq1\t",total);
total++;
tuidaoing[0]='seq';
tuidaoing[1]='=';
tuidaoing[2]='>';
tuidaoing[3]='lexp';
tuidaoing[4]='';
tuidaoing[5]='seq1';
tuidaoing[6]='#';
output();
flag=1;
input();
input1();
f=lexp();
if(f==0)
return(0);
if(ch==')')
return
(1);
elseif(ch=='')
{
ch=shuru[++i1];
f1=seq1();
if(f1==0)
return(0);
}
else
{return(0);}
return
(1);
}
intatom(){
if(ch=='a')//如果输入字符是a,则用atom-->iden推导式。
{
b[i1]=ch;
printf("%d\tatom-->iden\t",total);
total++;
tuidaoing[0]='atom';
tuidaoing[1]='=';
tuidaoing[2]='>';
tuidaoing[3]='a';
tuidaoing[4]='#';
output();
flag=0;
input();
input1();
ch=shuru[++i1];
}
elseif(ch=='1')//如果输入字符是1,则用atom-->num推导式。
{
b[i1]=ch;
printf("%d\tatom-->num\t",total);
total++;
tuidaoing[0]='atom';
tuidaoing[1]='=';
tuidaoing[2]='>';
tuidaoing[3]='1';
tuidaoing[4]='#';
output();
flag=0;
input();
input1();
ch=shuru[++i1];
}
else
{
//printf("error\n");
return(0);
}
return
(1);
}
intseq1(){
intf,f1;
if(ch=='1'||ch=='a'||ch==')')
{
b[i1]=ch;
printf("%d\tseq1--lexpseq1\t",total);
total++;
tuidaoing[0]='seq1';
tuidaoing[1]='=';
tuidaoing[2]='>';
tuidaoing[3]='lexp';
tuidaoing[4]='';
tuidaoing[5]='seq1';
tuidaoing[6]='#';
output();
flag=1;
input();
input1();
f=lexp();
if(f==0)
return(0);
if(ch==')')
return
(1);
elseif(ch=='')
return
(1);
else
return(0);
}
else
{
printf("%d\tseq1-->^\t",total);
total++;
tuidaoing[0]='seq1';
tuidaoing[1]='=';
tuidaoing[2]='>';
tuidaoing[3]='^';
tuidaoing[4]='#';
output();
flag=1;
shuru[i1]=ch;
input();
input1();
return
(1);
}
}
voidinput(){
intj=0;
for(;j<=i1-flag;j++)
printf("%c",b[j]);/*输出分析串*/
printf("\t\t");
printf("%c\t\t",ch);/*输出分析字符*/
}
voidinput1(){
intj;
for(j=i1+1-flag;jprintf("%c",shuru[j]);/*输出剩余字符*/
printf("\n");
}
voidoutput(){/*推导式计算*/
intm,k,j,q;
inti=0;
m=0;k=0;q=0;
i=n;
tuidao[n]='=';
tuidao[n+1]='>';
tuidao[n+2]='#';
n=n+2;
i=n;
i=i-2;
while(tuidao[i]!
='>'&&i!
=0)
i=i-1;
i=i+1;
while(tuidao[i]!
=tuidaoing[0])
i=i+1;
q=i;m=q;k=q;
while(tuidao[m]!
='>')
m=m-1;
m=m+1;
while(m!
=q)
{
tuidao[n]=tuidao[m];
m=m+1;
n=n+1;
}
tuidao[n]='#';
for(j=3;tuidaoing[j]!
='#';j++)
{
tuidao[n]=tuidaoing[j];
n=n+1;
}
k=k+1;
while(tuidao[k]!
='=')
{
tuidao[n]=tuidao[k];
n=n+1;
k=k+1;
}
tuidao[n]='#';
}
6.给出测试结果。