PL0编译程序设计说明书.docx

上传人:b****6 文档编号:4569218 上传时间:2022-12-06 格式:DOCX 页数:26 大小:220.59KB
下载 相关 举报
PL0编译程序设计说明书.docx_第1页
第1页 / 共26页
PL0编译程序设计说明书.docx_第2页
第2页 / 共26页
PL0编译程序设计说明书.docx_第3页
第3页 / 共26页
PL0编译程序设计说明书.docx_第4页
第4页 / 共26页
PL0编译程序设计说明书.docx_第5页
第5页 / 共26页
点击查看更多>>
下载资源
资源描述

PL0编译程序设计说明书.docx

《PL0编译程序设计说明书.docx》由会员分享,可在线阅读,更多相关《PL0编译程序设计说明书.docx(26页珍藏版)》请在冰豆网上搜索。

PL0编译程序设计说明书.docx

PL0编译程序设计说明书

PL/0编译程序

设计说明书

 

小组组长:

李 文(00000000)

小组成员:

******(00000000)

******(00000000)

******(00000000)

******(00000000)

 

2006年1月16日

1引言3

1.1编写目的3

1.2背景3

1.3定义3

1.4参考资料5

2总体设计5

2.1需求规定5

2.2运行环境6

2.3模块流程6

2.4模块机理说明7

2.5模块设计与实现10

2.6人工处理过程12

2.7程序的亮点13

2.8尚未问决的问题13

3程序介绍和使用说明13

4程序测试结果分析16

概要设计说明书

1引言

1.1编写目的

此文档为VK1.0版PL/0编译器详细设计说明书,旨在说明该编译器的设计思想和实现。

此说明书可以在阅读本编译器代码时有效地帮助您理解本编译器的设计方法和实现过程,希望能提供给您所需的帮助。

1.2背景

名称:

VK1.0版PL/0编译器

说明:

此编译器为北京师范大学信息科学学院计算机科学与技术系2003级2005-2006学年度第一学期编译原理课程实验作业。

本软件由李文小组合作开发,组长李文,同组人员有吕叶、刘晟忻、肖纯、曲文星。

本软件主要用于PL/0程序的编译,软件提供生成中间代码,并执行检测。

本软件为开源软件,故除了用于编译以外还可给编译器开发者提供开发参考。

本软件开发运行在Windows32位平台上,尚未开发其他平台版本。

1.3定义

本软件开发中,用到了一些PL/0语言和PCODE的定义以及编译原理术语,下面给予说明。

●PL/0语言:

ØBNF范式:

〈程序〉∷=〈分程序〉.

〈分程序〉∷=[〈常量说明部分〉][〈变量说明部分〉][〈过程说明部分〉]〈语句〉

〈常量说明部分〉∷=CONST〈常量定义〉{,〈常量定义〉};

〈常量定义〉∷=〈标识符〉=〈无符号整数〉

〈无符号整数〉∷=〈数字〉{〈数字〉}

〈变量说明部分〉∷=VAR〈标识符〉{,〈标识符〉};

〈标识符〉∷=〈字母〉{〈字母〉|〈数字〉}

〈过程说明部分〉∷=〈过程首部〉〈分程序〉{;〈过程说明部分〉};

〈过程首部〉∷=PROCEDURE〈标识符〉;

〈语句〉∷=〈赋值语句〉|〈条件语句〉|〈当型循环语句〉|〈过程调用语句〉|〈读语句〉|〈写语句〉|〈复合语句〉|〈空〉;

〈赋值语句〉∷=〈标识符〉∶=〈表达式〉

〈复合语句〉∷=BEGIN〈语句〉{;〈语句〉}END

〈条件〉∷=〈表达式〉〈关系运算符〉〈表达式〉|ODD〈表达式〉

〈表达式〉∷=[+|-]〈项〉{〈加法运算符〉〈项〉}

〈项〉∷=〈因子〉{〈乘法运算符〉〈因子〉}

〈因子〉∷=〈标识符〉|〈无符号整数〉|'('〈表达式〉')'

〈加法运算符〉∷=+|-

〈乘法运算符〉∷=*|/

〈关系运算符〉∷=#|=|<|<=|>|>=

〈条件语句〉∷=IF〈条件〉THEN〈语句〉

〈过程调用语句〉∷=CALL〈标识符〉

