📄 translator.java
字号:
package mycompiler.jieshiqi;
import java.io.*;
import java.awt.*;
import java.awt.event.*;
import java.util.*;
import java.applet.*;
/* 指令结构类型:操作码,操作数1,操作数2,操作数3 */
class Instruction
{
String iop;
int iarg1;
int iarg2;
int iarg3;
}
/*输入窗口*/
class Mywindow extends Frame
{
Button button1;
Label label1,label2;
TextField text1;
String stext;
Mywindow(String s)
{
super(s);
Panel panel1=new Panel(),panel2=new Panel(),panel3=new Panel();
button1=new Button("确定");
label1=new Label(s);
label2=new Label("TM simulation (enter h for help)...");
text1=new TextField(10);
panel1.add(label2);
panel2.add(label1);
panel2.add(text1);
panel3.add(new Label());
panel3.add(button1);
panel3.add(new Label());
setLayout(new GridLayout(3,1));
add(panel1);
add(panel2);
add(panel3);
setSize(60,70);
setVisible(false);
pack();
addWindowListener(new WindowAdapter()
{
public void windowClosing(WindowEvent e)
{setVisible(false); System.exit(0);}
});
}
}
/*显示窗口*/
class XWindow extends Frame
{
TextArea text;
XWindow(String name,String s)
{
super(name);
setLayout(new GridLayout(1,1));
text=new TextArea("",50,100);
text.setText(s);
add(text);
setSize(50,100);
setVisible(false);
pack();
addWindowListener(new WindowAdapter()
{
public void windowClosing(WindowEvent e)
{setVisible(false); System.exit(0);}
});
}
}
/*****************************************************/
/* 类 名 Translator */
/* 功 能 总程序的处理 */
/* 说 明 建立一个类,处理总程序 */
/*****************************************************/
public class Translator extends Applet implements ActionListener
{
/***************** 常量 *******************/
/* 为大型程序扩展,指令存储区大小,定义为1024 */
int IADDR_SIZE = 1024;
/* 为大型程序扩展,数据存储区大小,定义为1024 */
int DADDR_SIZE = 1024;
/* 寄存器数量,定义为8 */
int NO_REGS = 8;
/* PC寄存器,定义为7 */
int PC_REG = 7;
/* 目标代码行大小,定义为121 */
int LINESIZE = 121;
/* 字大小,定义为20 */
int WORDSIZE = 20;
/******** 变量 ********/
int iloc = 0; /* 指令存储计数指针,初始为0 */
int dloc = 0; /* 数据存储计数指针,初始为0 */
boolean traceflag = false; /* 指令执行追踪标志,初始为FALSE */
boolean icountflag = false; /* 指令执行计数标志,初始为FALSE */
/* iMem用于指令存储,为1024长的指令结构数组 */
Instruction iMem[]=new Instruction[IADDR_SIZE];
/* dMem用于数据存储,为1024长的整数类型数组 */
int dMem[]=new int[DADDR_SIZE];
/* reg用于寄存器存储,为8长的整数类型数组 */
int reg[]=new int[NO_REGS];
/* 指令操作码表,对应寻址模式分为三类,共20个字符串*/
String opCodeTab[ ] =
{"HALT","IN","OUT","ADD","SUB","MUL","DIV","????",
"LD","ST","????",
"LDA","LDC","JLT","JLE","JGT","JGE","JEQ","JNE","????"
};
int opRR=7; /*第一个"????"的位置,它的前面为寄存器寻址模式指令类型*/
int opRM=10; /*第二个"????"的位置,它的前面为寄存器-内存寻址模式指令类型*/
int opRA=19; /*第三个"????"的位置,它的前面为寄存器-立即数寻址模式指令类型*/
/** 单步执行结果状态表 **/
//String stepResultTab[] =
//{"OK","Halted","Instruction Memory Fault","Data Memory Fault","Division by 0"};
String pgm; /* 用于存储目标代码 */
char in_Line[]=new char[LINESIZE]; /* 用于存储一行代码 */
int lineLen; /* in_Line中代码的长度 */
int inCol; /* 用于指出在in_Line中的当前字符位置 */
int num; /* 用于存储当前所得数值 */
String word; /* 用于存储当前的字 */
char ch; /* 当前代码行中当前位置上的字符 */
String name; /* 显示窗口的名字 */
String expr="\n"; /* 显示窗口的内容 */
int in_s; /* 在函数actionPerformed与函数stepTM间传递一个int值 */
boolean do_com=true; /* 输入命令是否为q(退出) */
String stepResult; /* 结果状态 */
char cmd; /* 用户输入命令简称 */
int stepcnt=0; /* 执行命令数 */
Mywindow win1; /* 输入命令窗口 */
Mywindow win2; /* 输入值窗口 */
XWindow xwin; /* 显示窗口 */
public boolean Error1=false;
public boolean Error=false;
public String yerror;
public String serror;
public Translator(String s)
{
Target t = new Target(s);
if (t.Error1)
{
Error1=true;
serror=t.serror;
}
else if (t.Error)
{
Error=true;
yerror=t.yerror;
}
else
tmain(t.mbcode);
}
/********************************************/
/* 函数名 tmain */
/* 功 能 tm机主执行函数 */
/* 说 明 函数完成tm机的命令处理, */
/* 并解释执行目标指令 */
/********************************************/
void tmain(String codefile)
{
pgm = codefile;
/* 目标代码文件为空,输出错误信息 */
if (pgm == null)
{
xwin=new XWindow("ERROR","TargetCode file is null");
xwin.setVisible(true);
return;
}
/* 读入指令:将指令存储区iMem清空并从指定的文件中写入指令序列 */
if (!readInstructions())
return;
/* 交互执行,处理用户输入的TM命令,对已经输入到iMem中的指令进行操作 */
enterCom();
}
/********************************************************/
/* 函数名 readInstructions */
/* 功 能 指令文件读入函数 */
/* 说 明 将指令文件中的指令逐条读入到指令存储区iMem */
/********************************************************/
boolean readInstructions()
{
int op; /* 当前指令操作码在opCodeTab[]中的位置 */
int arg1=0,arg2=0,arg3=0; /* 当前指令操作数 */
int loc,regNo,lineNo;
/* 将8个寄存器内容初始化为0 */
for (regNo = 0;regNo < NO_REGS;regNo++)
reg[regNo] = 0;
/* dMem为数据存储区,0地址单元dMem[0]的值赋为数据存储区高端地址1023 *
* 此数值将在目标程序运行时由程序的先驱指令读入到mp寄存器中 */
dMem[0] = DADDR_SIZE - 1;
/* 将数据存储数区内除0地址单元外的各单元初始化为0 */
for (loc = 1;loc < DADDR_SIZE;loc++)
dMem[loc] = 0;
/* 将指令存储区中各单元初始化为指令;HALT 0,0,0 */
for (loc = 0 ; loc < IADDR_SIZE ; loc++)
{
iMem[loc]=new Instruction();
iMem[loc].iop = "HALT";
iMem[loc].iarg1 = 0;
iMem[loc].iarg2 = 0;
iMem[loc].iarg3 = 0;
}
lineNo = 0; /* lineNo用于记录当前代码指令行号 */
/*以\n为分隔符,将目标代码分成若干行*/
StringTokenizer LineCode=new StringTokenizer(pgm,"\n");
while (LineCode.hasMoreTokens())
{
String lineTok=LineCode.nextToken();
lineLen=lineTok.length();
in_Line=lineTok.toCharArray();
inCol = 0; /* 当前代码行in_Line中当前字符位置inCol初始为0 */
lineNo++; /* 当前代码行行号加1 */
/* 当前字符不是"*",即不是注释语句,应该是指令语句 */
if((nonBlank()) && (in_Line[inCol] != '*'))
{
/* 当前字符不是数字,报地址错,并给出行号lineNo */
if (!getNum())
return error("Bad location",lineNo,-1);
/* 将所得数值赋给当前代码地址标号loc */
loc = num;
/* 代码地址标号loc超出指令存储区地址IADDR_SIZE,报错 */
if (loc > IADDR_SIZE)
return error("Location too large",lineNo,loc);
/* 代码地址标号loc后面缺少冒号,报缺少冒号错 */
if (!skipCh(':'))
return error("Missing colon", lineNo,loc);
/* 当前位置不是单词,报缺少指令操作码错 */
if (!getWord())
return error("Missing opcode",lineNo,loc);
/* 初始查表op,op指向操作码表表首,值为0 */
op=0;
/* 查操作码表opCodeTab,比较当前字word中的字符
表中共有20个字符串 */
while ((op < opRA) && (!(word.equals(opCodeTab[op]))))
op = op+1;
/* 当前单词word中指定的操作码不在操作码表opCodeTab中,报非法操作码错误 */
if(!(word.equals(opCodeTab[op])))
return error("Illegal opcode",lineNo,loc);
/* 对查表得到的操作码值op的寻址模式,进行分类处理 */
String s_op=opClass(op);
if(s_op.equals("opclRR"))
{
/* 寄存器寻址模式操作码 */
/* 第一寄存器操作数错,非0-7之间数字, *
* 输出错误信息,行号lineNo,代码地址标号loc */
if ((!getNum()) || (num < 0) || (num >= NO_REGS))
return error("Bad first register",lineNo,loc);
/* 将第一操作数arg1赋值为当前数值num */
arg1 = num;
/* 第一操作数后漏掉","分隔符,报错 */
if (!skipCh(','))
return error("Missing comma",lineNo,loc);
/* 第二寄存器操作数错,非0-7之间数字, *
* 输出错误信息,行号lineNo,代码地址标号loc */
if ((!getNum()) || (num < 0) || (num >= NO_REGS))
return error("Bad second register",lineNo,loc);
/* 将第二个操作数arg2赋值为当前数值num */
arg2 = num;
/* 第二操作数后漏掉","分隔符,报错 */
if (!skipCh(','))
return error("Missing comma", lineNo,loc);
/* 第三寄存器操作数错,非0-7之间数字,报错 */
if ((!getNum()) || (num < 0) || (num >= NO_REGS))
return error("Bad third register",lineNo,loc);
/* 将第三操作数arg3赋值为当前数值num */
arg3 = num;
}
else if((s_op.equals("opclRM"))||(s_op.equals("opclRA")))
{
/* 寄存器-内存寻址模式 *
* 寄存器-立即数寻址模式 */
/* 第一寄存器操作数错,非0-7之间数字,报错 */
if ((!getNum()) || (num < 0) || (num >= NO_REGS))
return error("Bad first register",lineNo,loc);
/* 将第一操作数arg1赋值为当前数值num */
arg1 = num;
/* 第一操作数后漏掉","分隔符,报错 */
if (!skipCh(','))
return error("Missing comma",lineNo,loc);
/* 第二偏移地址操作数错误,非数字偏移地址,报错 */
if (!getNum())
return error("Bad displacement",lineNo,loc);
/* 将第二偏移地址操作数arg2赋值为当前地址num */
arg2 = num;
/* 第二偏移地址操作数后漏掉"("或者是","分隔符,报错 */
if ((!skipCh('(')) && (!skipCh(',')))
return error("Missing LParen or comma",lineNo,loc);
/* 第二寄存器操作数错,非0-7之间数字,报错 */
if ((!getNum()) || (num < 0) || (num >= NO_REGS))
return error("Bad second register",lineNo,loc);
/* 将第三操作数arg3赋值为当前数值num */
arg3 = num;
}
/* 按代码地址标号loc将指令存储到指令存储区iMem */
iMem[loc].iop = opCodeTab[op];
iMem[loc].iarg1 = arg1;
iMem[loc].iarg2 = arg2;
iMem[loc].iarg3 = arg3;
}
}
return true;
}
/****************************************************/
/* 函数名 opClass */
/* 功 能 指令寻址模式分类函数 */
/* 说 明 该函数对给定的指令操作码枚举值c进行分类 */
/* 返回指令所属寻址模式 */
/****************************************************/
String opClass(int c)
{
/* 如果枚举值c小于opRRLim(7),则指令为寄存器寻址模式指令类型 */
if(c <= opRR)
return "opclRR";
/* 如果枚举值c小于opRMLim(10),则指令为寄存器-内存寻址模式指令类型 */
else if(c <= opRM)
return "opclRM";
/* 为寄存器-立即数寻址模式指令类型 */
else
return "opclRA";
}
/****************************************************/
/* 函数名 opNum */
/* 功 能 指令寻址模式分类函数 */
/* 说 明 该函数对给定的指令操作码枚举值c进行分类 */
/* 返回指令所属寻址模式 */
/****************************************************/
int opNum(String s)
{
if((s.equals("HALT"))||(s.equals("IN"))||(s.equals("OUT"))||(s.equals("ADD"))||(s.equals("SUB"))||(s.equals("MUL"))||(s.equals("DIV")))
return 7;
else if((s.equals("LD"))||(s.equals("ST")))
return 10;
else
return 19;
}
/********************************************************/
/* 函数名 nonBlank */
/* 功 能 非空字符获取函数 */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -