1:  package compiler;
   2:   
   3:  import java.io.BufferedReader;
   4:  import java.io.BufferedWriter;
   5:  import java.io.IOException;
   6:  import java.util.Arrays;
   7:  import java.util.logging.Level;
   8:  import java.util.logging.Logger;
   9:   
  10:  /**
  11:   * 类P-code代码解释器(含代码生成函数)
  12:   *
  13:   * @author jiangnan
  14:   *
  15:   */
  16:  public class Interpreter {
  17:   
  18:      //运行栈上限
  19:      private static final int stackSize = 1000;
  20:      //pcode数组上线
  21:      private static final int arraySize = 500;
  22:      //虚拟机代码指针,取值范围[0,arraySize-1]
  23:      public int arrayPtr = 0;
  24:      //存放虚拟机代码的数组
  25:      public Pcode[] pcodeArray;
  26:      //显示虚拟代码与否
  27:      public static boolean listswitch = true;
  28:   
  29:      public Interpreter() {
  30:          pcodeArray = new Pcode[arraySize];
  31:      }
  32:   
  33:      /**
  34:       * 生成虚拟机代码
  35:       *
  36:       * @param x Pcodeuction.f
  37:       * @param y Pcodeuction.l
  38:       * @param z Pcodeuction.a
  39:       */
  40:      public void gen(int f, int l, int a) {
  41:          if (arrayPtr >= arraySize) {                                                                          //超出堆栈的上限
  42:              throw new Error("***ERROR:Program too long***");
  43:          }
  44:          pcodeArray[arrayPtr++] = new Pcode(f, l, a);
  45:   
  46:      }
  47:   
  48:      /**
  49:       * 输出目标代码清单
  50:       *
  51:       * @param start 开始输出的位置
  52:       */
  53:      public void listcode(int start) {
  54:          if (listswitch) {                                                                         //是否显示P-code代码
  55:              for (int i = start; i < arrayPtr; i++) {
  56:                  try {
  57:                      String msg = i + "  " + Pcode.pcode[pcodeArray[i].f] + "  " + pcodeArray[i].l + " " + pcodeArray[i].a;                //形如: lit l,a
  58:                      System.out.println(msg);
  59:                      PL0.pcodeWriter.write(i + "  " + msg + '\n');
  60:                  } catch (Exception e) {
  61:                      e.printStackTrace();
  62:                      System.out.println("***list pcode meet with error***");
  63:                  }
  64:   
  65:              }
  66:          }
  67:      }
  68:   
  69:      /**
  70:       * 这个过程模拟了一台可以运行类PCODE指令的栈式计算机。 它拥有一个栈式数据段用于存放运行期数据, 拥有一个代码段用于存放类PCODE程序代码。
  71:       * 同时还拥用数据段分配指针、指令指针、指令寄存器、局部段基址指针等寄存器。
  72:       *
  73:       * @param stdin 从键盘输入无符号整数
  74:       * @param stdout 显示pcode运行过程
  75:       */
  76:      public void interpret(BufferedReader stdin, BufferedWriter stdout) {
  77:          int[] runtimeStack = new int[stackSize];                  // 程序运行栈
  78:          Arrays.fill(runtimeStack, 0);                                   //初始化
  79:          System.out.println("***Start Interpret P_CODE***");
  80:   
  81:          int pc = 0, // pc:指令指针,
  82:                  bp = 0, //bp:指令基址,
  83:                  sp = 0;                                                                //sp:栈顶指针
  84:   
  85:          do {
  86:   
  87:              Pcode index = pcodeArray[pc++];// index :存放当前指令, 读当前指令
  88:              System.out.println(pc + "  " + Pcode.pcode[index.f] + " " + index.l + " " + index.a);
  89:              switch (index.f) {
  90:                  case Pcode.LIT:                                                   // 将a的值取到栈顶
  91:                      runtimeStack[sp++] = index.a;
  92:                      break;
  93:                  case Pcode.OPR:                                                   // 数学、逻辑运算
  94:                      switch (index.a) {
  95:                          case 0:                                                          //OPR 0 0;RETURN 返回
  96:                              sp = bp;
  97:                              pc = runtimeStack[sp + 2];
  98:                              bp = runtimeStack[sp + 1];
  99:                              break;
 100:                          case 1:                                                           //OPR 0 1 ;NEG取反
 101:                              runtimeStack[sp - 1] = -runtimeStack[sp - 1];
 102:                              break;
 103:                          case 2:                                                           //OPR 0 2;ADD加法
 104:                              sp--;
 105:                              runtimeStack[sp - 1] += runtimeStack[sp];
 106:                              break;
 107:                          case 3:                                                             //OPR 0 3;SUB减法
 108:                              sp--;
 109:                              runtimeStack[sp - 1] -= runtimeStack[sp];
 110:                              break;
 111:                          case 4:                                                             //OPR 0 4;MUL乘法
 112:                              sp--;
 113:                              runtimeStack[sp - 1] =runtimeStack[sp - 1] * runtimeStack[sp];
 114:                              break;
 115:                          case 5:                                                             //OPR 0 5;DIV除法
 116:                              sp--;
 117:                              runtimeStack[sp - 1] /= runtimeStack[sp];
 118:                              break;
 119:                          case 6:                                                              //OPR 0 6;ODD对2取模mod 2
 120:                              runtimeStack[sp - 1] %= 2;
 121:                              break;
 122:                          case 7:                                                              //OPR 0 7;MOD取模
 123:                              sp--;
 124:                              runtimeStack[sp - 1] %= runtimeStack[sp];
 125:                              break;
 126:                          case 8:                                                             //OPR 0 8;==判断相等
 127:                              sp--;
 128:                              runtimeStack[sp - 1] = (runtimeStack[sp] == runtimeStack[sp - 1] ? 1 : 0);
 129:                              break;
 130:                          case 9:                                                                //OPR 0 9;!=判断不相等
 131:                              sp--;
 132:                              runtimeStack[sp - 1] = (runtimeStack[sp] != runtimeStack[sp - 1] ? 1 : 0);
 133:                              break;
 134:                          case 10:                                                               //OPR 0 10;<判断小于
 135:                              sp--;
 136:                              runtimeStack[sp - 1] = (runtimeStack[sp] < runtimeStack[sp - 1] ? 1 : 0);
 137:                              break;
 138:                          case 11:                                                                //OPR 0 11;>=判断大于等于
 139:                              sp--;
 140:                              runtimeStack[sp - 1] = (runtimeStack[sp] >= runtimeStack[sp - 1] ? 1 : 0);
 141:                              break;
 142:                          case 12:                                                                //OPG 0 12;>判断大于
 143:                              sp--;
 144:                              runtimeStack[sp - 1] = (runtimeStack[sp] > runtimeStack[sp - 1] ? 1 : 0);
 145:                              break;
 146:                          case 13:                                                                 //OPG 0 13;<=判断小于等于
 147:                              sp--;
 148:                              runtimeStack[sp - 1] = (runtimeStack[sp] <= runtimeStack[sp - 1] ? 1 : 0);
 149:                              break;
 150:                          case 14:                                                                 //OPG 0 14;输出栈顶值
 151:                              System.out.println("runtimeStack[sp - 1]" + runtimeStack[sp - 1] + ' ');
 152:                              try {
 153:                                  stdout.write(" " + runtimeStack[sp - 1] + ' ');
 154:                                  stdout.flush();
 155:                              } catch (Exception ex) {
 156:                                  System.out.println("***case 14 meet with error***");
 157:                              }
 158:                              sp--;
 159:                              break;
 160:                          case 15:                                                                 //OPG 0 15;输出换行
 161:                              System.out.print("\n");
 162:                              try {
 163:                                  stdout.write("\n");
 164:                              } catch (Exception ex) {
 165:                                  System.out.println("***case 15 meet with error***");
 166:                              }
 167:                              break;
 168:                          case 16:                                                                 //OPG 0 16;读入一行输入,置入栈顶
 169:                              System.out.print("Please Input a Integer : ");
 170:                              runtimeStack[sp] = 0;
 171:                              try {
 172:                                  runtimeStack[sp] = Integer.parseInt(stdin.readLine().trim());       //读入一个整型数字
 173:                                  System.out.println(runtimeStack[sp]);
 174:                                  sp++;
 175:                              } catch (Exception e) {
 176:                                  e.printStackTrace();
 177:                                  System.out.println("***read data meet with error***");
 178:                              }
 179:                              try {
 180:                                  stdout.write(" " + runtimeStack[sp] + '\n');
 181:                                  stdout.flush();
 182:                              } catch (Exception ex) {
 183:                                  System.out.println("***case 16 meet with error***");
 184:                              }
 185:                              break;
 186:                      }
 187:                      break;
 188:                  case Pcode.LOD:                                          //取相对当前过程的数据基地址为a的内存的值到栈顶
 189:                      runtimeStack[sp] = runtimeStack[base(index.l, runtimeStack, bp) + index.a];
 190:                      sp++;
 191:                      break;
 192:                  case Pcode.STO:                                         //栈顶的值存到相对当前的过程的数据基地址为a的内存
 193:                      sp--;
 194:                      runtimeStack[base(index.l, runtimeStack, bp) + index.a] = runtimeStack[sp];
 195:                      break;
 196:                  case Pcode.CAL:                                                                 //调用子程序
 197:                      runtimeStack[sp] = base(index.l, runtimeStack, bp);            //将静态作用域基地址入栈
 198:                      runtimeStack[sp + 1] = bp;                                                //将动态作用域基地址
 199:                      runtimeStack[sp + 2] = pc;                                               //将当前指针入栈
 200:                      bp = sp;                                                                        //改变基地址指针值为新过程的基地址
 201:                      pc = index.a;                                                                 //跳转至地址a
 202:                      break;
 203:                  case Pcode.INT:                                                               //开辟空间大小为a
 204:                      sp += index.a;
 205:                      break;
 206:                  case Pcode.JMP:                                                               //直接跳转至a
 207:                      pc = index.a;
 208:                      break;
 209:                  case Pcode.JPC:
 210:                      sp--;
 211:                      if (runtimeStack[sp] == 0) //条件跳转至a(当栈顶指针为0时)
 212:                      {
 213:                          pc = index.a;
 214:                      }
 215:                      break;
 216:              }
 217:          } while (pc != 0);
 218:      }
 219:   
 220:      /**
 221:       * 通过给定的层次差来获得该层的堆栈帧基址
 222:       *
 223:       * @param l 目标层次与当前层次的层次差
 224:       * @param runtimeStack 运行栈
 225:       * @param b 当前层堆栈帧基地址
 226:       * @return 目标层次的堆栈帧基地址
 227:       */
 228:      private int base(int l, int[] runtimeStack, int b) {
 229:          while (l > 0) {                                                       //向上找l层
 230:              b = runtimeStack[b];
 231:              l--;
 232:          }
 233:          return b;
 234:      }
 235:   
 236:      public void debugPcodeArray() throws IOException {
 237:          System.out.println("***Auto-Generated Pcode Array***");
 238:          String msg = null;
 239:          for (int i = 0; pcodeArray[i] != null; i++) {
 240:              msg = "" + i + "  " + Pcode.pcode[pcodeArray[i].f] + "  " + pcodeArray[i].l + "  " + pcodeArray[i].a;
 241:              System.out.println(msg);
 242:              PL0.pcodeWriter.write(msg + '\n');
 243:          }
 244:      }
 245:  }