〈当型循环语句〉∷=WHILE〈条件〉DO〈语句〉

〈读语句〉∷=READ'('〈标识符〉{,〈标识符〉}')'

〈写语句〉∷=WRITE'('〈表达式〉{,〈表达式〉}')'

〈字母〉∷=a|b|…|X|Y|Z

〈数字〉∷=0|1|2|…|8|9

ØPL/0语言允许过程嵌套定义,函数及变量作用于本层。

即外层变量和程序对内层可见,内层变量和函数对外层不可见。

其中内层函数或变量将使外层的函数或变量不可见。

ØPL/0允许递归调用,以函数可见为调用原则。

●PCODE语言:

Pcode语言是PL/0语言的中间代码,其形式如下:

指令格式:

f

l

a

f功能码

l层次差(标识符引用层减去定义层)

a根据不同的指令有所区别

其代码有8条,如下:

LIT0a

将常数值取到栈顶,a为常数值

LODla

将变量值取到栈顶,a为偏移量,l为层差

STOla

将栈顶内容送入某变量单元中,a为偏移量,l为层差

CALla

调用过程,a为过程地址,l为层差

INT0a

在运行栈中为被调用的过程开辟a个单元的数据区

JMP0a

无条件跳转至a地址

JPC0a

条件跳转,当栈顶布尔值非真则跳转至a地址,否则顺序执行

OPR00

过程调用结束后,返回调用点并退栈

OPR01

栈顶元素取反

OPR02

次栈顶与栈顶相加,退两个栈元素,结果值进栈

OPR03

次栈顶减去栈顶,退两个栈元素,结果值进栈

OPR04

次栈顶乘以栈顶,退两个栈元素,结果值进栈

OPR05

次栈顶除以栈顶,退两个栈元素,结果值进栈

OPR06

栈顶元素的奇偶判断,结果值在栈顶

OPR07

无操作

OPR08

次栈顶与栈顶是否相等,退两个栈元素,结果值进栈

OPR09

次栈顶与栈顶是否不等,退两个栈元素,结果值进栈

OPR010

次栈顶是否小于栈顶,退两个栈元素,结果值进栈

OPR011

次栈顶是否大于等于栈顶,退两个栈元素,结果值进栈

OPR012

次栈顶是否大于栈顶,退两个栈元素,结果值进栈

OPR013

次栈顶是否小于等于栈顶,退两个栈元素,结果值进栈

OPR014

栈顶值输出至屏幕

OPR015

屏幕输出换行

OPR016

从命令行读入一个输入置于栈顶

●编译术语:

Ø开始符号集:

设G=(VT,VN,S,P)是上下文无关文法

FIRST(α)={a|α

aβ,a∈VT,α,β∈V*}

若α

ε,则规定ε∈FIRST(α).

Ø后跟符号集:

设G=(VT,VN,S,P)是上下文无关文法,A∈VN,S是开始符号

FOLLOW(A)={a|SμAβ,且a∈VT,a∈FIRST(β),μ∈VT*,β∈V+}

若SμAβ,且βε,则#∈FOLLOW(A)。

1.4参考资料

本软件为课程作业,故开发时主要参考了课程相关的书籍:

Ø编译原理电子课件北京师范大学信息科学学院计算机科学与技术系孙波教授提供

Ø《编译原理(第二版)》清华大学出版社张素云、吕映芝等编写。

Ø《编译原理及编译程序构造》北京航空航天大学出版社高仲仪金茂忠编

Ø《AdvancedCompilerDsignandImplementation》[USA]StenvenS.Muchnick

高级编译器设计与实现赵克佳沈志宇译机械工业出版社

2总体设计

2.1需求规定

说明对本系统的主要的输入输出项目、处理的功能性能要求,详细的说明可参见附录C。

本编译软件的设计目标是为PL/0提供编译和检错以及供开发参考。

●输入项目:

1.输入PL/0源程序文档名。

如果路径正确继续,否则退出

2.选择是否进行并输出词法分析结果(Y/N)。

3.选择是否输出中间代码到屏幕(Y/N)。

程序会在分析完毕输出中间代码到文件

4.运行时根据程序结构

●输出项目:

1.如果有错误输出错误

2.根据用户选择输出相应结果

3.PL/0程序运行的结果

●处理性能:

