编译原理课程设计
目录
1
程序功能描述----------------------------------3
程序测试用例----------------------------------3
程序的不足与缺陷------------------------------5
源代码----------------------------------------5
一.程序功能描述:
本程序用于判断某种文法是否为算符优先文法,并构造 FIRSTVT 集与 LASTVT 集
和优先表。如果不是算符优先算法,则在优先表中相应位置用“/”表示有多种
2
关系存在。
二.测试用例:
测试用例 1:
例如书本 90 页的文法:
(1) E->E+T|T
T->T*F|F
F->P^F|P
P->(E)|i
(2)
(3)
(4)
其中 E,T,F,P 为非终结符,其余为终结符。
测试输入与输出:
输入终结符名:(输入#并输入回车结束)
+
*
^
i
(
)#
输入非终结符名:(输入#并输入回车结束)
E
T
F
P#
输入产生式:(第一个符号为左部,其余为右部,每个产生式以回车间隔,输入
#结束,例
如:Xasd
Casd#)
EE+T
ET
TT*F
TF
FP^F
FP
P(E)
Pi#
确认所输入的产生式:
E—>E+T
E—>T
T—>T*F
T—>F
F—>P^F
F—>P
3
*
^
i
(
P—>(E)
P—>i
E 的 FIRSTVT 集: +
T 的 FIRSTVT 集: *
F 的 FIRSTVT 集: ^
P 的 FIRSTVT 集: i
*
E 的 LASTVT 集: +
^
T 的 LASTVT 集: *
i
F 的 LASTVT 集: ^
P 的 LASTVT 集: i
)
此文法为算符优先算法
(
i
(
)
i
)
^
i
(
^
i
)
优先表
+
>
>
>
>
<
>
*
<
>
>
>
<
>
+
*
^
i
(
)
Press any key to continue
<
^
<
<
<
>
<
>
i
<
<
<
(
<
<
<
<
)
>
>
>
>
=
>
测试用例 2:
有下列文法:
(1)S->bAb
(2)A->(B|a
(3)B->Aa)
测试输入与输出:
输入终结符名:(输入#并输入回车结束)
b
a
(
)#
输入非终结符名:(输入#并输入回车结束)
S
A
B#
输入产生式:(第一个符号为左部,其余为右部,每个产生式以回车间隔,输入
#结束,例
如:Xasd
Casd#)
SbAb
A(B
Aa
4
BAa)#
确认所输入的产生式:
S—>bAb
A—>(B
A—>a
B—>Aa)
S 的 FIRSTVT 集: b
A 的 FIRSTVT 集: a
B 的 FIRSTVT 集: a
S 的 LASTVT 集: b
A 的 LASTVT 集: a
B 的 LASTVT 集: )
此文法不是算符优先算法,优先表中“/”处表示有多个关系
(
(
(
)
b
=
>
>
>
a
<
>
/
>
优先表
)
(
<
b
a
(
)
Press any key to continue
不难证明,在优先表第三行第二列有下划线处,同时有<,>两种关系,所以不是
=
<
算符优先算法。
三.程序的缺陷与不足
本程序存在未能将#加入到优先表中,输入方式不太方便,不能把结果保存到文
件中等不足。
四.源代码
#include
#include
using namespace std;
typedef struct
{
char name;
char belong;
char FIRSTVT[20];
char LASTVT[20];
int FIRSTVTnum;
int LASTVTnum;
}character;
//每个符号为一个结构体
5
//用于存储存入栈中的结构体
typedef struct
{
char VTname;
char VNname;
}combine;
typedef struct
{
combine *base;
combine *top;
int stacksize;
int stacknumber;
}SqStack;
//以下为栈的基本操作
void InitStack(SqStack &S)
{
//构件栈的结构体
//创建栈
S.base=(combine *)malloc(20*sizeof(combine));
if(!S.base) exit(0);
S.top=S.base;
S.stacksize=20;
S.stacknumber=0;
}
int Pop(SqStack &S,combine &e)
并返回 1,若栈空,则返回 0
{
if(S.top==S.base) return 0;
e=*--S.top;
S.stacknumber--;
return 1;
}
//以下为其他函数
6
}
void Push(SqStack &S,combine e)
{
//将 e 压入栈内
if(S.top-S.base>=S.stacksize)
{ S.base=(combine *)realloc(S.base,(S.stacksize+10*sizeof(combine)));
if(!S.base) exit(0);
S.top=S.base+S.stacksize;
S.stacksize+=10;
}
*S.top++=e;
S.stacknumber++;
//若栈不空,删除栈顶元素,用 e 返回其值,
void getloc(char A,character ALLCHAR[2][10],int allterlen,int allunterlen,int *l,int
*r)
{
//寻找 A 所在 ALLCHAR 的位置
int i,j=0;
for(i=0;i
>ter;
i=0;
while(ter!='#')
{
ALLCHAR[0][i].belong='T';
ALLCHAR[0][i].name=ter;
ALLCHAR[0][i].FIRSTVTnum=0;
ALLCHAR[0][i].LASTVTnum=0;
cin>>ter;
i++;
cout<<"输入非终结符名:(输入#并输入回车结束)"<>unter;
j=0;
}
}
}
while(unter!='#')
{
ALLCHAR[1][j].belong='N';
ALLCHAR[1][j].name=unter;
ALLCHAR[1][j].FIRSTVTnum=0;
ALLCHAR[1][j].LASTVTnum=0;
7
cin.ignore();
cin.get(L);
i=0;j=0;k=0;
while(L!='#')
{if(L=='\n')
{j++;genlen[j-1]=i;i=0;cin.get(L);}
//若输入回车,记
cin>>unter;
j++;
}
*allterlen=i;
*allunterlen=j;
for(i=0;i<*allunterlen;i++)
for(j=0;j<*allterlen;j++)
{F[i][j]=0;F1[i][j]=0;}
}
//初始化矩阵 F
void creatgen(character gen[20][20],int genlen[20],character ALLCHAR[2][10],int
allterlen,int allunterlen,int *NUM)
{
//创建产生式表
int i,j,k,n;
int *l,*r;
l=&k;r=&n;
char L;
cout<<"输入产生式:(第一个符号为左部,其余为右部,每个产生式以回车间
隔,输入#结束,例如:Xasd\n Casd#)"<";
}
8