构建LR(0)分析表
例:
G[E]:
E->aA
E->bB
A->cA
A->d
B->cB
B->d
在网上找了好久,发现大多数都是概念和复杂公式,
因此为了使大家能够更好的理解LR(0)分析表的构建,我准备举一个例子进行详细解析,一步步进行分析,直到最后画出分析表。
文法:
E->aA
E->bB
A->cA
A->d
B->cB
B->d
char str[10][10];//存储文法
int n;//存储文法行数
int v=0;//存储生成项的个数
char r[20][10];//存储分析表的float值
int rr[20][10];//存储分析表的int值
struct DFA{
int num;//记录生成项的序号
int c[10];//存储该项目各个文法的去向(子代)
int f;//记录该项目的来源(父代)
char ss[10][10];//存储该项的文法
int count;//记录该项的文法行数
int l;//存储第一行字符串'.'的位置
}LR[20];
//初始化,输入上下文无关文法,以#号结尾
void Init(){
int i,j;
cout<<"输入上下文无关文法:"<>str[i];
if(str[i][0]=='#')
break;
}
strcat(str[0],"Z->");
str[0][3]=str[1][0];
n=i+1;
}
我在源代码里还附录了一个输入模块的代码,因为那个是直接将文法输入到字符串中,这样就可减少在进行测试时重复输入文法的时间。
即:
//在一开始编程时可先给定文法,避免每次测试重复输入
void input(){
int i,j;
strcat(str[0],"Z->E");
strcat(str[1],"E->aA");
strcat(str[2],"E->bB");
strcat(str[3],"A->cA");
strcat(str[4],"A->d");
strcat(str[5],"B->cB");
strcat(str[6],"B->d");
n=7;
for(i=0;i
LR(0)规范集构建模块
进行算法分析中第2、3、4三步,记住几个关键点,小圆点位置、小圆点后的字符、项目的开辟(递归)
当中为使测试方便,调用了几个子函数
以下只附录子函数代码,具体请看最后源代码
设置小圆点位置
输出模块
将生成的项目以分析表的形式得出,因水品有限,采用的是cout结合二维数组进行输出,代码较多,主要是为了使得输出的格式更加的整齐。
这部分就不重复贴出代码,大家请从源代码里查看。
//为文法添加小数点
void AddD(int a,int b){//为LR[a]的ss第b行字符串添加'.'
int i,j=0;
char c[10];
for(i=0;i<3;i++)
c[j++]=LR[a].ss[b][i];
c[3]='.';
j++;
for(i=3;i
//添加移进项目的文法
void AddG(int a,char s){//把str文法中左部非终结符与s相同的文法,添加进LR[a]中
int i,j,k;
for(i=0;i
//将文法小圆点向后移一位
void add(int a,int j){
int i,k;
char temp;
for(i=0;i
//更新某一项的来源(父代)和每一句文法的跳转项(子代)
void fix(int a,int b){
int i,j,k;
k=LR[b].f;//父代
for(i=0;i
//比较,删除相同的内容
void Compare(int a){
int i,j,k;
for(i=0;i
//主函数
int main(){
Init();;//输入上下文无关文法
//input();//输入上下文无关文法
gfj();//规范集的构建
Output();//输出分析表
}
源代码已经过编译,可直接使用。代码都有详细的注释,大家碰到任何问题都可以留言,一起讨论。
#include
#include
#include
using namespace std;
char str[10][10];//存储文法
int n;//存储文法行数
int v=0;//存储生成项的个数
char r[20][10];//存储分析表的float值
int rr[20][10];//存储分析表的int值
struct DFA{
int num;//记录生成项的序号
int c[10];//存储该项的上一项位置
int f;//记录
char ss[10][10];//存储该项的文法
int count;//记录该项的文法行数
int l;//存储第一行字符串'.'的位置
}LR[20];
//初始化,输入上下文无关文法,以#号结尾
void Init(){
int i,j;
cout<<"输入上下文无关文法:"<>str[i];
if(str[i][0]=='#')
break;
}
strcat(str[0],"Z->");
str[0][3]=str[1][0];
n=i+1;
}
//在一开始编程时可先给定文法,避免每次测试重复输入
void input(){
int i,j;
strcat(str[0],"Z->E");
strcat(str[1],"E->aA");
strcat(str[2],"E->bB");
strcat(str[3],"A->cA");
strcat(str[4],"A->d");
strcat(str[5],"B->cB");
strcat(str[6],"B->d");
n=7;
for(i=0;iE
for(k=0;k.E
LR[0].l=3;//小圆点的位置
LR[0].count++;//文法数目+1
if(LR[i].ss[0][4]>='A'&&LR[i].ss[0][4]<'Z')
AddG(i,LR[i].ss[0][4]);//添加移进项目的文法E->aA E->bB
v++;
//为每一个文法进行向外扩散 I1、I2、I3
for(j=0;j='A'&&LR[i].ss[0][p+1]<'Z')
AddG(i,LR[i].ss[0][p+1]);//添加移进项目的文法
//为每一个文法进行向外扩散
for(j=0;j0&&i<=10)
cout<<" "<10)
cout<