public class Parser { private String code; private int count; private StringBuffer resultParsing; private char Look; private char[] ST = new char[26]; private final char SPACE = ' '; private final char CR = '\n'; /** * constructor */ public Parser(String s) { code = s; count = 0; resultParsing = new StringBuffer(); startParsing(); } public String getParseResult(){ return new String(resultParsing); } private void startParsing(){ count = 0; init(); parseProgram(); } private void createProgram(){ emitLn(".class public Program"); emitLn(".method public ()V"); emitLn(".limit stack 0"); emitLn(".limit locals 0"); emitLn("return"); emitLn(".end method"); } private void destroyProgram(){ emitLn("invokevirtual Main/destroyApp(Z)V"); } private void parseProgram(){ match('p'); createProgram(); beginMethod(); parseTopDecls(); match('{'); parseMain(); match('}'); destroyProgram(); endMethod(); } private void parseMain(){ match('m'); match('('); match(')'); match('{'); match('}'); } private void parseTopDecls(){ while(Look!='{'){ switch(Look){ case 'v': parseDecl(); break; default: throw new ParsingException("Unknown key: " + getName()); } } } private void parseDecl(){ match('v'); alloc(getName()); while(Look==','){ match(','); alloc(getName()); } } private boolean inTable(char c){ return (ST[c-'A']!=SPACE); } private void alloc(char c){ if(inTable(c)) throw new ParsingException("Duplicate variable name"); else{ ST[c-'A']='v'; addField(c+new String()); if(Look=='='){ match('='); if(Look=='-'){ match('-'); emitLn("ldc "+'-'+new Integer(getNum()).toString()); }else emitLn("ldc "+new Integer(getNum()).toString()); emitLn("putfield Program/"+c+" I"); } } } private void addMethod(String methodName){ emitLn(".method public " + methodName + "()V"); emitLn(".limit stack 100"); emitLn(".limit locals 2"); } private void clear(){ emitLn("iconst_0"); emitLn("istore_0"); emitLn("pop"); } private void negate(){ emitLn("iload_0"); emitLn("ineg"); emitLn("istore_0"); emitLn("pop"); } private void loadConst(int i){ emitLn("ldc "+new Integer(i).toString()); emitLn("istore_0"); } /* private void loadVar(char c){ if(!inTable(c)) throw new ParsingException("Undefined variable "+c); else{ emitLn("aload_1"); emitLn("getfieldProgram/"+c+" I"); emitLn("istore_0"); emitLn("pop"); } }*/ private void push(){ emitLn("iload_0"); } private void popAdd(){ emitLn("iload_0"); emitLn("iadd"); emitLn("istore_0"); } private void popSub(){ emitLn("iload_0"); emitLn("swap"); emitLn("istore_0"); } private void popMul(){ emitLn("iload_0"); emitLn("imul"); emitLn("istore_0"); } private void popDiv(){ emitLn("iload_0"); emitLn("swap"); emitLn("idiv"); emitLn("istore_0"); } /* private void store(char c){ if(!inTable(c)) throw new ParsingException("Undefined variable "+c); else{ emitLn("iload_0"); emitLn("putfield Program/"+c+" I"); } }*/ private void call(String methodName){ emitLn("invokevirtual Program/" + methodName + "()V"); } private void addField(String fieldName){ String s = new String('\t'+"class public Program"+'\n'); resultParsing.insert(s.length(), ("\n.field public " + fieldName + " = 0 I")); } private void beginMethod(){ emitLn(".method public run()V"); emitLn(".limit stack 50"); emitLn(".limit locals 1"); } private void endMethod(){ emitLn("return"); emitLn(".end method"); } private void getChar(){ try{ Look = code.charAt(count++); }catch(StringIndexOutOfBoundsException sioobe){ count = 0; } } private void expected(String s) throws ParsingException{ throw new ParsingException(s + " expected"); } private void match(char x){ if(Look!=x) expected(x+new String()); else{ getChar(); } } private boolean isAlpha(char c){ return (Character.isUpperCase(c)||Character.isLowerCase(c)); } private boolean isDigit(char c){ return Character.isDigit(c); } private boolean isAddop(char c){ return (c=='+'||c=='-'); } private boolean isAlNum(char c){ return (isAlpha(c)||isDigit(c)); } private char getName(){ if(!isAlpha(Look)){ expected("Name"); return '?'; }else{ char value = Character.toUpperCase(Look); getChar(); return value; } } private int getNum(){ int value = 0; if(!isDigit(Look)){ expected("Integer"); return '&'; }else{ while(isDigit(Look)){ value*=10; value+=Integer.parseInt(Look+new String()); getChar(); } return value; } } private void emitLn(String s){ resultParsing.append('\t' + s + '\n'); } private void init(){ for(char c = 'A'; c<'Z'; c++) ST[c-'A']=0; getChar(); } }