POCOコンパイラ(笑)2
こんなものよりも早くアセンブラを作って、起きやすく修正に時間のかかる機械語への変換ミスを防ぐべきだと思う。こんなやっつけコンパイラじゃ定数との加算にイミディエイト命令でなくレジスタに即値ロード→レジスタ同士の加算とかやってアホ。
改善点
- javaccを使うことにより、自動でレキサが使えるようになったような感じ。変にスペースでトークンを区切らなくていい。負の定数と減算記号でこんがらがるので#-1のような記述法にした。無駄に1行コメントに対応。というか前回もscanf(" ");で[空白文字]*を読み飛ばしてgetchar()すれば良かった気もする。
- javaccを使うことにより、再帰下降法でめんどい1+2+3+4みたいなのもある程度簡単に記述。
input
// test [0] + [1] & [2] + #-5
output
LDUI r0, #0 LD r1, (r0) LDUI r0, #1 LD r2, (r0) ADD r1, r2 LDUI r0, #2 LD r2, (r0) AND r1, r2 LDI r2, #-5 ADD r1, r2
options { STATIC = false; } PARSER_BEGIN(Pococ) package pococ; public class Pococ { private boolean[] regTable = new boolean[] { true, false, false, false, false, false, false, false }; private int allocRegister() { for (int i=0; i<regTable.length; i++) { if (!regTable[i]) { regTable[i] = true; return i; } } throw new Error("Register full."); } private void releaseRegister(int reg) { assert !regTable[reg]; regTable[reg] = false; } public static void main(String[] args) throws Exception { Pococ p = new Pococ(System.in); p.expr(); } } PARSER_END(Pococ) SKIP: { " " | "\t" | "\r" | "\n" } SPECIAL_TOKEN: { < #COMMENT: "//" (~["\r", "\n"])* ("\r" | "\n" | "\r\n") > } TOKEN: { < S_NUMBER: "#" ("-")? (["0"-"9"])+ > | < U_NUMBER: (["0"-"9"])+ > | < LPAREN: "(" > | < RPAREN: ")" > | < LBRACKET: "[" > | < RBRACKET: "]" > | < ADDOP: "+" > | < SUBOP: "-" > | < ANDOP: "&" > | < OROP: "|" > } int expr(): {int result;} { result = op() {return result;} } int op(): {int lreg, rreg;} { lreg = term() ( <ADDOP> rreg = term() { System.out.printf("ADD r%d, r%d%n", lreg, rreg); releaseRegister(rreg); } | <SUBOP> rreg = term() { System.out.printf("SUB r%d, r%d%n", lreg, rreg); releaseRegister(rreg); } | <ANDOP> rreg = term() { System.out.printf("AND r%d, r%d%n", lreg, rreg); releaseRegister(rreg); } | <OROP> rreg = term() { System.out.printf("OR r%d, r%d%n", lreg, rreg); releaseRegister(rreg); } )* { return lreg; } } int term(): {Token numToken; int reg;} { numToken = <S_NUMBER> { reg = allocRegister(); int num = Integer.parseInt(numToken.image.substring(1)); System.out.printf("LDI r%d, #%d%n", reg, num); return reg; } | <LBRACKET> numToken = <U_NUMBER> <RBRACKET> { reg = allocRegister(); int addr = Integer.parseInt(numToken.image); System.out.printf("LDUI r0, #%d%n", addr); System.out.printf("LD r%d, (r0)%n", reg); return reg; } | <LPAREN> reg = expr() <RPAREN> { return reg; } }