分享
 
 
 

PL/0语言词法及语法分析系统的设计与实现

王朝vc·作者佚名  2006-01-17
窄屏简体版  字體: |||超大  

PL/0语言词法及语法分析系统的设计与实现

作者:陶善文

南京航空航天大学信息与计算机科学专业

下载源代码

摘要:本文介绍了一个PL/0语言的词法及语法分析系统的设计与实现

关键词:循环分支 递归下降 管道 输出重定向

现在的编译系统都是IDE(Integrated Development

Environment)和编译器独立实现,他们之间通过管道通信,本系统也采用这一方法来实现。我首先给出本文中的PL/0语言的文法:

PL/0语言的BNF描述(扩充的巴克斯范式表示法)

<prog → program <id;<block

<block → [<condecl][<vardecl][<proc]<body

<condecl → const <const{,<const}

<const → <id:=<integer

<vardecl → var <id{,<id}

<proc → procedure <id(<id{,<id});<block{;<proc}

<body → begin <statement{;<statement}end

<statement → <id := <exp

|if <lexp then <statement[else <statement]

|while <lexp do <statement

|call <id[(<exp{,<exp})]

|<body

|read (<id{,<id})

|write (<exp{,<exp})

<lexp → <exp <lop <exp|odd <exp

<exp → [+|-]<term{<aop<term}

<term → <factor{<mop<factor}

<factor→<id|<integer|(<exp)

<lop → =|<|<|<=||=

<aop → +|-

<mop → *|/

<id → l{l|d} (注:l表示字母)

<integer → d{d}

注释:<prog:程序 ;<block:块、程序体 ;<condecl:常量说明 ;<const:常量;

<vardecl:变量说明 ;<proc:分程序 ; <body:复合语句 ;<statement:语句;

<exp:表达式 ;<lexp:条件 ;<term:项 ; <factor:因子 ;<aop:加法运算符;

<mop:乘法运算符; <lop:关系运算符

odd:判断表达式的奇偶性。

下面我们先来看看词法及语法分析器的设计与实现。词法分析采用循环分支方法实现,语法分析采用递归下降来实现。它们的程序流程图如下:

下面我们来实现这个两个分析器。这两个分析器采用一个类CCompiler来实现,这个类的定义如下:

//编译类

class CCompiler

{

public:

CCompiler();

virtual ~CCompiler();

public:

void Compile(char *szFile);//编译,公共接口

vector<SYNTAXERR GetSyntaxErr(){return m_vectorSyntaxErr;};//得到语法错误

protected:

bool LexAnalysis(char *szStr);//词法分析

bool IsOprSym(char *szStr);//是否为运算符

bool IsBndSym(char *szStr);//是否为界符

bool IsKeyWord(char *szStr);//是否为关键字

bool IsInSymbolTab(char *szStr); //是否已在符号表中

char* JumpNoMatterChar(char *szStr);//跳过空格,回车,换行符,Tab

void OutSymbolTab(char *szFile);//输出符号表到文件

void SyntaxAnalysis();//语法分析

void SyntaxAnalysis_Prog();

bool SyntaxAnalysis_Mop();

bool SyntaxAnalysis_Integer();

bool SyntaxAnalysis_Aop();

bool SyntaxAnalysis_Lop();

int SyntaxAnalysis_Id();

int SyntaxAnalysis_Block();

int SyntaxAnalysis_Body();

int SyntaxAnalysis_Factor();

int SyntaxAnalysis_Term();

int SyntaxAnalysis_Lexp();

int SyntaxAnalysis_Exp();

int SyntaxAnalysis_Statement();

int SyntaxAnalysis_Const();

int SyntaxAnalysis_Proc();

int SyntaxAnalysis_Vardecl();

int SyntaxAnalysis_Condecl();

protected:

int m_iVecotrSymbolSize; //符号表大小

int m_iCurPointer; //符号表中当前指针

vector<LEXPROPERTYVS m_vectorSymbol;//符号表

vector<SYNTAXERR m_vectorSyntaxErr; //语法错误代码

};

其中:函数bool LexAnalysis(char *szStr);是对输入字符串szStr采用循环分支方法进行词法分析,分析出来的符号放在符号表m_vectorSymbol中,这个符号表采用向量这个数据结构来表示。词法分析得出符号表后,即进入语法分析阶段,语法分析由函数void

SyntaxAnalysis();完成。下面这些函数是各非终结符对应的递归子程序。bool SyntaxAnalysis_Mop();

bool SyntaxAnalysis_Integer();

bool SyntaxAnalysis_Aop();

bool SyntaxAnalysis_Lop();

int SyntaxAnalysis_Id();

int SyntaxAnalysis_Block();

int SyntaxAnalysis_Body();

int SyntaxAnalysis_Factor();

int SyntaxAnalysis_Term();

int SyntaxAnalysis_Lexp();

int SyntaxAnalysis_Exp();

int SyntaxAnalysis_Statement();

int SyntaxAnalysis_Const();

int SyntaxAnalysis_Proc();

int SyntaxAnalysis_Vardecl();

int SyntaxAnalysis_Condecl();

以上我介绍了词法及语法分析核心的设计实现,下面我简单介绍下IDE的实现和IDE与分析核心之间的通信。本系统的IDE与分析核心之间采用管道通信,代码如下:

