?? 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 + -