package mycc; import java_cup.runtime.*; import java.lang.*; import java.util.*; import java.io.*; parser code {: // one symbol table for global scope // each function has its own symbol table // each block statement has its own symbol table public static symTab globalSymTab; // global symbol table public static symTab currSymTab; // current symbol table public static boolean optFlag; // optimization flag /********* use later in code generation ******** public static astNodeList code; // list of proc ASTs public static ClassFile class_file; ***********************************************/ // keep track of current type specification public static int curType; // store current var type // output error message with current line number public static void msg(String s) { System.out.println("ERROR("+(Yylex.pos()+1)+") "+s); } public static void main(String args[]) throws Exception { globalSymTab = new symTab(); // init global symbol table currSymTab = globalSymTab; // global symtab is current // get name of input file String fname = null; String oFlag = null; if (args.length == 1) { fname = args[0]; optFlag = false; // optimization off } else if (args.length == 2) { fname = args[1]; oFlag = args[0]; optFlag = true; // optimization on } if ((fname == null) || !fname.endsWith(".c") || ((args.length == 2) && !oFlag.equals("-O"))) { System.out.println("usage: java mycc.parser [-O] .c"); System.exit(-1); } String cname = fname.substring(0, fname.length()-2); FileReader fp = new FileReader(fname); addPrintFunctions(); new parser(new Yylex(fp)).parse(); // parse input /********* use later in code generation ******** code.print(); // print AST ClassFile class_file = new ClassFile(cname); // prepare codegen ClassFile.generate_code(code, globalSymTab); // generate code ***********************************************/ } // add print functions in the global symbol table private static void addPrintFunctions() { symTabEntry param; symTabEntry func1; /* printStr(string) */ param = new symTabEntry("DUMMY", sym.STRING_LITERAL); func1 = new symTabEntry("printStr", sym.VOID); func1.setFunc(); func1.setParam(param); globalSymTab.addSym(func1); /* printInt (int) */ param = new symTabEntry("DUMMY", sym.INT); func1 = new symTabEntry("printInt", sym.VOID); func1.setFunc(); func1.setParam(param); globalSymTab.addSym(func1); /* printLn () */ func1 = new symTabEntry("printLn", sym.VOID); func1.setFunc(); globalSymTab.addSym(func1); } :} terminal EQ_OP, NE_OP, AND_OP, OR_OP, NOT_OP; terminal INT, VOID, BOOL, IF, ELSE, WHILE, RETURN; terminal PLUS, MINUS, DIV, MUL, LPAREN, RPAREN, LBRACKET, RBRACKET; terminal LCURL, RCURL, SEMI, COMMA, LESS, GR, ASSIGN; terminal Integer CONSTANT; terminal String IDENTIFIER, STRING_LITERAL; non terminal translation_unit; non terminal stmt, stmtList, blockStmt; non terminal declaration, declarationList; non terminal funcDef, funcDefList, identList; non terminal expNode exp, boolExp, lhsVal, typeSpec, optArg, funcCall; non terminal symTabEntry ident, funcID, optParam; precedence left AND_OP, OR_OP, EQ_OP, NE_OP, GR, LESS, PLUS, MINUS, MUL, DIV, NOT_OP; start with translation_unit ; translation_unit ::= declarationList funcDefList {: :} ; declarationList ::= declarationList declaration | ; declaration ::= typeSpec identList SEMI ; typeSpec ::= INT {: RESULT = new expNode(sym.INT); parser.curType = sym.INT; :} ; identList ::= ident ; ident ::= IDENTIFIER:id {: symTabEntry s = new symTabEntry(id, parser.curType); parser.currSymTab.addSym(s); RESULT = s; :} ; funcDefList ::= funcDef ; funcDef ::= funcID:id LPAREN optParam:p RPAREN {: id.setParam(p); :} blockStmt ; funcID ::= typeSpec IDENTIFIER:id {: symTabEntry s = new symTabEntry(id, parser.curType); s.setFunc(); s.setSymTab(parser.globalSymTab); parser.globalSymTab.addSym(s); RESULT = s; :} ; optParam ::= {: RESULT = null; :} ; blockStmt ::= LCURL {: // set up new symbol table :} declarationList stmtList RCURL {: // return to old symbol table :} ; stmtList ::= stmtList stmt | ; stmt ::= lhsVal:e1 ASSIGN exp:e2 SEMI {: :} | IF LPAREN boolExp:e1 RPAREN blockStmt {: :} | funcCall SEMI {: :} | error RCURL {: parser.msg("illegal statement"); :} ; lhsVal ::= IDENTIFIER:id {: symTabEntry s; s = parser.currSymTab.getSym(id); if (s == null) { parser.msg("undefined variable "+id); RESULT = new expNode(sym.INT); } else { RESULT = new expNode(s.getType()); } :} ; funcCall ::= IDENTIFIER:e1 LPAREN optArg:e2 RPAREN {: symTabEntry s; s = parser.currSymTab.getSym(e1); RESULT = new expNode(s.getType()); :} ; optArg ::= {: RESULT = null; :} ; exp ::= CONSTANT:e1 {: RESULT = new expNode(sym.INT, e1); :} | STRING_LITERAL:e1 {: RESULT = new expNode(sym.STRING_LITERAL, e1); :} | exp:e1 PLUS exp:e2 {: RESULT = e1; :} | lhsVal:e1 {: RESULT = e1; :} | funcCall:e1 {: RESULT = e1; :} ; boolExp ::= exp:e1 {: RESULT = e1; :} ;