由于PL/0程序较为简单,一般的机器平台均能很快地运行,故进行PL/0程序的编译程序设计时并未考虑性能方面的要求。

2.2运行环境

本编译软件要求运行在支持Windows32位系统的Intel8086以上机型中。

从理论上讲,如果源代码使用GCC编译器编译,应该可以在Linux等系统上运行,但尚未做过测试。

2.3模块流程

本系统各模块处理数据流程如下图所示:

2.4模块机理说明

本软件系统采用模块化架构,主要模块有:

●词法分析模块

词法分析模块的主要功能是从PL/0源文件读入字符流的代码,然后根据各个单词类型的定义采用自动机的模式,将单词识别出来,并将标识符存储到指定位置,供其他模块取用,同时提供给其他模块以接口,来调用本模块函数,以获得单词的类型。

其核心在于自动机的构建,本程序中使用自动机模型如下:

同时,为了便于阶段性理解编译过程,程序提供了只查看词法分析结果的功能,因为词法分析中采用提前读判断功能,故程序为了打印出各个单词及词型,把提前读和移动读指针分开,采用preread函数和move函数来实现这一功能。

●语法语义分析模块

本程序在处理语法分析时采用LL分析法,并使用递归子程序法来实现。

对应各个语法单元定义了相应的处理模块。

程序在进行语法语义分析时调用词法分析模块来获取当前单词的词型,并根据词型判断转向德语义分析模块,调用其处理函数执行。

在处理各语法单元时,程序根据各单元语义生成中间代码。

各语法单元调用关系如下图:

●代码生成模块

代码生成模块包括根据语义生成代码和管理代码列表两个部分。

其中错误表的管理较为简单,此处不再详细介绍。

根据语义生成代码这一部分已嵌入到语法语义分析模块内,一般而言随着语法单元可以顺序翻译,但有少部分单元需要迟后翻译,即在生成代码时无法获得出口或者跳转的目标地址(因为目标在下面,尚未翻译),因此需要采用回填的手段。

在本程序中,由于语法分析采用了递归子程序的方法,所考虑的回填问题仅局限在某个语法单元内,因此不用考虑层次回填的问题。

故程序中不必采用复杂的拉链技术,而是记下尚未回填的某几条语句位置,等到出口确定时,直接修改代码表中该代码的跳转值即可。

采用了回填技术的两个重要控制语句的原理图如下:

●错误处理模块

错误处理模块主要包括错误表的管理、错误补救和致命错误的处理三个方面。

Ø错误表的管理对外提供错误报告函数,由调用程序报告错误类型,管理模块将其记录到表中并记录出错行号。

程序中主要的错误类型如下:

错误类型

错误信息

致命错误

UNEXPECTED_FILE_END

不可预期的文件结尾

UNEXPECTED_EXTERN_CODE

程序结束还有多余代码

CODELIST_OVERFLOW

中间代码表溢出

TABLE_OVERFLOW

符号表溢出

词法错误

IDENT_TOO_LONG

标识符过长

NUM_TOO_BIG

数字过长

UNKNOWN_SYMBOL

不可识别的符号

语法错误

MISSING_PERIOD

程序末尾丢掉了'.'结束符号

IDENT_REDECLARED

标识符重复声明

IDENT_IN_CONST_EXPECTING

常量声明必须以标识符开始

EQL_IN_CONST_EXPECTING

常量声明中间应该为'='符号

NUM_IN_CONST_EXPECTING

常量声明的值必须是数字常量

MISSING_SEMICOLON_IN_CONST

常量声明末尾丢掉了';'

IDENT_IN_VAR_EXPECTING

变量必须为标识符

MISSING_SEMICOLON_IN_VAR

变量声明末尾丢掉了';'

PROC_LEV_TOO_DEEP

过程层次定义太深

IDENT_IN_PROC_EXPECTING

过程名必须为标识符

MISSING_SEMICOLON_IN_PROC

过程声明末尾丢掉了';'

MISSING_SEMICOLON_END_PROC

过程定义末尾丢掉了';'

UNEXPECTED_STATEMENT_BEGIN

无效的语句开始

VAR_UNDECLARED

未声明的变量

PROC_UNDECLARED

未声明的过程

IDENT_CONST_IN_ASSIGN

不可为常量赋值

IDENT_PROC_IN_ASSIGN

赋值语句左边不可为过程名

