options{ IGNORE_CASE=true; JJTREE_OUTPUT_DIRECTORY="wci/frontend"; NODE_EXTENDS="ICodeNode"; MULTI=true; VISITOR=true; } PARSER_BEGIN(PclParser) package wci.frontend; import java.util.ArrayList; import java.io.*; import wci.intermediate.*; import wci.intermediate.symtabimpl.*; import wci.backend.*; import wci.util.*; import static wci.intermediate.symtabimpl.SymTabKeyImpl.*; import static wci.intermediate.symtabimpl.DefinitionImpl.*; import static wci.intermediate.symtabimpl.RoutineCodeImpl.*; import static wci.intermediate.symtabimpl.SymTabKeyImpl.*; import static wci.intermediate.icodeimpl.ICodeKeyImpl.*; public class PclParser { private static final String SOURCE_SUFFIX = ".pcl"; private static final String OUTPUT_SUFFIX = ".j"; private static SymTabStack symTabStack; private static SymTabEntry programId; public static void main(String[] args) throws Exception { // Create and initialize the symbol table stack. symTabStack = SymTabFactory.createSymTabStack(); Predefined.initialize(symTabStack); // Process the source file path which ends in .pcl // and create the output file path which ends in .j String sourceFilePath = args[0]; int truncatedLength = sourceFilePath.length() - SOURCE_SUFFIX.length(); int suffixIndex = sourceFilePath.lastIndexOf(SOURCE_SUFFIX); String objectFilePath = (suffixIndex == truncatedLength) ? sourceFilePath.substring(0, truncatedLength) + OUTPUT_SUFFIX : sourceFilePath + OUTPUT_SUFFIX; // Parse a Pcl program. Reader reader = new FileReader(sourceFilePath); PclParser parser = new PclParser(reader); SimpleNode rootNode = parser.program(); // Print the cross-reference table. CrossReferencer crossReferencer = new CrossReferencer(); crossReferencer.print(symTabStack); // Visit the parse tree nodes to decorate them with type information. TypeSetterVisitor typeVisitor = new TypeSetterVisitor(); rootNode.jjtAccept(typeVisitor, null); // Create and initialize the ICode wrapper for the parse tree. ICode iCode = ICodeFactory.createICode(); iCode.setRoot(rootNode); programId.setAttribute(ROUTINE_ICODE, iCode); // Print the parse tree. ParseTreePrinter treePrinter = new ParseTreePrinter(System.out); treePrinter.print(symTabStack); // Create the compiler backend and generate code. Backend backend = BackendFactory.createBackend("compile"); backend.process(iCode, symTabStack, objectFilePath); } } PARSER_END(PclParser) SKIP: { " " | "\r" | "\t" | "\n" | } TOKEN: { /* Reserved words */ | | | } TOKEN: /* Special symbols */ { | | | | | } TOKEN: { /* Identifiers, strings, and numbers */ (|)*> | (~["'"] | "''")*> | > | | | > | <#LETTER : ["a"-"z", "A"-"Z"]> | <#DIGIT : ["0"-"9"]> | <#SIGN : ["+", "-"]> | <#UNSIGNED_NUMBER : ()+> | <#WHOLE : > | <#FRACTION : "." > | <#EXPONENT : "E"()?> } TOKEN: { /* Error token */ } SimpleNode program() #void : {SimpleNode rootNode;} { try { programHeader() rootNode = block() { return rootNode; } } catch (ParseException ex) { handleError(ex); return null; } } void programHeader() #void : {} { { programId = symTabStack.enterLocal(token.image); programId.setDefinition(DefinitionImpl.PROGRAM); programId.setAttribute(ROUTINE_SYMTAB, symTabStack.push()); symTabStack.setProgramId(programId); } } SimpleNode block() #void : {SimpleNode rootNode;} { variableDeclarations() rootNode = compoundStatement() { return rootNode; } } void variableDeclarations() #void : {ArrayList variableList; int index = 0;} { ( { variableList = new ArrayList(); processVariableDecl(token, index++, variableList); } ( { processVariableDecl(token, index++, variableList); } )* { SymTabEntry typeId = symTabStack.lookup(token.image); typeId.appendLineNumber(token.beginLine); TypeSpec type = typeId.getTypeSpec(); for (SymTabEntry variableId : variableList) { variableId.setTypeSpec(type); } } )+ } SimpleNode compoundStatement() : {} { [ statement() ( statement() )* ] { return jjtThis; } } void statement() : {} { assignmentStatement() } void assignmentStatement() : {} { variable() { SymTabEntry variableId = symTabStack.lookup(token.image); variableId.appendLineNumber(token.beginLine); } expression() } void expression() #void : {} { LOOKAHEAD(2) addition() | factor() } void addition() : {} { factor() "+" expression() } void factor() #void : {} { variable() | integerConstant() | realConstant() } void variable() : {} { { SymTabEntry variableId = symTabStack.lookup(token.image); variableId.appendLineNumber(token.beginLine); TypeSpec type = variableId.getTypeSpec(); jjtThis.setTypeSpec(type); jjtThis.setAttribute(ID, variableId); } } void integerConstant() : {} { { jjtThis.setTypeSpec(Predefined.integerType); jjtThis.setAttribute(VALUE, Integer.parseInt(token.image)); } } void realConstant() : {} { { jjtThis.setTypeSpec(Predefined.realType); jjtThis.setAttribute(VALUE, Float.parseFloat(token.image)); } } void Error() #void : {} { } JAVACODE void processVariableDecl(Token token, int index, ArrayList variableList) #void { SymTabEntry variableId = symTabStack.enterLocal(token.image); variableId.setIndex(index); variableId.setDefinition(DefinitionImpl.VARIABLE); variableId.appendLineNumber(token.beginLine); variableList.add(variableId); } JAVACODE String handleError(ParseException ex) #void { Token token = ex.currentToken; System.out.println(ex.getMessage()); do { token = getNextToken(); } while (token.kind != SEMICOLON); return token.image; }