PL/X编译器
软件设计说明书
1.介绍
本编译器可以按照PLX语言语法要求进行词法、语法、语义、出错处理,并最终成生目标代码,通过解释执行得到最终结果。
2.编译器系统结构
2.1 编译器
2.1.1 PL/X语法图
扩展部分:
1) 支持带参数的函数调用,函数可平行或嵌套定义,只允许内层访问外层,外层不能访问内层
2)支持单行注释
3)支持read语句,因此可从终端获取输入
4)支持for语句
5)支持空程序体
关于出错处理:分为词法分析错误、句法分析错误、运行时错误(如除数为0)
允许变量名或函数名重复,但访问的时候以最后一次声明的为有效
2.1.2判断是否符合两条限制规则
规则1:找出图中每一个分支点,考察每个分支点的各个分支的头符号是否相异
规则2:找出图中每一个透明结构,考察每个透明结构的头符号集合与其跟随符号是否相异
判断结果:根据两条限制规则,发现该语法图分析符合两条限制规则
2.1.3 过程调用相关图
2.1.5 语法出错表定义
1switch (errorNum)
2 {
3 case 0:
4 errorInfo="程序需以'.'结束";
5 break;
6 case 1:
7 errorInfo="用了未定义的变量";
8 break;
9 case 2:
10 errorInfo="算术因子里出现非整型变量";
11 break;
12 case 3:
13 errorInfo="丢失')'";
14 break;
15 case 4:
16 errorInfo="算术表示不能以此符号开始";
17 break;
18 case 5:
19 errorInfo="逻辑表达式里出现函数名";
20 break;
21 case 6:
22 errorInfo="逻辑表达式不能以此符号开始";
23 break;
24 case 7:
25 errorInfo="非法的变量名";
26 break;
27 case 8:
28 errorInfo="丢失')'";
29 break;
30 case 9:
31 errorInfo="非法的参数名";
32 break;
33 case 10:
34 errorInfo="丢失begin关键字";
35 break;
36 case 11:
37 errorInfo="丢失end关键字";
38 break;
39 case 12:
40 errorInfo="开始符号不是program";
41 break;
42 case 13:
43 errorInfo="此处应为整型变量";
44 break;
45 case 14:
46 errorInfo="关系表达式不能以此符号开始";
47 break;
48 case 15:
49 errorInfo="此处应为一个比较符号";
50 break;
51 case 16:
52 errorInfo="丢失';'";
53 break;
54 case 17:
55 errorInfo="语句后出现非法字符";
56 break;
57 case 18:
58 errorInfo="变量定义后出现非法字符";
59 break;
60 case 19:
61 errorInfo="丢失','";
62 break;
63 case 20:
64 errorInfo="变量定义不能以此符号开始";
65 break;
66 case 21:
67 errorInfo="变量定义后出现非法字符";
68 break;
69 case 22:
70 errorInfo="此处应为\":=\"";
71 break;
72 case 23:
73 errorInfo="此处不能为函数名";
74 break;
75 case 24:
76 errorInfo="缺了then";
77 break;
78 case 25:
79 errorInfo="缺了from";
80 break;
81 case 26:
82 errorInfo="缺了do";
83 break;
84 case 27:
85 errorInfo="缺了until";
86 break;
87 case 28:
88 errorInfo="缺了to";
89 break;
90 case 29:
91 errorInfo="此处应为函数名";
92 break;
93 case 30:
94 errorInfo="语句不能以此符号开始";
95 break;
96 case 31:
97 errorInfo="语句后不能跟此符号";
98 break;
99 case 32:
100 errorInfo="算术表达式不能以此符号开始";
101 break;
102 case 33:
103 errorInfo="丢失'('";
104 break;
105 case 34:
106 errorInfo="逻辑表达式后出现非法字符";
107 break;
108 case 35:
109 errorInfo="函数定义后出现非法字符";
110 break;
111 case 36:
112 errorInfo="多余的';'";
113 break;
114 case 37:
115 errorInfo="这里等待一个'*'或'/'";
116 break;
117 case 38:
118 errorInfo="这里等待一个'+'或'-'";
119 break;
120 case 39:
121 errorInfo="参数个数不符";
122 break;
123 case 40:
124 errorInfo="函数定义需以procedure开始";
125 break;
126 case 41:
127 errorInfo="函数定义后出现非法字符";
128 break;
129 case 42:
130 errorInfo="外层不能访问内层的变量或调用内层函数";
131 break;
132 case 43:
133 errorInfo="除数为0";
134 break;
135 }
136
2.2 虚拟机
2.2.1 虚拟机组织结构
2.2.2 虚拟机指令格式
l LIT指令,把一个常数置入栈顶
l LOD指令,把一个变量置入栈顶
l STO指令,从栈顶把数置入到一个变量单元里
l CAL指令,调用一个过程
l INT指令,预留数据存储位置
l JMP指令,是无条件转移指令
l JPC指令,是有条件转移指令
l OPR指令,一组算术和关系运算指令
l ADP指令,传递函数参数
2.2.3虚拟机指令系统及其解释
1.LIT 0,a (t++;s[t]=a;)(将数a置入栈顶)
2.OPR 0,a (a = 0:t = b - 1;p = s[t + 3];b = s[t + 2];)(返回调用程序)
(a=1:s[t] = -s[t];)(取负)
(a=2:t--;s[t] = s[t] + s[t + 1];)(加法)
(a=3; t--;s[t] = s[t] - s[t + 1];)(减法)
(a=4; t--;s[t] = s[t] * s[t + 1];)(乘法)
(a=5: t--;if (s[t + 1] == 0){ 报错 }else{ s[t] = s[t] / s[t + 1]; })(除法)
(a=6; if (s[t] > 0){ s[t] = 0; }else { s[t] = 1; })(逻辑not)
(a=7; t--;if (s[t] == s[t + 1]){ s[t] = 1; }else { s[t] = 0; })(等于)
(a=8; t--;if (s[t] != s[t + 1]){ s[t] = 1; }else { s[t] = 0; })(不等于)
(a=9; t--;if (s[t] < s[t + 1]){ s[t] = 1; }else { s[t] = 0; })(小于)
(a=10; t--;if (s[t] >= s[t + 1]){ s[t] = 1; }else { s[t] = 0; })(大于等于)
(a=11; t--;if (s[t] > s[t + 1]){ s[t] = 1; }else { s[t] = 0; })(大于)
(a=12; t--;if (s[t] <= s[t + 1]){ s[t] = 1; }else { s[t] = 0; })(小于等于)
(a=13; t--;if (s[t] != 0 && s[t + 1] != 0){ s[t] = 1; }else { s[t] = 0; })(逻辑and)
(a=14; t--;if (s[t] == 0 && s[t + 1] == 0){ s[t] = 0; }else { s[t] = 1; })(逻辑or)
(a=15; t--;输出s[t])(输出)
(a=16;t++;s[t]=输入)(输入)
3. LOD l,a (t++;s[t] = s[Base(l) + a];)( 将l,a形成的栈地址变量置入栈顶)
4. STO l,a (s[Base(l) + a] = s[t];t--;)(将栈顶值存到l,a形成的栈地址变量)
5. CAL l,a (s[t + 1] = Base(l);s[t + 2] = b;s[t + 3] = p;b = t + 1;p = a - 1;)[调用子程序
SL(静态链地址)DL(动态链地址)RA(返回地址)]
6. INT 0,a (t = t + a;)(预留a个存储位置);
7. JMP 0,a (p = a - 1;)(无条件跳转);
8. JPC 0,a (if (s[t] == 0){ p = a - 1; t--; })(条件跳转);
9.ADP 0,a (参数压栈)
3.全局数据结构、常量和变量
1//整型,逻辑、函数
2
3typedef enum
4
5{
6
7 aident,bident,pident
8
9}objectt;
10
11//符号表项
12
13typedef struct
14
15{
16
17 alfa name; //变量名(函数、整型、逻辑型)
18
19 objectt kind; //类型
20
21 int num ; //函数参数个数
22
23 int level; //层级
24
25 int adr ; //偏移量
26
27 int size ; //局部变量+函数参数的大小
28
29}item;
30
31//定义指令格式
32
33typedef struct
34
35{
36
37 fct f; //指令码
38
39 int l; //层号
40
41 int a; //偏移量
42
43}instruction;
44
45//定义跟随符号集合类型
46
47typedef set<symbol> symset;
48
49typedef vector<instruction> PCODE;
50
51
4.函数原型
1//begin accidence analyze(词法分析器)
2
3void getCh();
4
5void getSym();
6
7//end analyze
8
9 //语法分析器
10
11 void RelationExpression(int level,symset fsys);
12
13 void ArithmeticExpression(int level,symset fsys);
14
15 void ArithmeticTerm(int level,symset fsys);
16
17 void ArithmeticFactor(int level,symset fsys);
18
19 void BoolExpression(int level,symset fsys);
20
21 void BoolTerm(int level,symset fsys);
22
23 void BoolFactor(int level,symset fsys);
24
25 void Procedure(int level,symset fsys);
26
27 void ProcedureSque(int level,symset fsys);
28
29 void Sentence(int level,symset fsys);
30
31 void Definition(int level,int &dx,symset fsys);
32
33 void SentenceSque(int level,symset fsys);
34
35 void DefinitionSque(int level,int &dx,symset fsys);
36
37 void Program(symset fsys);
38
39 //生成中间代码
40
41 void gen(fct f,int l,int a);
42
43 //
44
45 //PLX虚拟机
46
47 int base(int l);
48
49 void plxInterpret();
50
51//出错处理
52
53 void error(int errorNum);
54
55 void test(symset s1,symset s2,int errorNum);
56
PL/X编译器
软件测试说明书
测试1:
1. 概述
u 测试描述:
通过运行几个不同的plx实例,来检查PLX Compiler是否能解析plx语言,进行基本的语法分析,以及出错的正确报错、解释执行等功能。
u 测试环境:
Windows XP VC++6.0
2. 测试用例描述
1 //find prime number between s to b
2
3 program
4
5 integer s ,b
6
7 begin
8
9 procedure findPrime(integer small,big)
10
11 integer i,j,k,c,t
12
13 begin
14
15 i:=small;
16
17 for i from small to big
18
19 do
20
21 j:=2;
22
23 if(i>=3) then
24
25 k:=i/2+1;
26
27 c:=0;
28
29 for j from 2 to k
30
31 do
32
33 if i=(i/j)*j then //由于没有提供取余运算,只能这样了~_~
34
35 c:=c+1
36
37 end
38
39 end;
40
41 if c=0 then
42
43 write i
44
45 end
46
47 end
48
49 end
50
51 end
52
53 read s;
54
55 read b;
56
57 call findPrime s b
58
59 end.
60
报错:
修改后运行结果:
中间代码:
测试2:
u 测试目标:求两数的最大公约数
u 测试用例:
1program
2
3integer a,b;
4
5integer temp
6
7begin
8
9 a:=12;
10
11 b:=42;
12
13 if a < b
14
15 then
16
17 temp := a;
18
19 a := b;
20
21 b := temp
22
23 end;
24
25 temp := a- a/ b*b;
26
27 while temp>0
28
29 do
30
31 a := b;
32
33 b := temp;
34
35 temp := a- a/ b*b
36
37 end;
38
39 temp := b;
40
41 if (a = 0 or b = 0)
42
43 then
44
45 write 0
46
47 else
48
49 write temp
50
51 end
52
53end.
54
55
中间代码:
结果:
posted on 2008-05-29 18:26
何克勤 阅读(1510)
评论(9) 编辑 收藏