编译原理 -实验3-4 预测分析表方法
合集下载
相关主题
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
(5)对正规式进行处理
3.错误处理机制
紧急方式的错误恢复方法(抛弃某些符号,继续向下分析)
(1)栈顶为非终结符A,串中当前单词属于FOLLOW(A),则从栈中弹出A(此时可认为输入串中缺少A表示的结构),继续分析。---------错误编号为1
(2)栈顶为非终结符A,串中当前单词不属于FOLLOW(A),则可使串指针下移一个位置(认为输入串中当前单词多余),继续分析。----------错误编号为2
{
//SeqStack *s;
s=new SeqStack;
if(!s)
{
printf("空间不足\n");
return NULL;
}
else
{
s->top=-1;
return s;
}
}
void Push_SeqStack(SeqStack *s,char x)//入栈
{
if (s->top==MAXSIZE-1)
if(x∈VT)
{
if(x==a)将下一输入符号读入a;
elseerror(3);
}
eΒιβλιοθήκη Baiduse
if(M[x,a]=“x→y1y2…yk”)
{
按逆序依次把yk、yk−1、…、y1压入栈中;
输出“x→y1y2…yk”;
}
elseif afollow(x)error(1);else error(2);
//在前述的数据定义中查表为-1表示afollow(x)
实验3-4预测分析表方法
班级:__学号:__姓名:_ _得分:_ _
一、实验目的
理解预测分析表方法的实现原理。
二、实验内容:
编写一通用的预测法分析程序,要求有一定的错误处理能力,出错后能够使程序继续运行下去,直到分析过程结束。可通过不同的文法(通过数据表现)进行测试。
二、实验内容提示
1.算法数据构造:
printf("栈满,不能入栈!");//return 0;
else
{
s->top++;
s->data[s->top]=x;
//return 1;
}
}
char Pop_SeqStack(SeqStack *s)//出栈
{
if(s->top==-1)
{
printf("栈空,不可出栈!");// return 0;
}
int BufVT(char s) //接收终结符并保存在VT[]数组中
{
int i=0;
while(i<15&&s!='\n')
{
if(VT[i][0]==s)
return 1;
else
i++;
}
return 0;
}
int BufVN(char s) //接收非终结符并保存在VN[]数组中
{
int i=0;
//产生式表:0:E->TE' 1:E'->+TE' 2:E'->空
// 3:T->FT' 4:T'->*FT' 5:T'->空6:F->(E) 7:F->id
intanalysis_table[10][11]={0,-2,-2,0,-1,-1,0,0,0,0,0,
-2,1,-2,-2,2,2,0,0,0,0,0,
构造终结符数组:char Vt[10][5]={“id”,”+”……};
构造非终结符数组:char Vn[10]={};
构造follow集数组:char *follow[10][10]={ } (可将follow集与预测分析表合并存放)
数据构造示例(使用的预测分析表构造方法1):
/*data1.h简单算术表达式数据*/
构造预测分析表:int analyze_table[10][10]={ } //数组元素值存放产生式的编号,-1、-2表示出错
(2)预测分析表的构造方法2
可使用三维数组
Char analyze_table[10][10][10]={ }
或
Char *analyze_table[10][10]={ }
Char Pa[15][10]={"E->TM","M->+TM","M->TM","M->空","T->FN","N->空","N->*FN","F->/FN","F->%FN","F->(E)","F->id","F->num"};
int analysis_table[10][11]={{-1,-1,-1,-1,-1,1,-2,1,1,-1,0},
Pop_SeqStack(s);
}
else if(errornum==2)
printf("第二种错误,跳过%c\n",x);
else
{
if(x='#')
{
printf("第三种错误,弹出栈顶元素\n");
Pop_SeqStack(s);
}
else
{
printf("第三种错误,指针下移弹出栈顶元素\n");
{
If(errornum==1)………………
Else if(errornum==2)……………
Else………………..
//或者可用choose case语句处理
}
4.增加了错误处理的预测分析程序预测分析程序的算法:
将“#”和文法开始符依次压入栈中;
把第一个输入符号读入a;
do{
把栈顶符号弹出并放入x中;
{2,3,-1,-1,-1,-1,4,-1,-1,4,0},
{-2,-2,-1,-1,-1,5,-2,5,5,-1,0},
{6,6,7,8,9,-1,6,-1,-1,6,0},
{-2,-2,-2,-2,-2,10,-2,11,12,-1,0}
};//预测分析表
SeqStack *Init_SeqSTACK()//栈初始化
charVN[10][5]={"E","E'","T","T'","F"};//非终结符表
intlength_vn=5;//非终结符的个数
charVT[15][5]={"id","+","*","(",")","#"};//终结符表
intlength_vt=6;//终结符的个数
charFa[15][10]={"TE'","+TE'","","FT'","*FT'","","(E)","id"};
printf("栈顶元素\t\t当前单词记号\t\t动作\n");
printf("=============================================================\n");
do
{
x=Top_SeqStack(s);
if(x=='#')
goto loop;
else
(3)栈顶为终结符,且不等于串中当前单词,则从栈中弹出此终结符(认为输入串中缺少当前单词)或者将串指针下移一个位置(认为串中当前单词多余)。在程序中可选择上述两种观点中的一种进行处理。-------------错误编号3
因此error()函数的编写方式可按如下方式处理
Error(int errornum)
3,-1,-2,3,-1,-1,0,0,0,0,0,
-2,5, 4,-2,5, 5,0,0,0,0,0,
7,-1,-1,6,-1,-1,0,0,0,0,0};
//预测分析表,-2表示出错不属于终结符的follow集合,-1表示该行终结符的follow集合,用于错误处理,正数表示产生式在数组Fa中的编号,右部五列0表示多余的列。
{
if(!BufVT(str2[sign])&&!BufVN(x))
{
printf("%c\t\t\t%s\t\t\t%s",x,str2[sign]);
printf("当前字符不合法!\n");
}
else if(BufVT(str2[sign]))
{
if(x==str2[sign])
{
printf("%c\t\t\t%c\t\t\t",x,str2[sign]);
}while(x!=“#”)
三.实验要求
给定算术表达式文法,编写程序。
测试数据:
1.算术表达式文法
E→TE’
E’→ +TE’|- TE’|ε
T→FT’
T’→*FT’|/ FT’|%FT’|ε
F→(E) |id|num
给定一符合该文法的句子,如id+id*id$,或输入二元式序列(词法分析的结果,预测分析程序只用到二元式中的第一个元的值):(id,0)(+,-)(id,1)(*,-)(id,2),运行预测分析程序,给出分析过程和每一步的分析结果。
while(i<10&&s!='\n')
{
if(VN[i][0]==s)
return 1;
else
i++;
}
return 0;
}
int VTT(char s) //终结符匹配
{
int i=0;
while((VT[i][0]!=s))
i++;
return i;
}
int VNN(char s) //非终结符匹配
printf("匹配终结符%c\n",str2[sign]);
Pop_SeqStack(s);
sign++;
}
else
{
BufVN(x);
num1=VTT(str2[sign]);
{
int i=0;
while(VN[i][0]!=s&&i<length_vn)
{
i++;
}
if(i==length_vn)
return -1;
return i;
}
void Error(int errornum,char x)
{
if(errornum==1)
{
printf("第一种错误,弹出栈顶元素\n");
exit(0);
}
else
{
char x=s->data[s->top];
s->top--;
return x;
}
}
DataType Top_SeqStack(SeqStack *s) //取栈顶元素
{
if(s->top==-1)
return 0;
else
return s->data [s->top ];
(1)预测分析表的构造方法1
给文法的正规式编号:存放在字符数组中,从0开始编号,正规式的编号即为该正规式在数组中对应的下标。如上述Fa数组表示存储产生式。
构造产生式数组:char P[10][10]={“E->TE’”,”E’->+TE’”,……..}; (产生式可只存储右半部分,如E->TE’可存储为TE’,正规式中的符号可替换,如可将E’改为M )
exit(0);
}
while(!feof(fp))
{
str2[i]=fgetc(fp);
i++;
}
str2[i]='\0';
fclose(fp);
Init_SeqSTACK();
s->top=-1;
Push_SeqStack(s,'#');
Push_SeqStack(s,'E');
char x;
printf("语法分析过程如下:\n");
输出形式参考下图($为结束符):
2.作业3.10文法
四、实验过程
源程序:
#include<stdio.h>
#include<string>
#include<stdlib.h>
#include<iostream>
using namespace std;
#define MAXSIZE 100
typedef char DataType;
char VT[15][5]={"+","-","*","/","%","(",")","i","n","#"};//终结符表
int length_vt=10; //终结符个数
char Fa[15][5]={"TM","+TM","-TM","","FN","","*FN","/FN","%FN","(E)","i","n"};//产生式表1:E->TM,2:M->+TM,3:M->-TM,4:M-> ,5:E->FN,6:N-> ,7:N->*FN,8:F->/FN,9:F->%FN,10:F->(E),11:F->i,12:f->n
2.针对预测分析表构造方法1的查预测分析表的方法提示:
(1)查非终结符表得到非终结符的序号no1
(2)查终结符表得到终结符的序号no2
(3)根据no1和no2查预测分析表得到对应正规式的序号no3=analyze_table[no1][no2],如果no3=-1表示出错。
(4)根据no3查找对应的正规式Fa[no3]
typedef struct //定义栈
{
DataType data[MAXSIZE];
int top;
}SeqStack;
SeqStack *s;
int sign=0;
int num1,num2,num3;
char VN[10][5]={"E","M","T","N","F"};//非终结符表
int length_vn=5;//非终结符个数
Pop_SeqStack(s);
sign++;
}
}
}
void main()
{
char str1[20],str2[20];
int i=0;
printf("请输入所要分析的文件名:");
scanf("%s",str1);
FILE *fp;
if((fp=fopen(str1,"r"))==NULL)
{
printf("没有这个文件!\n");
3.错误处理机制
紧急方式的错误恢复方法(抛弃某些符号,继续向下分析)
(1)栈顶为非终结符A,串中当前单词属于FOLLOW(A),则从栈中弹出A(此时可认为输入串中缺少A表示的结构),继续分析。---------错误编号为1
(2)栈顶为非终结符A,串中当前单词不属于FOLLOW(A),则可使串指针下移一个位置(认为输入串中当前单词多余),继续分析。----------错误编号为2
{
//SeqStack *s;
s=new SeqStack;
if(!s)
{
printf("空间不足\n");
return NULL;
}
else
{
s->top=-1;
return s;
}
}
void Push_SeqStack(SeqStack *s,char x)//入栈
{
if (s->top==MAXSIZE-1)
if(x∈VT)
{
if(x==a)将下一输入符号读入a;
elseerror(3);
}
eΒιβλιοθήκη Baiduse
if(M[x,a]=“x→y1y2…yk”)
{
按逆序依次把yk、yk−1、…、y1压入栈中;
输出“x→y1y2…yk”;
}
elseif afollow(x)error(1);else error(2);
//在前述的数据定义中查表为-1表示afollow(x)
实验3-4预测分析表方法
班级:__学号:__姓名:_ _得分:_ _
一、实验目的
理解预测分析表方法的实现原理。
二、实验内容:
编写一通用的预测法分析程序,要求有一定的错误处理能力,出错后能够使程序继续运行下去,直到分析过程结束。可通过不同的文法(通过数据表现)进行测试。
二、实验内容提示
1.算法数据构造:
printf("栈满,不能入栈!");//return 0;
else
{
s->top++;
s->data[s->top]=x;
//return 1;
}
}
char Pop_SeqStack(SeqStack *s)//出栈
{
if(s->top==-1)
{
printf("栈空,不可出栈!");// return 0;
}
int BufVT(char s) //接收终结符并保存在VT[]数组中
{
int i=0;
while(i<15&&s!='\n')
{
if(VT[i][0]==s)
return 1;
else
i++;
}
return 0;
}
int BufVN(char s) //接收非终结符并保存在VN[]数组中
{
int i=0;
//产生式表:0:E->TE' 1:E'->+TE' 2:E'->空
// 3:T->FT' 4:T'->*FT' 5:T'->空6:F->(E) 7:F->id
intanalysis_table[10][11]={0,-2,-2,0,-1,-1,0,0,0,0,0,
-2,1,-2,-2,2,2,0,0,0,0,0,
构造终结符数组:char Vt[10][5]={“id”,”+”……};
构造非终结符数组:char Vn[10]={};
构造follow集数组:char *follow[10][10]={ } (可将follow集与预测分析表合并存放)
数据构造示例(使用的预测分析表构造方法1):
/*data1.h简单算术表达式数据*/
构造预测分析表:int analyze_table[10][10]={ } //数组元素值存放产生式的编号,-1、-2表示出错
(2)预测分析表的构造方法2
可使用三维数组
Char analyze_table[10][10][10]={ }
或
Char *analyze_table[10][10]={ }
Char Pa[15][10]={"E->TM","M->+TM","M->TM","M->空","T->FN","N->空","N->*FN","F->/FN","F->%FN","F->(E)","F->id","F->num"};
int analysis_table[10][11]={{-1,-1,-1,-1,-1,1,-2,1,1,-1,0},
Pop_SeqStack(s);
}
else if(errornum==2)
printf("第二种错误,跳过%c\n",x);
else
{
if(x='#')
{
printf("第三种错误,弹出栈顶元素\n");
Pop_SeqStack(s);
}
else
{
printf("第三种错误,指针下移弹出栈顶元素\n");
{
If(errornum==1)………………
Else if(errornum==2)……………
Else………………..
//或者可用choose case语句处理
}
4.增加了错误处理的预测分析程序预测分析程序的算法:
将“#”和文法开始符依次压入栈中;
把第一个输入符号读入a;
do{
把栈顶符号弹出并放入x中;
{2,3,-1,-1,-1,-1,4,-1,-1,4,0},
{-2,-2,-1,-1,-1,5,-2,5,5,-1,0},
{6,6,7,8,9,-1,6,-1,-1,6,0},
{-2,-2,-2,-2,-2,10,-2,11,12,-1,0}
};//预测分析表
SeqStack *Init_SeqSTACK()//栈初始化
charVN[10][5]={"E","E'","T","T'","F"};//非终结符表
intlength_vn=5;//非终结符的个数
charVT[15][5]={"id","+","*","(",")","#"};//终结符表
intlength_vt=6;//终结符的个数
charFa[15][10]={"TE'","+TE'","","FT'","*FT'","","(E)","id"};
printf("栈顶元素\t\t当前单词记号\t\t动作\n");
printf("=============================================================\n");
do
{
x=Top_SeqStack(s);
if(x=='#')
goto loop;
else
(3)栈顶为终结符,且不等于串中当前单词,则从栈中弹出此终结符(认为输入串中缺少当前单词)或者将串指针下移一个位置(认为串中当前单词多余)。在程序中可选择上述两种观点中的一种进行处理。-------------错误编号3
因此error()函数的编写方式可按如下方式处理
Error(int errornum)
3,-1,-2,3,-1,-1,0,0,0,0,0,
-2,5, 4,-2,5, 5,0,0,0,0,0,
7,-1,-1,6,-1,-1,0,0,0,0,0};
//预测分析表,-2表示出错不属于终结符的follow集合,-1表示该行终结符的follow集合,用于错误处理,正数表示产生式在数组Fa中的编号,右部五列0表示多余的列。
{
if(!BufVT(str2[sign])&&!BufVN(x))
{
printf("%c\t\t\t%s\t\t\t%s",x,str2[sign]);
printf("当前字符不合法!\n");
}
else if(BufVT(str2[sign]))
{
if(x==str2[sign])
{
printf("%c\t\t\t%c\t\t\t",x,str2[sign]);
}while(x!=“#”)
三.实验要求
给定算术表达式文法,编写程序。
测试数据:
1.算术表达式文法
E→TE’
E’→ +TE’|- TE’|ε
T→FT’
T’→*FT’|/ FT’|%FT’|ε
F→(E) |id|num
给定一符合该文法的句子,如id+id*id$,或输入二元式序列(词法分析的结果,预测分析程序只用到二元式中的第一个元的值):(id,0)(+,-)(id,1)(*,-)(id,2),运行预测分析程序,给出分析过程和每一步的分析结果。
while(i<10&&s!='\n')
{
if(VN[i][0]==s)
return 1;
else
i++;
}
return 0;
}
int VTT(char s) //终结符匹配
{
int i=0;
while((VT[i][0]!=s))
i++;
return i;
}
int VNN(char s) //非终结符匹配
printf("匹配终结符%c\n",str2[sign]);
Pop_SeqStack(s);
sign++;
}
else
{
BufVN(x);
num1=VTT(str2[sign]);
{
int i=0;
while(VN[i][0]!=s&&i<length_vn)
{
i++;
}
if(i==length_vn)
return -1;
return i;
}
void Error(int errornum,char x)
{
if(errornum==1)
{
printf("第一种错误,弹出栈顶元素\n");
exit(0);
}
else
{
char x=s->data[s->top];
s->top--;
return x;
}
}
DataType Top_SeqStack(SeqStack *s) //取栈顶元素
{
if(s->top==-1)
return 0;
else
return s->data [s->top ];
(1)预测分析表的构造方法1
给文法的正规式编号:存放在字符数组中,从0开始编号,正规式的编号即为该正规式在数组中对应的下标。如上述Fa数组表示存储产生式。
构造产生式数组:char P[10][10]={“E->TE’”,”E’->+TE’”,……..}; (产生式可只存储右半部分,如E->TE’可存储为TE’,正规式中的符号可替换,如可将E’改为M )
exit(0);
}
while(!feof(fp))
{
str2[i]=fgetc(fp);
i++;
}
str2[i]='\0';
fclose(fp);
Init_SeqSTACK();
s->top=-1;
Push_SeqStack(s,'#');
Push_SeqStack(s,'E');
char x;
printf("语法分析过程如下:\n");
输出形式参考下图($为结束符):
2.作业3.10文法
四、实验过程
源程序:
#include<stdio.h>
#include<string>
#include<stdlib.h>
#include<iostream>
using namespace std;
#define MAXSIZE 100
typedef char DataType;
char VT[15][5]={"+","-","*","/","%","(",")","i","n","#"};//终结符表
int length_vt=10; //终结符个数
char Fa[15][5]={"TM","+TM","-TM","","FN","","*FN","/FN","%FN","(E)","i","n"};//产生式表1:E->TM,2:M->+TM,3:M->-TM,4:M-> ,5:E->FN,6:N-> ,7:N->*FN,8:F->/FN,9:F->%FN,10:F->(E),11:F->i,12:f->n
2.针对预测分析表构造方法1的查预测分析表的方法提示:
(1)查非终结符表得到非终结符的序号no1
(2)查终结符表得到终结符的序号no2
(3)根据no1和no2查预测分析表得到对应正规式的序号no3=analyze_table[no1][no2],如果no3=-1表示出错。
(4)根据no3查找对应的正规式Fa[no3]
typedef struct //定义栈
{
DataType data[MAXSIZE];
int top;
}SeqStack;
SeqStack *s;
int sign=0;
int num1,num2,num3;
char VN[10][5]={"E","M","T","N","F"};//非终结符表
int length_vn=5;//非终结符个数
Pop_SeqStack(s);
sign++;
}
}
}
void main()
{
char str1[20],str2[20];
int i=0;
printf("请输入所要分析的文件名:");
scanf("%s",str1);
FILE *fp;
if((fp=fopen(str1,"r"))==NULL)
{
printf("没有这个文件!\n");