exit
(1);
}
//产生式:
E→TE'
voidCRDM:
:
E()
{
T();
E1();
}
//产生式:
E'→+TE'|ε
voidCRDM:
:
E1()
{
if(!
(pare("+")))
{
match("+");
T();
E1();
}
}
//产生式:
T→FT'
voidCRDM:
:
T()
{
F();
T1();
}
//产生式:
T'→*FT'|ε
voidCRDM:
:
T1()
{
if(!
(pare("*")))
{
match("*");
F();
T1();
}
}
//产生式:
F→(E)|i
voidCRDM:
:
F()
{
if(!
(pare("i")))
match("i");
elseif(!
(pare("(")))
{
match("(");
E();
if(!
(pare(")")))
match(")");
else
ERROR();
}
else
ERROR();
}
//匹配函数:
voidCRDM:
:
match(stringt)
{
if(!
(pare(t)))
{
ch=nexttoken();
}
else
ERROR();
}
//主函数:
voidmain()
{
CRDMrdm;
rdm.BeginRDM();
}
请完成下述操作:
1.分别输入四组数据:
(i+i)*i#、i+i*i#、(i*i)+i#、i+i*i+#,测试它们是否合法,若不合法,请给出原因分析。
2.若将上述文法G1[E]进行修改(红色部分),得到G2[E]:
E→E+T|E-T|T(增加了减法“-”)
T→T*F|T/F|F(增加了除法“/”)
F→(E)|i
(1)请修改上述程序,使之适应新文法的语法要求。
提示:
主要考虑如何消除左递归,得到新的无左递归文法G2'[E]。
(2)依次输入四组符号串(i+i-i)*i#、(i+i)-*i#、(i/i)+i*i#、i+i*i/i-#,分别测试它们是否合法,并说明理由。
(二)基于预测分析法构造语法分析程序
这里需要借助实验1中建立的文法类CGrammar文件Grammar.h和Grammar.cpp,并在此基础上,公有派生出LL
(1)文法类:
CLL1Grammar,在CLL1Grammar类中完成语法分析的预测分析过程。
下面是参考代码,具体实现原理请参考教材有关章节或相关文献资料。
头文件LL1Grammar.h如下:
#include"Grammar.h"
#include"stack"
structNodeStruct
{
stringSign;//元素
NodeStruct*Next;//指针
};
//FIRST和FOLLOW的结构体,相同:
structFFStruct
{
stringGrammarSign;//元素
boolFlag;//表示已求过
NodeStruct*Next;//指针
};
//SELECT的结构体:
structSELECTStruct
{
stringLeft;//左部
stringRight;//右部
NodeStruct*Next;//指针
};
//LL
(1)文法类:
classCLL1Grammar:
publicCGrammar
{
public:
CLL1Grammar()
{
//预先划分一块内存给vector使用
FIRSTofSingleSign.reserve(1000);
FIRSTofSignString.reserve(2000);
SELECTofCR.reserve(2000);
FOLLOWofVN.reserve(2000);
}
~CLL1Grammar()
{
}
//显示信息:
voidDisplayAllSingleSignFIRST(char*Filename);//保存所有单符号的FIRST到文件
voidDisplayAllSignStringFIRST(char*Filename);//保存所有右部符号串的FIRST到文件
voidDisplayAllSingleSignFIRST();//显示所有单符号的FIRST
voidDisplayAllSignStringFIRST();//显示所有右部符号串的FIRST
vectorGetFIRSTofSingleSign(stringstr);//返回指定符号的FIRST
vectorGetFIRSTofSignString(stringstr);//返回指定符号串的FIRST
voidDisplayAllVNFOLLOW();//显示所有非终结符的FOLLOW
voidDisplayAllVNFOLLOW(char*Filename);//保存所有FOLLOW到文件
vectorGetFOLLOWofVN(stringstr);//返回指定符号的FOLLOW
voidDisplayAllSELECT();//显示所有SELECT
voidDisplayAllSELECT(char*Filename);//保存所有SELECT到文件
voidDisplayMMTable();//显示预测分析表
voidDisplayMMTable(char*Filename);//保存预测分析表到文件
voidDisplaySentencePressing(stringsignstr,char*Filename);//将句子分析过程保存到文件中
public:
voidIniLL1CGrammar();//初始化
boolGetIsLL1Grammar();//是否为LL
(1)文法
voidCreateMM();//构造预测分析表M
boolIsSentenceofLL1(stringsignstr);//基于LL
(1)分析法判断一个串是否是合法的句子
private:
voidFIRSTSetOfSingleSign(stringstrnum);//求解单符号的FIRST集
voidFIRSTSetOfAllSingleSign();//求解所有单符号的FIRST集
voidFOLLOWSetofVN(stringstrVN);//求非终结符的FOLLOW集
voidFOLLOWSetOfAllVN();//求所有非终结符的FOLLOW集
voidFIRSTSetOfAllSignString();//计算所有右部符号串的FIRST
FFStruct*FIRSTSetOfSTR(stringstr1);//求指定的符号串的FIRST
voidSELECTSetOfAllCR();//计算所有产生式的SELECT
voidCheckLL1Grammar();//判断是否为LL
(1)文法
voidClearStack();//清空栈
voidPreprocessing_LeftRecursion();//预处理
boolFindInList(stringstrVT,FFStruct*Head);//检查某首字符strVT是否已在Head中
intGetPtrFromstr(stringstr,vector&FFSet);//根据str得到其在FFSet中的指针
boolEnableToEmpty(stringstr);//字符串能否推出ε
voidMerge(FFStruct*Head,NodeStruct*head,boolFlagtemp);//合并集合
voidInsterNode(FFStruct*Head,stringstr);//将str加入链表;
intGetSignInVector(stringstr,vector&VnVt);//确定符号串str在容器中的位置:
stringGetStack(stackssLL1);//显示栈
private:
boolIsLL1Grammar;//是否是LL
(1)文法
vectorFIRSTofSingleSign;//单个符号的FIRST集
vectorFIRSTofSignString;//右部符号串的FIRST集
vectorFOLLOWofVN;//非终结符的FOLLOW集
vectorSELECTofCR;//产生式的SELECT集
vector>MMTable;//预测分析表
vectortempEndSign;//预测分析表临时用的终结符集
stacksLL1;//定义栈
};
实现文件LL1Grammar.cpp如下:
#include"LL1Grammar.h"
#include
#include
//预处理
voidCLL1Grammar:
:
Preprocessing_LeftRecursion()
{
//判断文法是否为2型或3型:
if(GetGrammarType()>=2)
{
//消除左递归
if(GetHavingLeftRecursion())
{
if(DelIndirectLeftRecursion())
{
cout<"<DisplayGrammar();
if(HavingRedundance())
{
MiniGrammar();//文法化简:
cout<"<DisplayGrammar();
}
}
}
}
}
//初始化(要调用CLL1Grammar的相关功能,必须首先执行此函数)
voidCLL1Grammar:
:
IniLL1CGrammar()
{
//
(1)判断是否有左递归,若有则消除左递归
Preprocessing_LeftRecursion();
//
(2)数据初始化
//A:
初始化FIRSTofSingleSign
FFStructtemp1;
inti;
//非终结符NoEndSign:
for(i=0;i{
temp1.GrammarSign=NoEndSign[i];
temp1.Flag=false;
temp1.Next=NULL;
FIRSTofSingleSign.push_back(temp1);
}
//终结符EndSign:
for(i=0;i{
temp1.GrammarSign=EndSign[i];
temp1.Flag=false;
temp1.Next=NULL;
FIRSTofSingleSign.push_back(temp1);
}
//B:
根据产生式数组GR_Array的右部,来初始化FIRSTofSignString
//注意:
不同的产生式的右部可能相同。
FFStructtemp2;
for(i=0;i{
intj;
for(j=0;jif(!
(GR_Array[i].RightPpare(FIRSTofSignString[j].GrammarSign)))
break;
if(j==FIRSTofSignString.size())
{
temp2.GrammarSign=GR_Array[i].RightPart;
temp2.Flag=false;
temp2.Next=NULL;
FIRSTofSignString.push_back(temp2);
}
}
//C:
初始化FOLLOWofVN
FFStructtemp3;
for(i=0;i{
temp3.GrammarSign=NoEndSign[i];
temp3.Flag=false;
temp3.Next=NULL;
FOLLOWofVN.push_back(temp3);
}
//D:
初始化SELECTofCR
SELECTStructtemp4;
for(i=0;i{
temp4.Left=GR_Array[i].LeftPart;
temp4.Right=GR_Array[i].RightPart;
temp4.Next=NULL;
SELECTofCR.push_back(temp4);
}
//(3)预执行有关函数:
FIRSTSetOfAllSingleSign();//1.计算所有单个符号的FIRST
FIRSTSetOfAllSignString();//2.计算所有右部符号串的FIRST
FOLLOWSetOfAllVN();//3.计算所有非终结符的FOLLOW
SELECTSetOfAllCR();//4.计算所有产生式的SELECT
CheckLL1Grammar();//5.判断是否为LL
(1)文法
}
//检查某首字符strVT是否已在链表Head中:
boolCLL1Grammar:
:
FindInList(stringstrVT,FFStruct*Head)
{
NodeStruct*p;
p=Head->Next;
while(p)
{
if(!
(p->Spare(strVT)))
returntrue;
p=p->Next;
}
returnfalse;
}
//将str加入链表的尾部:
voidCLL1Grammar:
:
InsterNode(FFStruct*Head,stringstr)
{
NodeStruct*q=newNodeStruct;
q->Sign=str;
q->Next=NULL;
if(!
Head->Next)//若只有表头
Head->Next=q;
else//若已有节点
{
NodeStruct*p=Head->Next;
while(p->Next)
p=p->Next;
p->Next=q;
}
}
//根据str得到其在FFSet中的指针
intCLL1Grammar:
:
GetPtrFromstr(stringstr,vector&FFSet)
{
for(intnum=0;numif(!
(FFSet[num].GrammarSpare(str)))
returnnum;
return-1;
}
//确定符号串str在容器VnVt中的位置:
intCLL1Grammar:
:
GetSignInVector(stringstr,vector&VnVt)
{
for(inti=0;iif(!
(VnVt[i].compare(str)))
returni;
return-1;
}
//判断字符串str能否推出ε:
boolCLL1Grammar:
:
EnableToEmpty(stringstr)
{
if(!
(pare("ε")))//若为ε,则当然可以导出ε
returntrue;
vector:
:
iteratorIter1;//迭代器
boolFlag1=false,Flag2;
for(Iter1=GR_Array.begin();Iter1!
=GR_Array.end();Iter1++)
{
if(!
((*Iter1).LeftPpare(str)))//若左部为str,
{
if((*Iter1).RightPart.length()==1//若右部长度==1,
&&FindSign((*Iter1).RightPart,EndSign))//,且是终结符,则
{
Flag1=Flag1||false;
}
elseif((*Iter1).RightPart.length()==2//若右部长度==2,
&&!
((*Iter1).RightPpare("ε")))//,且是ε,则
{
Flag1=Flag1||true;
}
else
{
//将产生式*Iter1的右部分解为单个符号:
vectortempRight=GetSingleSign((*Iter1).RightPart);
Flag2=true;
for(inti=0;i{
Flag2=Flag2&&EnableToEmpty(tempRight[i]);//递归求解
}
Flag1=Flag1||Flag2;
}
}
}
returnFlag1;
}
//将head合并到Head,参数Flagtemp表示是否剔除ε。
voidCLL1Gr