PL/X編譯器
軟件設(shè)計(jì)說(shuō)明書(shū)
1.介紹
本編譯器可以按照PLX語(yǔ)言語(yǔ)法要求進(jìn)行詞法、語(yǔ)法、語(yǔ)義、出錯(cuò)處理,并最終成生目標(biāo)代碼,通過(guò)解釋執(zhí)行得到最終結(jié)果。
2.編譯器系統(tǒng)結(jié)構(gòu)
2.1 編譯器
2.1.1 PL/X語(yǔ)法圖




擴(kuò)展部分:
1) 支持帶參數(shù)的函數(shù)調(diào)用,函數(shù)可平行或嵌套定義,只允許內(nèi)層訪問(wèn)外層,外層不能訪問(wèn)內(nèi)層
2)支持單行注釋
3)支持read語(yǔ)句,因此可從終端獲取輸入
4)支持for語(yǔ)句
5)支持空程序體
關(guān)于出錯(cuò)處理:分為詞法分析錯(cuò)誤、句法分析錯(cuò)誤、運(yùn)行時(shí)錯(cuò)誤(如除數(shù)為0)
允許變量名或函數(shù)名重復(fù),但訪問(wèn)的時(shí)候以最后一次聲明的為有效
2.1.2判斷是否符合兩條限制規(guī)則
規(guī)則1:找出圖中每一個(gè)分支點(diǎn),考察每個(gè)分支點(diǎn)的各個(gè)分支的頭符號(hào)是否相異
規(guī)則2:找出圖中每一個(gè)透明結(jié)構(gòu),考察每個(gè)透明結(jié)構(gòu)的頭符號(hào)集合與其跟隨符號(hào)是否相異
判斷結(jié)果:根據(jù)兩條限制規(guī)則,發(fā)現(xiàn)該語(yǔ)法圖分析符合兩條限制規(guī)則
2.1.3 過(guò)程調(diào)用相關(guān)圖

2.1.5 語(yǔ)法出錯(cuò)表定義
1
switch (errorNum)
2
{
3
case 0:
4
errorInfo="程序需以'.'結(jié)束";
5
break;
6
case 1:
7
errorInfo="用了未定義的變量";
8
break;
9
case 2:
10
errorInfo="算術(shù)因子里出現(xiàn)非整型變量";
11
break;
12
case 3:
13
errorInfo="丟失')'";
14
break;
15
case 4:
16
errorInfo="算術(shù)表示不能以此符號(hào)開(kāi)始";
17
break;
18
case 5:
19
errorInfo="邏輯表達(dá)式里出現(xiàn)函數(shù)名";
20
break;
21
case 6:
22
errorInfo="邏輯表達(dá)式不能以此符號(hào)開(kāi)始";
23
break;
24
case 7:
25
errorInfo="非法的變量名";
26
break;
27
case 8:
28
errorInfo="丟失')'";
29
break;
30
case 9:
31
errorInfo="非法的參數(shù)名";
32
break;
33
case 10:
34
errorInfo="丟失begin關(guān)鍵字";
35
break;
36
case 11:
37
errorInfo="丟失end關(guān)鍵字";
38
break;
39
case 12:
40
errorInfo="開(kāi)始符號(hào)不是program";
41
break;
42
case 13:
43
errorInfo="此處應(yīng)為整型變量";
44
break;
45
case 14:
46
errorInfo="關(guān)系表達(dá)式不能以此符號(hào)開(kāi)始";
47
break;
48
case 15:
49
errorInfo="此處應(yīng)為一個(gè)比較符號(hào)";
50
break;
51
case 16:
52
errorInfo="丟失';'";
53
break;
54
case 17:
55
errorInfo="語(yǔ)句后出現(xiàn)非法字符";
56
break;
57
case 18:
58
errorInfo="變量定義后出現(xiàn)非法字符";
59
break;
60
case 19:
61
errorInfo="丟失','";
62
break;
63
case 20:
64
errorInfo="變量定義不能以此符號(hào)開(kāi)始";
65
break;
66
case 21:
67
errorInfo="變量定義后出現(xiàn)非法字符";
68
break;
69
case 22:
70
errorInfo="此處應(yīng)為\":=\"";
71
break;
72
case 23:
73
errorInfo="此處不能為函數(shù)名";
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="此處應(yīng)為函數(shù)名";
92
break;
93
case 30:
94
errorInfo="語(yǔ)句不能以此符號(hào)開(kāi)始";
95
break;
96
case 31:
97
errorInfo="語(yǔ)句后不能跟此符號(hào)";
98
break;
99
case 32:
100
errorInfo="算術(shù)表達(dá)式不能以此符號(hào)開(kāi)始";
101
break;
102
case 33:
103
errorInfo="丟失'('";
104
break;
105
case 34:
106
errorInfo="邏輯表達(dá)式后出現(xiàn)非法字符";
107
break;
108
case 35:
109
errorInfo="函數(shù)定義后出現(xiàn)非法字符";
110
break;
111
case 36:
112
errorInfo="多余的';'";
113
break;
114
case 37:
115
errorInfo="這里等待一個(gè)'*'或'/'";
116
break;
117
case 38:
118
errorInfo="這里等待一個(gè)'+'或'-'";
119
break;
120
case 39:
121
errorInfo="參數(shù)個(gè)數(shù)不符";
122
break;
123
case 40:
124
errorInfo="函數(shù)定義需以procedure開(kāi)始";
125
break;
126
case 41:
127
errorInfo="函數(shù)定義后出現(xiàn)非法字符";
128
break;
129
case 42:
130
errorInfo="外層不能訪問(wèn)內(nèi)層的變量或調(diào)用內(nèi)層函數(shù)";
131
break;
132
case 43:
133
errorInfo="除數(shù)為0";
134
break;
135
}
136
2.2 虛擬機(jī)
2.2.1 虛擬機(jī)組織結(jié)構(gòu)
2.2.2 虛擬機(jī)指令格式
l LIT指令,把一個(gè)常數(shù)置入棧頂
l LOD指令,把一個(gè)變量置入棧頂
l STO指令,從棧頂把數(shù)置入到一個(gè)變量單元里
l CAL指令,調(diào)用一個(gè)過(guò)程
l INT指令,預(yù)留數(shù)據(jù)存儲(chǔ)位置
l JMP指令,是無(wú)條件轉(zhuǎn)移指令
l JPC指令,是有條件轉(zhuǎn)移指令
l OPR指令,一組算術(shù)和關(guān)系運(yùn)算指令
l ADP指令,傳遞函數(shù)參數(shù)
2.2.3虛擬機(jī)指令系統(tǒng)及其解釋
1.LIT 0,a (t++;s[t]=a;)(將數(shù)a置入棧頂)
2.OPR 0,a (a = 0:t = b - 1;p = s[t + 3];b = s[t + 2];)(返回調(diào)用程序)
(a=1:s[t] = -s[t];)(取負(fù))
(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){ 報(bào)錯(cuò) }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;)[調(diào)用子程序
SL(靜態(tài)鏈地址)DL(動(dòng)態(tài)鏈地址)RA(返回地址)]
6. INT 0,a (t = t + a;)(預(yù)留a個(gè)存儲(chǔ)位置);
7. JMP 0,a (p = a - 1;)(無(wú)條件跳轉(zhuǎn));
8. JPC 0,a (if (s[t] == 0){ p = a - 1; t--; })(條件跳轉(zhuǎn));
9.ADP 0,a (參數(shù)壓棧)
3.全局?jǐn)?shù)據(jù)結(jié)構(gòu)、常量和變量
1
//整型,邏輯、函數(shù)
2
3
typedef enum
4
5

