|
||||||||||
| PREV CLASS NEXT CLASS | FRAMES NO FRAMES | |||||||||
| SUMMARY: NESTED | FIELD | CONSTR | METHOD | DETAIL: FIELD | CONSTR | METHOD | |||||||||
java.lang.Object | +--JavaEmitter
JavaEmitter: A class that can take an ANTLR Java AST and produce reasonably formatted Java code from it. To use it, create a JavaEmitter object, call setOut() if you want to print to something other than System.out, and then call print(), passing the AST. Typically, the AST node that you pass would be the root of a tree - the SOURCE_FILE node that represents a Java file. See main() for example usage.
To compile, place this file and IndentingPrintStream.java in your antlr-x.x.x/examples/java/java directory. Make sure this directory and ANTLR classes are in your CLASSPATH. Run ANTLR on java.g and java.tree.g and then compile everything:
$ java antlr.Tool java.g $ java antlr.Tool java.tree.g $ javac *.java
Test by running the main method here:
java JavaEmitter MyJavaFile.java
This will print the formatted Java code (to stdout)
This has been tested with ANTLR 2.7.1 and 2.7.2.
| Field Summary |
| Fields inherited from interface JavaTokenTypes |
ABSTRACT, ARRAY_DECLARATOR, ARRAY_INIT, ASSIGN, BAND, BAND_ASSIGN, BLOCK, BNOT, BOR, BOR_ASSIGN, BSR, BSR_ASSIGN, BXOR, BXOR_ASSIGN, CASE_GROUP, CHAR_LITERAL, CLASS_DEF, COLON, COMMA, CTOR_CALL, CTOR_DEF, DEC, DIV, DIV_ASSIGN, DOT, ELIST, EMPTY_STAT, EOF, EQUAL, ESC, EXPONENT, EXPR, EXTENDS_CLAUSE, FINAL, FLOAT_SUFFIX, FOR_CONDITION, FOR_INIT, FOR_ITERATOR, GE, GT, HEX_DIGIT, IDENT, IMPLEMENTS_CLAUSE, IMPORT, INC, INDEX_OP, INSTANCE_INIT, INTERFACE_DEF, LABELED_STAT, LAND, LBRACK, LCURLY, LE, LITERAL_boolean, LITERAL_break, LITERAL_byte, LITERAL_case, LITERAL_catch, LITERAL_char, LITERAL_class, LITERAL_continue, LITERAL_default, LITERAL_do, LITERAL_double, LITERAL_else, LITERAL_extends, LITERAL_false, LITERAL_finally, LITERAL_float, LITERAL_for, LITERAL_if, LITERAL_implements, LITERAL_import, LITERAL_instanceof, LITERAL_int, LITERAL_interface, LITERAL_long, LITERAL_native, LITERAL_new, LITERAL_null, LITERAL_package, LITERAL_private, LITERAL_protected, LITERAL_public, LITERAL_return, LITERAL_short, LITERAL_static, LITERAL_super, LITERAL_switch, LITERAL_synchronized, LITERAL_this, LITERAL_threadsafe, LITERAL_throw, LITERAL_throws, LITERAL_transient, LITERAL_true, LITERAL_try, LITERAL_void, LITERAL_volatile, LITERAL_while, LNOT, LOR, LPAREN, LT, METHOD_CALL, METHOD_DEF, MINUS, MINUS_ASSIGN, ML_COMMENT, MOD, MOD_ASSIGN, MODIFIERS, NOT_EQUAL, NULL_TREE_LOOKAHEAD, NUM_DOUBLE, NUM_FLOAT, NUM_INT, NUM_LONG, OBJBLOCK, PACKAGE_DEF, PARAMETER_DEF, PARAMETERS, PLUS, PLUS_ASSIGN, POST_DEC, POST_INC, QUESTION, RBRACK, RCURLY, RPAREN, SEMI, SL, SL_ASSIGN, SL_COMMENT, SLIST, SOURCE_FILE, SR, SR_ASSIGN, STAR, STAR_ASSIGN, STATIC_INIT, STRICTFP, STRING_LITERAL, SUPER_CTOR_CALL, TYPE, TYPECAST, UNARY_MINUS, UNARY_PLUS, VARIABLE_DEF, VOCAB, WS |
| Constructor Summary | |
JavaEmitter()
|
|
| Method Summary | |
static void |
main(java.lang.String[] args)
This example takes a single filename on the command line, prints the AST to stderr and the Java code to stdout. |
void |
print(antlr.collections.AST ast)
Print the given AST. |
void |
setOut(java.io.PrintStream out)
Specify a PrintStream to print to. |
| Methods inherited from class java.lang.Object |
clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait |
| Constructor Detail |
public JavaEmitter()
| Method Detail |
public void setOut(java.io.PrintStream out)
out - the PrintStream to print topublic void print(antlr.collections.AST ast)
Overall Approach
It works by making recursive calls to print children. For example,
the root of the AST tree has type SOURCE_FILE. A Java AST node generated from the
ANTLR java.g file will have type SOURCE_FILE and will have
the following children, in this order:
0 or 1 children of type PACKAGE_DEF
0 or more children of type IMPORT
One child of type CLASS_DEF or type INTERFACE_DEF
So the code below is one big "switch" statement on the passed AST type. In the "SOURCE_FILE" case, the code here does the following:
Indenting
One important issue is how to do proper indenting. The IndentingPrintStream
class handles indenting. Here, we simply create an IndentingPrintStream from
our normal PrintStream (either System.out or whatever was passed to setOut()).
And then we call increaseIndent() and decreaseIndent() as we see "{" and "}"
AST nodes.
Adding Parentheses
The only other tricky part here is in printing parentheses, which are not kept
as AST nodes, but are built-in ("inherent") to the structure of the AST.
The printWithParens() method is used to print all unary and binary operators.
This method uses a precendence table to determine whether it needs to print
parentheses or not.
public static void main(java.lang.String[] args)
|
||||||||||
| PREV CLASS NEXT CLASS | FRAMES NO FRAMES | |||||||||
| SUMMARY: NESTED | FIELD | CONSTR | METHOD | DETAIL: FIELD | CONSTR | METHOD | |||||||||