}
将程序输出的单词流与理论分析的结果比较分析,若有差错,请找出原因,并进一步修
改你的程序,直至得到正确的结果。
四、思考题
1.将实验内容
(一)中的文法G[S]转化为正规式;
2.将实验内容
(一)中的有限自动机M转化为正规式。
五、实验报告
1.实验报告撰写在统一配发的纸质报告册上,下次上课时交给老师。
2.实验报告格式如下。
实验1词法分析程序
一、实验目的与要求
二、实验仪器及设备
三、实验内容
1•根据指导书要求,按顺序解答;
2•要求有结果,尤其是程序显示结果;
3•不需要附上源代码。
四、思考题
五、实验小结
阐述实验中碰到的问题、解决的方法或技术、得到的结论、体会感触等。
六、参考代码
(一)CGrammar类
1.头文件Grammar.h
#pragmawarning(disable:
4786)〃屏蔽"由于string和vector等STL模版产生很长的标识符
而引起的警告信息”
//使用vector容器
//产生式
//左部
//右部
#include#include#include#include#include#includeusingnamespacestd;
structCreateFormula{
stringLeftPart;stringRightPart;};
classCGrammar
{
public:
CGrammar();
~CGrammar();
〃外部操作函数:
voidSetGrammar(char*Filename);//根据文件内容设置文法产生式
voidDelDirectLeftRecursion(inti);//
boolDelIndirectLeftRecursion();//boolHavingRedundance();//
voidMiniGrammar();//
voidDisplayGrammar();//
消除“直接”左递归消除“间接”左递归含有无用产生式文法化简显示文法
voidDisplayGrammar(char*Filename);//将文法产生式保存在txt文件
//返回文法属性的函数:
intGetGrammarType();boolGetHavingLeftRecursion();vectorGetVN();vectorGetVT();vectorGetCF();stringGetStartSign();
//返回文法类型//是否存在左递归
//返回非终结符
//返回终结符
//返回产生式数据
//返回开始符号
public:
//基本函数:
boolFindSign(stringstr,vector&VnVt);//查找某符号串str是否属于VnVtvectorGetSingleSign(stringstr);//分解字符串为单个符号(包括形式为
的符号)
E'
private:
voidCountVn_and_Vt();//求非终结符和终结符集boolEnableDelLeftRecursion();//能否删除左递归voidExistDirectLeftRecursion();//含有“直接”左递归voidExistIndirectLeftRecursion();//含有“间接”左递归
boolIS_0_Grammar();//
boolIS_1_Grammar();//
boolIS_2_Grammar();//
boolIS_3_Grammar();//
voidGrammarType();//
stringCreateNewVn(stringvn);//protected:
//文法结构
vectorNoEndSign;//
vectorEndSign;//
识别0型文法识别1型文法识别2型文法识别3型文法判断文法类型构造新的非终结符
vectorGR_Array;//
非终结符集
终结符集产生式集合
stringStartSign;intGrammarTypeNum;
private:
intGR_Number;
boolIsDirectLeftRecursion;boolIsIndirectLeftRecursion;
};
//开始符号
//文法类型号码
//产生式的总数
//含有直接左递归的标识
//含有间接左递归的标识
2.实现文件Grammar.cpp
#include"Grammar.h"
#defineKONG"£"
CGrammar:
:
CGrammar()
{
GR_Array.reserve(1000);
//很重要,预先划分一块内存给vector使用
GrammarTypeNum=-1;
IsDirectLeftRecursion=false;
IsIndirectLeftRecursion=false;
}
CGrammar:
:
~CGrammar()
{
}
//从txt文件中获取文法的产生式集合:
//规则:
不用简写;用连接;用“&
表示空串;每行一条产生式。
voidCGrammar:
:
SetGrammar(char*Filename)
{
ifstreamfin(Filename,ios:
:
in);charline[1024]={0};
intpos;
CreateFormulatemp;
if(!
GR_Array.empty())
GR_Array.clear();//清空
while(fin.getline(line,sizeof(line))){
//下面的一段代码用于删除产生式中的所有空格:
chartempline[200]="";
inti=0,j=0;
while(line[i])
{
if(line[i]!
=''&&line[i]!
=''&&line[i]!
=''){
templine[j]=line[i];
j++;
}
i++;
}templine[j+1]='\0';//操作结束
strings(templine);
if((pos=s.find(”宀"))>=100)continue;
temp.LeftPart=s.substr(0,pos);
temp.RightPart=s.substr(pos+2,s.length()-pos);〃"宀"是汉字符号,所以“
+2”
GR_Array.push_back(temp);
}
GR_Number=GR_Array.size();
fin.clear();
fin.close();
//初始化操作:
CountVn_and_Vt();
GrammarType();
ExistDirectLeftRecursion();
//求非终结符集、终结符集
//判断文法的分类类型
//判断是否存在直接左递归
ExistIndirectLeftRecursion();
//判断是否存在间接左递归
//将文法产生式保存在txt文件
voidCGrammar:
:
DisplayGrammar(char*Filename)
{
ofstreamfout(Filename,ios:
:
out);
for(inti=0;ifout<(2)<"<fout.clear();
fout.close();
}
//查找某符号串str是否属于某个容器VnVt
boolCGrammar:
:
FindSign(stringstr,vector&VnVt)
{
for(inti=0;i(VnVt[i].compare(str)))returntrue;
returnfalse;
}
//求非终结符集Vn、终结符集Vt
voidCGrammar:
:
CountVn_and_Vt()
{
if(!
NoEndSign.empty())
NoEndSign.clear();
if(!
EndSign.empty())
EndSign.clear();
for(inti=0;i{//观察产生式的左部vectorstrtemp=GetSingleSign(GR_Array[i].LeftPart);//分解左部为单个符号for(intj=0;j{
stringtempvn=strtemp[j];
if(tempvn[0]>='A'&&tempvn[0]<='Z')//若为大写字母则是非终结符
{
if(!
FindSign(tempvn,NoEndSign))//若是新的非终结符,则添加进去
NoEndSign.push_back(tempvn);
}
else//否则,则为终结符
{
if(!
FindSign(tempvn,EndSign))//若是新的终结符,则添加进去
EndSign.push_back(tempvn);
}
}
//观察产生式的右部
if((GR_Array[i].RightPpare(”&")))〃若不是X形式,则
{//分解右部为单个符号vectorstrtemp1=GetSingleSign(GR_Array[i].RightPart);for(intk=0;kstringtempvt=strtemp1[k];if(!
(tempvt[0]>='A'&&tempvt[0]<='Z'))//若不是大写字母,则是终结符{
if(!
FindSign(tempvt,EndSign))//若是新的终结符,则添加进去
EndSign.push_back(tempvt);
}
else//否则,则为非终结符
{
if(!
FindSign(tempvt,NoEndSign))//若是新的终结符,则添加进去NoEndSign.push_back(tempvt);
}
}
}
}
if(!
NoEndSign.empty())
StartSign=NoEndSign[0];//文法开始符号默认为遇到的第一个非终结符}
//识别0型文法(所有产生式的左部含有非终结符):
boolCGrammar:
:
IS_0_Grammar()
{
intCapitalNumInLeftPart;//某产生式左部的非终结符的数目,即大写字母数
intcount=0;
for(inti=0;i{
CapitalNumInLeftPart=0;
for(intj=0;j{
stringtemp3=GR_Array[i].LeftPart.substr(j,1);if(FindSign(temp3,NoEndSign))
CapitalNumInLeftPart++;
}if(CapitalNumInLeftPart<=0)returnfalse;//表示当前产生式的左部没有非终结符,则直接终止
}
returntrue;//是0型文法
}
//识别1型文法(即上下文有关文法,所有产生式的左部长度<=右部长度):
boolCGrammar:
:
IS_1_Grammar()
{
for(inti=0;iGR_Array[i].RightPart.length())//若左部大于右部,
returnfalse;
returntrue;
}
//识别2型文法(即上下文无关文法:
左部长度=1,且左部为非终结符Vn)
boolCGrammar:
:
IS_2_Grammar()
{
for(inti=0;iif(GR_Array[i].LeftPart.length()!
=1)//若左部长度不为1returnfalse;
stringtemp4=GR_Array[i].LeftPart.substr(0,1);if(!
FindSign(temp4,NoEndSign))returnfalse;
}
returntrue;}
//识别3型文法(即正规文法,分为右线性、左线性)
boolCGrammar:
:
IS_3_Grammar()
{
intFlag仁0,Flag2=0;〃分别代表右线性A宀aB、左线性A宀Ba
的个数
for(inti=0;i{if(GR_Array[i].RightPart.length()==1)//右部字符个数等于1,{
stringtemp1=GR_Array[i].RightPart.substr(0,1);//取右部字符if(!
FindSign(temp1,NoEndSign)&&!
FindSign(temp1,EndSign))//若右部既不是
终结符
〃,即不满足Ata形式,也不是非终结符,既不满足AtB形式,则
returnfalse;
}
if((GR_Array[i].RightPpare(”&")))〃若不是X形式,则
{
stringtemp2=GR_Array[i].RightPart.substr(0,1);
stringtemp3=GR_Array[i].RightPart.substr(1,1);if(FindSign(temp2,EndSign)
&&FindSign(temp3,NoEndSign))Flag1++;
elseif(FindSign(temp2,NoEndSign)&&FindSign(temp3,EndSign))Flag2++;
else
returnfalse;
//
//
//
//
若右部首字符是终结符次首字符为非终结符,即AtaB
若右部首字符是非终结符
次首字符为终结符,即AtBa
elseif(GR_Array[i].RightPart.length()==2)//判断是否右线性AtaB或左线性AtBa形式
}else
returnfalse;
if(Flag1>0&&Flag2>0)//同时含有右线性、左线性returnfalse;
else
returntrue;
}
//判断文法的类型
voidCGrammar:
:
GrammarType()
{
GrammarTypeNum=-1;
if(IS_0_Grammar())
{
GrammarTypeNum=0;
if(IS_1_Grammar())
{
GrammarTypeNum=1;
if(IS_2_Grammar())
{
GrammarTypeNum=2;
if(IS_3_Grammar())
GrammarTypeNum=3;
}
}
}
}
//判断是否含有“直接”左递归
voidCGrammar:
:
ExistDirectLeftRecursion()
{
for(inti=0;i{
stringtemp1=GR_Array[i].LeftPart.substr(0,1);
if(FindSign(temp1,NoEndSign)&&//若左部首字符为指定非终结符NoEndSign[i],
GR_Array[i].LeftPart[0]==GR_Array[i].RightPart[0])//,且存在直接左递归
{
IsDirectLeftRecursion=true;
return;
}
}
IsDirectLeftRecursion=false;
}
//判断是否含有“间接”左递归
voidCGrammar:
:
ExistIndirectLeftRecursion()
{
vector:
:
iteratorIter1,Iter2;vectorGR_ArrayTemp;//备份用:
GR_ArrayTemp.reserve(1000);
GR_ArrayTemp=GR_Array;//此处仅是判断是否存在左递归,//所有不能对原产生式进行破坏性操作,而只能对备份数据操作。
for(inti=0;i{
for(intj=0;j
{
for(Iter1=GR_ArrayTemp.begin();Iter1!
=GR_ArrayTemp.end();Iter1++)
{
stringtemp1=(*Iter1).LeftPart.substr(0,1);
stringtemp2=(*Iter1).RightPart.substr(0,1);if(!
pare(NoEndSign[i])//左部首字符为Pi,
&&!
pare(NoEndSign[j]))//右部首字符为Pj,即形如Pi宀Pjy
//注:
这里,y是终结符,i、j是下标。
{
//寻找所有形为:
Pjt...的产生式:
for(Iter2=GR_ArrayTemp.begin();Iter2!
=GR_ArrayTemp.end();Iter2++)
stringtemp3=(*Iter2).LeftPart.substr(0,1);
if(!
pare(NoEndSign[j]))//若某产生式的左部为Pj,则替换,{
CreateFormulatemp;temp=(*Iter1);temp.RightPart.replace(0,1,(*Iter2).RightPart);GR_ArrayTemp.push_back(temp);
}
}
//当替换完成后,需要删除第k条产生式((*Iter1)),
Iter1=GR_ArrayTemp.erase(Iter1);
}
}
}
}
for(Iter1=GR_ArrayTemp.begin();Iter1!
=GR_ArrayTemp.end();Iter1++)
{
stringtemp