刚刚学习编译原理,这是第二章的代码的改写,源码
http://www.blogjava.net/Files/zhaochengming/compiler%20section%202%20parse.rar
1.KeyWord.java 关键字对象类
package parse;
public class KeyWord {
private String lexptr;
private int token;
public KeyWord(String lexptr, int token) {
this.lexptr = lexptr;
this.token = token;
}
public String getLexptr() {
return lexptr;
}
public void setLexptr(String lexptr) {
this.lexptr = lexptr;
}
public int getToken() {
return token;
}
public void setToken(int token) {
this.token = token;
}
}
2.SymTable.java 符号表对象类
package parse;
import java.util.ArrayList;
import java.util.List;
/** *//**
* 符号表
* @author Administrator
*
*/
public class SymTable {
private static List<KeyWord> SYMTABLE = new ArrayList<KeyWord>();
// 符号表最大容量
private static final int SYMMAX = 999;
// 字符串最大长度
public static final int STRMAX = 100;
private static final KeyWord KEYWORDS[] = {
new KeyWord(null,0),
new KeyWord("DIV", Token.DIV),
new KeyWord("ADD", Token.ADD),
new KeyWord("SUB", Token.SUB),
new KeyWord("MOD", Token.MOD),
new KeyWord("MUL", Token.MUL),
};
// 初始化symtable
static {
for(KeyWord keyword : KEYWORDS) {
insert(keyword.getLexptr(), keyword.getToken());
}
}
/** *//**
* 在符号表中插入新的符号
* @param lexptr
* @param token
* @return
*/
public static int insert(String lexptr, int token) {
int lexptrlen = 0;
if(lexptr != null) lexptrlen = lexptr.length();
if(SYMTABLE.size() >= SYMMAX) {
throw new IllegalStateException("符号表满。");
}
if(lexptrlen >= STRMAX) {
throw new IllegalStateException("lexptr超过最大长度。");
}
SYMTABLE.add(new KeyWord(lexptr, token));
return SYMTABLE.size() - 1;
}
/** *//**
* 返回lexptr在符号表中的下标
* @param lexptr
* @return
*/
public static int lookup(String lexptr) {
for (int i = 1; i < SYMTABLE.size(); i++) {
if(SYMTABLE.get(i).getLexptr().equals(lexptr)) {
return i;
}
}
return 0;
}
public static KeyWord getKeyWord(int index) {
return SYMTABLE.get(index);
}
}
3.Lex.java 词法分析对象类
package parse;
public class Lex {
private int last = -1;
private int pos = 0; // 当前位置
private ParseReader pr;
private String buf;
private int tokenVal;
private Parser parser;
public Lex(ParseReader pr, Parser parse) {
this.pr = pr;
this.parser = parse;
}
public int lexan() {
int t;
while (true) {
t = getChar();
if(t == ' ' || t == '\r');
else if(isDigit(t)) {
tokenVal = 0;
while(isDigit(t)) {
tokenVal = tokenVal* 10 + (t - '0');
t = getChar();
}
ungetc(t);
return Token.NUM;
} else if (isAlpha(t)) {
int p = -1, b = 0;
StringBuilder sb = new StringBuilder();
while (isDigit(t) || isAlpha(t)) {
sb.append((char)t);
t = getChar();
b++;
}
if(b >= SymTable.STRMAX) {
parser.error("词法分析错误");
}
if(t != Token.EOF) {
ungetc(t);
}
p = SymTable.lookup(sb.toString());
if(p == 0) {
p = SymTable.insert(sb.toString(), Token.ID);
}
tokenVal = p;
return SymTable.getKeyWord(tokenVal).getToken();
} else if (t == Token.EOF) {
return Token.DONE;
} else {
tokenVal = Token.NULL;
return t;
}
}
}
public int getTokenVal() {
return tokenVal;
}
public int getChar() {
if(last < 0) {
if(buf != null && pos < buf.length()) {
return buf.charAt(pos++);
} else {
if(pr.isEof()) {
return Token.EOF;
} else {
buf = pr.readLine();
pos = 0;
return getChar();
}
}
} else {
int c = last;
last = -1;
return c;
}
}
public void ungetc(int c) {
last = c;
}
public boolean isDigit(int t) {
return t >= '0' && t <= '9';
}
public boolean isAlpha (int t) {
return ((t >= 'A' && t <= 'Z') || (t >= 'a' && t <= 'z'));
}
public int getLineNo() {
return pr.getLineNo();
}
public int getPos() {
return pos;
}
}
4.Parser.java 语法分析对象类
package parse;
import java.io.FileNotFoundException;
public class Parser {
private StringBuilder temp = new StringBuilder();
private Lex lex;
int lookahead;
public Parser(ParseReader pr) {
lex = new Lex(pr,this);
}
public void parse() {
lookahead = lex.lexan();
while (lookahead != Token.DONE) {
expr(); match(';');
}
out("后缀表达式为: "+temp.toString());
}
private void expr() {
int t;
term();
while(true) {
switch(lookahead) {
case '+':
case '-':
case Token.ADD:
case Token.SUB:
t = lookahead;
match(lookahead); term(); emit(t, Token.NULL);
continue;
default:
return;
}
}
}
private void term() {
int t;
factor();
while(true){
switch(lookahead) {
case '*':
case '/':
case '%':
case Token.MOD:
case Token.DIV:
case Token.MUL:
t = lookahead;
match(lookahead); factor(); emit(t, Token.NULL);
continue;
default:
return;
}
}
}
private void factor() {
switch(lookahead) {
case '(':
match('('); expr(); match(')'); break;
case Token.NUM:
emit(Token.NUM, lex.getTokenVal()); match(Token.NUM); break;
case Token.ID:
emit(Token.ID, lex.getTokenVal()); match(Token.ID); break;
default:
error("语法分析错误");
}
}
private void match(int t) {
if(lookahead == t) {
lookahead = lex.lexan();
} else error("语法错误");
}
public void emit(int t, int token) {
switch(t) {
case '+':
case '-':
case '*':
case '%':
case '/':
temp.append(" ").append((char)t).append(" ");
out(String.valueOf((char)t));break;
case Token.DIV:
temp.append(" DIV ");
out("DIV");break;
case Token.MOD:
temp.append(" MOD ");
out("MOD");break;
case Token.MUL:
temp.append(" MUL ");
out("MUL");break;
case Token.ADD:
temp.append(" ADD ");
out("ADD");break;
case Token.SUB:
temp.append(" SUB ");
out(" SUB ");break;
case Token.ID:
temp.append(SymTable.getKeyWord(token).getLexptr());
out(SymTable.getKeyWord(token).getLexptr());
break;
default:
temp.append(" ").append(token).append(" ");
out("token " + Token.name(t) + ", tokenval "+token);
}
}
public void out(String msg) {
System.out.println(msg);
}
public static void main(String args[]) {
Parser pr;
try {
pr = new Parser(new ParseReaderRAF("c:/a.txt"));
pr.parse();
} catch (FileNotFoundException e) {
e.printStackTrace();
}
}
public void error(String msg) {
System.err.println("ERROR:[" + msg + "] LineNumber : " + lex.getLineNo() +", position :" + lex.getPos());
System.exit(0);
}
}
5.ParseReader 词法分析读字符流接口
package parse;
public interface ParseReader {
public String readLine();
public boolean isEof();
public int getLineNo();
}
6.ParseReaderRAF 词法分析读字符流RandomAccessFile对象
package parse;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.RandomAccessFile;
public class ParseReaderRAF implements ParseReader{
private RandomAccessFile raf;
private int lineno = 0;
private String buf;
public ParseReaderRAF(String filepath) throws FileNotFoundException {
this.raf = new RandomAccessFile(new File(filepath), "r");
}
public int getLineNo() {
return lineno;
}
public boolean isEof() {
try {
if(raf.getFilePointer() >= raf.length())
return true;
} catch (IOException e) {
e.printStackTrace();
}
return false;
}
public String readLine() {
try {
buf = raf.readLine();
//System.out.println(buf);
lineno++;
} catch (Exception e) {
e.printStackTrace();
}
return buf;
}
}
</script>