詞法分析
詞法分析又稱詞法分析器或者掃描器,是編譯程序的基本子程序之一。本項目采用手工方式設計并實現詞法分析程序。
詞法分析的功能
掃描源程序,按語言的詞法規則識別出各類單詞符號(Token),并將有關字符組合成為單詞并輸出,同時進行詞法檢查。語言的保留字,標識符,常數和運算符等都是單詞的例子。
Token分類
將PL/0編譯系統中所有的字符,字符串的類型按如下表格分類:
類型 | 字符or字符串 |
---|---|
保留字 | begin, end, if,then, else, const, procedure,var,do,while, call,read, write, repeat, until |
算數運算符 | + ,—,*,/ |
比較運算符 | <> , < ,<= , >, >= ,= |
賦值符 | := , = |
標識符 | 變量名,過程名,常數名 |
常數 | 10,25等整數 |
界符 | ‘,’,‘.’,‘;’,‘(’,‘)’ |
其他符號 | :,EOF |
Token結構
在具體實現時,由于出錯處理及語法分析的需求,定義如下Token結構:
public class Token {
private SymType st; //token的類別
private int line; //token所在行,錯誤處理使用
private String value; //token的值,只有標識符和常量有值
}
Token分析程序的構造
首先,給出狀態圖:
狀態圖
根據狀態圖,可以寫出分析程序analysis()
private Token analysis() {
strToken = "";
getChar();
while ((ch == ' ' || ch == '\n' || ch == '\t' || ch == '\0') && searchPtr < buffer.length) {
if (ch == '\n') {
line++;
}
getChar();
}
if (ch == '$' && searchPtr >= buffer.length) { //到達文件末尾
return new Token(SymType.EOF, line, "-1");
}
if (isLetter()) { //首位為字母,可能為保留字或者變量名
while (isLetter() || isDigit()) {
strToken += ch;
getChar();
}
retract();
for (int i = 0; i < keyWords.length; i++) {
if (strToken.equals(keyWords[i])) { //說明是保留字
return new Token(SymType.values()[i], line, "-");
}
}
//不是保留字,則為標識符,需要保存值
return new Token(SymType.SYM, line, strToken);
} else if (isDigit()) { //首位為數字,即為整數
while (isDigit()) {
strToken += ch;
getChar();
}
retract();
return new Token(SymType.CONST, line, strToken);
} else if (ch == '=') { //等號
return new Token(SymType.EQU, line, "-");
} else if (ch == '+') { //加號
return new Token(SymType.ADD, line, "-");
} else if (ch == '-') { //減號
return new Token(SymType.SUB, line, "-");
} else if (ch == '*') { //乘號
return new Token(SymType.MUL, line, "-");
} else if (ch == '/') { //除號
return new Token(SymType.DIV, line, "-");
} else if (ch == '<') { //小于或不等于或小于等于
getChar();
if (ch == '=') {
return new Token(SymType.LESE, line, "-");
} else if (ch == '>') {
return new Token(SymType.NEQE, line, "-");
} else {
retract();
return new Token(SymType.LES, line, "-");
}
} else if (ch == '>') { //大于或大于等于
getChar();
if (ch == '=') {
return new Token(SymType.LARE, line, "-");
} else {
retract();
return new Token(SymType.LAR, line, "-");
}
} else if (ch == ',') { //逗號
return new Token(SymType.COMMA, line, "-");
} else if (ch == ';') { //分號
return new Token(SymType.SEMIC, line, "-");
} else if (ch == '.') { //點
return new Token(SymType.POI, line, "-");
} else if (ch == '(') { //左括號
return new Token(SymType.LBR, line, "-");
} else if (ch == ')') { //右括號
return new Token(SymType.RBR, line, "-");
} else if (ch == ':') { //賦值號
getChar();
if (ch == '=') {
return new Token(SymType.CEQU, line, "-");
} else {
retract();
return new Token(SymType.COL, line, "-");
}
}
return new Token(SymType.EOF, line, "-");
}
analysis()每次分析出一個Token。對代碼進行一遍遍歷,即可得到源程序的token數組。