.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }

PL/0编译器(java version) - Interpreter.java的更多相关文章

  1. PL/0编译器(java version) - MainFrame.java

    1: /* 2: * To change this license header, choose License Headers in Project Properties. 3: * To chan ...

  2. PL/0编译器实践---后记

    花了几天时间,把清华版的<编译原理>一书中的PL/0编译器实践了一遍.颇有收获,记录如下: 理解代码的技巧,如何理解一份代码,比如这个程序,其逻辑相对于一般程序就比较复杂了,如何翻译,虚拟 ...

  3. PL/0编译器(java version)–Praser.java

    1: package compiler; 2:   3: import java.io.IOException; 4: import java.util.BitSet; 5:   6: /** 7: ...

  4. PL/0编译器(java version)–PL0.java

    1: package compiler; 2:   3: import java.io.BufferedWriter; 4: import java.io.FileWriter; 5:   6: /* ...

  5. PL/0编译器(java version) – SymbolTable.java

    1: package compiler; 2: //竟然没有对符号表检查大小,会溢出的. 3:   4: import java.io.IOException; 5:   6: public clas ...

  6. PL/0编译器(java version) – Scanner.java

    1: package compiler; 2:   3: import java.io.BufferedReader; 4: import java.io.FileNotFoundException; ...

  7. PL/0编译器(java version) - Err.java

    1: package compiler; 2:   3: import java.io.BufferedWriter; 4:   5: public class Err { 6:   7: publi ...

  8. PL/0编译器(java version) – Symbol.java

    1: package compiler; 2:   3: /** 4: * 采用全局变量sym来存储符号码,并用全局变量id和num来传递语义值 5: * 6: * @author jiangnan ...

  9. PL/0编译器(java version)–Pcode.java

    1: package compiler; 2:   3: /** 4: * //虚拟机指令 5: * 6: * @author jiangnan 7: * 8: */ 9: public class ...

