📄 java.g
字号:
options { language = "Sather";}/* Java 1.2 Recognizer * * Run 'java Main <directory full of java files>' * * Contributing authors: * John Mitchell johnm@non.net * Terence Parr parrt@magelang.com * John Lilley jlilley@empathy.com * Scott Stanchfield thetick@magelang.com * Markus Mohnen mohnen@informatik.rwth-aachen.de * Peter Williams pwilliams@netdynamics.com * * Version 1.00 December 9, 1997 -- initial release * Version 1.01 December 10, 1997 * fixed bug in octal def (0..7 not 0..8) * Version 1.10 August 1998 (parrt) * added tree construction * fixed definition of WS,comments for mac,pc,unix newlines * added unary plus * Version 1.11 (Nov 20, 1998) * Added "shutup" option to turn off last ambig warning. * Fixed inner class def to allow named class defs as statements * synchronized requires compound not simple statement * add [] after builtInType DOT class in primaryExpression * "const" is reserved but not valid..removed from modifiers * Version 1.12 (Feb 2, 1999) * Changed LITERAL_xxx to xxx in tree grammar. * Updated java.g to use tokens {...} now for 2.6.0 (new feature). * * Version 1.13 (Apr 23, 1999) * Didn't have (stat)? for else clause in tree parser. * Didn't gen ASTs for interface extends. Updated tree parser too. * Updated to 2.6.0. * Version 1.14 (Jun 20, 1999) * Allowed final/abstract on local classes. * Removed local interfaces from methods * Put instanceof precedence where it belongs...in relationalExpr * It also had expr not type as arg; fixed it. * Missing ! on SEMI in classBlock * fixed: (expr) + "string" was parsed incorrectly (+ as unary plus). * fixed: didn't like Object[].class in parser or tree parser * Version 1.15 (Jun 26, 1999) * Screwed up rule with instanceof in it. :( Fixed. * Tree parser didn't like (expr).something; fixed. * Allowed multiple inheritance in tree grammar. oops. * Version 1.16 (August 22, 1999) * Extending an interface built a wacky tree: had extra EXTENDS. * Tree grammar didn't allow multiple superinterfaces. * Tree grammar didn't allow empty var initializer: {} * Version 1.17 (October 12, 1999) * ESC lexer rule allowed 399 max not 377 max. * java.tree.g didn't handle the expression of synchronized * statements. * * Version tracking now done with following ID: * * $Id: //depot/code/org.antlr/release/antlr-2.7.0/examples/sather/java/java.g#1 $ * * BUG: * Doesn't like boolean.class! * * class Test { * public static void main( String args[] ) { * if (boolean.class.equals(boolean.class)) { * System.out.println("works"); * } * } * } * * This grammar is in the PUBLIC DOMAIN * */class JAVA_RECOGNIZER extends Parser;options { k = 2; // two token lookahead exportVocab=JAVA; // Call its vocabulary "JAVA" codeGenMakeSwitchThreshold = 2; // Some optimizations codeGenBitsetTestThreshold = 3; defaultErrorHandler = false; // Don't generate parser error handlers buildAST = true;}tokens { BLOCK; MODIFIERS; OBJBLOCK; SLIST; CTOR_DEF; METHOD_DEF; VARIABLE_DEF; INSTANCE_INIT; STATIC_INIT; TYPE; CLASS_DEF; INTERFACE_DEF; PACKAGE_DEF; ARRAY_DECLARATOR; EXTENDS_CLAUSE; IMPLEMENTS_CLAUSE; PARAMETERS; PARAMETER_DEF; LABELED_STAT; TYPECAST; INDEX_OP; POST_INC; POST_DEC; METHOD_CALL; EXPR; ARRAY_INIT; IMPORT; UNARY_MINUS; UNARY_PLUS; CASE_GROUP; ELIST; FOR_INIT; FOR_CONDITION; FOR_ITERATOR; EMPTY_STAT; FINAL="final"; ABSTRACT="abstract";} // Compilation Unit: In Java, this is a single file. This is the start// rule for this parsercompilationUnit : // A compilation unit starts with an optional package definition ( packageDefinition | /* nothing */ ) // Next we have a series of zero or more import statements ( importDefinition )* // Wrapping things up with any number of class or interface // definitions ( typeDefinition )* EOF! ;// Package statement: "package" followed by an identifier.packageDefinition options {defaultErrorHandler = true;} // let ANTLR handle errors : p:"package"^ {@p.ttype(PACKAGE_DEF);} identifier SEMI! ;// Import statement: import followed by a package or class nameimportDefinition options {defaultErrorHandler = true;} : i:"import"^ {@i.ttype(IMPORT);} identifierStar SEMI! ;// A type definition in a file is either a class or interface definition.typeDefinition options {defaultErrorHandler = true;} : m:modifiers! ( classDefinition[@m] | interfaceDefinition[@m] ) | SEMI! ;/* A declaration is the creation of a reference or primitive-type variable * Create a separate Type/Var tree for each var in the var list. */declaration! : m:modifiers t:typeSpec[false] v:variableDefinitions[@m,@t] {@declaration := @v;} ;// A list of zero or more modifiers. We could have used (modifier)* in// place of a call to modifiers, but I thought it was a good idea to keep// this rule separate so they can easily be collected in a Vector if// someone so desiresmodifiers : ( modifier )* {@modifiers := @([MODIFIERS, "MODIFIERS"], @modifiers);} ;// A type specification is a type name with possible brackets afterwards// (which would make it an array type).typeSpec[addImagNode : BOOL] : classTypeSpec[addImagNode] | builtInTypeSpec[addImagNode] ;// A class type specification is a class type with possible brackets afterwards// (which would make it an array type).classTypeSpec[addImagNode : BOOL] : identifier (lb:LBRACK^ {@lb.ttype(ARRAY_DECLARATOR);} RBRACK!)* { if ( addImagNode ) then @classTypeSpec := @(@[TYPE,"TYPE"], @classTypeSpec); end; -- if } ;// A builtin type specification is a builtin type with possible brackets// afterwards (which would make it an array type).builtInTypeSpec[addImagNode : BOOL] : builtInType (lb:LBRACK^ {@lb.ttype(ARRAY_DECLARATOR);} RBRACK!)* { if ( addImagNode ) then @builtInTypeSpec := @(@[TYPE,"TYPE"], @builtInTypeSpec); end; -- if } ;// A type name. which is either a (possibly qualified) class name or// a primitive (builtin) typetype_ : identifier | builtInType ;// The primitive types.builtInType : "void" | "boolean" | "byte" | "char" | "short" | "int" | "float" | "long" | "double" ;// A (possibly-qualified) java identifier. We start with the first IDENT// and expand its name by adding dots and following IDENTSidentifier : IDENT ( DOT^ IDENT )* ;identifierStar : IDENT ( DOT^ IDENT )* ( DOT^ STAR )? ;// modifiers for Java classes, interfaces, class/instance vars and methodsmodifier : "private" | "public" | "protected" | "static" | "transient" | "final" | "abstract" | "native" | "threadsafe" | "synchronized"// | "const" // reserved word; leave out | "volatile" ;// Definition of a Java classclassDefinition![modifiers : AST] : "class" IDENT // it _might_ have a superclass... sc:superClassClause // it might implement some interfaces... ic:implementsClause // now parse the body of the class cb:classBlock {@classDefinition := @(@[CLASS_DEF,"CLASS_DEF"], modifiers,IDENT,sc,ic,cb);} ;superClassClause! : ( "extends" id:identifier )? {@superClassClause := @(@[EXTENDS_CLAUSE,"EXTENDS_CLAUSE"],id);} ;// Definition of a Java InterfaceinterfaceDefinition![modifiers : AST] : "interface" IDENT // it might extend some other interfaces ie:interfaceExtends // now parse the body of the interface (looks like a class...) cb:classBlock {@interfaceDefinition := @(@[INTERFACE_DEF,"INTERFACE_DEF"], modifiers,IDENT,ie,cb);} ;// This is the body of a class. You can have fields and extra semicolons,// That's about it (until you see what a field is...)classBlock : LCURLY! ( field | SEMI! )* RCURLY! {@classBlock := @([OBJBLOCK, "OBJBLOCK"], @classBlock);} ;// An interface can extend several other interfaces...interfaceExtends : ( e:"extends"! identifier ( COMMA! identifier )* )? {@interfaceExtends := @(@[EXTENDS_CLAUSE,"EXTENDS_CLAUSE"], @interfaceExtends);} ;// A class can implement several interfaces...implementsClause : ( i:"implements"! identifier ( COMMA! identifier )* )? {@implementsClause := @(@[IMPLEMENTS_CLAUSE,"IMPLEMENTS_CLAUSE"], @implementsClause);} ;// Now the various things that can be defined inside a class or interface...// Note that not all of these are really valid in an interface (constructors,// for example), and if this grammar were used for a compiler there would// need to be some semantic checks to make sure we're doing the right thing...field! : // method, constructor, or variable declaration mods:modifiers ( h:ctorHead s:compoundStatement // constructor {@field := @(@[CTOR_DEF,"CTOR_DEF"], mods, h, s);} | cd:classDefinition[@mods] // inner class {@field := @cd;} | id:interfaceDefinition[@mods] // inner interface {@field := @id;} | t:typeSpec[false] // method or variable declaration(s) ( IDENT // the name of the method // parse the formal parameter declarations. LPAREN! param:parameterDeclarationList RPAREN! rt:returnTypeBrackersOnEndOfMethodHead[@t] // get the list of exceptions that this method is declared to throw (tc:throwsClause)? ( s2:compoundStatement | SEMI ) {@field := @(@[METHOD_DEF,"METHOD_DEF"], mods, @(@[TYPE,"TYPE"],rt), IDENT, param, tc, s2);} | v:variableDefinitions[@mods,@t] SEMI// {@field := @(@[VARIABLE_DEF,"VARIABLE_DEF"], v);} {@field := @v;} ) ) // "static { ... }" class initializer | "static" s3:compoundStatement {@field := @(@[STATIC_INIT,"STATIC_INIT"], s3);} // "{ ... }" instance initializer | compoundStatement {@field := @(@[INSTANCE_INIT,"INSTANCE_INIT"], s3);} ;variableDefinitions[ mods : AST, t : AST] : variableDeclarator[ANTLR_AST_UTIL{AST}::dup_tree(mods), ANTLR_AST_UTIL{AST}::dup_tree(t) ] ( COMMA! variableDeclarator[ANTLR_AST_UTIL{AST}::dup_tree(mods), ANTLR_AST_UTIL{AST}::dup_tree(t) ] )* ;/* Declaration of a variable. This can be a class/instance variable, * or a local variable in a method * It can also include possible initialization. */variableDeclarator![mods : AST, t : AST] : id:IDENT d:declaratorBrackets[t] v:varInitializer {@variableDeclarator := @(@[VARIABLE_DEF,"VARIABLE_DEF"], mods, @(@[TYPE,"TYPE"],d), id, v);} ;declaratorBrackets[typ : AST] : {@declaratorBrackets := typ;} (lb:LBRACK^ {@lb.ttype(ARRAY_DECLARATOR);} RBRACK!)* ;varInitializer : ( ASSIGN^ initializer )? ;// This is an initializer used to set up an array.arrayInitializer : lc:LCURLY^ {@lc.ttype(ARRAY_INIT);} ( initializer ( // CONFLICT: does a COMMA after an initializer start a new // initializer or start the option ',' at end? // ANTLR generates proper code by matching // the comma as soon as possible. options { warnWhenFollowAmbig = false; } : COMMA! initializer )* (COMMA!)? )? RCURLY! ;// The two "things" that can initialize an array element are an expression// and another (nested) array initializer.initializer : expression | arrayInitializer ;// This is the header of a method. It includes the name and parameters// for the method.// This also watches for a list of exception classes in a "throws" clause.ctorHead : IDENT // the name of the method // parse the formal parameter declarations. LPAREN! parameterDeclarationList RPAREN! // get the list of exceptions that this method is declared to throw (throwsClause)? ;// This is a list of exception classes that the method is declared to throwthrowsClause : "throws"^ identifier ( COMMA! identifier )* ;returnTypeBrackersOnEndOfMethodHead[typ: AST] : {@returnTypeBrackersOnEndOfMethodHead := typ;} (lb:LBRACK^ {@lb.ttype(ARRAY_DECLARATOR);} RBRACK!)* ;// A list of formal parametersparameterDeclarationList : ( parameterDeclaration ( COMMA! parameterDeclaration )* )? {@parameterDeclarationList := @(@[PARAMETERS,"PARAMETERS"], @parameterDeclarationList);} ;// A formal parameter.parameterDeclaration! : pm:parameterModifier t:typeSpec[false] id:IDENT pd:parameterDeclaratorBrackets[@t] {@parameterDeclaration := @(@[PARAMETER_DEF,"PARAMETER_DEF"], pm, @([TYPE,"TYPE"],pd), id);} ;parameterDeclaratorBrackets[t : AST] : {@parameterDeclaratorBrackets := t;} (lb:LBRACK^ {@lb.ttype(ARRAY_DECLARATOR);} RBRACK!)* ;parameterModifier : (f:"final")? {@parameterModifier := @(@[MODIFIERS,"MODIFIERS"], f);} ;// Compound statement. This is used in many contexts:// Inside a class definition prefixed with "static":// it is a class initializer// Inside a class definition without "static":// it is an instance initializer// As the body of a method// As a completely indepdent braced block of code inside a method// it starts a new scope for variable definitionscompoundStatement : lc:LCURLY^ {@lc.ttype(SLIST);} // include the (possibly-empty) list of statements (statement)* RCURLY! ;statement // A list of statements in curly braces -- start a new scope! : compoundStatement // class definition | classDefinition[@[MODIFIERS, "MODIFIERS"]] // final class definition | "final"! classDefinition[@(@[MODIFIERS, "MODIFIERS"],@[FINAL,"final"])] // abstract class definition | "abstract"! classDefinition[@(@[MODIFIERS, "MODIFIERS"],@[ABSTRACT,"abstract"])] // declarations are ambiguous with "ID DOT" relative to expression // statements. Must backtrack to be sure. Could use a semantic // predicate to test symbol table to see what the type was coming // up, but that's pretty hard without a symbol table ;) | (declaration)=> declaration SEMI! // An expression statement. This could be a method call, // assignment statement, or any other expression evaluated for // side-effects. | expression SEMI! // Attach a label to the front of a statement | IDENT c:COLON^ {@c.ttype(LABELED_STAT);} statement // If-else statement | "if"^ LPAREN! expression RPAREN! statement ( // CONFLICT: the old "dangling-else" problem... // ANTLR generates proper code matching // as soon as possible. Hush warning. options { warnWhenFollowAmbig = false; } : "else"! statement )? // For statement | "for"^ LPAREN! forInit SEMI! // initializer forCond SEMI! // condition test forIter // updater RPAREN! statement // statement to loop over // While statement | "while"^ LPAREN! expression RPAREN! statement // do-while statement | "do"^ statement "while"! LPAREN! expression RPAREN! SEMI! // get out of a loop (or switch) | "break"^ (IDENT)? SEMI! // do next iteration of a loop | "continue"^ (IDENT)? SEMI! // Return an expression | "return"^ (expression)? SEMI! // switch/case statement | "switch"^ LPAREN! expression RPAREN! LCURLY! ( casesGroup )* RCURLY! // exception try-catch block | tryBlock // throw an exception | "throw"^ expression SEMI! // synchronize a statement | "synchronized"^ LPAREN! expression RPAREN! compoundStatement // empty statement | s:SEMI {@s.ttype(EMPTY_STAT);} ;casesGroup : ( // CONFLICT: to which case group do the statements bind? // ANTLR generates proper code: it groups the // many "case"/"default" labels together then // follows them with the statements options { warnWhenFollowAmbig = false; } : aCase )+ caseSList {@casesGroup := @([CASE_GROUP, "CASE_GROUP"], @casesGroup);} ;aCase : ("case"^ expression | "default") COLON! ;caseSList : (statement)* {@caseSList := @(@[SLIST,"SLIST"],@caseSList);} ;// The initializer for a for loopforInit // if it looks like a declaration, it is : ( (declaration)=> declaration // otherwise it could be an expression list... | expressionList )? {@forInit := @(@[FOR_INIT,"FOR_INIT"],@forInit);} ;forCond : (expression)? {@forCond := @(@[FOR_CONDITION,"FOR_CONDITION"],@forCond);} ;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -