options { STATIC=false; } PARSER_BEGIN(PL0Parser) package pl0front; import java.io.FileReader; import java.util.Iterator; import coins.HirRoot; import coins.IoRoot; import coins.SymRoot; import coins.ir.IrList; import coins.ir.hir.BlockStmt; import coins.ir.hir.Exp; import coins.ir.hir.HIR0; import coins.ir.hir.Program; import coins.ir.hir.Stmt; import coins.ir.hir.SubpDefinition; import coins.ir.hir.FunctionExp; import coins.sym.Const; import coins.sym.IntConst; import coins.sym.NamedConst; import coins.sym.Subp; import coins.sym.Sym0; import coins.sym.SymTable; import coins.sym.Type; import coins.sym.Var; import coins.sym.Param; public class PL0Parser { private SymRoot symRoot; // root of symbol information private Sym0 sym; // Sym object creator private HirRoot hirRoot; // root of HIR information private HIR0 hir; // HIR object creator private IoRoot ioRoot; // root of I/O information private Subp printfSym = null; // symbol of function printf private Const dStringConst = null; // Const of String "%d" private Const nStringConst = null; // Const of String "\n" private Type typeInt; private Type typePtrInt; private int nestLevel = 0; private static final int MAX_LEVEL = 5; private Subp[] funcSubps = new Subp[MAX_LEVEL]; private IrList allSubps; private IrList outerFuncCalls; private IrList funcCalls; public PL0Parser(SymRoot sRoot, HirRoot hRoot, IoRoot iRoot, FileReader reader) { this(reader); symRoot = sRoot; sym = (Sym0)symRoot.sym; hirRoot = hRoot; hir = (HIR0)hirRoot.hir; ioRoot = iRoot; typeInt = symRoot.typeInt; typePtrInt = sym.pointerType(typeInt); allSubps = hir.irList(); outerFuncCalls = hir.irList(); funcCalls = hir.irList(); hirRoot.programRoot = hir.program(null, symRoot.symTableRoot, null, null); // make program root node printfSym = sym.defineSubp("printf".intern(), typeInt); //int printf() printfSym.addParamType(sym.pointerType(symRoot.typeChar)); printfSym.setOptionalParam(); printfSym.setVisibility(Sym0.SYM_EXTERN); printfSym.closeSubpPrototype(); dStringConst = sym.stringConst("%d".intern()); // Const "%d" nStringConst = sym.stringConst("\n".intern()); // Const "\n" } class SubpInf { SymTable symTable; int level; IrList originalParamTypeList; IrList addedVars; IrList addedParams; IrList recursivelyCalled; SubpInf(int defLevel, SymTable sTable){ symTable = sTable; level = defLevel; addedVars = hir.irList(); addedParams = hir.irList(); recursivelyCalled = hir.irList(); } void setOrgParamTypeList(IrList tList){ originalParamTypeList =hir.irList(); for (Iterator it = tList.iterator(); it.hasNext(); ) originalParamTypeList.add(it.next()); } IrList getOrgParamTypeList(){ return originalParamTypeList; } Param addedParam(Var v){ Iterator itP = addedParams.iterator(); for (Iterator it = addedVars.iterator(); it.hasNext(); ){ Var nextVar = (Var)it.next(); Param param = (Param)itP.next(); if (nextVar == v) return param; } addedVars.add(v); Subp funcSubp = symTable.getSubp(); Param p = symTable.generateParam(typePtrInt, funcSubp); funcSubp.getParamList().add(p); funcSubp.getParamTypeList().add(typePtrInt); addedParams.add(p); // System.out.println("added to func:"+funcSubp+" var:"+v+" as "+p); return p; } void addRecursivelyCalled(FuncCall fCall){ recursivelyCalled.add(fCall); } void addRecursiveToOuterFuncCalls(){ for ( Iterator it = recursivelyCalled.iterator(); it.hasNext(); ){ outerFuncCalls.add(0, it.next()); } } } class FuncCall{ FunctionExp callExp; Subp withinSubp; Subp calledSubp; IrList subpChain; FuncCall(FunctionExp e, Subp w, Subp c){ callExp = e; withinSubp = w; calledSubp = c; subpChain = null; // System.out.println("new FuncCall within "+w+" to "+c+", HIR "+e); int withinLevel = ((SubpInf)withinSubp.getWork()).level; int calledLevel = ((SubpInf)calledSubp.getWork()).level; if (calledLevel <= withinLevel ){ subpChain = hir.irList(); for (int i = calledLevel+1; i <= withinLevel; i++){ subpChain.add(funcSubps[i]); } //outerFuncCalls.add(this); ((SubpInf)calledSubp.getWork()).addRecursivelyCalled(this); } else funcCalls.add(this); } } void printIrList(IrList list, String s){ // for debug System.out.println("printIrList:"+s); for (Iterator it = list.iterator(); it.hasNext(); ){ System.out.println(it.next()); } } } PARSER_END(PL0Parser) SKIP : { } TOKEN : { | | | | | | | | | | | | } TOKEN : { ( | )*> | )+> | <#LETTER: ["a"-"z","A"-"Z"]> | <#DIGIT: ["0"-"9"]> } void program() : { Subp mainSubp; BlockStmt mainBlock; } { { mainSubp = sym.defineSubp("main".intern(), typeInt); mainSubp.setVisibility(Sym0.SYM_PUBLIC); SymTable lSymTable = symRoot.symTableCurrent.pushSymTable(mainSubp); mainSubp.closeSubpHeader(); funcSubps[nestLevel] = mainSubp; mainSubp.setWork(new SubpInf(nestLevel, lSymTable)); } mainBlock = block() "." { SubpDefinition mainSubpDef = hir.subpDefinition(mainSubp, symRoot.symTableCurrent); mainSubpDef.setHirBody(mainBlock); ((Program)hirRoot.programRoot).addSubpDefinition(mainSubpDef); adjustOuterFuncCalls(); adjustFuncCalls(); } } BlockStmt block() : { BlockStmt blockStmt = hir.blockStmt(null); Stmt stmt; } { (decl())* stmt = statement() { blockStmt.addLastStmt(stmt); return blockStmt; } } void decl() : { } { constDecl() { } | varDecl() { } | funcDecl() { } } void constDecl() : { } { constDef() ( "," constDef() )* ";" { } } void constDef() : { Token tId, tNum; } { tId = "=" tNum = { IntConst intConst = sym.intConst(Integer.parseInt(tNum.image), typeInt); NamedConst nc = sym.namedConst(tId.image.intern(), intConst); } } void varDecl() : { Token t; } { t = { sym.defineVar(t.image.intern(), typeInt); } ( "," t = { sym.defineVar(t.image.intern(), typeInt); } )* ";" { } } void funcDecl() : { Token t; Subp funcSubp; BlockStmt funcBlock; } { t = { nestLevel++; funcSubp = sym.defineSubp(t.image.intern(), typeInt); funcSubps[nestLevel] = funcSubp; allSubps.add(funcSubp); SymTable lSymTable = symRoot.symTableCurrent.pushSymTable(funcSubp); funcSubp.setWork(new SubpInf(nestLevel, lSymTable)); } "(" [ t = { funcSubp.addParam(sym.defineParam(t.image.intern(), typeInt)); } ( "," t = { funcSubp.addParam(sym.defineParam(t.image.intern(), typeInt)); } )* ] ")" { funcSubp.closeSubpHeader(); ((SubpInf)funcSubp.getWork()).setOrgParamTypeList(funcSubp.getParamTypeList()); } funcBlock = block() ";" { funcSubp.closeSubpHeader(); ((SubpInf)funcSubp.getWork()).addRecursiveToOuterFuncCalls(); SubpDefinition funcSubpDef = hir.subpDefinition(funcSubp, symRoot.symTableCurrent); funcSubpDef.setHirBody(funcBlock); ((Program)hirRoot.programRoot).addSubpDefinition(funcSubpDef); symRoot.symTableCurrent.popSymTable(); nestLevel--; // IrList paramList = funcSubp.getParamList(); // for debug // System.out.println("closed function:"+funcSubp); // for debug // for (Iterator it = paramList.iterator(); it.hasNext(); ){ // for debug // Param p = (Param)it.next(); // System.out.println("param:"+p); // } } } Stmt statement() : { Token t; Exp exp; BlockStmt innerBlock; Stmt stmt; IrList lParamList; Exp printfNode; } { [ t = ":=" exp = expression() { stmt = hir.assignStmt( makeExp(t.image), exp); stmt.setLineNumber(t.beginLine); return stmt; } | { innerBlock = hir.blockStmt(null); } stmt = statement() { innerBlock.addLastStmt(stmt); } (";" stmt = statement() { innerBlock.addLastStmt(stmt); } )* { return innerBlock; } | t = exp = condition() stmt = statement() { stmt = hir.ifStmt(exp, stmt, null); stmt.setLineNumber(t.beginLine); return stmt; } | t = exp = condition() stmt = statement() { stmt = hir.whileStmt(exp, stmt); stmt.setLineNumber(t.beginLine); return stmt; } | t = exp = expression() { stmt = hir.returnStmt(exp); stmt.setLineNumber(t.beginLine); return stmt; } | t = exp = expression() { lParamList = hir.irList(); lParamList.add(hir.decayExp(hir.constNode(dStringConst))); lParamList.add(exp); printfNode = hir.exp(HIR0.OP_ADDR, hir.subpNode(printfSym)); stmt = hir.callStmt(printfNode, lParamList); stmt.setLineNumber(t.beginLine); return stmt; } | t = { lParamList = hir.irList(); lParamList.add(hir.decayExp(hir.constNode(nStringConst))); printfNode = hir.exp(HIR0.OP_ADDR, hir.subpNode(printfSym)); stmt = hir.callStmt(printfNode, lParamList); stmt.setLineNumber(t.beginLine); return stmt; } ] { return null; } } Exp condition() : { Exp exp, exp1; int op; } { exp = expression() { exp1 = hir.exp(HIR0.OP_AND, exp, hir.constNode(symRoot.intConst1)); return hir.exp(HIR0.OP_CMP_EQ, exp1, hir.constNode(symRoot.intConst1)); } | exp = expression() ("=" { op = HIR0.OP_CMP_EQ; } | "<>" { op = HIR0.OP_CMP_NE; } | "<" { op = HIR0.OP_CMP_LT; } | "<=" { op = HIR0.OP_CMP_LE; } | ">" { op = HIR0.OP_CMP_GT; } | ">=" { op = HIR0.OP_CMP_GE; } ) exp1 = expression() { return hir.exp(op, exp, exp1); } } Exp expression() : { boolean prefixOp = false; int op; Exp exp, exp1; } { [("-" { prefixOp = true; } | "+")] exp = term() { if (prefixOp) exp = hir.exp(HIR0.OP_NEG, exp); } (("-" { op = HIR0.OP_SUB; } | "+" { op = HIR0.OP_ADD; } ) exp1 = term() { exp = hir.exp(op, exp, exp1); } )* { return exp; } } Exp term(): { Exp exp, exp1; int op; } { exp = factor() (("*" { op = HIR0.OP_MULT; } | "/" { op = HIR0.OP_DIV; } ) exp1 = factor() { exp = hir.exp(op, exp, exp1); } )* { return exp; } } Exp factor() : { Token t; Exp exp; IrList aParamList = hir.irList(); } { LOOKAHEAD(2) t = "(" [ exp = expression() { aParamList.add(exp); } ("," exp = expression() { aParamList.add(exp); } )*] ")" { Sym0 lSym = symRoot.symTableCurrent.search(t.image.intern(), Sym0.KIND_SUBP); if (lSym == null) { ioRoot.msgError.put("undefined function " + t.image); return hir.constNode(symRoot.intConst1); } else { Subp lSubp = (Subp)lSym; IrList fParamList = ((SubpInf)lSubp.getWork()).getOrgParamTypeList(); if ( fParamList.size() != aParamList.size()) ioRoot.msgError.put("unmatched parameters of " + t.image); FunctionExp e = hir.functionExp(hir.exp(HIR0.OP_ADDR, hir.subpNode(lSubp)), aParamList); new FuncCall(e, funcSubps[nestLevel], lSubp); return e; } } | t = { IntConst intConst = sym.intConst(Integer.parseInt(t.image), typeInt); return hir.constNode(intConst); } | t = { Sym0 lVar = symRoot.symTableConst.searchLocal (t.image.intern(), Sym0.KIND_NAMED_CONST); if ( lVar != null ) return hir.constNode(((NamedConst)lVar).getConstValue()); return makeExp(t.image); } | "(" exp = expression() ")" { return exp; } } JAVACODE Exp makeExp(String ident){ String id = ident.intern(); SymTable t = symRoot.symTableCurrent; Sym0 s = t.searchLocal(id, Sym0.KIND_VAR); if (s == null) s = t.searchLocal(id, Sym0.KIND_PARAM); Var v; if (s != null) return hir.varNode((Var)s); t=t.getParent(); for(int lev=nestLevel ; t!=null; t=t.getParent(), lev--) { s = t.searchLocal(id, Sym0.KIND_VAR); if (s == null) s = t.searchLocal(id, Sym0.KIND_PARAM); if(s!=null) { v = (Var)s; for ( ; lev <= nestLevel; lev++){ Subp funcSubp = funcSubps[lev]; v = ((SubpInf)funcSubp.getWork()).addedParam(v); } return hir.contentsExp(hir.varNode(v)); } } ioRoot.msgRecovered.put("undeclared " + id); v = sym.defineVar(id, typeInt); //dummy return hir.varNode(v); } JAVACODE void adjustOuterFuncCalls(){ for ( Iterator it = outerFuncCalls.iterator(); it.hasNext(); ){ FuncCall fCall = (FuncCall)it.next(); IrList actualParams = fCall.callExp.getParamList(); IrList addedParams = ((SubpInf)fCall.calledSubp.getWork()).addedParams; // System.out.println("called outer Subp:"+fCall.calledSubp); // for debug IrList subpChain = fCall.subpChain; for (Iterator itP = addedParams.iterator(); itP.hasNext(); ){ Param p = (Param)itP.next(); for (Iterator itS = subpChain.iterator(); itS.hasNext(); ){ p = ((SubpInf)((Subp)itS.next()).getWork()).addedParam(p); } actualParams.add(hir.varNode(p)); // System.out.println("added actual param = "+p); // for debug } for (Iterator itS = subpChain.iterator(); itS.hasNext(); ){ Subp funcSubp = (Subp)itS.next(); funcSubp.closeSubpHeader(); // IrList paramList = funcSubp.getParamList(); // for debug // System.out.println("closed function:"+funcSubp); // for debug // for (Iterator itP = paramList.iterator(); itP.hasNext(); ){ // for debug // Param p = (Param)itP.next(); // System.out.println("param:"+p); // } } fCall.callExp.replaceThisNode(hir.functionExp(hir.exp(HIR0.OP_ADDR, hir.subpNode(fCall.calledSubp)), actualParams)); } } JAVACODE void adjustFuncCalls(){ for ( Iterator it = funcCalls.iterator(); it.hasNext(); ){ FuncCall fCall = (FuncCall)it.next(); // System.out.println("within "+fCall.withinSubp+" call "+fCall.calledSubp); // System.out.println("called inner Subp:"+fCall.calledSubp); // for debug IrList actualParams = fCall.callExp.getParamList(); IrList addedVars = ((SubpInf)fCall.calledSubp.getWork()).addedVars; for (Iterator itV = addedVars.iterator(); itV.hasNext(); ){ Var v = (Var)itV.next(); if ( ((SubpInf)fCall.withinSubp.getWork()).addedParams.contains(v) ) actualParams.add(hir.varNode(v)); else actualParams.add(hir.exp(HIR0.OP_ADDR,hir.varNode(v))); // System.out.println("added actual param = "+v); // for debug } fCall.callExp.replaceThisNode(hir.functionExp(hir.exp(HIR0.OP_ADDR, hir.subpNode(fCall.calledSubp)), actualParams)); } }