BECOMES_EXPECTING_IN_ASSIGN

赋值语句中间应该为":

="

MISSING_SEMICOLON_IN_STATEMENT

语句末尾丢掉了';'

THEN_EXPECTING_IN_IF

if语句条件后面应该为then

DO_EXPECTING_IN_WHILE

while语句条件后面应该为do

PROC_EXPECTING_IN_CALL

call后面必须是过程名

IDENT_CONST_IN_READ

read语句中不应有常量

IDENT_PROC_IN_READ

read语句中不应有过程名

KEYWORD_APPEAR_IN_READ

read语句中不应该出现关键字

IDENT_EXPECTING_IN_READ

read语句中'('或者'

IDENT_PROC_IN_EXP

表达式中不因该出现过程名

RELATIONOPR_EXPECTING_IN_CDT

条件中的不应出现非关系运算符

MISSING_LPAREN

丢掉了左括号

MISSING_RPAREN

丢掉了右括号

MISSING_END

缺少END

UNEXPECTED_STATEMENT_FOLLOW

语句follow集不符

UNEXPECTED_PROCDECL_FOLLOW

过程声明follow集不符

UNEXPECTED_CONST_FOLLOW

常量声明follow集不符

UNEXPECTED_VAR_FOLLOW

变量声明follow集不符

UNEXPECTED_PROCBODY_FOLLOW

过程定义follow集不符

UNEXPECTED_CDT_FOLLOW

条件follow集不符

UNEXPECTED_FACTOR_FOLLOW

表达式follow集不符

表2错误类型表

在错误处理时,可以发现,FOLLOW集不正确的错误大都是由于其他错误在先而引起的,故为了有效准确的报告错误,在处理错误报告时采取如果已有错误报告,则对FOLLOW集不予报告,否则,则报告的方式,有效减少无效错误的发生。

Ø致命错误的处理,采用函数返回terminate标志TMNT,如果在子程序调用时返回了TMNT,则当前程序也应该立即返回TMNT,直到main函数为止来报告该错误。

为了调用子程序方便,程序中把所有子程序调用使用宏定义来实现TMNT返回,将子程序调用保护起来。

Ø错误补救采用了判断开始符号集和后跟符号集的方式。

即将所有错误均认为是丢掉了语法模块,然后根据后跟符号集来读取本语法单元的内容,将错误缩小在本语法单元内。

●符号表管理模块

符号表管理采用栈式存储管理,以解决符号可见性的问题。

即每次进入语法块时记录此时位置,等退出时出栈该层符号。

●中间代码解释模块

中间代码解释实际上是做了一个简单的虚拟机,用bx,cx,sp等模拟寄存器来解释执行指令。

根据指令含义执行相应的动作。

2.5模块设计与实现

此部分主要介绍各个模块的程序实现及其处理数据的流程示意

各模块的主要设计如下:

●词法分析模块

●语法语义分析模块

●代码生成模块

●错误处理模块

●中间代码解释模块

2.6人工处理过程

本软件在开发时尽量避免使用人工处理,所需要人工处理的地方主要包括对非终结符的开始符号集和后跟符号集的求解。

这些求解将在语法语义分析中用于宏定义,以方便程序设计。

开始符号和后跟符号及求解结果如下:

非终结符名

开始符号集合

后继符号集合

分程序

constvarprocedureidentifcallbeginwhilereadwrite

.

语句

identcallbeginifwhilereadwrite

.;end

条件

