private PdeRecognizer createParser(final String program) { // create a lexer with the stream reader, and tell it to handle // hidden tokens (eg whitespace, comments) since we want to pass these // through so that the line numbers when the compiler reports errors // match those that will be highlighted in the PDE IDE // PdeLexer lexer = new PdeLexer(new StringReader(program)); lexer.setTokenObjectClass("antlr.CommonHiddenStreamToken"); // create the filter for hidden tokens and specify which tokens to // hide and which to copy to the hidden text // filter = new TokenStreamCopyingHiddenTokenFilter(lexer); filter.hide(PdePartialTokenTypes.SL_COMMENT); filter.hide(PdePartialTokenTypes.ML_COMMENT); filter.hide(PdePartialTokenTypes.WS); filter.copy(PdePartialTokenTypes.SEMI); filter.copy(PdePartialTokenTypes.LPAREN); filter.copy(PdePartialTokenTypes.RPAREN); filter.copy(PdePartialTokenTypes.LCURLY); filter.copy(PdePartialTokenTypes.RCURLY); filter.copy(PdePartialTokenTypes.COMMA); filter.copy(PdePartialTokenTypes.RBRACK); filter.copy(PdePartialTokenTypes.LBRACK); filter.copy(PdePartialTokenTypes.COLON); filter.copy(PdePartialTokenTypes.TRIPLE_DOT); // Because the meanings of < and > are overloaded to support // type arguments and type parameters, we have to treat them // as copyable to hidden text (or else the following syntax, // such as (); and what not gets lost under certain circumstances) // -- jdf filter.copy(PdePartialTokenTypes.LT); filter.copy(PdePartialTokenTypes.GT); filter.copy(PdePartialTokenTypes.SR); filter.copy(PdePartialTokenTypes.BSR); // create a parser and set what sort of AST should be generated // final PdeRecognizer parser = new PdeRecognizer(this, filter); // use our extended AST class // parser.setASTNodeClass("antlr.ExtendedCommonASTWithHiddenTokens"); return parser; }
/** * preprocesses a pde file and writes out a java file * * @return the class name of the exported Java */ private String write(final String program, final PrintWriter stream) throws SketchException, RecognitionException, TokenStreamException { // Match on the uncommented version, otherwise code inside comments used // http://code.google.com/p/processing/issues/detail?id=1404 String uncomment = scrubComments(program); PdeRecognizer parser = createParser(program); if (PUBLIC_CLASS.matcher(uncomment).find()) { try { final PrintStream saved = System.err; try { // throw away stderr for this tentative parse System.setErr(new PrintStream(new ByteArrayOutputStream())); parser.javaProgram(); } finally { System.setErr(saved); } setMode(Mode.JAVA); } catch (Exception e) { // I can't figure out any other way of resetting the parser. parser = createParser(program); parser.pdeProgram(); } } else if (FUNCTION_DECL.matcher(uncomment).find()) { setMode(Mode.ACTIVE); parser.activeProgram(); } else { parser.pdeProgram(); } // set up the AST for traversal by PdeEmitter // ASTFactory factory = new ASTFactory(); AST parserAST = parser.getAST(); AST rootNode = factory.create(ROOT_ID, "AST ROOT"); rootNode.setFirstChild(parserAST); makeSimpleMethodsPublic(rootNode); // unclear if this actually works, but it's worth a shot // // ((CommonAST)parserAST).setVerboseStringConversion( // true, parser.getTokenNames()); // (made to use the static version because of jikes 1.22 warning) BaseAST.setVerboseStringConversion(true, parser.getTokenNames()); final String className; if (mode == Mode.JAVA) { // if this is an advanced program, the classname is already defined. className = getFirstClassName(parserAST); } else { className = this.name; } // if 'null' was passed in for the name, but this isn't // a 'java' mode class, then there's a problem, so punt. // if (className == null) return null; // debug if (false) { final StringWriter buf = new StringWriter(); final PrintWriter bufout = new PrintWriter(buf); writeDeclaration(bufout, className); new PdeEmitter(this, bufout).print(rootNode); writeFooter(bufout, className); debugAST(rootNode, true); System.err.println(buf.toString()); } writeDeclaration(stream, className); new PdeEmitter(this, stream).print(rootNode); writeFooter(stream, className); // if desired, serialize the parse tree to an XML file. can // be viewed usefully with Mozilla or IE if (Preferences.getBoolean("preproc.output_parse_tree")) { writeParseTree("parseTree.xml", parserAST); } return className; }