PL/X编译器设计与实现

PL/X编译器设计与实现
 

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 语法出错表定义

  1 switch  (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
 3 typedef  enum
 4
 5 {
 6
 7       aident,bident,pident
 8
 9}
objectt;
10
11 // 符号表项
12
13 typedef  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
33 typedef  struct
34
35 {
36
37       fct    f;   //指令码
38
39       int    l;   //层号
40
41       int    a;   //偏移量
42
43}
instruction;
44
45 // 定义跟随符号集合类型
46
47 typedef  set < symbol >  symset;
48
49 typedef vector < instruction >  PCODE;
50
51


4.函数原型

 1 // begin accidence analyze(词法分析器)
 2
 3 void  getCh();
 4
 5 void  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       测试用例:

 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


中间代码:

结果:

你可能感兴趣的:(PL/X编译器设计与实现)