编译原理实验——算符优先算法
2010-12-02 21:40
351 查看
/*本实验参照学校实验报告册的算法所作,行事仓促,有很多不足,望加指正*/
/*验证文法1:
E->E+T|T
T->T*F|F
F->(E)|a
语句示例:a+a$
验证文法2:
S->a|b|(T)
T->T,S|S
语句示例:(a,(a,a))$
因未加入对'|'的拆分,所以输入文法是需手动拆分产生式.
本程序所输文法,必须为算符优先文法
*/
/*结束符号是$;
vn[]中第一个字符是开始符号;
FIRST集、FOLLOW集和优先分析表T的字符顺序和vt[]及vn[]一致
*/
#include<iostream>
#include<stdio.h>
#include<fstream>
#include<malloc.h>
using namespace std;
#define OK 1
#define ERROR 0
#define OVERFLOW -2
#define N 200
#define Y 10
#define STACK_INIT_SIZE 100
#define STACKINCREMENT 10
int vtnum,vnnum,pronum;//依次是终结符、非终结符、产生式个数
int FIRST
;//FIRSTVT集
int LAST
;//LASTVT集
int T
;//优先关系表
char vt
;
char vn
; //终结符和非终结符集
char old
;//用于存储产生式
typedef struct{
char VN;
char VT;
}SqE;
typedef struct{
SqE *base;
SqE *top;
int stacksize;
}SqStack;//定义堆栈用于求FIRSTVT和LASTVT
void InitStack(SqStack &);
void Push(SqStack &,char,char);
int Pop(SqStack &,char &,char &);
bool Empty(SqStack &);
void first();
int test(char);
void insertf(char,char,SqStack &);
void last();
int tail(int);
void insertl(char,char,SqStack &);
void printf_ff();
void table();
void printf_t();
int control();
void main()
{
int i,j;
ifstream in("input1.txt",ios_base::in);
for(i=0;i<N;i++)
for(j=0;j<N;j++)
old[i][j]='/0';
in>>pronum>>vnnum>>vtnum;
in>>vn;
in>>vt;
for(i=0;i<pronum;i++)
in>>old[i];//从文件中读入pronum,vtnum,vnnum以及产生式
for(i=0;i<vnnum;i++)
for(j=0;j<vtnum;j++)
FIRST[i][j]=0;
for(i=0;i<vnnum;i++)
for(j=0;j<vtnum;j++)
LAST[i][j]=0;//初始化FIRSTVT和LASTVT,0意味着不存在
for(i=0;i<N;i++)
for(j=0;j<N;j++)
T[i][j]=3;//初始化T[][],3意味着不存在
first();
last();
printf_ff();
table();
printf_t();
control();
}
void InitStack(SqStack &S1)//堆栈操作,分别是初始化堆栈,压栈,弹出栈顶元素和判断是否为空
{
S1.base=(SqE *)malloc(STACK_INIT_SIZE * sizeof(SqE));
if(!S1.base)
exit(OVERFLOW);
S1.top=S1.base;
S1.stacksize=STACK_INIT_SIZE;
}
void Push(SqStack &S1,char e,char v)
{
if(S1.top-S1.base>=S1.stacksize)
{
S1.base=(SqE *)realloc(S1.base,(S1.stacksize+STACKINCREMENT)*sizeof(SqE));
if(!S1.base)
exit(OVERFLOW);
S1.top=S1.base+S1.stacksize;
S1.stacksize+=STACKINCREMENT;
}
(*S1.top).VN=e;
(*S1.top).VT=v;
S1.top++;
}
int Pop(SqStack &S1,char &e,char &v)
{
if(S1.top==S1.base)
return ERROR;
--S1.top;
e=(* S1.top).VN;
v=(* S1.top).VT;
return OK;
}
bool Empty(SqStack &S1)
{
if(S1.top==S1.base)
return true;
else
return false;
}
void first()//求所有非终结符的FIRSTVT集
{
int i;
char X,a;
SqStack S;
InitStack(S);
for(i=0;i<pronum;i++)//找到形如P->a...或者P->Qa...的产生式,并对(P,a)调用insertf()
{
if(test(old[i][1])<100)
insertf(old[i][0],old[i][1],S);
else
{
if(test(old[i][2])<100)
insertf(old[i][0],old[i][2],S);
}
}
while(!Empty(S))//假设弹出元素是(Q,a),找寻形如P->Q...的产生式,对(P,a)调用insertf()
{
Pop(S,X,a);
for(i=0;i<pronum;i++)
{
if(old[i][0]!=old[i][1])
{
if(old[i][1]==X)
insertf(old[i][0],a,S);
}
}
}
}
int test(char c)//判断符号的类型,0<=终结符返回值<100,100<=非终结符返回值<200,错误符号返回值=200
{
int i,j;
for(i=0;i<vtnum;i++)
{
if(vt[i]==c)
break;
}
if(i<vtnum)
return i;
else
{
for(j=0;j<vnnum;j++)
{
if(vn[j]==c)
break;
}
if(j<vtnum)
return (100+j);
else
return 200;
}
}
void insertf(char a,char b,SqStack &S)//插入FIRSTVT集,(a,b)是非终结符和终结符对
{
FIRST[test(a)-100][test(b)]=1;//赋值为1,表示存在
Push(S,a,b);//压栈
}
void last()//求所有非终结符的LASTVT集,思想和求FIRSTVT相同
{
int i;
char X,a;
SqStack S;
InitStack(S);
for(i=0;i<pronum;i++)//找到形如P->...a或者P->...aQ的产生式
{
if(test(old[i][tail(i)])<100)
insertl(old[i][0],old[i][tail(i)],S);
else
{
if(test(old[i][tail(i)-1])<100)
insertl(old[i][0],old[i][tail(i)-1],S);
}
}
while(!Empty(S))//假设弹出元素是(Q,a),找寻形如P->...Q的产生式
{
Pop(S,X,a);
for(i=0;i<pronum;i++)
{
if(old[i][0]!=old[i][tail(i)])
{
if(old[i][tail(i)]==X)
insertl(old[i][0],a,S);
}
}
}
}
int tail(int i)//返回产生式最后一位符号的下标
{
int j;
for(j=0;old[i][j]!='/0';j++)
{
}
return (j-1);
}
void insertl(char a,char b,SqStack &S)//插入LASTVT集
{
LAST[test(a)-100][test(b)]=1;
Push(S,a,b);
}
void printf_ff()//输出FIRSTVT和LASTVT
{
int i,j;
printf("注:1代表在集合中,0代表不在集合中/nFIRSTVT集为:/n ");
for(i=0;i<vtnum;i++)
printf("%c ",vt[i]);
printf("/n");
for(i=0;i<vnnum;i++)
{
printf("%c ",vn[i]);
for(j=0;j<vtnum;j++)
printf("%d ",FIRST[i][j]);
printf("/n");
}
printf("/nLASTVT集为:/n ");
for(i=0;i<vtnum;i++)
printf("%c ",vt[i]);
printf("/n");
for(i=0;i<vnnum;i++)
{
printf("%c ",vn[i]);
for(j=0;j<vtnum;j++)
printf("%d ",LAST[i][j]);
printf("/n");
}
}
void table()//构造优先关系表,0代表相等,1代表小于,2代表大于,3代表不存在
{
int i,j,k;
for(i=0;i<pronum;i++)
{
for(j=1;j<=tail(i)-1;j++)
{
if(test(old[i][j])<100&&test(old[i][j+1])<100)//如果P->...ab... 那么a=b
T[test(old[i][j])][test(old[i][j+1])]=0;
if(j<=tail(i)-2&&test(old[i][j])<100&&test(old[i][j+1])>=100&&test(old[i][j+1])<200&&test(old[i][j+2])<100)//如果P->...aQb... 那么a=b
T[test(old[i][j])][test(old[i][j+2])]=0;
if(test(old[i][j])<100&&test(old[i][j+1])>=100&&test(old[i][j+1])<200)//如果P->...aQ... 那么a<FIRSTVT(Q)
{
for(k=0;k<vtnum;k++)
{
if(FIRST[test(old[i][j+1])-100][k]==1)
T[test(old[i][j])][k]=1;
}
}
if(test(old[i][j])>=100&&test(old[i][j])<200&&test(old[i][j+1])<100)//如果P->...Qa... 那么LASTVT(Q)>a
{
for(k=0;k<vtnum;k++)
{
if(LAST[test(old[i][j])-100][k]==1)
T[k][test(old[i][j+1])]=2;
}
}
}
}
for(i=0;i<vtnum;i++)//对$的处理
{
if(FIRST[0][i]==1)
T[vtnum][i]=1;
}
for(i=0;i<vtnum;i++)
{
if(LAST[0][i]==1)
T[i][vtnum]=2;
}
T[vtnum][vtnum]=0;
}
void printf_t()
{
int i,j;
printf("/n优先关系表为:/n ");
for(i=0;i<vtnum;i++)
printf("%c ",vt[i]);
printf("$ /n");
for(i=0;i<vtnum;i++)
{
printf("%c ",vt[i]);
for(j=0;j<=vtnum;j++)
{
if(T[i][j]==0)
printf("= ");
else if(T[i][j]==1)
printf("< ");
else if(T[i][j]==2)
printf("> ");
else
printf(" ");
}
printf("/n");
}
printf("$ ");
for(j=0;j<=vtnum;j++)
{
if(T[i][j]==0)
printf("= ");
else if(T[i][j]==1)
printf("< ");
else if(T[i][j]==2)
printf("> ");
else
printf(" ");
}
printf("/n");
}
int control()//主控程序,核心是当前符号a[p]和s[j]的关系
{
char s
;//分析栈
char a[20]={'/0'};//存放待分析字符串
char q;//工作单元
int x,y,z,j=0,k=1,p=0;//j是栈的查找指针,k是栈顶指针,p是字符串指针,s[1]作为栈底
vt[vtnum]='$';
vtnum++;//把结束符'$'加入终结符集,后面将用到
printf("/n请输入要分析的字符串(以$结尾):");
cin>>a;
s[k]='$';//把$压栈
s[k+1]='/0';
printf("/n分析过程:/n堆栈 优先关系 当前符号 输入流 动作 /n");
if(test(s[k])<100)//判断s[k]是否是终结符或'$',如果是,j=k,s[j]是从栈顶向下首个终结符或者'$'
j=k;
else
j=k-1;
do
{
if(T[test(s[j])][test(a[p])]==3)//s[j]和a[p]间不存在关系,报错
{
printf("/nError,您输入的句型和文法不符!/n");
return ERROR;
}
for(x=1;s[x]!='/0';x++)
printf("%c",s[x]);
for(y=0;y<Y-x+1;y++)
printf(" ");//输出堆栈情况
if(T[test(s[j])][test(a[p])]==2)
printf(" > ");
else if(T[test(s[j])][test(a[p])]==1)
printf(" < ");
else
printf(" = ");//输出关系
printf(" %c ",a[p]);//输出当前符号
z=0;
for(x=p+1;a[x]!='/0';x++)
{
printf("%c",a[x]);
z++;
}
for(x=0;x<Y-z;x++)
printf(" ");//输出输入流
if(T[test(s[j])][test(a[p])]==1||T[test(s[j])][test(a[p])]==0)
printf(" 移进 ");
else
printf(" 归约 ");//输出动作
printf("/n");
if(T[test(s[j])][test(a[p])]==2)//s[j]>a[p],找到最左素短语,归约
{
do
{
q=s[j];
j--;
if(!(test(s[j])<100))
j--;
}while(!(T[test(s[j])][test(q)]==1));
k=j+1;
s[k]='N';//归约,'N'代表任意非终结符
s[k+1]='/0';
}
else//s[j]<=a[p],未找到最左素短语,移进
{
k++;
s[k]=a[p];//把当前符号移进
s[k+1]='/0';
p++;
if(test(s[k])<100)
j=k;
else
j=k-1;
}
}while(!(k==2&&a[p]=='$'&&s[k]=='N'));
printf("$N = $ 结束 /n");
printf("/nSucceed,您输入的句型和文法相符!/n");
return OK;
}
/*验证文法1:
E->E+T|T
T->T*F|F
F->(E)|a
语句示例:a+a$
验证文法2:
S->a|b|(T)
T->T,S|S
语句示例:(a,(a,a))$
因未加入对'|'的拆分,所以输入文法是需手动拆分产生式.
本程序所输文法,必须为算符优先文法
*/
/*结束符号是$;
vn[]中第一个字符是开始符号;
FIRST集、FOLLOW集和优先分析表T的字符顺序和vt[]及vn[]一致
*/
#include<iostream>
#include<stdio.h>
#include<fstream>
#include<malloc.h>
using namespace std;
#define OK 1
#define ERROR 0
#define OVERFLOW -2
#define N 200
#define Y 10
#define STACK_INIT_SIZE 100
#define STACKINCREMENT 10
int vtnum,vnnum,pronum;//依次是终结符、非终结符、产生式个数
int FIRST
;//FIRSTVT集
int LAST
;//LASTVT集
int T
;//优先关系表
char vt
;
char vn
; //终结符和非终结符集
char old
;//用于存储产生式
typedef struct{
char VN;
char VT;
}SqE;
typedef struct{
SqE *base;
SqE *top;
int stacksize;
}SqStack;//定义堆栈用于求FIRSTVT和LASTVT
void InitStack(SqStack &);
void Push(SqStack &,char,char);
int Pop(SqStack &,char &,char &);
bool Empty(SqStack &);
void first();
int test(char);
void insertf(char,char,SqStack &);
void last();
int tail(int);
void insertl(char,char,SqStack &);
void printf_ff();
void table();
void printf_t();
int control();
void main()
{
int i,j;
ifstream in("input1.txt",ios_base::in);
for(i=0;i<N;i++)
for(j=0;j<N;j++)
old[i][j]='/0';
in>>pronum>>vnnum>>vtnum;
in>>vn;
in>>vt;
for(i=0;i<pronum;i++)
in>>old[i];//从文件中读入pronum,vtnum,vnnum以及产生式
for(i=0;i<vnnum;i++)
for(j=0;j<vtnum;j++)
FIRST[i][j]=0;
for(i=0;i<vnnum;i++)
for(j=0;j<vtnum;j++)
LAST[i][j]=0;//初始化FIRSTVT和LASTVT,0意味着不存在
for(i=0;i<N;i++)
for(j=0;j<N;j++)
T[i][j]=3;//初始化T[][],3意味着不存在
first();
last();
printf_ff();
table();
printf_t();
control();
}
void InitStack(SqStack &S1)//堆栈操作,分别是初始化堆栈,压栈,弹出栈顶元素和判断是否为空
{
S1.base=(SqE *)malloc(STACK_INIT_SIZE * sizeof(SqE));
if(!S1.base)
exit(OVERFLOW);
S1.top=S1.base;
S1.stacksize=STACK_INIT_SIZE;
}
void Push(SqStack &S1,char e,char v)
{
if(S1.top-S1.base>=S1.stacksize)
{
S1.base=(SqE *)realloc(S1.base,(S1.stacksize+STACKINCREMENT)*sizeof(SqE));
if(!S1.base)
exit(OVERFLOW);
S1.top=S1.base+S1.stacksize;
S1.stacksize+=STACKINCREMENT;
}
(*S1.top).VN=e;
(*S1.top).VT=v;
S1.top++;
}
int Pop(SqStack &S1,char &e,char &v)
{
if(S1.top==S1.base)
return ERROR;
--S1.top;
e=(* S1.top).VN;
v=(* S1.top).VT;
return OK;
}
bool Empty(SqStack &S1)
{
if(S1.top==S1.base)
return true;
else
return false;
}
void first()//求所有非终结符的FIRSTVT集
{
int i;
char X,a;
SqStack S;
InitStack(S);
for(i=0;i<pronum;i++)//找到形如P->a...或者P->Qa...的产生式,并对(P,a)调用insertf()
{
if(test(old[i][1])<100)
insertf(old[i][0],old[i][1],S);
else
{
if(test(old[i][2])<100)
insertf(old[i][0],old[i][2],S);
}
}
while(!Empty(S))//假设弹出元素是(Q,a),找寻形如P->Q...的产生式,对(P,a)调用insertf()
{
Pop(S,X,a);
for(i=0;i<pronum;i++)
{
if(old[i][0]!=old[i][1])
{
if(old[i][1]==X)
insertf(old[i][0],a,S);
}
}
}
}
int test(char c)//判断符号的类型,0<=终结符返回值<100,100<=非终结符返回值<200,错误符号返回值=200
{
int i,j;
for(i=0;i<vtnum;i++)
{
if(vt[i]==c)
break;
}
if(i<vtnum)
return i;
else
{
for(j=0;j<vnnum;j++)
{
if(vn[j]==c)
break;
}
if(j<vtnum)
return (100+j);
else
return 200;
}
}
void insertf(char a,char b,SqStack &S)//插入FIRSTVT集,(a,b)是非终结符和终结符对
{
FIRST[test(a)-100][test(b)]=1;//赋值为1,表示存在
Push(S,a,b);//压栈
}
void last()//求所有非终结符的LASTVT集,思想和求FIRSTVT相同
{
int i;
char X,a;
SqStack S;
InitStack(S);
for(i=0;i<pronum;i++)//找到形如P->...a或者P->...aQ的产生式
{
if(test(old[i][tail(i)])<100)
insertl(old[i][0],old[i][tail(i)],S);
else
{
if(test(old[i][tail(i)-1])<100)
insertl(old[i][0],old[i][tail(i)-1],S);
}
}
while(!Empty(S))//假设弹出元素是(Q,a),找寻形如P->...Q的产生式
{
Pop(S,X,a);
for(i=0;i<pronum;i++)
{
if(old[i][0]!=old[i][tail(i)])
{
if(old[i][tail(i)]==X)
insertl(old[i][0],a,S);
}
}
}
}
int tail(int i)//返回产生式最后一位符号的下标
{
int j;
for(j=0;old[i][j]!='/0';j++)
{
}
return (j-1);
}
void insertl(char a,char b,SqStack &S)//插入LASTVT集
{
LAST[test(a)-100][test(b)]=1;
Push(S,a,b);
}
void printf_ff()//输出FIRSTVT和LASTVT
{
int i,j;
printf("注:1代表在集合中,0代表不在集合中/nFIRSTVT集为:/n ");
for(i=0;i<vtnum;i++)
printf("%c ",vt[i]);
printf("/n");
for(i=0;i<vnnum;i++)
{
printf("%c ",vn[i]);
for(j=0;j<vtnum;j++)
printf("%d ",FIRST[i][j]);
printf("/n");
}
printf("/nLASTVT集为:/n ");
for(i=0;i<vtnum;i++)
printf("%c ",vt[i]);
printf("/n");
for(i=0;i<vnnum;i++)
{
printf("%c ",vn[i]);
for(j=0;j<vtnum;j++)
printf("%d ",LAST[i][j]);
printf("/n");
}
}
void table()//构造优先关系表,0代表相等,1代表小于,2代表大于,3代表不存在
{
int i,j,k;
for(i=0;i<pronum;i++)
{
for(j=1;j<=tail(i)-1;j++)
{
if(test(old[i][j])<100&&test(old[i][j+1])<100)//如果P->...ab... 那么a=b
T[test(old[i][j])][test(old[i][j+1])]=0;
if(j<=tail(i)-2&&test(old[i][j])<100&&test(old[i][j+1])>=100&&test(old[i][j+1])<200&&test(old[i][j+2])<100)//如果P->...aQb... 那么a=b
T[test(old[i][j])][test(old[i][j+2])]=0;
if(test(old[i][j])<100&&test(old[i][j+1])>=100&&test(old[i][j+1])<200)//如果P->...aQ... 那么a<FIRSTVT(Q)
{
for(k=0;k<vtnum;k++)
{
if(FIRST[test(old[i][j+1])-100][k]==1)
T[test(old[i][j])][k]=1;
}
}
if(test(old[i][j])>=100&&test(old[i][j])<200&&test(old[i][j+1])<100)//如果P->...Qa... 那么LASTVT(Q)>a
{
for(k=0;k<vtnum;k++)
{
if(LAST[test(old[i][j])-100][k]==1)
T[k][test(old[i][j+1])]=2;
}
}
}
}
for(i=0;i<vtnum;i++)//对$的处理
{
if(FIRST[0][i]==1)
T[vtnum][i]=1;
}
for(i=0;i<vtnum;i++)
{
if(LAST[0][i]==1)
T[i][vtnum]=2;
}
T[vtnum][vtnum]=0;
}
void printf_t()
{
int i,j;
printf("/n优先关系表为:/n ");
for(i=0;i<vtnum;i++)
printf("%c ",vt[i]);
printf("$ /n");
for(i=0;i<vtnum;i++)
{
printf("%c ",vt[i]);
for(j=0;j<=vtnum;j++)
{
if(T[i][j]==0)
printf("= ");
else if(T[i][j]==1)
printf("< ");
else if(T[i][j]==2)
printf("> ");
else
printf(" ");
}
printf("/n");
}
printf("$ ");
for(j=0;j<=vtnum;j++)
{
if(T[i][j]==0)
printf("= ");
else if(T[i][j]==1)
printf("< ");
else if(T[i][j]==2)
printf("> ");
else
printf(" ");
}
printf("/n");
}
int control()//主控程序,核心是当前符号a[p]和s[j]的关系
{
char s
;//分析栈
char a[20]={'/0'};//存放待分析字符串
char q;//工作单元
int x,y,z,j=0,k=1,p=0;//j是栈的查找指针,k是栈顶指针,p是字符串指针,s[1]作为栈底
vt[vtnum]='$';
vtnum++;//把结束符'$'加入终结符集,后面将用到
printf("/n请输入要分析的字符串(以$结尾):");
cin>>a;
s[k]='$';//把$压栈
s[k+1]='/0';
printf("/n分析过程:/n堆栈 优先关系 当前符号 输入流 动作 /n");
if(test(s[k])<100)//判断s[k]是否是终结符或'$',如果是,j=k,s[j]是从栈顶向下首个终结符或者'$'
j=k;
else
j=k-1;
do
{
if(T[test(s[j])][test(a[p])]==3)//s[j]和a[p]间不存在关系,报错
{
printf("/nError,您输入的句型和文法不符!/n");
return ERROR;
}
for(x=1;s[x]!='/0';x++)
printf("%c",s[x]);
for(y=0;y<Y-x+1;y++)
printf(" ");//输出堆栈情况
if(T[test(s[j])][test(a[p])]==2)
printf(" > ");
else if(T[test(s[j])][test(a[p])]==1)
printf(" < ");
else
printf(" = ");//输出关系
printf(" %c ",a[p]);//输出当前符号
z=0;
for(x=p+1;a[x]!='/0';x++)
{
printf("%c",a[x]);
z++;
}
for(x=0;x<Y-z;x++)
printf(" ");//输出输入流
if(T[test(s[j])][test(a[p])]==1||T[test(s[j])][test(a[p])]==0)
printf(" 移进 ");
else
printf(" 归约 ");//输出动作
printf("/n");
if(T[test(s[j])][test(a[p])]==2)//s[j]>a[p],找到最左素短语,归约
{
do
{
q=s[j];
j--;
if(!(test(s[j])<100))
j--;
}while(!(T[test(s[j])][test(q)]==1));
k=j+1;
s[k]='N';//归约,'N'代表任意非终结符
s[k+1]='/0';
}
else//s[j]<=a[p],未找到最左素短语,移进
{
k++;
s[k]=a[p];//把当前符号移进
s[k+1]='/0';
p++;
if(test(s[k])<100)
j=k;
else
j=k-1;
}
}while(!(k==2&&a[p]=='$'&&s[k]=='N'));
printf("$N = $ 结束 /n");
printf("/nSucceed,您输入的句型和文法相符!/n");
return OK;
}
相关文章推荐
- 哈工大编译原理实验1——词法分析
- 设计有穷自动机DFA实现C++简单程序的词法分析、扫描(编译原理实验) 推荐
- 编译原理实验 之 符号表
- 编译原理实验 之 词法分析
- 哈工大编译原理实验--动手写自己的编译器(一)之大体描述和我的成果
- 编译原理——实验 1.2 在 Windows平台下使用 Flex和 Bison
- 编译原理实验之用C模拟C++虚方法表机制
- 编译原理 ->实验1
- 编译原理实验一:为PL/0语言编写一个词法分析程序
- 编译原理课程实验
- 编译原理实验一
- 编译原理实验-FLEX+BISON+DEV C++完美解决方案
- 编译原理 实验2 语法分析器的构造 LL(1)
- CSUFT 编译原理实验四 LR(1)
- 编译原理实验----词法分析
- 语义分析-哈工大编译原理第三次实验
- 编译原理语法分析实验(Java实现)
- C++词法扫描程序-编译原理实验一
- 编译原理实验一:词法分析
- 编译原理:实验二、集合与线性表操作