odd+-(identnumber

thendo

表达式

+-(identnumber

.;)ropendthendo

identnumber(

.;)rop+-endthendo

因子

identnumber(

.;+-*/endthendo

2.7程序的亮点

Ø为了便于观察和理解编译过程,程序专门实现了词法分析的结果显示。

可以在程序运行时选择是否显示词法分析结果。

Ø程序在错误处理上很注重错误提示的有效性,实现错误提示了定位到出错行,定位到出错标识符的功能。

Ø程序在符号表管理上采用栈式管理,很适合于解决PL/0的嵌套定义中符号的作用域及可见性问题。

2.8尚未问决的问题

Ø程序在错误处理上下了很大功夫,实现了定位到标识符的提示。

由于实现时时根据错误类型以及错误点的上一标识符和当前标识符来判断,可能在某些极特殊的错误(错误的标识符既不是上一个也不是当前的)中,会出现提示失误的情况。

Ø本程序在设计之初已经实现了一个Win32的窗口界面,后来由于加入了解释执行程序,不得不忍痛割爱,将其拆掉。

目前亟待解决的问题是,如何能在窗口界面中调用解释执行程序来模拟运行。

3程序介绍和使用说明

本程序为DOS界面,程序运行时,会弹出如下窗口

输入PL/0源文件名会给出两个选项,输入y/n即可:

选中选项后将看到词法分析结果以及中间代码

中间代码位于下面,滚动即可看到

并且给出中间代码运行结果:

4程序测试结果分析

为了检验程序是否达到预期目标,结果是否正确,程序使用了大量的PL/0源文件来进行测试,在此以一个正确的源文件和一个错误的源文件为例来测试程序功能:

●正确的源文件:

PL/0源文件:

standard.pl

CONSTa=10;

varb,c;

procedurep;

begin

c:

=b+a

end;

begin

read(b);

whileb#0do

begin

callp;

write(2*c);

read(b)

end

end.

运行结果:

请输入PL/0源程序文件名:

standard.pl

是否显示词法分析结果?

y

是否显示中间代码列表?

y

Compiling...

词法分析结果如下:

CONST Type:

constsym

aType:

ident

=Type:

eql

10Type:

number

;Type:

semicolon

varType:

varsym

bType:

ident

Type:

comma

cType:

ident

;Type:

semicolon

procedureType:

procsym

pType:

ident

;Type:

semicolon

beginType:

beginsym

cType:

ident

:

=Type:

becomes

bType:

ident

+Type:

plus

aType:

ident

endType:

endsym

;Type:

semicolon

beginType:

beginsym

readType:

readsym

(Type:

lparen

bType:

ident

)Type:

rparen

;Type:

semicolon

whileType:

whilesym

bType:

ident

#Type:

neq

0Type:

number

doType:

dosym

beginType:

beginsym

callType:

callsym

pType:

ident

;Type:

semicolon

writeType:

writesym

(Type:

lparen

2Type:

number

*Type:

times

cType:

ident

)Type:

rparen

;Type:

semicolon

readType:

readsym

(Type:

lparen

bType:

ident

)Type:

rparen

endType:

endsym

endType:

endsym

.Type:

period

Syntaxing...

中间代码如下:

0:

JMP08

1:

JMP02

2:

INT03

3:

LOD13

4:

LIT010

5:

OPR02

6:

STO14

7:

OPR00

8:

INT05

9:

OPR016

10:

STO03

11:

LOD03

12:

LIT00

13:

OPR09

14:

JPC024

15:

CAL02

16:

LIT02

17:

LOD04

18:

OPR04

19:

OPR014

20:

OPR015

21:

OPR016

22:

STO03

23:

JMP011

24:

OPR00

运行结果如下:

Running....

>:

1

22

>:

2

24

>:

3

26

>:

4

28

>:

5

30

>:

6

32

>:

7

34

>:

8

36

>:

9

38

>:

2

24

>:

3

26

>:

4

28

>:

0

Programendnormally!

Pressanykeytocontinue

可以看到结果与预期相同,程序通过。

本程序有测试了许多其他的文件,全部通过,与预期相同。

所有测试的源文件及结果均附上。

●错误文件测试:

PL/0源文件:

error.pl

constm=7,n=85

varx,y,z,q,r;

proceduremultiply;

vara,b;

begin

a:

=u;

b:

=y;

z:

=c

whileb>0do

begin

ifoddbdo

z:

=z+a;

a:

=2a;

b:

=b/2;

end

end;

proceduredivide

consttwo=2,three:

=3;

varw;

begin

r=w;

q:

=0;

w:

=y;

whilew<=rdow:

=two*w;

whilew>y

beginq:

=(2*q;w:

=w/2);

ifw<=rthen

beginr:

=r-2q:

q+1

end

end

end;

proceduregcd;

varf,g;

beginf:

=x;g:

=y

whilef<>gdo

beginiff

=g-f;

ifg

=f-g;

z:

=f

end;

begin

x:

=m;y:

=n;callmultiply;

x:

25;y:

=3;calldivide;

x:

=84;y:

36;callgcd;

callx;x:

=gcd;gcd=x

end.

程序运行情况如下:

可以看出,程序很好的报告了出现的错误。

..

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

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

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

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