{
6
7
aident,bident,pident
8
9
}objectt;
10
11
//符號(hào)表項(xiàng)
12
13
typedef struct
14
15

{
16
17
alfa name; //變量名(函數(shù)、整型、邏輯型)
18
19
objectt kind; //類型
20
21
int num ; //函數(shù)參數(shù)個(gè)數(shù)
22
23
int level; //層級(jí)
24
25
int adr ; //偏移量
26
27
int size ; //局部變量+函數(shù)參數(shù)的大小
28
29
}item;
30
31
//定義指令格式
32
33
typedef struct
34
35

{
36
37
fct f; //指令碼
38
39
int l; //層號(hào)
40
41
int a; //偏移量
42
43
}instruction;
44
45
//定義跟隨符號(hào)集合類型
46
47
typedef set<symbol> symset;
48
49
typedef vector<instruction> PCODE;
50
51
4.函數(shù)原型
1
//begin accidence analyze(詞法分析器)
2
3
void getCh();
4
5
void getSym();
6
7
//end analyze
8
9
//語(yǔ)法分析器
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虛擬機(jī)
46
47
int base(int l);
48
49
void plxInterpret();
50
51
//出錯(cuò)處理
52
53
void error(int errorNum);
54
55
void test(symset s1,symset s2,int errorNum);
56
PL/X編譯器
軟件測(cè)試說(shuō)明書(shū)
測(cè)試1:
1. 概述
u 測(cè)試描述:
通過(guò)運(yùn)行幾個(gè)不同的plx實(shí)例,來(lái)檢查PLX Compiler是否能解析plx語(yǔ)言,進(jìn)行基本的語(yǔ)法分析,以及出錯(cuò)的正確報(bào)錯(cuò)、解釋執(zhí)行等功能。
u 測(cè)試環(huán)境:
Windows XP VC++6.0
2. 測(cè)試用例描述
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 //由于沒(méi)有提供取余運(yùn)算,只能這樣了~_~
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
報(bào)錯(cuò):

修改后運(yùn)行結(jié)果:
中間代碼:

測(cè)試2:
u 測(cè)試目標(biāo):求兩數(shù)的最大公約數(shù)
u 測(cè)試用例:
1
program
2
3
integer a,b;
4
5
integer temp
6
7
begin
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
53
end.
54
55
中間代碼:

結(jié)果:
posted on 2008-05-29 18:26
何克勤 閱讀(1517)
評(píng)論(9) 編輯 收藏