SLR1文法与算符优先文法程序实现.docx
- 文档编号:27592171
- 上传时间:2023-07-03
- 格式:DOCX
- 页数:30
- 大小:264.42KB
SLR1文法与算符优先文法程序实现.docx
《SLR1文法与算符优先文法程序实现.docx》由会员分享,可在线阅读,更多相关《SLR1文法与算符优先文法程序实现.docx(30页珍藏版)》请在冰豆网上搜索。
SLR1文法与算符优先文法程序实现
目录
一、设计题目1
二、运行环境1
三、算法设计思想1
1、LR算法思想1
2、算符优先算法思想2
四、算法流程图3
1、SLR
(1)流程图3
2、算符优先流程图4
五、算法设计分析5
1、SLR
(1)分析设计5
2、算符优先文法分析与设计7
六、运行结果分析8
1、SLR
(1)运行结果8
2、算符优先运行结果8
七、收获及体会10
附录:
程序清单11
一、设计题目
SLR
(1)文法与算符优先文法程序实现
二、运行环境
操作系统:
MicrosoftWindowsXP
可视化环境:
MicrosoftVisualC++6.0
三、算法设计思想
1、LR算法思想
LR分析方法在规范规约的过程中,一方面记住已移进和规约出的整个符号串,即记住“历史”,另一方面根据所用的产生式推测未来可能碰到的输入符号,即对未来进行“展望”。
当一串貌似句柄的符号串呈现于分析栈的顶端时,我们希望能够根据记载的“历史”和“展望”以及“现实”的输入符号等三个方面的材料,来确定栈顶的符号串是否构成相对某一产生式的句柄。
LR分析器实质上是一个带先进后出存储器(栈)的确定有限状态自动机,每一步工作是由栈顶状态和现行输入符号所唯一决定的。
LR分析器的核心部分是一张分析表。
这张分析表包括两个部分,一是“动作”(ACTION)表,另一是“状态转换”(GOTO)表。
他们都是二维数组。
ACTION(s,a)规定了当状态s面临输入符号a时应采取什么动作。
GOTO(s,X)规定了状态s面对文法符号X(终结符或非终结符)时下一状态是什么。
显然,GOTO(s,X)定义了一个以文法符号为字母表的DFA。
每项ACTION(s,a)所规定的动作不外是下述四种可能之一:
(1)移进:
把(s,a)的下一个状态s’=GOTO(s,X)和输入符号a推进栈,下一输入符号变成现行输入符号。
(2)规约:
指用某一产生式A→β进行规约。
假若β的长度为r,规约的动作是A,去除栈顶的r个项,使状态Sm-r变成栈顶状态,然后把(Sm-r,A)的下一状态s’=GOTO(Sm-r,A)和文法符号A推进栈。
规约动作不改变现行输入符号。
执行规约动作意味着β(=Xm-r+1…Xm)已呈现于栈顶而且是一个相对于A的句柄。
(3)接受:
宣布分析成功,停止分析器的工作。
(4)报错:
发现源程序含有错误,调用出错处理程序。
2、算符优先算法思想
算符优先分析方法是根据算符之间的优先关系而设计的一种自下而上的分析方法。
算符优先分析的基本思想是只规定算符之间的优先关系,也就是只考虑终结符之间的优先关系。
算符优先分析过程是自下而上的归约过程,所谓的算符优先分析就是定义算符之间(确切地说,终结符之间)的某种优先关系,借助于这种优先关系寻找“可归约串”和进行归约。
该文法必须满足以下条件:
文法它的任一产生式的右部都不含两个相继(并列)的非终结符,即不含如下产生式右部:
…QR…;
首先求出该文法的优先关系表,在程序中用2维数组表示,-1表示小于或者等于,大于为1,其它为0表示错误。
在输入一串字符串以后进行按照文法一步一步的进行规约,我所进行的是直接规约到文法的符号而不是规约到N。
数据结构使用的是链表,用一个STRUCT来表示一个元素,其中包含符号和下一个符号的指针。
算符优先分析法的关键是比较两个相继出现的终结符号的优先级而决定应采取的动作。
要完成算符间的优先级比较,就要先定义各种可能出相继出现的运算符的优先级,并将其表示成矩阵形式,在分析过程中通过查询矩阵元素而得算符间的优先关系。
四、算法流程图
1、SLR
(1)流程图
2、算符优先流程图
五、算法设计分析
1、SLR
(1)分析设计
(1)将文法:
G[S]:
S->Sb|bAaA->aSc|aSb|a拓广增加文法:
(0)M->S
(1)S->Sb
(2)S->bAa(3)A->aSc(4)A->aSb(5)A->a
(2)构造拓广文法G的LR(0)项目集族,初始化项目G’
C=closure({[S·S]})
repeat
for对C的每个项目集I和每个文法符号X,
ifgoto(I,X)非空且不在C中
then把goto(I,X)加入C中
until没有更多的项目可以加入C
冲突分析与解决
首先检测所有的LR(0)项目集,当发现有移进—规约或规约—规约冲突时,判断其FOLLOW集是否为空,若为空,说明是SLR
(1)文法,若不是,则说明不是SLR
(1)文法。
计算FIRST、FOLLOW和unllable(可为空)的算法。
将所有的FIRST和FLLOW初始为空集合,将所有的unllable初始为false。
for每一个终结符Z
FIRST[Z][Z]
repeat
for每个产生式X—>Y1Y2…………Yk
for每个i从1到k,每个j从i+1到k,
if所有的Y i都是可为空的
Thennullable[X]true
ifY1Y2……Yi—1都是可为空的
ThenFIRST[X]FIRST[X]UFIRST[Y i]
ifYi+1……Yk都是可为空的
ThenFOLLOW[Yi]FLLOW[Yi]UFOLLOW[X]
ifYi+1……Yj-1都是可为空的
ThenFOLLOW[Yi]FOLLOW[Yi]UFIRST[Yj]
UntilFIRST、FOLLOW和unllable在此轮迭代中没有改变
判断解决:
ifFOLLOW[Yi]nFIRST[Yi]=空
该文法是SLR
(1)文法
else
该文法不是SLR
(1)文法。
(3)构造该文法的项目规范族及转换函数
文法G[S]LR(0)项目集及转换函
分析这些项目集,可知在项目集I1、I5中存在“移进-归约”冲突,在I9中存在“归约-归约”冲突,因此该文法不是LR(0)文法。
考虑含有冲突的项目集,能否用SLR
(1)方法来解决。
对于I1={S’->•S,S->•Sb},由于FOLLOW(S’)∩{b}=Φ,I1中的存在“移进-归约”冲突可以用SLR
(1)方法来解决。
对于I5={A->a•,S->•bAa},由于FOLLOW(A)∩{b}={a}∩{b}=Φ,I5中的存在“移进-归约”冲突可以用SLR
(1)方法来解决。
对于I9={A->aSb•,S->Sb•},由于FOLLOW(A)∩{b}={a}∩{b,c,#}=Φ,I9中的存在“归约-归约”冲突可以用SLR
(1)方法来解决。
该文法是SLR
(1)文法,相应的文法分析
(4)构造G[S]的SLR
(1)分析表
状态
ACTION(动作)
GOTO(转换)
a
b
c
#
S
A
0
S2
1
1
S3
acc
2
S5
4
3
r1
r1
r1
4
S6
5
r5
S2
7
6
r2
r2
r2
7
S9
S8
8
r3
9
r4
r1
r4
r1
G[S]的SLR
(1)分析表
2、算符优先文法分析与设计
(1)对给定文法:
E->E-TE->TT->T/FT->FF->(E)F->i进行拓广有:
(0)W->#E#
(1)E->E-T
(2)E->T(3)T->T/F(4)T->F(5)
F->(E)(6)F->i
(2)每个非终结符的FIRSTVT和LASTVT集合如下所示:
✪
FIRSTVT
LASTVT
E
{-,/,(,I}
{-,/,),I}
T
{/,(,I}
{/,},i}
F
{(,I}
{},I}
W
{#}
{#}
(3)构造优先关系表
⏹
-
/
(
)
i
#
-
>
<
<
>
<
>
/
>
>
<
>
<
>
(
<
<
<
=
<
)
>
>
>
>
i
>
>
>
>
#
<
<
<
<
=
六、运行结果分析
1、SLR
(1)运行结果
ØSLR
(1)分析表生成
Ø对句子baab#进行分析
2、算符优先运行结果
Ø对输入的文法进行拓广
Ø生成各个非终结符的FIRSTVT集合LASTVT集
Ø自动生成所给文法的关系矩阵
Ø对句子(i-i)/i进行分析
Ø对句子(i-i进行分析
七、收获及体会
本课程设计任务是对两种语法分析技术的实现:
SLR
(1)类文法和算符优先文法。
实现对SLR
(1)类文法和算符优先文法的判断及其相应分析表的构造,能够完成对所给的句子进行分析,判断它是否是该文法的句子。
其中算符优先程序可以自动对所输入的文法进行扩展,并生成算符优先关系表和各个非终结符的FIRSTVT集和LASTVT集。
同时能对所给的句子进行分析,打印输出各个分析栈的状态。
SLR
(1)程序可以对输入的句子进行分析,并打印输出各个分析栈的状态。
在整个程序设计过程中,实现各个部分功能都需要利用到程序设计语言的知识和大量编程技巧,也利用到了大量的编译原理,自动生成算符优先矩阵是最困难的,其次是自动生成FIRSTVT集和LASTVT集也是比较棘手的,代码量比较大。
而由于在SLR
(1)程序中分析表不是自动生成的,所以整个程序的难易度比算符优先小了许多,代码量也是比较少的。
本次编译原理课程设计虽然只经过了短短的一周时间,但是在这期间我学到了许多,提高了自己的综合分析问题、解决问题的能力,在此过程中懂得如何将书本的理论知识应用到实践中去,加深了对语法分析特别是算符优先和LR分析法思想理解理论知识的理解,与此同时也巩固了我C语言编程的基本能力,对指针、链表、结构体的操作更加熟练,最重要的是本次编译实验加深了我对《编译原理》这门课程的理解。
从代码的编写、修改到文档的编写,自己都付出了很大的努力。
但是,由于所学知识不够全面,课程设计在很多方面还有待完善:
在算符优先分析过程中编写的程序原意是可以对任意文法进行分析,但是在测试时却发现该程序不能对任意文法进行分析,而只能对确定的一类文法进行分析,问题之所在还没有能够找出来;在SLR
(1)类文法部分,分析表不是通过程序自动生成的,也没有实现对是否是SLR
(1)文法进行判断。
我相信在以后的学习过程中,会掌握更多知识,力求做到更好。
本次课程设计的完成离不开老师的悉心指导和帮助,同时在本次课程设计过程中也得到了同学们的帮助和支持,他们在整个过程中给我提出了许多宝贵的意见和建议,再此向各位老师和同学表示感谢!
在老师和同学们的帮助下,我查阅了大量的资料,完成了本次课程设计。
最后,在做课程设计的过程中,同学之间那种团结互助,老师那种优良的工作的工作作风值得我们学习,希望在以后的学习和工作中也要不断的发扬这种精神。
附录:
程序清单
一、SLR
(1)程序实现
#defineNVT4
#defineNVN2
#defineNLR6
charACTION[10][NVT]={/*ACTION表*/
NULL,"s2",NULL,NULL,NULL,"s3",NULL,"acc","s5",NULL,NULL,NULL,NULL,"r1","r1","r1","s6",NULL,NULL,NULL,"r5","s2",NULL,NULL,
NULL,"r2","r2","r2",NULL,"s9","s8",NULL,"r3",NULL,NULL,NULL,"r4","r1","r1","r1"};
intGOTO[10][NVN]={1,0,0,0,0,4,0,0,0,0,7,0,0,0,0,0,0,0,0,0};
charTer[NVT]={'a','b','c','#'};
charImTer[NVN]={'S','A'};
charRule[NLR]=
{"M->S","S->Sb","S->bAa","A->aSc","A->aSb","A->a"};/*存放产生式*/
intState[10];//状态栈
charSymbol[10],Input[10],ch;
voidPrint_LR(){
intv,c;
printf("1>SLR
(1)分析表:
\n");
printf("ACTION\t\tGOTO\n");
for(v=0;v<70;v++)printf("-");
printf("\t\t");
printf("状态a\tb\tc\t#\tSA\n");
for(v=0;v<70;v++)printf("-");
printf("\t\t");
for(v=0;v<10;v++){
printf("%5d",v);
for(c=0;c<4;c++){
if(ACTION[v][c]==NULL)
ACTION[v][c]="";
printf("%8s",ACTION[v][c]);}
printf("\t");
for(c=0;c<2;c++){
if(GOTO[v][c]==0)
printf("");
elseprintf("%4d",GOTO[v][c]);}
printf("\n");}
for(v=0;v<70;v++)
printf("-");
printf("\t\t");
for(v=0;v<70;v++)
printf("-");
printf("\t\t");}
voidmain(){
intStateTop=0;//状态栈栈顶
intSymbolTop=0;//符号栈栈顶
intInputTop=0;//目前输入串的位置
intInputIndex=0;//输入栈栈顶
inti,j,k,y,z,StepCount=0,index;
charx,copy[4],copy1[10];
State[0]=0;y=State[0];
Symbol[0]='#';z=0;Print_LR();
printf("\n2>请输入表达式(以#结束):
");
do{
scanf("%c",&ch);
nput[InputTop]=ch;
InputTop++;}while(ch!
='#');
printf("\n");
for(intv=0;v<70;v++)printf("-");
printf("\n");
printf("步骤\t状态栈\t\t符号栈\t\t输入串\t\tACTIONGOTO\n");
do{y=z;index=0;
j=0;k=0;x=Input[InputIndex];StepCount++;
printf("%3d\t",StepCount);while(index<=StateTop)/*输出状态栈*/{
printf("%d",State[index]);index++;}
printf("\t\t");index=0;
while(index<=SymbolTop)/*输出符号栈
{printf("%c",Symbol[index]);index++;}
printf("\t\t");
index=InputIndex;
while(index<=InputTop)/*输出输入串*{
printf("%c",Input[index]);index++;}
printf("\t\t");
while(x!
=Ter[j]&&j if(j==NVT&&x! =Ter[j]){ printf("\n输入字符串不是由终结符组成\n");return;} if(ACTION[y][j]==NULL){ printf("Error: ActionISNULL! \n"); return;} elsestrcpy(copy,ACTION[y][j]); if(copy[0]=='s')/*处理移进*/ {if(copy[2]! ='\0')z=(copy[1]-'0')*10+copy[2]-'0'; Elsez=copy[1]-'0'; StateTop++;SymbolTop++; State[StateTop]=z; Symbol[SymbolTop]=x; InputIndex++;i=0; while(copy[i]! ='\0') {printf("%c",copy[i]); i++;} printf("\n");} if(copy[0]=='r')/*处理归约*/{ i=0; while(copy[i]! ='\0') {printf("%c",copy[i]);i++; }strcpy(copy1,Rule[copy[1]-'0']); while(copy1[0]! =ImTer[k])k++;StateTop=StateTop-(strlen(Rule[copy[1]-'0'])-4);SymbolTop=SymbolTop-(strlen(Rule[copy[1]-'0'])-4); y=State[StateTop-1];State[StateTop]=GOTO[y][k];Symbol[SymbolTop]=copy1[0]; z=GOTO[y][k];printf("\t");printf("%4d\n",GOTO[y][k]);} }while(ACTION[y][j]! ="acc"); printf("acc\n"); for(intf=0;f<70;f++)printf("-"); 二、算符优先程序实现 typedefstruct{ charNT; charT; intflag; }array; typedefstruct{ charE; chare; }charLode; typedefstruct{ charLode*base; inttop; }charstack; arrayF[20];charstr[50][50]; charFirstvt[50][50]; charLastvt[50][50];intFnum; intTnum;intNTnum; intlec;intFF=1;charr[20]; intFsignal[30][30]; intFLAG=0;charTsig1[1][30]; charTsig2[30][1]; voidInitstack(charstack*s){ s->base=(charLode*)malloc(30*sizeof(charLode)); s->top=-1; } voidPush(charstack*s,charLodew){ s->top++; s->base[s->top].E=w.E; s->base[s->top].e=w.e; } voidPop(charstack*s,charLode*w){ w->E=s->base[s->top].E; w->e=s->base[s->top].e; s->top--;} intIsEmpty(charstacks){ if(s.top==-1)return1; elsereturn0; } intISTerminator(charch){ if(ch>='A'&&ch<='Z')return1; elsereturn0; } intYN_Operator_Grammar(intn){ intj=3,flag=1,i; for(i=0;i<=n;i++) while(str[i][j]! ='\0'){ chara=str[i][j]; charb=str[i][j+1];if(ISTerminator(a)&&ISTerminator(b)){ flag=0;break; }elsej++; }returnflag; } voidIS_Operator_priority_grammar(intn){ inti; for(i=0;i<=n;i++)if(str[i][3]=='~'||YN_Operator_Grammar(n)==0||FLAG==1){ printf("文法G不是算符优先文法! \n"); FF=0;break; } if(i>n) printf("G是算符优先文法! \n");} intsearch1(charr[],intTnum,chara)inti; for(i=0;i if(r[i]==a)break; if(i==Tnum)return0; elsereturn1; } voidcreateF(intn){ intk=0,i=1;charc;intj; chart[10];t[0]=str[0][0]; while(i<=n){ if(t[k]! =str[i][0]){ k++;t[k]=str[i][0];i++; } Elsei++; } Tnum=0; for(i=0;i<=n;i++){ j=3; while(str[i][j]! ='\0'){ c=str[i][j]; if(ISTerminator(c)==0){if(! search1(r,Tnum,c)) r[Tnum]=c; Tnum++;} j++; } } Fnum=0; for(i=0;i for(j=0;j F[Fnum].NT=t[i];F[Fnum].T=r[j];F[Fnum].flag=0;Fnum++; } } voidsearch(charLodew){ inti; for(i=0;i F[i].flag=1;break; } } voidFirstVT(intn){ charstacksta;charLodeww; charLodew;inti=0,k; chara,b;Initstack(&sta); while(i<=n){ k=3;
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- SLR1 文法 优先 程序 实现