算符优先文法的编程实现
来源:互联网 发布:windows 10 superfetch 编辑:程序博客网 时间:2024/05/16 12:19
实验三 算符优先文法的编程实现
一、实验目的
1. 通过本次实验,加深对移进规约分析法中算符优先法的理解;
2. 学习程序设计语言的语法分析器的手工编程方法。
二、实验内容
1. 对于任意给定的文法,判断其是否是算符优先文法。
2. 通过语法分析,生成抽象语法树,在此基础上设计并实现一个简单的计算器。
三、实验原理
1. 自底向上优先分析方法
也称移进-归约分析,粗略地说它的思想是对输入符号串自左向右进行扫描,并将输入符号逐个移入一个后进先出栈,边移入边分析,一旦栈顶符号串形成某个句型的句柄或可归约串时,就将该产生式的左部非终极符代替相应的右边文法符号串。
2. 算符优先分析
依照算术表达式的四则运算过程来进行语法分析,即这种分析方法要预先规定运算符(确切地说是终结符)之间的优先关系和结合性质,然后借助于这种关系来比较相邻运算符的优先级,以确定句型的“可归约串”来进行归约。
因此,算符优先分析法不是一种规范归约,在整个归约过程中起决定性作用的是相继两个终结符的优先关系。
3. 算符优先文法
首先定义一个任何产生式的右部都不含两个相继(并列)的非终结符的文法为算符文法,即算符优先文法首先应是一个算符文法;其次,还要定义任何两个可能相继出现的终结符a与b (它们之间最多插有一个非终结符)的优先关系。
4. 终结符号间优先关系的确定,用FIRSTVT集和LASTVT集计算。
FIRSTVT集:
(1) 若有产生式P→a…或P→Qa…,则a∈FIRSTVT(P);
(2) 若a∈FIRSTVT(Q),且产生式P→Q…,则a∈FIRSTVT(P)。
LASTVT集:
(1) 若有产生式P→…a或P→…aQ,则a∈LASTVT(P);
(2) 若a∈LASTVT(Q),且P→…Q,则a∈LASTVT(P)。
四、算法思想
1.根据所输入文法规则,求文法中每个非终结符的FIRSTVT集和LASTVT集。
算符描述如下:
/*求 FirstVT 集的算法*/
PROCEDURE insert(P,a); IF not F[P,a] then begin
F[P,a] = true; //(P,a)进栈 end;
Procedure FirstVT; Begin
for 对每个非终结符 P和终结符 a do F[P,a] = false for 对每个形如 P a…或 P→Qa…的产生式 do
Insert(P,a) while stack 非空 begin
栈顶项出栈,记为(Q,a)
for 对每条形如 P→Q…的产生式 do insert(P,a) end; end.
2.构造算符优先关系表
算法描述如下:
for 每个形如 P->X1X2…Xn的产生式 do for i =1 to n-1 do begin
if Xi和Xi+1都是终结符 then Xi = Xi+1
if i<= n-2, Xi和Xi+2 是终结符, 但Xi+1 为非终结符 then Xi = Xi+2
if Xi为终结符, Xi+1为非终结符
then
for FirstVT 中的每个元素 a
do Xi < a
if Xi为非终结符, Xi+1为终结符
then
for LastVT 中的每个元素 a
do a > Xi+1
end
五、具体实现
#include <stdio.h>#include <stdlib.h>char data[20][20]; //算符优先关系char s[100]; //模拟符号栈s char lable[20]; //文法终极符集char input[100]; //文法输入符号串char string[20][10]; //用于输入串的分析int k; char a; int j; char q; int r; //文法规则个数int r1; int m,n,N; //转化后文法规则个数char st[10][30]; //用来存储文法规则char first[10][10]; //文法非终结符FIRSTVT集char last[10][10]; //文法非终结符LASTVT集int fflag[10]={0}; //标志第i个非终结符的FIRSTVT集是否已求出int lflag[10]={0}; //标志第i个非终结符的LASTVT集是否已求出int zhongjie(char c); //判断字符c是否是终极符int xiabiao(char c); //求字符c在算符优先关系表中的下标void out(int j,int k,char *s); //打印s栈void firstvt(char c); //求非终结符c的FIRSTVT集void lastvt(char c); //求非终结符c的LASTVT集void table(); //创建文法优先关系表int main(){int i,j,k=0; printf("请输入文法规则数:");scanf("%d",&r);printf("请输入文法规则:\n");for(i=0;i<r;i++){scanf("%s",st[i]); //存储文法规则,初始化FIRSTVT集和LASTVT集*/ first[i][0]=0; //first[i][0]和last[i][0]分别表示st[i][0]非终极符的FIRSTVT集和LASTVT集中元素的个数last[i][0]=0;}for(i=0;i<r;i++) //判断文法是否合法{for(j=0;st[i][j]!='\0';j++){if(st[i][0]<'A'||st[i][0]>'Z'){printf("不是算符文法!\n"); exit(-1);}if(st[i][j]>='A'&&st[i][j]<='Z'){ if(st[i][j+1]>='A'&&st[i][j+1]<='Z'){printf("不是算符文法!\n"); exit(-1);}}}} for(i=0;i<r;i++){for(j=0;st[i][j]!='\0';j++){if((st[i][j]<'A'||st[i][j]>'Z')&&st[i][j]!='-'&&st[i][j]!='>'&&st[i][j]!='|')lable[k++]=st[i][j];}}lable[k]='#';lable[k+1]='\0'; table();printf("每个非终结符的FIRSTVT集为:\n"); //输出每个非终结符的FIRSTVT集for(i=0;i<r;i++){printf("%c: ",st[i][0]);for(j=0;j<first[i][0];j++){printf("%c ",first[i][j+1]);}printf("\n");}printf("每个非终结符的LASTVT集为:\n"); //输出每个非终结符的LASTVT集for(i=0;i<r;i++){printf("%c: ",st[i][0]);for(j=0;j<last[i][0];j++){printf("%c ",last[i][j+1]);}printf("\n");}printf("算符优先分析表如下:\n");for(i=0;lable[i]!='\0';i++) printf("\t%c",lable[i]);printf("\n"); for(i=0;i<k+1;i++){printf("%c\t",lable[i]);for(j=0;j<k+1;j++){printf("%c\t",data[i][j]);}printf("\n");}for(i=0;i<k+1;i++){for(j=0;j<k+1;j++){if(data[i][j]=='>'&&data[j][i]!='<'&&data[j][i]!='\0') break;else if(data[i][j]=='<'&&data[j][i]!='>'&&data[j][i]!='\0') break;else if(data[i][j]=='='&&data[j][i]!='='&&data[j][i]!='\0') break;}}if(i==(k+1)&&j==(k+1)) printf("该文法是算符优先文法。\n"); else printf("该文法不是算符优先文法。\n"); return 0;}void table(){char text[20][10];int i,j,k,t,l,x=0,y=0;int m,n;x=0;for(i=0;i<r;i++){firstvt(st[i][0]);lastvt(st[i][0]);}for(i=0;i<r;i++){text[x][y]=st[i][0];y++;for(j=1;st[i][j]!='\0';j++){if(st[i][j]=='|'){text[x][y]='\0';x++;y=0;text[x][y]=st[i][0];y++;text[x][y++]='-';text[x][y++]='>';}else{text[x][y]=st[i][j];y++;}}text[x][y]='\0';x++;y=0;}r1=x;printf("转化后的文法为:\n");for(i=0;i<x;i++) {printf("%s\n",text[i]);}for(i=0;i<x;i++) {string[i][0]=text[i][0];for(j=3,l=1;text[i][j]!='\0';j++,l++)string[i][l]=text[i][j];string[i][l]='\0';}for(i=0;i<x;i++){for(j=1;text[i][j+1]!='\0';j++){if(zhongjie(text[i][j])&&zhongjie(text[i][j+1])){m=xiabiao(text[i][j]);n=xiabiao(text[i][j+1]);data[m][n]='=';}if(text[i][j+2]!='\0'&&zhongjie(text[i][j])&&zhongjie(text[i][j+2])&&!zhongjie(text[i][j+1])){m=xiabiao(text[i][j]);n=xiabiao(text[i][j+2]);data[m][n]='=';}if(zhongjie(text[i][j])&&!zhongjie(text[i][j+1])){for(k=0;k<r;k++){if(st[k][0]==text[i][j+1])break;}m=xiabiao(text[i][j]);for(t=0;t<first[k][0];t++){n=xiabiao(first[k][t+1]);data[m][n]='<';}}if(!zhongjie(text[i][j])&&zhongjie(text[i][j+1])){for(k=0;k<r;k++){if(st[k][0]==text[i][j])break;}n=xiabiao(text[i][j+1]);for(t=0;t<last[k][0];t++){m=xiabiao(last[k][t+1]);data[m][n]='>';}}}}m=xiabiao('#');for(t=0;t<first[0][0];t++){n=xiabiao(first[0][t+1]);data[m][n]='<';}n=xiabiao('#');for(t=0;t<last[0][0];t++){m=xiabiao(last[0][t+1]);data[m][n]='>';}data[n][n]='=';}void firstvt(char c) {int i,j,k,m,n;for(i=0;i<r;i++){if(st[i][0]==c)break;}if(fflag[i]==0){n=first[i][0]+1;m=0;do{if(m==2||st[i][m]=='|'){if(zhongjie(st[i][m+1])){first[i][n]=st[i][m+1];n++;}else{if(zhongjie(st[i][m+2])){first[i][n]=st[i][m+2];n++;}if(st[i][m+1]!=c){firstvt(st[i][m+1]);for(j=0;j<r;j++){if(st[j][0]==st[i][m+1])break;}for(k=0;k<first[j][0];k++){int t;for(t=0;t<n;t++){if(first[i][t]==first[j][k+1])break;}if(t==n){first[i][n]=first[j][k+1];n++;}}}}}m++;}while(st[i][m]!='\0');first[i][n]='\0';first[i][0]=--n;fflag[i]=1;}}void lastvt(char c){int i,j,k,m,n;for(i=0;i<r;i++){if(st[i][0]==c)break;}if(lflag[i]==0){n=last[i][0]+1;m=0;do{if(st[i][m+1]=='\0'||st[i][m+1]=='|'){if(zhongjie(st[i][m])){last[i][n]=st[i][m];n++;}else{if(zhongjie(st[i][m-1])){last[i][n]=st[i][m-1];n++;}if(st[i][m]!=c){lastvt(st[i][m]);for(j=0;j<r;j++){if(st[j][0]==st[i][m])break;}for(k=0;k<last[j][0];k++){int t;for(t=0;t<n;t++){if(last[i][t]==last[j][k+1])break;}if(t==n){last[i][n]=last[j][k+1];n++;}}}}}m++;}while(st[i][m]!='\0');last[i][n]='\0';last[i][0]=--n;lflag[i]=1;}}void out(int j,int k,char *s){int n=0;int i;for(i=j;i<=k;i++){printf("%c",s[i]);n++;}for(;n<15;n++){printf(" ");}}int xiabiao(char c) //求字符c在算符优先关系表中的下标{int i;for(i=0;lable[i]!='\0';i++){if(c==lable[i])return i;}return -1;}int zhongjie(char c)//判断字符c是否是终极符{int i;for(i=0;lable[i]!='\0';i++){if(c==lable[i])return 1;}return 0;}
六、测试与运行情况
1.输入测试样例1:
运行结果:
- 算符优先文法的编程实现
- 算符优先文法的一个实现
- 算符优先文法的实现代码
- 算符优先文法实现
- 语法分析(算符优先文法)
- [编译原理]算符优先文法分析与实现
- 一个算符文法分析的实现
- 简单算符优先文法分析程序(编译原理)
- 算符优先算法(FIRSTVT集,LASTVT集,判读是否是算符优先文法,算符优先矩阵,句子分析)
- 文法驱动计算器的实现
- 编译原理实验四——算符优先文法语法分析
- 左线性文法标示符识别的c++实现
- 2.java编程实现压缩文法的等价变化--加标记算法
- 基于文法分析的简单计算器实现
- 基于文法分析的表达式计算器的实现
- 学编译原理,一个文法规则的实现
- 程序实现给定文法的LL(1)分析
- 基于LL(1)文法实现的简单计算器
- HashSet中是如何判断元素是否重复的
- 过滤字母,只能输入数字的设置
- linux的crontab实现秒级别定时调用脚本
- APP加固技术历程及未来级别方案:虚机源码保护
- libevent 多线程实现高并发
- 算符优先文法的编程实现
- hive快速上手
- ORA-00054: 资源正忙, 但指定以 NOWAIT 方式获取资源, 或者超时失效
- js面试题解析
- java.lang.NoSuchMethodError异常可能出现的原因
- 去掉输入框选择框等在移动端聚焦时出现一闪的情况
- 有分段函数如下,求age(5)。age(n)=10 (n=1) age(n)=age(n-1)+2 n>1
- 大型网站技术架构(四)——网站的高性能架构
- Ubuntu 16.04,双显卡,GTX1060,安装 NVIDIA 显卡驱动