深 圳 大 学
实
验
报
告
课程名称:编译原理
实验名称:文法的化简和改造
姓
名:
学
号:
班
级:
实验日期:
一.实验目的
1) 编写文法的化简和改造程序;
二.实验环境
1) 硬件环境:计算机;
2) 软件环境:C/C++编译器;
三.实验内容
1. 用 C/C++语言编写方法的化简和改造程序,实现以下功能之一(如实现两个功能,则满
分为 110 分;如实现三个功能,则满分为 120 分):
(1) 无用符号和无用产生式的删除,参考课本中算法 2.1 和算法 2.2。
(2) ε-产生式的消除,参考课本中算法 2.3、2.4 和 2.5。
(3) 单产生式的消除,参考课本中算法 2.6。
从文件或终端中读入文法,并将化简和改造后的文法输出到另一文件或终端中。文法的表
示如下:
S->aS
S->W
S->U
U->a
V->bV
V->ac
W->aW
用空字符表示ε
用大写的拉丁字母表示文法的非终结符号,用小写的拉丁字母表示文法的终结符号,每个
产生式占一行,第一个产生式的左部为开始符号。在下面写出代码,并用课本 2.4 节中相应
的例子进行验证,提供相应的截图(对窗口截图时先同时按 alt 和 prtscn 键,再按 ctrl+v
粘贴)
答:因为这一次的实验的代码量大概有 1300 行,所以没有在下面只写出书本中算法的主要
代码,其他的实验代码请老师看压缩包;因为我这一次的实验是以 txt 的格式输出结果,请
老师去看压缩包里的输出结果 删除单产生式.txt 、删除无用产生式.txt 、消除空产生
式.txt 等文件。实验代码通过课后的习题验证都没有问题,但在课本 2.4 节中相应的例子中
删除掉无用符号和无用产生式后的结果与课本中的结果不一样
课本中的结果为:
S->aS
S->U
U->a
而在实验中输出结果为:
S->aS
S->a
下面是书本中算法的主要代码:
//algorithm21, algorithm22 用于消除无用产生式
//算法 2.1
void algorithm21()
{
SymbolSet VN1;
ProductionSet P1;
struct Lnode *left = NULL;
struct Rnode *right = NULL;
int flag = 0, added = 1;
VN1.next = NULL;
P1.next = NULL;
P1.num = 0;
//第一步
left = Productions.next;
while(left)
{
flag = 1;
right = left->right;
while(right)
{
if(strcmp(right->name, "") == 0)
break;
if(IsInSet(&Terminators, right->name) == 0)
{
}
flag = 0;
break;
right = right->next;
}
if(flag == 1)
{
}
//如果原来不存在则添加
if(IsInSet(&VN1, left->name) == 0)
AddSym(&VN1, left->name);
left = left->next;
}
//第二步
added = 1;
while(added)
{
added = 0;
left = Productions.next;
while(left)
{
flag = 1;
right = left->right;
while(right)
{
if(strcmp(right->name, "") == 0)
break;
if((IsInSet(&Terminators, right->name) == 0) && ( IsInSet(&VN1,
right->name) == 0))
{
}
flag = 0;
break;
right = right->next;
}
if(flag == 1)
{
}
//如果原来不存在则添加
if(IsInSet(&VN1, left->name) == 0)
{
}
AddSym(&VN1, left->name);
added = 1;
left = left->next;
}
}
//第三步
left = Productions.next;
while(left)
{
flag = 1;
right = left->right;
while(right)
{
if(strcmp(right->name, "") == 0)
break;
if((IsInSet(&Terminators,
right->name)
==
0) &&(
IsInSet(&VN1,
right->name) == 0))
{
}
flag = 0;
break;
right = right->next;
}
if(flag == 1)
AddPro(&P1, left);
left = left->next;
}
//转移到系统链表集合
{
}
//删除原有的
ClearProductionSet(&Productions);
DestroySymbolSet(&NonTerminators);
//转移
Productions.num = P1.num;
Productions.next = P1.next;
NonTerminators.next = VN1.next;
}
//算法 2.2
void algorithm22()
{
SymbolSet VN1, VT1;
ProductionSet P1;
struct Lnode *left = NULL;
struct Rnode *right = NULL;
int flag = 0, added = 1;
VN1.next = NULL;
VT1.next = NULL;
P1.next = NULL;
P1.num = 0;
//开始符号放入 VN1
AddSym(&VN1, Start);
//第一步
added = 1;
while(added)
{
added = 0;
left = Productions.next;
while(left)
{
if(IsInSet(&VN1, left->name) == 1)
{
right = left->right;
while(right)
{
if(IsInSet(&NonTerminators, right->name) == 1)
added = AddSym(&VN1, right->name);
else
if(IsInSet(&Terminators,
right->name)
==
1
||
strcmp(right->name, "") == 0)
added = AddSym(&VT1, right->name);
right = right->next;
}
}
left = left->next;
}
}
//第二步
left = Productions.next;
while(left)
{
flag = 1;
if(IsInSet(&VN1, left->name) == 1)
0)
{
}
right = left->right;
while(right)
{
}
if(IsInSet(&VN1, right->name) == 0 && IsInSet(&VT1, right->name) ==
{
}
flag = 0;
break;
right = right->next;
if(flag == 1)
AddPro(&P1, left);
left = left->next;
}
//转移到系统链表集合
{
//删除原有的