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: }