?? interpreter.java
字號(hào):
import java.io.*;
/**
* 這個(gè)類對(duì)應(yīng)C語言版本中的 fct 枚舉類型和 instruction 結(jié)構(gòu),代表虛擬機(jī)指令
*/
class Instr {
// fct枚舉類型的常數(shù)
public static final int lit = 0;
public static final int opr = 1;
public static final int lod = 2;
public static final int sto = 3;
public static final int cal = 4;
public static final int inte= 5;
public static final int jmp = 6;
public static final int jpc = 7;
// 各符號(hào)的名字
public static final String[] mnemonic = new String[]{
"lit", "opr", "lod", "sto",
"cal", "int", "jmp", "jpc"};
/**
* 虛擬機(jī)代碼指令
*/
public int f;
/**
* 引用層與聲明層的層次差
*/
public int l;
/**
* 指令參數(shù)
*/
public int a;
}
/**
* 類P-Code代碼解釋器(含代碼生成函數(shù)),這個(gè)類包含了C語言版中兩個(gè)重要的全局變量 cx 和 code
* @author 梁英毅
*
*/
public class Interpreter {
// 解釋執(zhí)行時(shí)使用的棧大小
final int stacksize = 500;
/**
* 虛擬機(jī)代碼指針,取值范圍[0, cxmax-1]
*/
public int cx = 0;
/**
* 存放虛擬機(jī)代碼的數(shù)組
*/
public Instr[] code = new Instr[PL0.cxmax];
/**
* 生成虛擬機(jī)代碼
* @param x instruction.f
* @param y instruction.l
* @param z instruction.a
*/
public void gen(int x, int y, int z) {
if (cx >= PL0.cxmax) {
throw new Error("Program too long");
}
code[cx] = new Instr();
code[cx].f = x;
code[cx].l = y;
code[cx].a = z;
cx ++;
}
/**
* 輸出目標(biāo)代碼清單
* @param start 開始輸出的位置
*/
public void listcode(int start) {
if (PL0.listswitch) {
for (int i=start; i<cx; i++) {
String msg = i + " " + Instr.mnemonic[code[i].f] + " " + code[i].l + " " + code[i].a;
System.out.println(msg);
PL0.fa.println(msg);
}
}
}
/**
* 解釋程序
*/
public void interpret() {
BufferedReader stdin = new BufferedReader(new InputStreamReader(System.in));
int p, b, t; // 指令指針,指令基址,棧頂指針
Instr i; // 存放當(dāng)前指令
int[] s = new int[stacksize]; // 棧
System.out.println("start pl0");
t = b = p = 0;
s[0] = s[1] = s[2] = 0;
do {
i = code[p]; // 讀當(dāng)前指令
p ++;
switch (i.f) {
case Instr.lit: // 將a的值取到棧頂
s[t] = i.a;
t++;
break;
case Instr.opr: // 數(shù)學(xué)、邏輯運(yùn)算
switch (i.a)
{
case 0:
t = b;
p = s[t+2];
b = s[t+1];
break;
case 1:
s[t-1] = -s[t-1];
break;
case 2:
t--;
s[t-1] = s[t-1]+s[t];
break;
case 3:
t--;
s[t-1] = s[t-1]-s[t];
break;
case 4:
t--;
s[t-1] = s[t-1]*s[t];
break;
case 5:
t--;
s[t-1] = s[t-1]/s[t];
break;
case 6:
s[t-1] = s[t-1]%2;
break;
case 8:
t--;
s[t-1] = (s[t-1] == s[t] ? 1 : 0);
break;
case 9:
t--;
s[t-1] = (s[t-1] != s[t] ? 1 : 0);
break;
case 10:
t--;
s[t-1] = (s[t-1] < s[t] ? 1 : 0);
break;
case 11:
t--;
s[t-1] = (s[t-1] >= s[t] ? 1 : 0);
break;
case 12:
t--;
s[t-1] = (s[t-1] > s[t] ? 1 : 0);
break;
case 13:
t--;
s[t-1] = (s[t-1] <= s[t] ? 1 : 0);
break;
case 14:
System.out.print(s[t-1]);
PL0.fa2.print(s[t-1]);
t--;
break;
case 15:
System.out.println();
PL0.fa2.println();
break;
case 16:
System.out.print("?");
PL0.fa2.print("?");
s[t] = 0;
try {
s[t] = Integer.parseInt(stdin.readLine());
} catch (Exception e) {}
PL0.fa2.println(s[t]);
t++;
break;
}
break;
case Instr.lod: // 取相對(duì)當(dāng)前過程的數(shù)據(jù)基地址為a的內(nèi)存的值到棧頂
s[t] = s[base(i.l,s,b)+i.a];
t++;
break;
case Instr.sto: // 棧頂?shù)闹荡娴较鄬?duì)當(dāng)前過程的數(shù)據(jù)基地址為a的內(nèi)存
t--;
s[base(i.l, s, b) + i.a] = s[t];
break;
case Instr.cal: // 調(diào)用子過程
s[t] = base(i.l, s, b); // 將靜態(tài)作用域基地址入棧
s[t+1] = b; // 將動(dòng)態(tài)作用域基地址入棧
s[t+2] = p; // 將當(dāng)前指令指針入棧
b = t; // 改變基地址指針值為新過程的基地址
p = i.a; // 跳轉(zhuǎn)
break;
case Instr.inte: // 分配內(nèi)存
t += i.a;
break;
case Instr.jmp: // 直接跳轉(zhuǎn)
p = i.a;
break;
case Instr.jpc: // 條件跳轉(zhuǎn)(當(dāng)棧頂為0的時(shí)候跳轉(zhuǎn))
t--;
if (s[t] == 0)
p = i.a;
break;
}
} while (p != 0);
}
/**
* 通過給定的層次差來獲得該層的堆棧幀基地址
* @param l 目標(biāo)層次與當(dāng)前層次的層次差
* @param s 運(yùn)行棧
* @param b 當(dāng)前層堆棧幀基地址
* @return 目標(biāo)層次的堆棧幀基地址
*/
private int base(int l, int[] s, int b) {
int b1 = b;
while (l > 0) {
b1 = s[b1];
l --;
}
return b1;
}
}
?? 快捷鍵說明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號(hào)
Ctrl + =
減小字號(hào)
Ctrl + -