实验2语法分析程序.docx

上传人:b****5 文档编号:7681193 上传时间:2023-01-25 格式:DOCX 页数:43 大小:30.10KB
下载 相关 举报
实验2语法分析程序.docx_第1页
第1页 / 共43页
实验2语法分析程序.docx_第2页
第2页 / 共43页
实验2语法分析程序.docx_第3页
第3页 / 共43页
实验2语法分析程序.docx_第4页
第4页 / 共43页
实验2语法分析程序.docx_第5页
第5页 / 共43页
点击查看更多>>
下载资源
资源描述

实验2语法分析程序.docx

《实验2语法分析程序.docx》由会员分享,可在线阅读,更多相关《实验2语法分析程序.docx(43页珍藏版)》请在冰豆网上搜索。

实验2语法分析程序.docx

实验2语法分析程序

实验2语法分析程序

一、实验目的与要求

1.复习上下文无关文法的基本概念、判断方法即构造技术;

2.学习根据文法产生式使用递归子程序来构造语法分析器,进而理解递归下降分析法的理论基础、技术原理及实现步骤;

3.理解文法存在左递归、回溯现象的害处及消除方法,掌握FIRST集、FOLLOW集的含义、求解方法与用途,掌握LL

(1)文法的判断方法;

4.掌握预测分析法的理论精髓,理解下推自动机的基本概念;

5.学会基于上下文无关文法构造LL

(1)预测表,并能使用VisualC++编写基于LL

(1)预测表的语法分析器;

6.能利用预测分析法,在给定的文法基础上,分析特定输入串的语法结构,能判断其是否合法,并能提取大部分中间信息,以备后续分析时使用。

二、实验仪器及设备

1.微型电子计算机80台

2.配置Windows2000及以上版本操作系统

3.安装VisualC++6.0/VisualC#2000/Delphi6.0等以上版本的开发环境

三、实验内容及步骤

已知某正规文法G1[E]如下:

E→E+T|T

T→T*F|F

F→(E)|i

首先消除文法左递归,得到下面的文法G1'[E]:

E→TE'

E'→+TE'|

T→FT'

T'→*FT'|

F→(E)|i

请用两种方法构造该文法的语法分析程序。

(一)基于递归下降分析法构造语法分析器

按照递归下降分析的基本思想,为每个非终结符编写一个子程序。

从E开始,依据产生式右部的符号组成,调用相关的子程序,完成输入串“(i+i)*i”的语法分析。

下面是参考代码(部分):

#include"iostream.h"

#include"stdlib.h"

#include"string"

usingnamespacestd;

classCRDM//递归下降分析法(Recursive,Descent,Method)

{

public:

CRDM()//构造函数

{

myExpression="(i+i)*i#";//输入串以“#”作为结束标识

}

voidBeginRDM();//开始递归分析

private:

voidE();//对应非终结符E的子程序

voidE1();//对应非终结符E'的子程序

voidT();//对应非终结符T的子程序

voidT1();//对应非终结符T'的子程序

voidF();//对应非终结符F的子程序

voidmatch(stringt);//匹配函数

voidERROR();

stringnexttoken();

private:

stringmyExpression;//表达式

stringch;//符号

inti;//符号序号

};

//获取下一个符号:

stringCRDM:

:

nexttoken()

{

stringtemp;

i++;

temp=myExpression.substr(i,1);

returntemp;

}

//启动递归下降分析程序:

voidCRDM:

:

BeginRDM()

{

i=-1;

ch=nexttoken();

E();

if(!

(pare("#")))

{

cout<<"恭喜您,匹配成功!

"<

exit(0);

}

else

ERROR();

}

//错误提示函数:

voidCRDM:

:

ERROR()

{

cout<

"<

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;j

if(!

(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;num

if(!

(FFSet[num].GrammarSpare(str)))

returnnum;

return-1;

}

//确定符号串str在容器VnVt中的位置:

intCLL1Grammar:

:

GetSignInVector(stringstr,vector&VnVt)

{

for(inti=0;i

if(!

(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

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 高中教育 > 英语

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1