随机推荐

  1. ralitive absolute

    3.relative与absolute的主要区别: 首先,是上面已经提到过的在正常流中的位置存在与否. 其次,relative定位的层总是相对于其最近的父元素,无论其父元素是何种定位方式.如图3: 图 ...

  2. [解决方案]在Sql Server 2008/2005 数据库还原出现 3154错误

    在Sql Server 2008/2005 数据库还原出现 3154错误 解决方法1:不要在数据库名字上点右键选择还原,而要是在根目录“数据库”三个字上点右键选择还原,然后再选择数据库,问题便可以解决 ...

  3. 【转】【C#】在 Windows 窗体 DataGridView 单元格中承载控件

    using System; using System.Windows.Forms; public class CalendarColumn : DataGridViewColumn { public ...

  4. openresty 前端开发进阶一之http后端

    做前端开发,大多数情况下,都需要跟后端打交道,而最常见的方式则是通过http请求,进行通信. 在openresty中,通过http跟后端整合通信的方式又很多种,各有各的好处,可以根据情况交叉使用 1. ...

  5. [转]php 解决json_encode中文UNICODE转码问题

    FROM : http://blog.csdn.net/bjash/article/details/9834497 用PHP的json_encode来处理中文的时候, 中文都会被编码, 变成不可读的, ...

  6. 加密算法使用(四):AES的使用

    AES是一种对称加密方式,比DES更为安全,用一个秘钥加密数据之后,可以用同一个秘钥对加密后的数据解密还原,以下是一套以字符串为例子的使用全过程演示, 用到了 commons-codec.jar pa ...

  7. 网站如何启用SSL安全证书?IIS7启用新建Https:/

    网站使用SSL,通过SSL证书申请,然后导入之后.我们需要对网站进行设置才能正常使用SSL证书,具体如何操作让网站启用SSL呢,本经验以一个网站添加SSL主机头的方式为例来,网站启用SSL服务器安全证 ...

  8. Linux10.11-10.18)学习笔记(

    1Y86指令集体系结构 ISA:指令集体系结构,一个处理器支持的指令和指令的字节级编码 程序员可见的状态 Y86程序中的每条指令都会读取或修改处理器状态的某些部分,称为程序员可见状态.其中包括: 8个 ...

  9. jenkins publish over ssh使用

    1.在需要远程的ubuntu服务器上生成密钥,指令:ssh-keygen   一路默认下去,会在~/.ssh目录下生成 id_rsa(私钥).id_rsa.pub(公钥) 2.复制公钥文件id_rsa ...

  10. Scala学习笔记(六):Scala程序

    想要编写能够独立运行的Scala程序,就必须创建有main方法(仅带一个参数Array[String],且结果类型为Unit)的单例对象. 任何拥有合适签名的main方法的单例对象都可以用来作为程序的 ...