DWORD dwThreadID;

::CreateThread(0,0,CompileThread,this,0,&dwThreadID);//创建进程

进程创建后调用进程函数,

//进程函数

DWORD WINAPI CompileThread(LPVOID pParam)

{

CCompileSysView *pView=(CCompileSysView*)pParam;

pView-GetCompileResult();

return 0;

}

进程函数调用类的自身函数GetCompileResult();得到分析核心的输出结果,这个函数的实现如下:

void CCompileSysView::GetCompileResult()

{

SECURITY_ATTRIBUTES sa;

HANDLE hRead,hWrite;

CString strFile;

CString strOut;

strFile.Format("..\\pl\\pl.exe ");//指定分析核心程序的路径

//当前文件作为参数传给分析核心程序,防止这个文件名中含有空格,故用双引号""将文件名括住

strFile=strFile+(char)34+m_szCurFile+(char)34;

sa。nLength=sizeof(SECURITY_ATTRIBUTES);

sa。lpSecurityDescriptor=NULL;

sa。bInheritHandle=TRUE;

if(!CreatePipe(&hRead,&hWrite,&sa,0))//创建管道进行通信

{

MessageBox("Error On CreatePipe()");

return;

}

STARTUPINFO si;

PROCESS_INFORMATION pi;

si。cb=sizeof(STARTUPINFO);

GetStartupInfo(&si);

si。hStdError=hWrite;

si。hStdOutput=hWrite;//输出重定向到文件

si。wShowWindow=SW_HIDE;

si。dwFlags=STARTF_USESHOWWINDOW | STARTF_USESTDHANDLES;

//创建进程启动分析核心程序

if(!CreateProcess(NULL,(LPSTR)(LPCTSTR)strFile,NULL,NULL,TRUE,NULL,NULL,NULL,&si,&pi))

{

MessageBox("Error on CreateProcess()");

return;

}

CloseHandle(hWrite);

char buffer[4096]={0};

DWORD bytesRead;

while(true)

{

if(!ReadFile(hRead,buffer,4095,&bytesRead,NULL))

break;

strOut+=buffer;

m_pwndOutBar-SetColorRichEditText(strOut);//将输出结果显示出来

Sleep(500);

}

}

这样就完成了整个分析系统的设计与实现。下面我们来看看整个系统是怎样运行的。我们先来看看这个系统的运行界面:

程序运行后,出现如图所示的界面,首先设置分析程序的路径,方法是:点菜单IDE环境(I),设置,会出现如下图所示的对话框:

在编辑框中输入分析器所在路径即可(默认分析器和源文件在一个目录下)。设置好以后,就可以在代码编辑区输入代码了,或者点“打开”打开文件,然后点击工具栏“启动”(也可按快捷键F7)按钮进行分析,分析完以后,词法分析结果会在“分析结果显示区”显示,词法和语法分析信息会在"输出信息显示区"显示。

已知的 bug 说明

由于时间关系,现有如下Bug本人未能调试出来,若有高手调试出来的话,还望告知。

PL.exe 有大量内存泄漏,但是本人在 CCompiler 的析构函数中用如下代码释放内存,不知为何出错:

CCompiler::~CCompiler()

{

//下面这段释放内存的代码不知道为什么出错

// for(int i=0;i<m_iVecotrSymbolSize;i++)

// delete m_vectorSymbol[i].szStr;

}

用测试源文件中的 Test3.pas 测试 PL.exe 时,不知道为什么在Debug状态下不出错,而在Release状态下出错。

用测试源文件中的Test3.pas测试 IDE.exe 时,输出信息栏会多出一些前面已经显示过的信息,不知道为什么,估计读管道信息时,又把原来的已经读过了的信息又读了一遍

源码编辑区的行和列显示问题:我目前只显示了行,列还不能显示。

工作区间栏:点击右键,再选“展开”。有时候会出现不了你想要的效果,再用右键点击时,必须先用左键点击,这样才能得到你想要的效果,原因是:函数GetSelectedItem()得到的选中的项必须先用左键点击

,不知道怎样才能解决这个问题。

双击工作空间的最子节点时,应该使该节点对应的单词进入用户的视区范围内。

类CIDEView中的函数GetCompileResult()中的一段代码,在Release版本中运行没有出错,在Debug版本中出错.代码如下

: pDoc-SetPathName(strFile,1);

pDoc-SetModifiedFlag(0);

pDoc-OnSaveDocument((LPSTR)(LPCSTR)strFile);//先保存该文件

str=pDoc-GetTitle();

pDoc-SetTitle(str);

if(str.Right(1)=="*")

{

str=str.Left(str.GetLength()-1);

pDoc-SetTitle(str);

}

UpdateWindow();

这段代码的意思就是在启动分析程序之前先保存文件并把窗口上做未保存标记的星号去掉。

参考文献

陈火旺等,程序设计语言编译原理,国防工业出版社,2001.1

王咏刚,《编写自己的IDE》,2005-1-10

作者联系方式

http://home.pudn.com/ahei

http://AIfan.54sc.com

QQ:8261525 计算机博弈QQ群:5620663

ahei080210114@hotmail.com

ahei0802@126.com

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
推荐阅读
 
 
 
>>返回首頁<<
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有