要求分析和规格说明Word下载.docx
- 文档编号:21617533
- 上传时间:2023-01-31
- 格式:DOCX
- 页数:25
- 大小:80.16KB
要求分析和规格说明Word下载.docx
《要求分析和规格说明Word下载.docx》由会员分享,可在线阅读,更多相关《要求分析和规格说明Word下载.docx(25页珍藏版)》请在冰豆网上搜索。
d)常量定义
一般形式:
const<
常量名>
=<
常量>
常量定义说明常量的名字:
constn=100
e)变量定义
<
类型符>
<
变量表>
或:
array<
[常量]
前者是定义一般变量,后者是定义数组变量。
数组的常量必须是自然数1,2,……,n。
它代表要定义的数组的元素个数,而数组的下标是从1开始的。
例:
integera,b,c;
integerA[10];
$定义有10个元素的数组变量A
PL遵循变量先定义后使用的规则,而且在同一个作用域范围内不允许有相同的变量名。
但不同作用域变量名可以相同。
也不能用PL的保留字做变量名。
f)过程定义说明
Proc<
过程名>
PL的过程遵循先定义后使用的规则,而且在同一个作用域范围内不允许有相同的过程名。
但不同作用域过程名可以相同。
也不能用PL的保留字做过程名。
Procwrite$错误,这是PL的标准过程,不能重定义
g)PL的语句
空语句:
skip;
它表示什么也不做。
读语句
read<
变量访问表>
;
其中变量访问表:
变量访问>
{,<
}
它是PL的标准过程,也是唯一的一条输入语句。
表示输入一个或多个整数并赋值给相应变量。
例:
reada,b,c;
写语句
write<
表达式表>
其中表达式表:
表达式>
它是PL的标准过程,也是唯一的一条输出语句。
表示输出一个或多个由表达式定义的整数。
writea,b,c*d,100;
赋值语句
:
=<
;
PL的赋值语句具有并行赋值的特点。
a,b:
=1,x+y;
它表示依次把右边的表达式的值分别赋给左边对应的变量。
上例就是把1赋给变量a,把x+y的值赋给变量b。
过程语句
call<
它表示调用用户自己定义过程,PL规定过程必须是先定义后使用的。
if语句
if<
警戒命令表>
fi;
其中警戒命令表:
警戒命令>
{[]<
警戒命令:
->
语句部分>
PL依次检测各警戒命令,如果表达式的值为true则执行相应的语句部分,然后忽略其余警戒命令,执行if后面的语句。
如果所有表达式的值均为false这发出“if语句逻辑错误”的提示并终止程序的执行。
ifa>
b->
t:
=a;
a<
=b;
do语句
do<
do;
PL依次检测各警戒命令,如果表达式的值为true则执行相应的语句部分,然后重新检测各警戒命令,直到所有表达式的值均为false才继续执行do后面的语句。
doi>
100->
readi;
od
h)程序注释
PL的注释以“$”字符开头,直到本行末为止。
例如:
begin
I:
=90;
$这里也是程序的注释
end.
i)运算
PL有下列四种运算与或运算:
&
:
与运算,只有当两个布尔值均为true结果才为true
|:
或运算,只要其中一个布尔值为true结果就为true
关系运算:
PL的关系运算和关系运算符有<
=>
运算的结果为布尔值
加减运算
加减运算+-参加运算的两个操作数和结果均为整数。
乘除运算
乘除运算*/\参加运算的两个操作数和结果均为整数。
*:
两个数相乘
/:
两个数相除结果只取整数部分
\:
两个数相相除结果只取余数部分
非运算
运算符~表示把原来的布尔值取反。
(3)文法分析:
PL的BNF文法:
程序>
:
“.”
=“begin”<
定义部分>
“end”
={<
定义>
“;
”}
常量定义>
|<
变量定义>
过程定义>
=“const”<
“=“<
|
“array”<
“[“<
“]”
=“integer”|“Boolean”
变量名>
{“,”<
=“Proc”<
={<
语句>
空语句>
读语句>
写语句>
赋值语句>
过程语句>
if语句>
do语句>
=“skip”
=“read”<
=“write”<
“:
=”<
=“call”<
=“if”<
“fi”
=“do”<
“od”
{“[]”<
“->
”<
初等表达式>
{<
与或运算符>
初等表达式表>
=“&
”|“|”
简单表达式>
关系运算符>
=“<
”|“=”|“>
”
=[“-”]<
项>
加减运算符>
=“+”|“-”
因子>
乘除运算符>
=“*”|“/”|“\”
|“(“<
“)”|“~”<
[<
下标选择器>
]
=“[“<
数>
布尔量>
数字>
=“false”|“ture”
名>
字母>
|“_”}
从上面的文法中,我们可以得出各语法成分的first和follow集合,这两个集合也是以后进行编译程序编写的关键。
First集合
begin
constintegerBooleanProc
constintegerBooleanProc
const
integerBoolean
namearray
Proc
skipreadwritenamecallifdo
skipreadwritenamecallifdo
skip
read
name
write
-namenumeral(~,
call
if
do
-namenumeral(~[]
-namenumeral(~
-namenumeral(~
+-
namenumeral(~
*/\
[
namenumeral
numeral
falsetrue
name
Follow集合
.
first(语句部分)
first(语句部分);
first(变量定义)first(过程定义)first(语句部分)follow(定义)
first(常量定义)first(过程定义)first(语句部分)follow(定义)
first(变量表)
[follow(变量定义)
first(常量定义)first(变量定义)first(语句部分)follow(定义)
end
;
follow(读语句):
=
follow(写语句)follow(赋值语句)
fiod
[]follow(警戒命令表)
follow(表达式表)->
)]
first(初等表达式)
first(与或运算符)follow(表达式)
first(简单表达式)
first(关系运算符)follow(初等表达式)
first(项)
first(加减运算符)follow(简单表达式)
first(因子)
first(乘除运算符)follow(项)
follow(变量访问表)follow(因子)
follow(变量访问)
follow(常量定义)]
2、PL编译程序的功能要求:
(1)分析器
读入源程序文件作为输入,逐个扫描字符。
识别保留字和专用符号以及名字,把程序正文转化为符号序列,而且用简单值表示符号,定义一个表示这些符号的枚举类型。
输出数的时候,在符号名后跟一个整数,即名字索引;
是保留字的时候就输出它的顺序值。
当扫描器检测到一个不认识的名字时,就输出符号Unknown1。
(2)语法分析
以PASS1的输出文件作为输入。
这个语法分析的过程将识别正确的句子和检测语法错误,根据的文法规则分析程序是否符合Pl文法规则,检查其是否组成PL句子。
并做作用域分析,类型分析,并在错误的时候输出错误信息来。
最后根据Pl的指令集输出中间代码。
(3)代码生成器
代码生成器是为PL计算机生成代码,代码生成有两部分,一个是扩展分析器,输出PL代码,另外一个是汇编器,定义向前引用和代码的优化。
代码生成器有4个输出过程,分别输出指令操作码、参数、寻址、以及对应的命令。
选择代码优化可以节省更多的空间。
(4)解释执行器
解释执行器部分是对所提供的样本程序进行解释执行,前提是前面所有的词法和语法分析、代码生成已经全部通过执行完毕。
二、设计
我们的目标是编写一个PL语言的集成IDE环境,它即能编辑PL程序,又可以在集成环境下运行PL程序的目标代码,而且还具应有出错提示等基本功能。
1.总体设计思想
我们先来看一下编译程序的一般工作流程。
先对高级语言原代码进行词法分析,得到中间代码,然后进行语法分析、语义分析,得到第二个中间代码,接着进行代码优化,得到高效中间代码,再则生成汇编代码,最后是生成可执行的程序代码。
我们看到从一个原程序到可执行代码的生成是要经过很多阶段的,所以我们必须用模块化的思想来进行程序设计,不然程序的编写和维护将会变得异常复杂。
又由于各功能部分经常是互相调用的,如果用面向过程的思想进行程序设计,那么各函数和过程间的调用次序就变得非常重要了,因为函数和过程必须是先定义后使用的。
而且过多的使用全程变量,当程序的复杂性提高时,必将增加程序的出错率。
所以我们用面向对象的思想来程序的设计。
把每个模块定义成一个类,而由于编译过程的每一步又是在它上一步完成后才能执行的,所以具有一种传递性,这样我们又可以用继承的思想来设计我们的类。
模块划分
由于我们的PL语言语法简单,所以我们的编译程序的编译流程可以大大的简化。
从下面的流图我们可以看到整个编译流程得到了巨大的简化。
首先是省略了代码优化模块,然后是把语法分析、作用域分析、类型分析和汇编代码生成合成在一个模块中,最后把语意分析后的中间代码的生成也省略掉了,而直接生成汇编代码。
为了进一步代码的重用性,我们把所有可能重复使用的代码都方在一个单元中――ShareCommand。
而且定义了一个基类TshareCommand。
TshareCommand是实行文件的存取和错误处理。
因为这两个处理所以模块都要用到的。
把他定义成基类的确是好方法。
所以整个编译程序划分为三个模块,基本处理模块,词法分析模块和语法分析模块(包括代码生成),而每个模块又定义成一个类,分别为TshareCommand、PSscan和Tsyntax。
它们的继承关系为:
被继承被继承
2.基本处理模块
1.文件操作
编译程序涉及大量的文件操作,如文件的打开、关闭、读取、写入等等。
因此类TshareCommand中有相应的文件操作方法:
文件读取操作:
procedureTShareCommand.LoadFromFile(FileName:
string);
文件写入操作:
procedureTShareCommand.Emit(Value:
integer);
2.错误处理
错误处理涉及的方法有:
长度检测:
procedureTestLimit(Text1:
overload;
functionTestLimit(Length,Maximum:
integer):
Boolean;
错误提示:
procedureError(Kind:
TErrorKind);
procedureError(Msg:
String);
大家可能看有两个TestLimit和Error方法,不要奇怪,这就是面向对象的好处,这里利用了函数名的重载,这样的好处就是对于处理同类信息的方法我们不用定义多个方法名称,这样类的封装性得到了进一步的提高,隐含了更多的细节,提高了系统的可靠性。
TshareCommand的完整定义
所以TshareCommand的完整定义是:
TShareCommand=class
PSName:
string;
LineNo:
integer;
Emitting,Errors,CorrectLine:
Boolean;
Input1,Output1,Notes:
TextFile;
procedureLoadFromFile(FileName:
procedureTestLimit(Text1:
functionTestLimit(Length,Maximum:
procedureEmit(Value:
procedureRerun;
procedureNewLine(Number:
private
{Privatedeclarations}
public
{Publicdeclarations}
end;
3。
词法分析模块
程序编译的第一步就是词法分析,这个任务由类PSscan来完成。
他是继承TshareCommand类的,所以他具有了文件操作功能和错误处理功能。
我们来看一下他的完整定义。
2.PSscan的完整定义
PSScan=class(TShareCommand)
procedurePass1;
AlphaNumeric,Digits,
EndComment,Invisible,
Letters,Separators,
SmallLetters,CapitalLetters:
TCharSet;
ch:
char;
Characters:
Link:
TWordPointer;
procedureEmit1(Symbol:
TSymbolType);
procedureEmit2(Symbol:
TSymbolType;
Argument:
procedureBeginLine(Number:
procedureEndLine;
procedureNextChar;
procedureInsert(IsName:
Text1:
constIndex:
integer=-1);
procedureDefine(IsName:
Index:
procedureSearch(Text1:
varIsname:
varIndex:
procedureInitialize;
procedureComment;
procedureNextSymbol;
字符读取
词法分析模块逐个字符的读取PL原程序,并用一个控制字符ETX来表示正文的结尾。
字符的读取就由方法NextChar负责。
它可以跳过除新行符(NL)和正文结束符(ETX)以外的所有不可见字符。
扫描
对输入的字符进行的处理我们称为扫描。
这里我们采用超前读一字符的方法。
该功能有NextSymbol负责,具体实现为:
启动扫描器时,预先读入原程序的第一个字符
每当扫描器识别一个字符为一个特定符号的一部分时,立即读入下一个字符
分隔符
扫描器跳过每个符号前的任何空格、新行符和注解。
分隔符以下列字符开头
Separators:
=[SP,NL,Dollar];
在每行末尾,扫描器调用方法EndLine,把行号加1并与符号NewLine一起输出。
whilechinSeparatorsdo
ifch=SPthenNextChar
else
ifch=NLthen
EndLine;
NextChar
else{ch=Dollar}Comment;
注释是以“$”字符开头,直到本行末为止,属于实现起来比较简单
procedureTScan.Comment;
begin{ch=Dollar}
NextChar;
whilenot(chinEndComment)do//到本行末尾
end;
专用符号
如果读入的是专用符号,如“+”,则立即输出该符号的代码并超前读下一个字符。
Emit1(Plus1);
但对应多字符组成的专用符号,例如“[]”就必须如下处理
Nextchar;
ifch='
]'
then
Emit1(bracket1);
elseEmit1(LeftBracket1);
因子“[”和“[]”都是以“[”开头的,所以必须用超前读下一字符的方法来处理。
数字的处理只要解决的是数的最大值问题,程序规定数值的绝对值不能超过32767,所以在ShareCommand模块中有一句MaxInt=32767,具体的算法如下:
ifchinDigitsthen//数字
Value:
=0;
whilechinDigitsdo
Digit:
=ord(ch)-ord('
0'
);
ifValue<
=(MaxInt-Digit)div10then
=10*Value+Digit;
Error(Numeral3);
Emit2(Numeral1,Value)
End
单词
单词的识别,也就是识别保留字和名字。
算法如下,
ifchinLettersthen
Text1:
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 要求 分析 规格 说明
![提示](https://static.bdocx.com/images/bang_tan.gif)