LL(1)预测分析法实验报告
合集下载
相关主题
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
for(i=0;i<p.length()-1;i++)
{
cout<<p[i]<<",";
}
cout<<p[i]<<"}";
}
//连续输出符号
void outfu(int a,string c)
{
int i;
for(i=0;i<a;i++)
cout<<c;
}
//输出预测分析表
void outgraph(edge *n,string (*yc)[50])
//edge.cpp
#include<iostream>
#include "edge.h"
using namespace std;
edge::edge()
{
cin>>left>>right;
rlen=right.length();
if(NODE.find(left)>NODE.length())
NODE+=left;
为了使一个文法是LR的,只要保证当句柄出现在栈顶时,自左向右扫描的移进-归约分析器能够及时识别它便足够了。当句柄出现在栈顶时,LR分析器必须要扫描整个栈就可以知道这一点,栈顶的状态符号包含了所需要的一切信息。如果仅知道栈内的文法符号就能确定栈顶是什么句柄。LR分析表的转移函数本质上就是这样的有限自动机。不过,这个有限自动机不需要根据每步动作读栈,因为,如果这个识别句柄的有限自动机自底向上读栈中的文法符号的话,它达到的状态正是这时栈顶的状态符号所表示的状态,所以,LR分析器可以从栈顶的状态确定它需要从栈中了解的一切。
{
ni.newselect(ni.getro());
if(ni.getro()=="*")
ni.newselect(ni.getfollow());
}
else
for(i=0;i<ni.getrlen();i++)
for(j=0;j<SUM;j++)
if(ni.getrg()[i]==n[j].getlf()[0])
for(i=0;i<w.length();i++)
if(first.find(w[i])>first.length())
first+=w[i];
}
void edge::newfollow(string w)
{
int i;
for(i=0;i<w.length();i++)
if(follow.find(w[i])>follow.length()&&w[i]!='*')
class edge
{
public:
edge();
string getlf();
string getrg();
string getfirst();
string getfollow();
string getselect();
string getro();
int getrlen();
void newfirst(string w);
{
ni.newselect(n[j].getfirst());
if(n[j].getfirst().find('*')>n[j].getfirst().length())
return;
}
}
//输出集合
void out(string p)
{
int i;
if(p.length()==0)
return;
cout<<"{";
if(x<n[j].getselect().length()&&x>-1)
{
cout<<"->"<<n[j].getrg();
yc[i][k]=n[j].getrg();
outfu(9-n[j].getrlen()," ");
flag=0;
}
x=n[j].getselect().find('#');
编
译
原
理
实
验
报
告
一、实验目的及要求
1.通过本次实验,加深对LL(1)预测分析法原理的认识和理解。
2.构造LR(1)分析程序,利用它进行语法分析,判断给出的符号串是否为该文法识别的句子。
3.了解LR(K)分析方法是严格的从左向右扫描,和自底向上的语法分析方法。
二、运行环境:
硬件:windows xp
软件:visual c++6.0
}
}
//分析符号串
int pipei(string &chuan,string &fenxi,string (*yc)[50],int &b)
{
char ch,a;
int x,i,j,k;
b++;
cout<<endl<<" "<<b;
if(b>9)
outfu(8," ");
else
outfu(9," ");
{
int i=first.find('*');
first.erase(i,1);
}
//LL1.cpp
#include<iostream>
#include<string>
#include "edge.h"
using namespace std;
int SUM;
string NODE,ENODE;
//计算first
follow+=w[i];
}
void edge::newselect(string w)
{
int i;
for(i=0;i<w.length();i++)
if(select.find(w[i])>select.length()&&w[i]!='*')
select+=w[i];
}
void edge::delfirst()
{
return select;
}
string edge::getro()
{
string str;
str+=right[0];
return str;
}
int edge::getrlen()
{
return right.length();
}
void edge::newfirst(string w)
{
int i;
void newfollow(string w);
void newselect(string w);
void delfirst();
private:
string left,right,first,follow,select;
int rlen;
};
#endif
/////////////////////////////////////////////////////////////////////////////
if(n[i].getlf()==n[j].getro())
first(n[i],n,x);
}
else
n[x].newfirst(n[j].getro());
}
}
}
//计算follow
void follow(edge ni,edge *n,int x)
{
int i,j,k,s;
string str;
{
if(ch==a)
{
fenxi.erase(fenxi.length()-1,1);
chuan.erase(0,1);
cout<<"'"<<a<<"'匹配";
if(pipei(chuan,fenxi,yc,b))
return 1;
else
return 0;
}
else
return 0;
}
else
{
if(ch=='#')
{
if(ch==a)
{
cout<<"分析成功"<<endl;
return 1;
}
else
return 0;
}
else
if(ch=='*')
{
fenxi.erase(fenxi.length()-1,1);
if(pipei(chuan,fenxi,yc,b))
return 1;
else
return 0;
{
int i,j,k;
bool flag;
for(i=0;i<ENODE.length();i++)
{
if(ENODE[i]!='*')
{
outfu(10," ");
cout<<ENODE[i];
}
}
outfu(10," ");
cout<<"#"<<endl;
int x;
for(i=0;i<NODE.length();i++)
分析器的动作就是由栈顶状态和当前输入符号所决定。
四、程序源代码:
//edge.h
#ifndef HEAD_EDGE
#define HEAD_EDGE
#include<string>
using namespace std;
extern int SUM;
extern string NODE,ENODE;
}
else
{
i=NODE.find(ch);
if(a=='#')
{
x=ENODE.find('*');
if(x<ENODE.length()&&x>-1)
j=ENODE.length()-1;
else
j=ENODE.length();
}
{
outfu(4," ");
cout<<NODE[i];
outfu(5," ");
for(k=0;k<ENODE.length();k++)
{
flag=1;
for(j=0;j<SUM;j++)
{
if(NODE[i]==n[j].getlf()[0])
{
x=n[j].getselect().find(ENODE[k]);
for(i=0;i<ni.getrlen();i++)
{
s=NODE.find(ni.getrg()[i]);
if(s<NODE.length()&&s>-1) //是非终结符
if(i<ni.getrlen()-1) //不在最右
for(j=0;j<SUM;j++)
if(n[j].getlf().find(ni.getrg()[i])==0)
cout<<fenxi;
outfu(26-chuan.length()-fenxi.length()," ");
cout<<chuan;
outfu(10," ");
a=chuan[0];
ch=fenxi[fenxi.length()-1];
x=ENODE.find(ch);
if(x<ENODE.lenBiblioteka Baiduth()&&x>-1)
{
if(NODE.find(ni.getrg()[i+1])<NODE.length())
{
for(k=0;k<SUM;k++)
if(n[k].getlf().find(ni.getrg()[i+1])==0)
{
n[j].newfollow(n[k].getfirst());
if(n[k].getfirst().find("*")<n[k].getfirst().length())
n[j].newfollow(ni.getfollow());
}
}
else
{
str.erase();
str+=ni.getrg()[i+1];
n[j].newfollow(str);
}
}
}
}
//计算select
void select(edge &ni,edge *n)
{
int i,j;
if(ENODE.find(ni.getro())<ENODE.length())
if(k==ENODE.length()-1&&x<n[j].getselect().length()&&x>-1)
{
cout<<"->"<<n[j].getrg();
yc[i][j]=n[j].getrg();
}
}
}
if(flag&&ENODE[k]!='*')
outfu(11," ");
}
cout<<endl;
2、LR分析器由三个部分组成:
(1)总控程序,也可以称为驱动程序。对所有的LR分析器总控程序都是相同的。
(2)分析表或分析函数,不同的文法分析表将不同,同一个文法采用的LR分析器不同时,分析表将不同,分析表又可以分为动作表(ACTION)和状态转换(GOTO)表两个部分,它们都可用二维数组表示。
(3)分析栈,包括文法符号栈和相应的状态栈,它们均是先进后出栈。
}
string edge::getlf()
{
return left;
}
string edge::getrg()
{
return right;
}
string edge::getfirst()
{
return first;
}
string edge::getfollow()
{
return follow;
}
string edge::getselect()
void first(edge ni,edge *n,int x)
{
int i,j;
for(j=0;j<SUM;j++)
{
if(ni.getlf()==n[j].getlf())
{
if(NODE.find(n[j].getro())<NODE.length())
{
for(i=0;i<SUM;i++)
三、实验内容
1、分析使用LR(1)的优点:
(1)LR分析器能够构造来识别所有能用上下文无关文法写的程序设计语言的结构。
(2)LR分析方法是已知的最一般的无回溯移进-归约方法,它能够和其他移进-归约方法一样有效地实现。
(3)LR方法能分析的文法类是预测分析法能分析的文法类的真超集。
(4)LR分析器能及时察觉语法错误,快到自左向右扫描输入的最大可能。
{
cout<<p[i]<<",";
}
cout<<p[i]<<"}";
}
//连续输出符号
void outfu(int a,string c)
{
int i;
for(i=0;i<a;i++)
cout<<c;
}
//输出预测分析表
void outgraph(edge *n,string (*yc)[50])
//edge.cpp
#include<iostream>
#include "edge.h"
using namespace std;
edge::edge()
{
cin>>left>>right;
rlen=right.length();
if(NODE.find(left)>NODE.length())
NODE+=left;
为了使一个文法是LR的,只要保证当句柄出现在栈顶时,自左向右扫描的移进-归约分析器能够及时识别它便足够了。当句柄出现在栈顶时,LR分析器必须要扫描整个栈就可以知道这一点,栈顶的状态符号包含了所需要的一切信息。如果仅知道栈内的文法符号就能确定栈顶是什么句柄。LR分析表的转移函数本质上就是这样的有限自动机。不过,这个有限自动机不需要根据每步动作读栈,因为,如果这个识别句柄的有限自动机自底向上读栈中的文法符号的话,它达到的状态正是这时栈顶的状态符号所表示的状态,所以,LR分析器可以从栈顶的状态确定它需要从栈中了解的一切。
{
ni.newselect(ni.getro());
if(ni.getro()=="*")
ni.newselect(ni.getfollow());
}
else
for(i=0;i<ni.getrlen();i++)
for(j=0;j<SUM;j++)
if(ni.getrg()[i]==n[j].getlf()[0])
for(i=0;i<w.length();i++)
if(first.find(w[i])>first.length())
first+=w[i];
}
void edge::newfollow(string w)
{
int i;
for(i=0;i<w.length();i++)
if(follow.find(w[i])>follow.length()&&w[i]!='*')
class edge
{
public:
edge();
string getlf();
string getrg();
string getfirst();
string getfollow();
string getselect();
string getro();
int getrlen();
void newfirst(string w);
{
ni.newselect(n[j].getfirst());
if(n[j].getfirst().find('*')>n[j].getfirst().length())
return;
}
}
//输出集合
void out(string p)
{
int i;
if(p.length()==0)
return;
cout<<"{";
if(x<n[j].getselect().length()&&x>-1)
{
cout<<"->"<<n[j].getrg();
yc[i][k]=n[j].getrg();
outfu(9-n[j].getrlen()," ");
flag=0;
}
x=n[j].getselect().find('#');
编
译
原
理
实
验
报
告
一、实验目的及要求
1.通过本次实验,加深对LL(1)预测分析法原理的认识和理解。
2.构造LR(1)分析程序,利用它进行语法分析,判断给出的符号串是否为该文法识别的句子。
3.了解LR(K)分析方法是严格的从左向右扫描,和自底向上的语法分析方法。
二、运行环境:
硬件:windows xp
软件:visual c++6.0
}
}
//分析符号串
int pipei(string &chuan,string &fenxi,string (*yc)[50],int &b)
{
char ch,a;
int x,i,j,k;
b++;
cout<<endl<<" "<<b;
if(b>9)
outfu(8," ");
else
outfu(9," ");
{
int i=first.find('*');
first.erase(i,1);
}
//LL1.cpp
#include<iostream>
#include<string>
#include "edge.h"
using namespace std;
int SUM;
string NODE,ENODE;
//计算first
follow+=w[i];
}
void edge::newselect(string w)
{
int i;
for(i=0;i<w.length();i++)
if(select.find(w[i])>select.length()&&w[i]!='*')
select+=w[i];
}
void edge::delfirst()
{
return select;
}
string edge::getro()
{
string str;
str+=right[0];
return str;
}
int edge::getrlen()
{
return right.length();
}
void edge::newfirst(string w)
{
int i;
void newfollow(string w);
void newselect(string w);
void delfirst();
private:
string left,right,first,follow,select;
int rlen;
};
#endif
/////////////////////////////////////////////////////////////////////////////
if(n[i].getlf()==n[j].getro())
first(n[i],n,x);
}
else
n[x].newfirst(n[j].getro());
}
}
}
//计算follow
void follow(edge ni,edge *n,int x)
{
int i,j,k,s;
string str;
{
if(ch==a)
{
fenxi.erase(fenxi.length()-1,1);
chuan.erase(0,1);
cout<<"'"<<a<<"'匹配";
if(pipei(chuan,fenxi,yc,b))
return 1;
else
return 0;
}
else
return 0;
}
else
{
if(ch=='#')
{
if(ch==a)
{
cout<<"分析成功"<<endl;
return 1;
}
else
return 0;
}
else
if(ch=='*')
{
fenxi.erase(fenxi.length()-1,1);
if(pipei(chuan,fenxi,yc,b))
return 1;
else
return 0;
{
int i,j,k;
bool flag;
for(i=0;i<ENODE.length();i++)
{
if(ENODE[i]!='*')
{
outfu(10," ");
cout<<ENODE[i];
}
}
outfu(10," ");
cout<<"#"<<endl;
int x;
for(i=0;i<NODE.length();i++)
分析器的动作就是由栈顶状态和当前输入符号所决定。
四、程序源代码:
//edge.h
#ifndef HEAD_EDGE
#define HEAD_EDGE
#include<string>
using namespace std;
extern int SUM;
extern string NODE,ENODE;
}
else
{
i=NODE.find(ch);
if(a=='#')
{
x=ENODE.find('*');
if(x<ENODE.length()&&x>-1)
j=ENODE.length()-1;
else
j=ENODE.length();
}
{
outfu(4," ");
cout<<NODE[i];
outfu(5," ");
for(k=0;k<ENODE.length();k++)
{
flag=1;
for(j=0;j<SUM;j++)
{
if(NODE[i]==n[j].getlf()[0])
{
x=n[j].getselect().find(ENODE[k]);
for(i=0;i<ni.getrlen();i++)
{
s=NODE.find(ni.getrg()[i]);
if(s<NODE.length()&&s>-1) //是非终结符
if(i<ni.getrlen()-1) //不在最右
for(j=0;j<SUM;j++)
if(n[j].getlf().find(ni.getrg()[i])==0)
cout<<fenxi;
outfu(26-chuan.length()-fenxi.length()," ");
cout<<chuan;
outfu(10," ");
a=chuan[0];
ch=fenxi[fenxi.length()-1];
x=ENODE.find(ch);
if(x<ENODE.lenBiblioteka Baiduth()&&x>-1)
{
if(NODE.find(ni.getrg()[i+1])<NODE.length())
{
for(k=0;k<SUM;k++)
if(n[k].getlf().find(ni.getrg()[i+1])==0)
{
n[j].newfollow(n[k].getfirst());
if(n[k].getfirst().find("*")<n[k].getfirst().length())
n[j].newfollow(ni.getfollow());
}
}
else
{
str.erase();
str+=ni.getrg()[i+1];
n[j].newfollow(str);
}
}
}
}
//计算select
void select(edge &ni,edge *n)
{
int i,j;
if(ENODE.find(ni.getro())<ENODE.length())
if(k==ENODE.length()-1&&x<n[j].getselect().length()&&x>-1)
{
cout<<"->"<<n[j].getrg();
yc[i][j]=n[j].getrg();
}
}
}
if(flag&&ENODE[k]!='*')
outfu(11," ");
}
cout<<endl;
2、LR分析器由三个部分组成:
(1)总控程序,也可以称为驱动程序。对所有的LR分析器总控程序都是相同的。
(2)分析表或分析函数,不同的文法分析表将不同,同一个文法采用的LR分析器不同时,分析表将不同,分析表又可以分为动作表(ACTION)和状态转换(GOTO)表两个部分,它们都可用二维数组表示。
(3)分析栈,包括文法符号栈和相应的状态栈,它们均是先进后出栈。
}
string edge::getlf()
{
return left;
}
string edge::getrg()
{
return right;
}
string edge::getfirst()
{
return first;
}
string edge::getfollow()
{
return follow;
}
string edge::getselect()
void first(edge ni,edge *n,int x)
{
int i,j;
for(j=0;j<SUM;j++)
{
if(ni.getlf()==n[j].getlf())
{
if(NODE.find(n[j].getro())<NODE.length())
{
for(i=0;i<SUM;i++)
三、实验内容
1、分析使用LR(1)的优点:
(1)LR分析器能够构造来识别所有能用上下文无关文法写的程序设计语言的结构。
(2)LR分析方法是已知的最一般的无回溯移进-归约方法,它能够和其他移进-归约方法一样有效地实现。
(3)LR方法能分析的文法类是预测分析法能分析的文法类的真超集。
(4)LR分析器能及时察觉语法错误,快到自左向右扫描输入的最大可能。