📄 yufaanalyse.java
字号:
while (word.getSym().equals("comma"))// 循环得到read语句的参数,直到该参数后不是逗号为止
{
word = CiFa.GetToken();
if (word.getSym().equals("ident")) {
i = position(word.getNam());
if (i == -1) {
errorNumber++;
new erro(word.getLineNum(), 11);
} else {
pcodeArray.addElement(new pcode("opr", 0, 16));
pcodeArray.addElement(new pcode("sto", lev
- ((nameClass) nameArray.get(i)).getLev(),
((nameClass) nameArray.get(i)).getAdr()));
}
}
word = CiFa.GetToken();
}
if (!word.getSym().equals("rparen")) {
errorNumber++;
new erro(word.getLineNum(), 9);
}// 如果不是预想的右括号,抛出9号错误
} else {
errorNumber++;
new erro(word.getLineNum(), 0);
}// 如果不是左括号,抛出0号错误
word = CiFa.GetToken();
} else if (word.getSym().equals("writesym")) {
word = CiFa.GetToken();
if (word.getSym().equals("lparen")) {
word = CiFa.GetToken();
expression();
pcodeArray.addElement(new pcode("opr", 0, 14));
while (word.getSym().equals("comma")) {
word = CiFa.GetToken();
expression();
pcodeArray.addElement(new pcode("opr", 0, 14));
}
if (!word.getSym().equals("rparen")) {
errorNumber++;
new erro(word.getLineNum(), 9);
} else {
word = CiFa.GetToken();
}
}
pcodeArray.addElement(new pcode("opr", 0, 15));
}
}
public void condition() // 条件分析;
{
String relop = null;
if (word.getSym().equals("oddsym")) // 如果是一元运算符
{
word = CiFa.GetToken();
expression();// 对一元运算的表达式进行分析
pcodeArray.addElement(new pcode("opr", 0, 6));// 生成奇偶判断指令
} else // 不是一元运算符则是2元运算符
{
expression();// 对左边的表达式进行分析
relop = word.getSym();// 把2元运算符保存起来
word = CiFa.GetToken();
expression();// 对右边的表达式进行分析 然后根据刚才保存的运算符,生成相应判断指令
if (relop.equals("eql")) {
pcodeArray.addElement(new pcode("opr", 0, 8));
} else if (relop.equals("neq")) {
pcodeArray.addElement(new pcode("opr", 0, 9));
} else if (relop.equals("lss")) {
pcodeArray.addElement(new pcode("opr", 0, 10));
} else if (relop.equals("geq")) {
pcodeArray.addElement(new pcode("opr", 0, 11));
} else if (relop.equals("gtr")) {
pcodeArray.addElement(new pcode("opr", 0, 12));
} else if (relop.equals("leg")) {
pcodeArray.addElement(new pcode("opr", 0, 13));
} else {
System.out.println(word.getNam() + " " + relop);
errorNumber++;
new erro(word.getLineNum(), 20);
}// 如果刚才保存的不是逻辑运算符,则抛出20号错误
}
}// 条件分析完毕
public void expression() // 表达式的处理
{
String addop = null; // 保存表达式开头的符号 用于表示正负
if (word.getSym().equals("plus") || word.getSym().equals("minus")) {
addop = word.getSym();// 把正负号保存在string类型的addop中,继续读取一个token,正常应该为表达式的一个项
word = CiFa.GetToken();
term();// 进行项的分析
if (addop.equals("minus")) // 如果保存下来的是个负号,则生成一条1号指令,取反运算
{
pcodeArray.addElement(new pcode("opr", 0, 1));
}
} else // 如果不是正负号开头,就应该是一个表达式的项开头,直接进行项的分析
{
term();
}
while (word.getSym().equals("plus") || word.getSym().equals("minus"))// 项后应该应该是加运算或者减法运算
{
addop = word.getSym();// 把运算符保存在addop中
word = CiFa.GetToken();
term();// 分析项
if (addop.equals("plus")) // 项分析完毕后,如果刚才保存的是加号,则生成加法指令
{
pcodeArray.addElement(new pcode("opr", 0, 2));
} else // 否则生成减法指令
{
pcodeArray.addElement(new pcode("opr", 0, 3));
}
}
}// 表达式分析完毕
public void term()// 项的处理
{
String mulop = null;
factor();// 每个项都是由一个因子开头,所以直接调用因子分析方法
while (word.getSym().equals("times") || word.getSym().equals("slash"))// 因子后应该遇到乘号或是除号
{
mulop = word.getSym(); // 把运算符保存在mulop中(乘法或是除法)
word = CiFa.GetToken();
factor();// 运算符后应该是一个因子,进行因子分析
if (mulop.equals("times")) // 如果刚才保存的运算符为乘号则生成opr 4号乘法指令,
{
pcodeArray.addElement(new pcode("opr", 0, 4));
} else // 如果刚才保存的不是乘号,则生成除法运算指令
{
pcodeArray.addElement(new pcode("opr", 0, 5));
}
}
}// 项分析完毕
public void factor() // 因子的分析处理;
{
int i;
while (word.getSym().equals("ident") || word.getSym().equals("number")
|| word.getSym().equals("lqaren"))// 循环处理因子
{
if (word.getSym().equals("ident"))// 如果遇到的是标识符,则查符号表
{
i = position(word.getNam());
if (i == -1) // 如果查符号表后返回负值,则表示没有找到,抛出11号错误
{
errorNumber++;
new erro(word.getLineNum(), 11);
}
// 如果返回的不是负值,则表示在符号表中的找到了该标识符,getKind返回该标识符的类型
else if (((nameClass) nameArray.get(i)).getKind().equals(
"constant"))
// 如果该标识符为常量,则生成lit指令,把val放到栈顶
{
pcodeArray.addElement(new pcode("lit", 0,
((nameClass) nameArray.get(i)).getVal()));
word = CiFa.GetToken();
} else if (((nameClass) nameArray.get(i)).getKind().equals(
"variable")) { // 如果该标识符为变量,则生成lod指令,把变量放到栈顶
pcodeArray.addElement(new pcode("lod", lev
- ((nameClass) nameArray.get(i)).getLev(),
((nameClass) nameArray.get(i)).getAdr()));
word = CiFa.GetToken();
} else if (((nameClass) nameArray.get(i)).getKind().equals(
"procedure")) {// 如果该标识符为过程名,出错,抛出21号错误
errorNumber++;
new erro(word.getLineNum(), 21);
word = CiFa.GetToken();
}
} else if (word.getSym().equals("number"))// 如果因子分析时遇到的为数字
{
int num = Integer.parseInt(word.getNam());
if (num > 2047)// 判断数字大小超过允许最大值amax
{
errorNumber++;
new erro(word.getLineNum(), 7);// 如果数字越界,则抛出7号错误,并把数字按0处理;
num = 0;
}
pcodeArray.addElement(new pcode("lit", 0, num));// 生成lit指令,把这个数值字面常量放到栈顶
word = CiFa.GetToken();
} else if (word.getSym().equals("lqaren"))// 如果因子分析遇到的为左括号
{
word = CiFa.GetToken();// 继续读取一个token
expression(); // 递归调用表达式分析
if (word.getSym().equals("rqaren"))// 表达式分析完后,应该遇到右括号
{
word = CiFa.GetToken();
} else {
errorNumber++;
new erro(word.getLineNum(), 22);
}// 如果表达式分析完后,没有遇到右括号,则抛出22号错误
}
}
} // 因子分析完毕
public void printName() // 这段代码没用,仅仅是用来查看符号表内容的
{
for (int t = 0; t < nameArray.size(); t++)// 测试用
{
nameClass name = (nameClass) nameArray.get(t);
System.out.println("符号表内容NAME " + name.getNam() + " KIND "
+ name.getKind() + " VAL " + name.getVal() + " LEVL "
+ name.getLev() + " ADR " + name.getAdr());
}
}
public int base(int l) // 用来寻找各段基址的方法
{
int b1;
b1 = b;
while (l > 0) {
b1 = s[b1];
l--;
}
return b1;
}
public void interpret() { //解释器,用于执行pcode代码
s[1] = 0;
s[2] = 0;
// s[3]=0;
System.out.println("start pl/0");
do {
i = (pcode) pcodeArray.get(p);
p++;
if (i.getF().equals("lit")) {
t++;
s[t] = i.getA();
} else if (i.getF().equals("opr")) {
if (i.getA() == 0) {
t = b - 1;
p = s[t + 3];
b = s[t + 2];
} else if (i.getA() == 1)// 返回指令
{
s[t] = -s[t];
} else if (i.getA() == 2)// 加法操作
{
t--;
s[t] = s[t] + s[t + 1];
} else if (i.getA() == 3)// 3号减法操作
{
t--;
s[t] = s[t] - s[t + 1];
} else if (i.getA() == 4)// 4号乘法操作
{
t--;
s[t] = s[t] * s[t + 1];
} else if (i.getA() == 5)// 5号除法操作
{
t--;
s[t] = s[t] / s[t + 1];
} else if (i.getA() == 6)// 6号判断奇数操作
{
if (s[t] % 2 == 0)
s[t] = 0;
else
s[t] = 1;
} else if (i.getA() == 8)// 8号判等操作
{
t--;
if (s[t] == s[t + 1])
s[t] = 1;
else
s[t] = 0;
} else if (i.getA() == 9)// 9号判断不等操作
{
t--;
if (s[t] == s[t + 1])
s[t] = 0;
else
s[t] = 1;
} else if (i.getA() == 10)// 10号判断小于操作
{
t--;
if (s[t] < s[t + 1])
s[t] = 1;
else
s[t] = 0;
} else if (i.getA() == 11)// 11号判断大于等于操作
{
t--;
if (s[t] >= s[t + 1])
s[t] = 1;
else
s[t] = 0;
} else if (i.getA() == 12)// 12号判断大于操作
{
t--;
if (s[t] > s[t + 1])
s[t] = 1;
else
s[t] = 0;
} else if (i.getA() == 13)// 13号判断小于等于操作
{
t--;
if (s[t] <= s[t + 1])
s[t] = 1;
else
s[t] = 0;
} else if (i.getA() == 14)// 14号输出栈顶值操作
{
System.out.println(s[t]);
t--;
} else if (i.getA() == 15)// 15号输出换行操作
{
System.out.println();
} else if (i.getA() == 16)// 16号接受键盘输入值到栈顶操作
{
System.out.println("请输入数字(0是退出):");
int age;
try {
InputStreamReader fin = new InputStreamReader(System.in);
BufferedReader br = new BufferedReader(fin);
String name = br.readLine();
age = Integer.parseInt(name);
} catch (Exception e) {
age = 0;
}
t++;
s[t] = age;
}
} else if (i.getF().equals("lod")) {
t++;
s[t] = s[base(i.getL()) + i.getA()];
} else if (i.getF().equals("sto")) {
s[base(i.getL()) + i.getA()] = s[t];
t--;
} else if (i.getF().equals("cal")) {
s[t + 1] = base(i.getL());
s[t + 2] = b;
s[t + 3] = p;
b = t + 1;
p = i.getA();
} else if (i.getF().equals("int")) {
t = t + i.getA();
} else if (i.getF().equals("jmp")) {
p = i.getA();
} else if (i.getF().equals("jpc")) {
if (s[t] == 0)
p = i.getA();
t--;
} else if (i.getF().equals("wrt")) {
System.out.println(s[t]);
t--;
}
} while (p != 0);
System.out.println("end pl/0");
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -