posts - 134,comments - 22,trackbacks - 0
 

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 虚拟机组织结构

i

指令寄存器

Code

程序存储器

s

数据存储器

P

程序地址寄存器

b

基本地址存储器

T

地址寄存器

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];)( la形成的栈地址变量置入栈顶)

4. STO l,a    (s[Base(l) + a] = s[t];t--;)(将栈顶值存到la形成的栈地址变量)

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 何克勤 阅读(1504) 评论(9)  编辑  收藏

FeedBack:
# re: PL/X编译器设计与实现
2008-12-31 01:36 | susan
您好,我看了您这份PLX语言编译器的说明书,很受启发。我自己也在写一个PLX的编译器,和您这个主体、语法结构都非常相似,只在call语句的实现部分有些不同。现在我的程序遇到些问题,请问您方不方便把您的编译器源代码发给我参考一下呢?非常感谢!  回复  更多评论
  
# re: PL/X编译器设计与实现
2008-12-31 01:40 | susan
呃。。留下我的邮箱吧,windmoon_1987@163.com
麻烦您了。。  回复  更多评论
  
# re: PL/X编译器设计与实现
2009-11-19 16:15 | rainbow
高手,是ECNU吗?  回复  更多评论
  
# re: PL/X编译器设计与实现
2009-11-30 19:26 | Saturn
ecnu 的人 V.S PL/X...,hehe@rainbow
  回复  更多评论
  
# re: PL/X编译器设计与实现
2009-12-27 00:53 | gantian
哈哈满世界找到的PL/X都是华师大的~  回复  更多评论
  
# re: PL/X编译器设计与实现
2009-12-28 16:59 | fuck all
请问你认识靓姐么?  回复  更多评论
  
# re: PL/X编译器设计与实现
2009-12-28 18:50 | 何克勤
@fuck all
窦亮?  回复  更多评论
  
# re: PL/X编译器设计与实现
2009-12-30 02:03 | fuck all
yes就是亮姐!
haha  回复  更多评论
  
# re: PL/X编译器设计与实现[未登录]
2010-11-07 15:48 | FRANK WANG
我擦,果然都是亮姐的。。。  回复  更多评论
  

只有注册用户登录后才能发表评论。


网站导航: