📄 parser.java
字号:
break;
case plus:
nextSym();
startid = PL0.lex.num;
break;
case minus:
nextSym();
startid = -PL0.lex.num;
break;
}
table.get(table.tx).adr = table.get(table.tx).adr -
startid;
nextSym();
nextSym();
switch (sym) {
case ident:
endid = table.get(table.position(lex.id)).
val;
table.get(table.tx).size = endid - startid +
1;
break;
case number:
endid = PL0.lex.num;
table.get(table.tx).size = endid - startid +
1;
break;
case plus:
nextSym();
endid = PL0.lex.num;
table.get(table.tx).size = endid - startid +
1;
break;
case minus:
nextSym();
endid = -PL0.lex.num;
table.get(table.tx).size = endid - startid +
1;
break;
}
dx = dx + endid - startid; //dx在判断为var时已经++运算过
nextSym();
nextSym();
}
}
else {
String ss1 = err.report(4); // var 后应是标识
ss = ss + ss1 + "\n";
}
}
/**
* 分析<语句>
* @param fsys 后跟符号集
* @param lev 当前层次
*/
void parseStatement(SymSet fsys, int lev) {
SymSet nxtlev;
// Wirth 的 PL/0 编译器使用一系列的if...else...来处理
// 但是你的助教认为下面的写法能够更加清楚地看出这个函数的处理逻辑
switch (sym) {
case ident:
parseAssignStatement(fsys, lev);
break;
case readsym:
parseReadStatement(fsys, lev);
break;
case writesym:
parseWriteStatement(fsys, lev);
break;
case callsym:
parseCallStatement(fsys, lev);
break;
case ifsym:
parseIfStatement(fsys, lev);
break;
case beginsym:
parseBeginStatement(fsys, lev);
break;
case whilesym:
parseWhileStatement(fsys, lev);
break;
default:
nxtlev = new SymSet(symnum);
test(fsys, nxtlev, 19);
break;
}
}
/**
* 分析<当型循环语句>
* @param fsys 后跟符号集
* @param lev 当前层次
*/
private void parseWhileStatement(SymSet fsys, int lev) {
int cx1, cx2;
SymSet nxtlev;
cx1 = interp.cx; // 保存判断条件操作的位置
nextSym();
nxtlev = (SymSet) fsys.clone();
nxtlev.set(Symbol.dosym); // 后跟符号为do
parseCondition(nxtlev, lev); // 分析<条件>
cx2 = interp.cx; // 保存循环体的结束的下一个位置
interp.gen(Fct.JPC, 0, 0); // 生成条件跳转,但跳出循环的地址未知
if (sym == Symbol.dosym) {
nextSym();
}
else {
String ss1 = err.report(18); // 缺少do
ss = ss + ss1 + "\n";
}
parseStatement(fsys, lev); // 分析<语句>
interp.gen(Fct.JMP, 0, cx1); // 回头重新判断条件
interp.code[cx2].a = interp.cx; // 反填跳出循环的地址,与<条件语句>类似
}
/**
* 分析<复合语句>
* @param fsys 后跟符号集
* @param lev 当前层次
*/
private void parseBeginStatement(SymSet fsys, int lev) {
SymSet nxtlev;
nextSym();
nxtlev = (SymSet) fsys.clone();
nxtlev.set(Symbol.semicolon);
nxtlev.set(Symbol.endsym);
parseStatement(nxtlev, lev);
// 循环分析{; <语句>},直到下一个符号不是语句开始符号或收到end
while (statbegsys.get(sym) || sym == Symbol.semicolon) {
if (sym == Symbol.semicolon) {
nextSym();
}
else {
String ss1 = err.report(10); // 缺少分号
ss = ss + ss1 + "\n";
}
parseStatement(nxtlev, lev);
}
if (sym == Symbol.endsym) {
nextSym();
}
else {
String ss1 = err.report(17); // 缺少end或分号
ss = ss + ss1 + "\n";
}
}
/**
* 分析<条件语句>
* @param fsys 后跟符号集
* @param lev 当前层次
*/
private void parseIfStatement(SymSet fsys, int lev) {
int cx1;
SymSet nxtlev;
nextSym();
nxtlev = (SymSet) fsys.clone();
nxtlev.set(Symbol.thensym); // 后跟符号为then或do ???
nxtlev.set(Symbol.dosym);
parseCondition(nxtlev, lev); // 分析<条件>
if (sym == Symbol.thensym) {
nextSym();
}
else {
String ss1 = err.report(16); // 缺少then
ss = ss + ss1 + "\n";
}
cx1 = interp.cx; // 保存当前指令地址
interp.gen(Fct.JPC, 0, 0); // 生成条件跳转指令,跳转地址未知,暂时写0
parseStatement(fsys, lev); // 处理then后的语句
interp.code[cx1].a = interp.cx; // 经statement处理后,cx为then后语句执行
// 完的位置,它正是前面未定的跳转地址
if (sym == Symbol.elsesym) {
interp.code[cx1].a++;
nextSym();
int cx2;
cx2 = interp.cx;
interp.gen(Fct.JMP, 0, 0);
parseStatement(fsys, lev);
interp.code[cx2].a = interp.cx;
}
}
/**
* 分析<过程调用语句>
* @param fsys 后跟符号集
* @param lev 当前层次
*/
private void parseCallStatement(SymSet fsys, int lev) {
int i;
nextSym();
if (sym == Symbol.ident) {
i = table.position(lex.id);
if (i == 0) {
String ss1 = err.report(11); // 过程未找到
ss = ss + ss1 + "\n";
}
else {
Table.Item item = table.get(i);
if (item.kind == Objekt.procedure) {
interp.gen(Fct.CAL, lev - item.level, item.adr);
}
else {
String ss1 = err.report(15); // call后标识符应为过程
ss = ss + ss1 + "\n";
}
}
nextSym();
}
else {
String ss1 = err.report(14); // call后应为标识符
ss = ss + ss1 + "\n";
}
}
/**
* 分析<写语句>
* @param fsys 后跟符号集
* @param lev 当前层次
*/
private void parseWriteStatement(SymSet fsys, int lev) {
SymSet nxtlev;
nextSym();
if (sym == Symbol.lparen) {
do {
nextSym();
nxtlev = (SymSet) fsys.clone();
nxtlev.set(Symbol.rparen);
nxtlev.set(Symbol.comma);
parseExpression(nxtlev, lev);
interp.gen(Fct.OPR, 0, 14);
}
while (sym == Symbol.comma);
if (sym == Symbol.rparen) {
nextSym();
}
else {
String ss1 = err.report(33); // write()中应为完整表达式
ss = ss + ss1 + "\n";
}
}
interp.gen(Fct.OPR, 0, 15);
}
/**
* 分析<读语句>
* @param fsys 后跟符号集
* @param lev 当前层次
*/
private void parseReadStatement(SymSet fsys, int lev) {
int i;
nextSym();
if (sym == Symbol.lparen) {
do {
nextSym();
if (sym == Symbol.ident) {
i = table.position(lex.id);
}
else {
i = 0;
}
if (i == 0) {
String ss1 = err.report(35); // read()中应是声明过的变量名
ss = ss + ss1 + "\n";
}
else {
Table.Item item = table.get(i);
if (item.kind != Objekt.variable) {
String ss1 = err.report(32); // read()中的标识符不是变量, thanks to amd
ss = ss + ss1 + "\n";
}
else {
nextSym();
if (sym != Symbol.lparen) { //非数组,即变量
interp.gen(Fct.OPR, 0, 16);
interp.gen(Fct.STO, lev - item.level,
item.adr);
}
else { //TODO 数组
nextSym();
SymSet nxtlev = (SymSet) fsys.clone();
nxtlev.set(Symbol.rparen);
parseExpression(nxtlev, lev);
int ltmp = lev - item.level;
int adrtmp = item.adr;
interp.gen(Fct.OPR, 0, 16);
interp.gen(Fct.STA, ltmp, adrtmp);
nextSym(); //右)
//nextSym();//读下个
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -