编译原理提高型实验报告.docx
《编译原理提高型实验报告.docx》由会员分享,可在线阅读,更多相关《编译原理提高型实验报告.docx(16页珍藏版)》请在冰豆网上搜索。
![编译原理提高型实验报告.docx](https://file1.bdocx.com/fileroot1/2023-2/28/ebd7558a-aa7f-48ce-bc8e-4a37a94f63c8/ebd7558a-aa7f-48ce-bc8e-4a37a94f63c81.gif)
编译原理提高型实验报告
黄冈师范学院
提高型实验报告
实验课题OPG分析程序的设计___
(实验类型:
□综合型□设计型□应用型)
实验课程编译原理__
实验时间2014年12月16日
学生姓名
专业班级
学号
OPG分析表和分析程序的设计
实验目的和要求:
通过设计、编写和调试构造优先关系表的程序,了解构造算符优先关系表的步骤以及对文法的要求,并能够从文法G出发自动生成算符优先关系表。
实验原理分析(包括算法):
设计一个自动构造优先关系表的程序,该程序的输入是算符文法G,输出的是相应的优先关系表,并指出是否为算符优先文法。
(1)例如以下文法:
E->T+E|TT->F*T|FF->F↑P|PP->(E)|i
注:
I为整型常数后者为标识符表示的整型变量,使用中↑用**表示。
(2)构造优先分析表的算法,构造优先分析表需以下几个步骤:
1构造文法G中非终结符号的FIRSTVT集合
FIRSTVT集合用一个布尔数组F[P,a]表示,F是一个m*n的二维数组(m=文法G中非终结符号个数,n=文法G中终结符号个数)。
其中P∈VN,a∈VT,F[P,a]=TRUE的条件是当且仅当a∈FIRSTVT[P]。
对于文法G的所有非终结符号,构造布尔数组F[P,a]的算法(该算法使用一个数据结构STACK栈,用于存放相应于F[P,a]=TRUE的符号对(P,a))。
2构造文法G中非终结符号的LASTVT集合
类似于构造FIRSTVT集合,LASTVT集合用一个布尔数组L[P,a]表示,F是一个m*n的二维数组(m=文法G中非终结符号个数,n=文法G中终结符号个数)。
其中P∈VN,a∈VT,L[P,a]=TRUE的条件是当且仅当a∈LASTVT[P]。
对于文法G的所有非终结符号,构造布尔数组L[P,a]的算法(该算法使用一个数据结构STACK栈,用于存放相应于L[P,a]=TRUE的符号对(P,a))。
3构造文法G的优先关系表
使用文法G任何非终结符号的FIRSTVT集合和LASTVT集合,可以构造文法G的优先关系表。
优先关系表用一个数组R[a,b]表示,R是一个n*n的二维数组(n=文法G中终结符号个数)。
其中a,b∈VT,R[a,b]=‘=’、‘<’、‘>’或空(可能为多值),表示终结符号对(a,b)之间具有“=”“<”“>”优先关系或无优先关系。
4判断文法G是否为算符优先文法
构造出文法G的算符优先表R[a,b]后,判别文法G是否为算符优先文法的算法。
实验方案或步骤(流程图、主要数据结构、程序、小结)
·OPG分析程序的设计
·实验目的和要求:
通过设计,编写和调试算符优先分析程序,了解算符优先分析器的组成结构以及对文法的要求,掌握实现通用算符优先分析算法的方法。
·实验原理分析:
程序流程图
N
Y
结束
N
Y
N
Y
结束
算符优先分析属于自下而上的分析方法,该语法分析程序的输入是终结符号串(即单词符号串,以一个“#”结尾)。
如果输入串是句子,则输出“YES”,否则输出“NO”和错误信息。
算符优先分析过程与非终结符号无关,当由文法产生了优先关系之后文法就失去了作用。
本题目给出文法的目的是为了便于对语法分析结果进行验证。
(1)文法设算符优先文法G为:
E→E+T|T
T→T*F|F
F→P↑F|P
P→(E)|i
说明:
i为整形常数或者为表示符表示整形变量;使用中↑用**表示。
(2)优先关系表设优先关系表如下所示。
+
*
↑
i
(
)
#
+
>
<
<
<
<
>
>
*
>
>
<
<
<
>
>
↑
>
>
<
<
<
>
>
i
>
>
>
>
>
(
<
<
<
<
<
=
)
>
>
>
>
>
#
<
<
<
<
<
=
·实验方案或步骤
输出移近——规约过程。
源代码如下:
#include
#include
#include
#defineSIZE128
charpriority[6][6];//算符优先关系表数组
charinput[SIZE];//存放输入的要进行分析的句子
charremain[SIZE];//存放剩余串
charAnalyseStack[SIZE];//分析栈
voidanalyse();
inttestchar(charx);//判断字符X在算符优先关系表中的位置
voidremainString();//移进时处理剩余字符串,即去掉剩余字符串第一个字符
intk;
voidinit()//构造算符优先关系表,并将其存入数组中
{
priority[0][0]='>';
priority[0][1]='<';
priority[0][2]='<';
priority[0][3]='<';
priority[0][4]='>';
priority[0][5]='>';
priority[1][0]='>';
priority[1][1]='>';
priority[1][2]='<';
priority[1][3]='<';
priority[1][4]='>';
priority[1][5]='>';
priority[2][0]='>';
priority[2][1]='>';
priority[2][2]='$';//无优先关系的用$表示
priority[2][3]='$';
priority[2][4]='>';
priority[2][5]='>';
priority[3][0]='<';
priority[3][1]='<';
priority[3][2]='<';
priority[3][3]='<';
priority[3][4]='=';
priority[3][5]='$';
priority[4][0]='>';
priority[4][1]='>';
priority[4][2]='$';
priority[4][3]='$';
priority[4][4]='>';
priority[4][5]='>';
priority[5][0]='<';
priority[5][1]='<';
priority[5][2]='<';
priority[5][3]='<';
priority[5][4]='$';
priority[5][5]='=';
}
/*对所输入的句子进行算符优先分析过程的函数*/
voidanalyse()
{
inti,j,f,z,z1,n,n1,z2,n2;
intcount=0;//操作的步骤数
chara;//用于存放正在分析的字符
charp,Q,p1,p2;
f=strlen(input);//测出数组的长度
for(i=0;i<=f;i++)
{
a=input[i];
if(i==0)
remainString();
if(AnalyseStack[k]=='+'||AnalyseStack[k]=='*'||AnalyseStack[k]=='i'||AnalyseStack[k]=='('||AnalyseStack[k]==')'||AnalyseStack[k]=='#')
j=k;
else
j=k-1;
z=testchar(AnalyseStack[j]);//从优先关系表中查出s[j]和a的优先关系
if(a=='+'||a=='*'||a=='i'||a=='('||a==')'||a=='#')
n=testchar(a);
else//如果句子含有不是终结符集合里的其它字符,不合法
{
printf("错误!
该句子不是该文法的合法句子!
\n");
break;
}
p=priority[z][n];
if(p=='$')
{
printf("错误!
该句子不是该文法的合法句子!
\n");
return;
}
if(p=='>')
{for(;;)
{
Q=AnalyseStack[j];
if(AnalyseStack[j-1]=='+'||AnalyseStack[j-1]=='*'||AnalyseStack[j-1]=='i'||AnalyseStack[j-1]=='('||AnalyseStack[j-1]==')'||AnalyseStack[j-1]=='#')
j=j-1;
else
j=j-2;
z1=testchar(AnalyseStack[j]);
n1=testchar(Q);
p1=priority[z1][n1];
if(p1=='<')//把AnalyseStack[j+1]~AnalyseStack[k]归约为N
{
count++;
printf("(%d)%s\t%10c\t%5c%17s\t归约\n",count,AnalyseStack,p,a,remain);
k=j+1;
i--;
AnalyseStack[k]='N';
intr,r1;
r=strlen(AnalyseStack);
for(r1=k+1;r1AnalyseStack[r1]='\0';
break;
}
else
continue;
}
}
else
{
if(p=='<')//表示移进
{
count++;
printf("(%d)%s\t%10c\t%5c%17s\t移进\n",count,AnalyseStack,p,a,remain);
k=k+1;
AnalyseStack[k]=a;
remainString();
}
else
{
if(p=='=')
{
z2=testchar(AnalyseStack[j]);
n2=testchar('#');
p2=priority[z2][n2];
if(p2=='=')
{
count++;
printf("(%d)%s\t%10c\t%5c%17s\t接受\n",count,AnalyseStack,p,a,remain);
printf("该句子是该文法的合法句子。
\n");
break;
}
else
{
count++;
printf("(%d)%s\t%10c\t%5c%17s\t移进\n",count,AnalyseStack,p,a,remain);
k=k+1;
AnalyseStack[k]=a;
remainString();
}
}
else
{
printf("错误!
该句子不是该文法的合法句子!
\n");
break;
}
}
}
}
}
inttestchar(charx)
{
intm;
if(x=='+')
m=0;
if(x=='*')
m=1;
if(x=='i')
m=2;
if(x=='(')
m=3;
if(x==')')
m=4;
if(x=='#')
m=5;
returnm;
}
/*余下的字符串*/
voidremainString()
{
inti,j;
i=strlen(remain);
for(j=0;j
remain[j]=remain[j+1];
remain[i-1]='\0';
}
/*主函数*/
voidmain()
{
init();
printf("文法为:
\n");
printf("(0)E'->#E#\n");
printf("
(1)E->E+T\n");
printf("
(2)E->T*F\n");
printf("(3)T->T\n");
printf("(4)T->F\n");
printf("(5)F->P↑F\n");
printf("(6)F->P\n");
printf("(7)P->(E)\n");
printf("(8)P->i\n");
printf("\n--------------------------------------------------------\n\n");
printf("**********************算符优先关系表********************\n");
printf("\t+\t*\ti\t↑\t(\t)\t#\n");
printf("+\t>\t<\t<\t<\t<\t>\t>\n");
printf("*\t>\t>\t<\t<\t<\t>\t>\n");
printf("↑\t>\t>\t<\t<\t<\t>\t>\n");
printf("i\t>\t>\t>\t\t\t>\t>\n");
printf("(\t<\t<\t<\t<\t(\t=\t\n");
printf(")\t>\t>\t>\t\t\t>\t>\n");
printf("#\t<\t<\t<\t<\t<\t\t=\n");
printf("==========================================================\n");
printf("请输入要进行分析的句子(以#号结束输入):
\n");
gets(input);//将输入的字符串存到数组中
printf("步骤栈优先关系当前符号剩余输入串移进或归约\n");
k=0;
AnalyseStack[k]='#';
AnalyseStack[k+1]='\0';
intlength,i;//初始化剩余字符串数组为输入串
length=strlen(input);//
for(i=0;iremain[i]=input[i];
remain[i]='\0';
analyse();//对所输入的句子进行算符优先分析过程的函数
}
程序运行结果截图:
实验小结:
通过此次实验,使我对算符优先分析算法的设计过程有了更深一层的了解:
即先对已给定的文法按其产生式构造算符优先关系表,有了算符优先关系表并满足算符优先文法时,我们就可以对任意给定的符号串进行分析,形成句柄时就归约,否则就移进,最后判定输入串是否为该文法的句子。