PL/0编译器(java version) - Interpreter.java
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的更多相关文章
- PL/0编译器(java version) - MainFrame.java
1: /* 2: * To change this license header, choose License Headers in Project Properties. 3: * To chan ...
- PL/0编译器实践---后记
花了几天时间,把清华版的<编译原理>一书中的PL/0编译器实践了一遍.颇有收获,记录如下: 理解代码的技巧,如何理解一份代码,比如这个程序,其逻辑相对于一般程序就比较复杂了,如何翻译,虚拟 ...
- PL/0编译器(java version)–Praser.java
1: package compiler; 2: 3: import java.io.IOException; 4: import java.util.BitSet; 5: 6: /** 7: ...
- PL/0编译器(java version)–PL0.java
1: package compiler; 2: 3: import java.io.BufferedWriter; 4: import java.io.FileWriter; 5: 6: /* ...
- PL/0编译器(java version) – SymbolTable.java
1: package compiler; 2: //竟然没有对符号表检查大小,会溢出的. 3: 4: import java.io.IOException; 5: 6: public clas ...
- PL/0编译器(java version) – Scanner.java
1: package compiler; 2: 3: import java.io.BufferedReader; 4: import java.io.FileNotFoundException; ...
- PL/0编译器(java version) - Err.java
1: package compiler; 2: 3: import java.io.BufferedWriter; 4: 5: public class Err { 6: 7: publi ...
- PL/0编译器(java version) – Symbol.java
1: package compiler; 2: 3: /** 4: * 采用全局变量sym来存储符号码,并用全局变量id和num来传递语义值 5: * 6: * @author jiangnan ...
- PL/0编译器(java version)–Pcode.java
1: package compiler; 2: 3: /** 4: * //虚拟机指令 5: * 6: * @author jiangnan 7: * 8: */ 9: public class ...
随机推荐
- ralitive absolute
3.relative与absolute的主要区别: 首先,是上面已经提到过的在正常流中的位置存在与否. 其次,relative定位的层总是相对于其最近的父元素,无论其父元素是何种定位方式.如图3: 图 ...
- [解决方案]在Sql Server 2008/2005 数据库还原出现 3154错误
在Sql Server 2008/2005 数据库还原出现 3154错误 解决方法1:不要在数据库名字上点右键选择还原,而要是在根目录“数据库”三个字上点右键选择还原,然后再选择数据库,问题便可以解决 ...
- 【转】【C#】在 Windows 窗体 DataGridView 单元格中承载控件
using System; using System.Windows.Forms; public class CalendarColumn : DataGridViewColumn { public ...
- openresty 前端开发进阶一之http后端
做前端开发,大多数情况下,都需要跟后端打交道,而最常见的方式则是通过http请求,进行通信. 在openresty中,通过http跟后端整合通信的方式又很多种,各有各的好处,可以根据情况交叉使用 1. ...
- [转]php 解决json_encode中文UNICODE转码问题
FROM : http://blog.csdn.net/bjash/article/details/9834497 用PHP的json_encode来处理中文的时候, 中文都会被编码, 变成不可读的, ...
- 加密算法使用(四):AES的使用
AES是一种对称加密方式,比DES更为安全,用一个秘钥加密数据之后,可以用同一个秘钥对加密后的数据解密还原,以下是一套以字符串为例子的使用全过程演示, 用到了 commons-codec.jar pa ...
- 网站如何启用SSL安全证书?IIS7启用新建Https:/
网站使用SSL,通过SSL证书申请,然后导入之后.我们需要对网站进行设置才能正常使用SSL证书,具体如何操作让网站启用SSL呢,本经验以一个网站添加SSL主机头的方式为例来,网站启用SSL服务器安全证 ...
- Linux10.11-10.18)学习笔记(
1Y86指令集体系结构 ISA:指令集体系结构,一个处理器支持的指令和指令的字节级编码 程序员可见的状态 Y86程序中的每条指令都会读取或修改处理器状态的某些部分,称为程序员可见状态.其中包括: 8个 ...
- jenkins publish over ssh使用
1.在需要远程的ubuntu服务器上生成密钥,指令:ssh-keygen 一路默认下去,会在~/.ssh目录下生成 id_rsa(私钥).id_rsa.pub(公钥) 2.复制公钥文件id_rsa ...
- Scala学习笔记(六):Scala程序
想要编写能够独立运行的Scala程序,就必须创建有main方法(仅带一个参数Array[String],且结果类型为Unit)的单例对象. 任何拥有合适签名的main方法的单例对象都可以用来作为程序的 ...