一.前言
作为当代大学生的我,我喜极而泣,最后一个编译原理实验报告了,这次是一个提高性实验报告。肝完这个,编译原理,这门课,再也没有实验报告了,我再也不要担心我没有头发了。行了,废话不多说,我直接呈现内容吧。实验心得这类的什么东西,还是留一点小小的隐私吧。直接肝!!
二.内容
1.问题描述
预测分析属于自上而下不带回溯的语法分析方法,这种分析方法要求文法是LL(1)的,语法分析程序的输入是终结符号串(即单词符号串,一一个“#”结尾),如果输入串是句子,则输出YES,否则输出NO和错误信息。
以算术表达式的文法为例来进行LL(1)分析程序的设计。
(1)文法: 设LL(1)文法G为:
E→TE’
E’→+TE’|ε
T→FT’
T’→*FT’|ε
F→(E)|i
注:i为整型常数或者为标示符表示的整型变量。
(2)分析表 设LL(1)分析表M如下表所示。
2.问题实现的算法
预测分析算法 实现预测分析算法需要使用一个分析栈stack存放文法符号。变量top为stack的栈顶指针,变量a存放当前输入符号。LL(1)分析表为整型二维数组M[m][n].
x为栈顶符号
分析算法思想:
①若x=a=’#’,则分析成功,分析器停止工作。
②若x=a≠’#’,即栈顶符号x与当前扫描的输入符号a匹配;则将x从栈顶弹出,输入指针指向下一个输入符号,继续对下一个字符进行分析。
③若x为一非终结符号A,则查M[A,a]:
1.若M[A,a]中为一个A的产生式,则将A自栈顶弹出,并将M[A,a]中的产生式右部符号串按逆序逐一入栈;如果M[A,a]中的产生式为A->ε,则只将A自栈顶弹出。
2.若M[A,a]中为空,则发现语法错误,调用出错处理程序进行处理。
控制程序描述如下:
将“#“和文法开始符号依次压入栈中;
把第一个输入符号读入a;
do{
把栈顶符号弹出并放入x中;
if(x∈VT)
{
if(x==a)
{
if(a!=’#’) 将下一个输入符号读入a;
}
else error();
}
else
if(M[x,a]=”x→Y1Y2…Yk”)
{
按逆序依次把Yk,Yk-1…Y1压入栈中,
输出”x→Y1Y2…Yk”;
}
else error();
}while (x!=”#”)
3.问题选用的数据结构
实现预测分析算法需要使用一个分析栈stack存放文法符号。变量top为stack的栈顶指针,变量a存放当前输入符号。LL(1)分析表为整型二维数组M[m][n].x为栈顶符号,ex存放输入串,j为输入串的指针。non_sign数组存放非终结符号,ter_sign数组存放终结符号,字符串数组form存放产生式。本程序采用c++语言来实现。
non_sign:char[]//存放非终结符号
ter_sign:char[]//存放终结符号
form:string[]//存放产生式
M:int[][]//分析表
stack:char[]//符号栈(分析栈)
a:char //当前输入符号
ex:string//输入串
j:int //输入串的指针
4.整个程序的流程图
5.详细设计(设计各个函数)
本程序将如下设置为全局变量,故下函数均没有形参(print_tip函数例外)
non_sign:char[]//存放非终结符号
ter_sign:char[]//存放终结符号
form:string[]//存放产生式
M:int[][]//分析表
stack:char[]//符号栈(分析栈)
a:char //当前输入符号
ex:string//输入串
j:int //输入串的指针
各个函数:
void init_form()//算术表达式的产生式的初始化 //@代替ε A代替E’ B代替T’
void init_table()//LL(1)分析表的初始化
void suanshu_table()//赋值成算术表达式的LL(1)分析表
void display()//显示主界面
void print_match()//匹配情况
void error()//错误情况
int seek_non()//找到当前非终结符号对应的下标 返回值非终结符号对应的下标
int seek_ter()//找到当前终结符号对应的下标 返回值当前终结符号对应的下标
void print_tip(char t)//输出信息,弹出栈顶元素,,
//输入当前栈顶元素
6.程序功能效果图:
3.代码
#include<iostream>
#include<string>
#include<string.h>
#define max 100
#include<stdlib.h>
using namespace std;
int i;//循环变量
char non_sign[10]={'E','A','T','B','F'};//存放非终结符号 从0开始
char ter_sign[10]={'i','+','*','(',')','#'};//存放终结符号 从0开始
string form[10];//存放产生式 从0开始
int M[5][6];//LL(1)分析表 从0开始
char stack[max];//分析栈(符号栈) 从1开始
char x;//栈顶符号
int top=0;//栈顶指针
char a;//当前输入的符号
string ex;//输入串 从0开始
int j=0;//输入串指针
int main(){
void init_form();
void init_table();
void suanshu_table();
void display();
void print_match();
int seek_non();
int seek_ter();
void error();
void print_tip(char t);//输出信息,弹出栈顶元素,,
int flag;//分析表中的数
init_form();//算术表达式的产生式的初始化
init_table();//LL(1)分析表的初始化
suanshu_table();//赋值成算术表达式的LL(1)分析表
display();//显示主界面
//将#和文法开始符依次压入栈中
top++;
stack[top]='#';
top++;
stack[top]='E';
a=ex[j];//把第一个输入符号读入a
cout<<endl;
cout<<"符号栈";
cout<<'\t';
cout<<"当前输入符号";
cout<<'\t';
cout<<"输入串";
cout<<'\t';
cout<<"说明"<<endl;
do{
x=stack[top];//把栈顶符号弹出并放入x中
print_tip(x);//输出信息,弹出栈顶元素,,
top--;
if(x<'A'||x>'Z'){//栈顶符号是终结符号
if(x==a){//匹配
if(a!='#'){
j++;
a=ex[j];//将下一个输入符号读入a
print_match();//匹配情况
cout<<a<<endl;
}
else{//x=a='#'的情况
cout<<",匹配";
}
// cout<<",匹配";
}
else{
error();//错误情况
exit(0);
}
}
else{//栈顶符号是非终结符号
flag=M[seek_non()] [seek_ter()];
if(flag!=-1){
if(form[flag][3]=='@'){
// top--;
cout<<",因M["<<x<<","<<a<<"]中为"<<form[flag]<<",故不压栈"<<endl;
}
else{
for(i=form[flag].size()-1;i>=3;i--){//按逆序依次将产生式的候选式压入栈
top++;
stack[top]=form[flag][i];
}
cout<<",将M["<<x<<","<<a<<"]中为"<<form[flag]<<"的";
for(i=3;i<form[flag].size();i++){
cout<<form[flag][i];
}
cout<<"逆序压栈"<<endl;
}
}
else{
error();
exit(0);
}
}
}while(x!='#');
if(x==a){
// for(i=1;i<=top;i++){//符号栈
// cout<<stack[i];
// }
// cout<<'\t';
// cout<<'\t';
// cout<<a;//当前输入符号
// cout<<'\t';
// for(i=j+1;i<=ex.size();i++){//输入串
// cout<<ex[i];
// }
// cout<<'\t';
cout<<",分析成功,YES,accept!";
}
return 0;
}
void init_form(){//算术表达式的产生式的初始化 //@代替ε A代替E' B代替T'
form[0]="E->TA";
form[1]="A->+TA";
form[2]="A->@";
form[3]="T->FB";
form[4]="B->*FB";
form[5]="B->@";
form[6]="F->(E)";
form[7]="F->i";
}
void init_table(){//LL(1)分析表的初始化
int i;//循环变量
int j; //循环变量
for(i=0;i<5;i++){
for(j=0;j<6;j++){
M[i][j]=-1;
}
}
}
void suanshu_table(){//赋值成算术表达式的LL(1)分析表
M[0][0]=0;M[0][3]=0;//E->TA
M[1][1]=1; //A->+TA
M[1][4]=2;M[1][5]=2;//A->@
M[2][0]=3;M[2][3]=3;//T->FB
M[3][1]=5;M[3][4]=5;M[3][5]=5;//B->@
M[3][2]=4;//B->*FB
M[4][0]=7;//F->i
M[4][3]=6;//F->(E)
}
void display(){//显示主界面
cout<<"***************@代替ε A代替E' B代替T'*****************"<<endl;
cout<<"算术表达式的文法为:"<<endl;
for(i=0;i<8;i++){
cout<<'\t'<<form[i]<<endl;
}
cout<<"****************************************************"<<endl;
cout<<"请输入一个算术表达式串(以#结束):(串只能以i,+,*,(,)构成)"<<endl;
cin>>ex;
ex[ex.size()]='#';//用户忘记输入#,系统自动加上
}
void print_match(){//匹配情况
// cout<<'\t';
// for(i=1;i<=top;i++){//符号栈
// cout<<stack[i];
// }
// cout<<'\t';
// cout<<'\t';
// cout<<a;//当前输入符号
// cout<<'\t';
// for(i=j+1;i<=ex.size();i++){//输入串
// cout<<ex[i];
// }
// cout<<'\t'; //说明
cout<<",匹配";
cout<<",读出输入串的下一个输入符号";
}
void error(){//错误情况
for(i=1;i<=top;i++){
cout<<stack[i];
}
cout<<'\t';
cout<<a;
cout<<'\t';
for(i=j+1;i<ex.size();i++){
cout<<ex[i];
}
cout<<'\t';
cout<<"NO,输入的符号不正确!!"<<endl;
}
int seek_non(){//找到当前非终结符号对应的下标
for(i=0;i<strlen(non_sign);i++){
if(x==non_sign[i]){
break;
}
}
return i;
}
int seek_ter(){//找到当前终结符号对应的下标
for(i=0;i<strlen(ter_sign);i++){
if(a==ter_sign[i]){
break;
}
}
return i;
}
void print_tip(char t){//输出信息,弹出栈顶元素,,
for(i=1;i<=top;i++){//符号栈
cout<<stack[i];
}
cout<<'\t';
cout<<'\t';
cout<<a;//当前输入符号
cout<<'\t';
for(i=j+1;i<=ex.size();i++){//输入串
cout<<ex[i];
}
cout<<'\t';
cout<<"弹出栈顶符号"<<t;
}