| Grammar GroovyRecognizer |
| ANTLR-generated HTML file from /Users/j6wbs/projects/groovy/groovy.head/groovy/trunk/groovy/jsr/ideas/parsers/antlr/src/org/codehaus/groovy/antlr/groovy.g |
| |
| Terence Parr, MageLang Institute |
| ANTLR Version 2.7.5 (20050128); 1989-2005 |
| |
| /** JSR-241 Groovy Recognizer |
| * |
| * Run 'java Main [-showtree] directory-full-of-groovy-files' |
| * |
| * [The -showtree option pops up a Swing frame that shows |
| * the AST constructed from the parser.] |
| * |
| * 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 pete.williams@sun.com |
| * Allan Jacobs Allan.Jacobs@eng.sun.com |
| * Steve Messick messick@redhills.com |
| * James Strachan jstrachan@protique.com |
| * John Pybus john@pybus.org |
| * John Rose rose00@mac.com |
| * Jeremy Rayner groovy@ross-rayner.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 1.18 (August 12, 2001) |
| * Terence updated to Java 2 Version 1.3 by |
| * observing/combining work of Allan Jacobs and Steve |
| * Messick. Handles 1.3 src. Summary: |
| * o primary didn't include boolean.class kind of thing |
| * o constructor calls parsed explicitly now: |
| * see explicitConstructorInvocation |
| * o add strictfp modifier |
| * o missing objBlock after new expression in tree grammar |
| * o merged local class definition alternatives, moved after declaration |
| * o fixed problem with ClassName.super.field |
| * o reordered some alternatives to make things more efficient |
| * o long and double constants were not differentiated from int/float |
| * o whitespace rule was inefficient: matched only one char |
| * o add an examples directory with some nasty 1.3 cases |
| * o made Main.java use buffered IO and a Reader for Unicode support |
| * o supports UNICODE? |
| * Using Unicode charVocabulay makes code file big, but only |
| * in the bitsets at the end. I need to make ANTLR generate |
| * unicode bitsets more efficiently. |
| * Version 1.19 (April 25, 2002) |
| * Terence added in nice fixes by John Pybus concerning floating |
| * constants and problems with super() calls. John did a nice |
| * reorg of the primary/postfix expression stuff to read better |
| * and makes f.g.super() parse properly (it was METHOD_CALL not |
| * a SUPER_CTOR_CALL). Also: |
| * |
| * o "finally" clause was a root...made it a child of "try" |
| * o Added stuff for asserts too for Java 1.4, but *commented out* |
| * as it is not backward compatible. |
| * |
| * Version 1.20 (October 27, 2002) |
| * |
| * Terence ended up reorging John Pybus' stuff to |
| * remove some nondeterminisms and some syntactic predicates. |
| * Note that the grammar is stricter now; e.g., this(...) must |
| * be the first statement. |
| * |
| * Trinary ?: operator wasn't working as array name: |
| * (isBig ? bigDigits : digits)[i]; |
| * |
| * Checked parser/tree parser on source for |
| * Resin-2.0.5, jive-2.1.1, jdk 1.3.1, Lucene, antlr 2.7.2a4, |
| * and the 110k-line jGuru server source. |
| * |
| * Version 1.21 (October 17, 2003) |
| * Fixed lots of problems including: |
| * Ray Waldin: add typeDefinition to interfaceBlock in java.tree.g |
| * He found a problem/fix with floating point that start with 0 |
| * Ray also fixed problem that (int.class) was not recognized. |
| * Thorsten van Ellen noticed that \n are allowed incorrectly in strings. |
| * TJP fixed CHAR_LITERAL analogously. |
| * |
| * Version 1.21.2 (March, 2003) |
| * Changes by Matt Quail to support generics (as per JDK1.5/JSR14) |
| * Notes: |
| * o We only allow the "extends" keyword and not the "implements" |
| * keyword, since thats what JSR14 seems to imply. |
| * o Thanks to Monty Zukowski for his help on the antlr-interest |
| * mail list. |
| * o Thanks to Alan Eliasen for testing the grammar over his |
| * Fink source base |
| * |
| * Version 1.22 (July, 2004) |
| * Changes by Michael Studman to support Java 1.5 language extensions |
| * Notes: |
| * o Added support for annotations types |
| * o Finished off Matt Quail's generics enhancements to support bound type arguments |
| * o Added support for new for statement syntax |
| * o Added support for static import syntax |
| * o Added support for enum types |
| * o Tested against JDK 1.5 source base and source base of jdigraph project |
| * o Thanks to Matt Quail for doing the hard part by doing most of the generics work |
| * |
| * Version 1.22.1 (July 28, 2004) |
| * Bug/omission fixes for Java 1.5 language support |
| * o Fixed tree structure bug with classOrInterface - thanks to Pieter Vangorpto for |
| * spotting this |
| * o Fixed bug where incorrect handling of SR and BSR tokens would cause type |
| * parameters to be recognised as type arguments. |
| * o Enabled type parameters on constructors, annotations on enum constants |
| * and package definitions |
| * o Fixed problems when parsing if ((char.class.equals(c))) {} - solution by Matt Quail at Cenqua |
| * |
| * Version 1.22.2 (July 28, 2004) |
| * Slight refactoring of Java 1.5 language support |
| * o Refactored for/"foreach" productions so that original literal "for" literal |
| * is still used but the for sub-clauses vary by token type |
| * o Fixed bug where type parameter was not included in generic constructor's branch of AST |
| * |
| * Version 1.22.3 (August 26, 2004) |
| * Bug fixes as identified by Michael Stahl; clean up of tabs/spaces |
| * and other refactorings |
| * o Fixed typeParameters omission in identPrimary and newStatement |
| * o Replaced GT reconcilliation code with simple semantic predicate |
| * o Adapted enum/assert keyword checking support from Michael Stahl's java15 grammar |
| * o Refactored typeDefinition production and field productions to reduce duplication |
| * |
| * Version 1.22.4 (October 21, 2004) |
| * Small bux fixes |
| * o Added typeArguments to explicitConstructorInvocation, e.g. new <String>MyParameterised() |
| * o Added typeArguments to postfixExpression productions for anonymous inner class super |
| * constructor invocation, e.g. new Outer().<String>super() |
| * o Fixed bug in array declarations identified by Geoff Roy |
| * |
| * Version 1.22.4.g.1 |
| * o I have taken java.g for Java1.5 from Michael Studman (1.22.4) |
| * and have applied the groovy.diff from java.g (1.22) by John Rose |
| * back onto the new root (1.22.4) - Jeremy Rayner (Jan 2005) |
| * o for a map of the task see... |
| * http://groovy.javanicus.com/java-g.png |
| * |
| * This grammar is in the PUBLIC DOMAIN |
| */ |
| Definition of parser GroovyRecognizer, which is a subclass of LLkParser. |
| |
| |
| compilationUnit |
| : ( SH_COMMENT |
| | |
| ) |
| nls |
| ( packageDefinition |
| | ( statement |
| | |
| ) |
| ) |
| ( sep |
| ( statement |
| | |
| ) )* EOF |
| ; |
| |
| |
| /** Zero or more insignificant newlines, all gobbled up and thrown away. */ |
| nls |
| : ( NLS |
| | |
| ) |
| ; |
| |
| |
| annotationsOpt |
| : ( annotation nls )* |
| ; |
| |
| |
| packageDefinition |
| : annotationsOpt "package" identifier |
| ; |
| |
| |
| /** A statement is an element of a block. |
| * Typical statements are declarations (which are scoped to the block) |
| * and expressions. |
| */ |
| statement |
| : declaration |
| | statementLabelPrefix |
| ( openOrClosableBlock |
| | statement |
| ) |
| | expressionStatement |
| | modifiersOpt typeDefinitionInternal |
| | "if" LPAREN assignmentLessExpression RPAREN nlsWarn compatibleBodyStatement |
| ( ( sep |
| | |
| ) |
| "else" nlsWarn compatibleBodyStatement |
| | |
| ) |
| | forStatement |
| | "while" LPAREN strictContextExpression RPAREN nlsWarn compatibleBodyStatement |
| | "with" LPAREN strictContextExpression RPAREN nlsWarn compoundStatement |
| | STAR nls expressionStatement |
| | importStatement |
| | "switch" LPAREN strictContextExpression RPAREN nlsWarn LCURLY nls ( casesGroup )* RCURLY |
| | tryBlock |
| | "synchronized" LPAREN strictContextExpression RPAREN nlsWarn compoundStatement |
| | branchStatement |
| ; |
| |
| |
| /** A statement separator is either a semicolon or a significant newline. |
| * Any number of additional (insignificant) newlines may accompany it. |
| */ |
| sep |
| : SEMI ( NLS )* |
| | NLS ( SEMI ( NLS )* )* |
| ; |
| |
| |
| /** A Groovy script or simple expression. Can be anything legal inside {...}. */ |
| snippetUnit |
| : nls blockBody |
| ; |
| |
| |
| /** A block body is a parade of zero or more statements or expressions. */ |
| blockBody |
| : ( statement |
| | |
| ) |
| ( sep |
| ( statement |
| | |
| ) )* |
| ; |
| |
| |
| identifier |
| : IDENT ( DOT nls IDENT )* |
| ; |
| |
| |
| importStatement |
| : "import" |
| ( "static" |
| | |
| ) |
| identifierStar |
| ; |
| |
| |
| identifierStar |
| : IDENT ( DOT nls IDENT )* |
| ( DOT nls STAR |
| | "as" nls IDENT |
| | |
| ) |
| ; |
| |
| |
| protected typeDefinitionInternal |
| : classDefinition |
| | interfaceDefinition |
| | enumDefinition |
| | annotationDefinition |
| ; |
| |
| |
| classDefinition |
| : "class" IDENT nls |
| ( typeParameters |
| | |
| ) |
| superClassClause implementsClause classBlock |
| ; |
| |
| |
| interfaceDefinition |
| : "interface" IDENT nls |
| ( typeParameters |
| | |
| ) |
| interfaceExtends interfaceBlock |
| ; |
| |
| |
| enumDefinition |
| : "enum" IDENT implementsClause enumBlock |
| ; |
| |
| |
| annotationDefinition |
| : AT "interface" IDENT annotationBlock |
| ; |
| |
| |
| /** A declaration is the creation of a reference or primitive-type variable, |
| * or (if arguments are present) of a method. |
| * Generically, this is called a 'variable' definition, even in the case of a class field or method. |
| * It may start with the modifiers and/or a declaration keyword "def". |
| * It may also start with the modifiers and a capitalized type name. |
| * <p> |
| * AST effect: Create a separate Type/Var tree for each var in the var list. |
| * Must be guarded, as in (declarationStart) => declaration. |
| */ |
| declaration |
| : modifiers |
| ( typeSpec |
| | |
| ) |
| variableDefinitions |
| | typeSpec variableDefinitions |
| ; |
| |
| |
| /** A list of one or more modifier, annotation, or "def". */ |
| modifiers |
| : modifiersInternal |
| ; |
| |
| |
| typeSpec |
| : classTypeSpec |
| | builtInTypeSpec |
| ; |
| |
| |
| /** The tail of a declaration. |
| * Either v1, v2, ... (with possible initializers) or else m(args){body}. |
| * The two arguments are the modifier list (if any) and the declaration head (if any). |
| * The declaration head is the variable type, or (for a method) the return type. |
| * If it is missing, then the variable type is taken from its initializer (if there is one). |
| * Otherwise, the variable type defaults to 'any'. |
| * DECIDE: Method return types default to the type of the method body, as an expression. |
| */ |
| variableDefinitions |
| : variableDeclarator ( COMMA nls variableDeclarator )* |
| | ( IDENT |
| | STRING_LITERAL |
| ) |
| LPAREN parameterDeclarationList RPAREN |
| ( throwsClause |
| | |
| ) |
| ( ( nlsWarn openBlock ) |
| | |
| ) |
| |
| ; |
| |
| |
| /** A declaration with one declarator and no initialization, like a parameterDeclaration. |
| * Used to parse loops like <code>for (int x in y)</code> (up to the <code>in</code> keyword). |
| */ |
| singleDeclarationNoInit |
| : modifiers |
| ( typeSpec |
| | |
| ) |
| singleVariable |
| | typeSpec singleVariable |
| ; |
| |
| |
| /** Used in cases where a declaration cannot have commas, or ends with the "in" operator instead of '='. */ |
| singleVariable |
| : variableName |
| ; |
| |
| |
| /** A declaration with one declarator and optional initialization, like a parameterDeclaration. |
| * Used to parse declarations used for both binding and effect, in places like argument |
| * lists and <code>while</code> statements. |
| */ |
| singleDeclaration |
| : singleDeclarationNoInit |
| ( varInitializer |
| | |
| ) |
| ; |
| |
| |
| /** An assignment operator '=' followed by an expression. (Never empty.) */ |
| varInitializer |
| : ASSIGN nls expression |
| ; |
| |
| |
| /** Used only as a lookahead predicate, before diving in and parsing a declaration. |
| * A declaration can be unambiguously introduced with "def", an annotation or a modifier token like "final". |
| * It may also be introduced by a simple identifier whose first character is an uppercase letter, |
| * as in {String x}. A declaration can also be introduced with a built in type like 'int' or 'void'. |
| * Brackets (array and generic) are allowed, as in {List[] x} or {int[][] y}. |
| * Anything else is parsed as a statement of some sort (expression or command). |
| * <p> |
| * (In the absence of explicit method-call parens, we assume a capitalized name is a type name. |
| * Yes, this is a little hacky. Alternatives are to complicate the declaration or command |
| * syntaxes, or to have the parser query the symbol table. Parse-time queries are evil. |
| * And we want both {String x} and {println x}. So we need a syntactic razor-edge to slip |
| * between 'println' and 'String'.) |
| * |
| * *TODO* The declarationStart production needs to be strengthened to recognize |
| * things like {List<String> foo}. |
| * Right now it only knows how to skip square brackets after the type, not |
| * angle brackets. |
| * This probably turns out to be tricky because of >> vs. > >. If so, |
| * just put a TODO comment in. |
| */ |
| declarationStart |
| : "def" |
| | modifier |
| | AT IDENT |
| | ( upperCaseIdent |
| | builtInType |
| | qualifiedTypeName |
| ) |
| ( LBRACK balancedTokens RBRACK )* IDENT |
| ; |
| |
| |
| modifier |
| : "private" |
| | "public" |
| | "protected" |
| | "static" |
| | "transient" |
| | "final" |
| | "abstract" |
| | "native" |
| | "threadsafe" |
| | "synchronized" |
| | "volatile" |
| | "strictfp" |
| ; |
| |
| |
| /** An IDENT token whose spelling is required to start with an uppercase letter. |
| * In the case of a simple statement {UpperID name} the identifier is taken to be a type name, not a command name. |
| */ |
| upperCaseIdent |
| : IDENT |
| ; |
| |
| |
| builtInType |
| : "void" |
| | "boolean" |
| | "byte" |
| | "char" |
| | "short" |
| | "int" |
| | "float" |
| | "long" |
| | "double" |
| | "any" |
| ; |
| |
| |
| /** Not yet used - but we could use something like this to look for fully qualified type names |
| */ |
| qualifiedTypeName |
| : IDENT ( DOT IDENT )* DOT upperCaseIdent |
| ; |
| |
| |
| balancedTokens |
| : ( balancedBrackets |
| | ( LPAREN |
| | LBRACK |
| | LCURLY |
| | STRING_CTOR_START |
| | RPAREN |
| | RBRACK |
| | RCURLY |
| | STRING_CTOR_END |
| ) |
| )* |
| ; |
| |
| |
| /** Used to look ahead for a constructor |
| */ |
| constructorStart |
| : modifiersOpt IDENT nls LPAREN |
| ; |
| |
| |
| /** A list of zero or more modifiers, annotations, or "def". */ |
| modifiersOpt |
| : ( modifiersInternal |
| | |
| ) |
| |
| ; |
| |
| |
| /** Used only as a lookahead predicate for nested type declarations. */ |
| typeDeclarationStart |
| : modifiersOpt |
| ( "class" |
| | "interface" |
| | "enum" |
| | AT "interface" |
| ) |
| ; |
| |
| |
| classTypeSpec |
| : classOrInterfaceType declaratorBrackets |
| ; |
| |
| |
| builtInTypeSpec |
| : builtInType declaratorBrackets |
| ; |
| |
| |
| classOrInterfaceType |
| : IDENT |
| ( typeArguments |
| | |
| ) |
| ( DOT IDENT |
| ( typeArguments |
| | |
| ) )* |
| ; |
| |
| |
| /** After some type names, where zero or more empty bracket pairs are allowed. |
| * We use ARRAY_DECLARATOR to represent this. |
| * TODO: Is there some more Groovy way to view this in terms of the indexed property syntax? |
| */ |
| declaratorBrackets |
| : ( LBRACK RBRACK )* |
| ; |
| |
| |
| typeArguments |
| : LT nls typeArgument ( COMMA nls typeArgument )* nls |
| ( typeArgumentsOrParametersEnd |
| | |
| ) |
| |
| ; |
| |
| |
| typeArgumentSpec |
| : classTypeSpec |
| | builtInTypeArraySpec |
| ; |
| |
| |
| builtInTypeArraySpec |
| : builtInType |
| ( declaratorBrackets |
| | |
| ) |
| |
| ; |
| |
| |
| typeArgument |
| : ( typeArgumentSpec |
| | wildcardType |
| ) |
| |
| ; |
| |
| |
| wildcardType |
| : QUESTION |
| ( typeArgumentBounds |
| | |
| ) |
| ; |
| |
| |
| typeArgumentBounds |
| : ( "extends" |
| | "super" |
| ) |
| nls classOrInterfaceType nls |
| ; |
| |
| |
| protected typeArgumentsOrParametersEnd |
| : GT nls |
| | SR nls |
| | BSR nls |
| ; |
| |
| |
| type |
| : classOrInterfaceType |
| | builtInType |
| ; |
| |
| |
| modifiersInternal |
| : ( "def" nls |
| | modifier nls |
| | annotation nls |
| )+ |
| ; |
| |
| |
| annotation |
| : AT identifier |
| ( LPAREN |
| ( annotationArguments |
| | |
| ) |
| RPAREN |
| | |
| ) |
| |
| ; |
| |
| |
| annotationArguments |
| : annotationMemberValueInitializer |
| | anntotationMemberValuePairs |
| ; |
| |
| |
| annotationMemberValueInitializer |
| : conditionalExpression |
| | annotation |
| ; |
| |
| |
| anntotationMemberValuePairs |
| : annotationMemberValuePair ( COMMA nls annotationMemberValuePair )* |
| ; |
| |
| |
| annotationMemberValuePair |
| : IDENT ASSIGN nls annotationMemberValueInitializer |
| ; |
| |
| |
| conditionalExpression |
| : logicalOrExpression |
| ( QUESTION nls assignmentExpression COLON nls conditionalExpression |
| | |
| ) |
| ; |
| |
| |
| annotationMemberArrayValueInitializer |
| : conditionalExpression |
| | annotation nls |
| ; |
| |
| |
| superClassClause |
| : ( "extends" nls classOrInterfaceType nls |
| | |
| ) |
| |
| ; |
| |
| |
| typeParameters |
| : LT nls typeParameter ( COMMA nls typeParameter )* nls |
| ( typeArgumentsOrParametersEnd |
| | |
| ) |
| |
| ; |
| |
| |
| implementsClause |
| : ( "implements" nls classOrInterfaceType ( COMMA nls classOrInterfaceType )* nls |
| | |
| ) |
| |
| ; |
| |
| |
| classBlock |
| : LCURLY |
| ( classField |
| | |
| ) |
| ( sep |
| ( classField |
| | |
| ) )* RCURLY |
| ; |
| |
| |
| interfaceExtends |
| : ( "extends" nls classOrInterfaceType ( COMMA nls classOrInterfaceType )* nls |
| | |
| ) |
| |
| ; |
| |
| |
| interfaceBlock |
| : LCURLY |
| ( interfaceField |
| | |
| ) |
| ( sep |
| ( interfaceField |
| | |
| ) )* RCURLY |
| ; |
| |
| |
| enumBlock |
| : LCURLY |
| ( enumConstants |
| | ( classField |
| | |
| ) |
| ) |
| ( sep |
| ( classField |
| | |
| ) )* RCURLY |
| ; |
| |
| |
| annotationBlock |
| : LCURLY |
| ( annotationField |
| | |
| ) |
| ( sep |
| ( annotationField |
| | |
| ) )* RCURLY |
| ; |
| |
| |
| typeParameter |
| : ( IDENT ) |
| ( typeParameterBounds |
| | |
| ) |
| |
| ; |
| |
| |
| typeParameterBounds |
| : "extends" nls classOrInterfaceType ( BAND nls classOrInterfaceType )* |
| ; |
| |
| |
| classField |
| : modifiersOpt constructorDefinition |
| | declaration |
| | modifiersOpt ( typeDefinitionInternal ) |
| | "static" compoundStatement |
| | compoundStatement |
| ; |
| |
| |
| interfaceField |
| : declaration |
| | modifiersOpt ( typeDefinitionInternal ) |
| ; |
| |
| |
| annotationField |
| : modifiersOpt |
| ( typeDefinitionInternal |
| | typeSpec |
| ( IDENT LPAREN RPAREN |
| ( "default" nls annotationMemberValueInitializer |
| | |
| ) |
| |
| | variableDefinitions |
| ) |
| ) |
| ; |
| |
| |
| /** Guard for enumConstants. */ |
| enumConstantsStart |
| : enumConstant |
| ( COMMA |
| | SEMI |
| | NLS |
| | RCURLY |
| ) |
| ; |
| |
| |
| /** Comma-separated list of one or more enum constant definitions. */ |
| enumConstants |
| : enumConstant ( COMMA nls enumConstant )* |
| ( COMMA nls |
| | |
| ) |
| ; |
| |
| |
| enumConstant |
| : annotationsOpt IDENT |
| ( LPAREN argList RPAREN |
| | |
| ) |
| ( enumConstantBlock |
| | |
| ) |
| |
| ; |
| |
| |
| argList |
| : ( argument ( COMMA argument )* |
| | |
| ) |
| ( COMMA |
| | |
| ) |
| |
| ; |
| |
| |
| enumConstantBlock |
| : LCURLY |
| ( enumConstantField |
| | |
| ) |
| ( sep |
| ( enumConstantField |
| | |
| ) )* RCURLY |
| ; |
| |
| |
| enumConstantField |
| : modifiersOpt |
| ( typeDefinitionInternal |
| | ( typeParameters |
| | |
| ) |
| typeSpec |
| ( IDENT LPAREN parameterDeclarationList RPAREN |
| ( throwsClause |
| | |
| ) |
| ( compoundStatement |
| | |
| ) |
| |
| | variableDefinitions |
| ) |
| ) |
| | compoundStatement |
| ; |
| |
| |
| /** A list of zero or more formal parameters. |
| * If a parameter is variable length (e.g. String... myArg) it should be |
| * to the right of any other parameters of the same kind. |
| * General form: (req, ..., opt, ..., [rest], key, ..., [restKeys], [block] |
| * This must be sorted out after parsing, since the various declaration forms |
| * are impossible to tell apart without backtracking. |
| */ |
| parameterDeclarationList |
| : ( parameterDeclaration ( COMMA nls parameterDeclaration )* |
| | |
| ) |
| |
| ; |
| |
| |
| throwsClause |
| : nls "throws" nls identifier ( COMMA nls identifier )* |
| ; |
| |
| |
| compoundStatement |
| : openBlock |
| ; |
| |
| |
| /** I've split out constructors separately; we could maybe integrate back into variableDefinitions |
| * later on if we maybe simplified 'def' to be a type declaration? |
| */ |
| constructorDefinition |
| : IDENT LPAREN parameterDeclarationList RPAREN |
| ( throwsClause |
| | |
| ) |
| nlsWarn constructorBody |
| ; |
| |
| |
| constructorBody |
| : LCURLY nls |
| ( explicitConstructorInvocation |
| ( sep blockBody |
| | |
| ) |
| | blockBody |
| ) |
| RCURLY |
| ; |
| |
| |
| /** Catch obvious constructor calls, but not the expr.super(...) calls */ |
| explicitConstructorInvocation |
| : ( typeArguments |
| | |
| ) |
| ( "this" LPAREN argList RPAREN |
| | "super" LPAREN argList RPAREN |
| ) |
| ; |
| |
| |
| /** 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 |
| : variableName |
| ( varInitializer |
| | |
| ) |
| |
| ; |
| |
| |
| /** Zero or more insignificant newlines, all gobbled up and thrown away, |
| * but a warning message is left for the user, if there was a newline. |
| */ |
| nlsWarn |
| : ( |
| | |
| ) |
| nls |
| ; |
| |
| |
| /** An open block is not allowed to have closure arguments. */ |
| openBlock |
| : LCURLY nls blockBody RCURLY |
| ; |
| |
| |
| variableName |
| : IDENT |
| ; |
| |
| |
| expression |
| : assignmentExpression |
| ; |
| |
| |
| /** A formal parameter for a method or closure. */ |
| parameterDeclaration |
| : parameterModifiersOpt |
| ( typeSpec |
| | |
| ) |
| ( TRIPLE_DOT |
| | |
| ) |
| IDENT |
| ( varInitializer |
| | |
| ) |
| |
| ; |
| |
| |
| parameterModifiersOpt |
| : ( "def" nls |
| | "final" nls |
| | annotation nls |
| )* |
| |
| ; |
| |
| |
| /** Closure parameters are exactly like method parameters, |
| * except that they are not enclosed in parentheses, but rather |
| * are prepended to the front of a block, just after the brace. |
| * They are separated from the closure body by a CLOSABLE_BLOCK_OP token '->'. |
| */ |
| closableBlockParamsOpt |
| : parameterDeclarationList nls CLOSABLE_BLOCK_OP nls |
| | implicitParameters |
| | |
| ; |
| |
| |
| /** A block known to be a closure, but which omits its arguments, is given this placeholder. |
| * A subsequent pass is responsible for deciding if there is an implicit 'it' parameter, |
| * or if the parameter list should be empty. |
| */ |
| implicitParameters |
| : |
| ; |
| |
| |
| /** Lookahead to check whether a block begins with explicit closure arguments. */ |
| closableBlockParamsStart |
| : parameterDeclarationList nls CLOSABLE_BLOCK_OP |
| ; |
| |
| |
| /** Simple names, as in {x|...}, are completely equivalent to {(def x)|...}. Build the right AST. */ |
| closableBlockParam |
| : IDENT |
| ; |
| |
| |
| /** A block which is known to be a closure, even if it has no apparent arguments. |
| * A block inside an expression or after a method call is always assumed to be a closure. |
| * Only labeled, unparameterized blocks which occur directly as substatements are kept open. |
| */ |
| closableBlock |
| : LCURLY nls closableBlockParamsOpt blockBody RCURLY |
| ; |
| |
| |
| /** A sub-block of a block can be either open or closable. |
| * It is closable if and only if there are explicit closure arguments. |
| * Compare this to a block which is appended to a method call, |
| * which is given closure arguments, even if they are not explicit in the code. |
| */ |
| openOrClosableBlock |
| : LCURLY nls closableBlockParamsOpt blockBody RCURLY |
| ; |
| |
| |
| /** A labeled statement, consisting of a vanilla identifier followed by a colon. */ |
| statementLabelPrefix |
| : IDENT COLON nls |
| ; |
| |
| |
| /** An expression statement can be any general expression. |
| * <p> |
| * An expression statement can also be a <em>command</em>, |
| * which is a simple method call in which the outermost parentheses are omitted. |
| * <p> |
| * Certain "suspicious" looking forms are flagged for the user to disambiguate. |
| */ |
| expressionStatement |
| : ( checkSuspiciousExpressionStatement |
| | |
| ) |
| expression |
| ( commandArguments |
| | |
| ) |
| |
| ; |
| |
| |
| assignmentLessExpression |
| : ( conditionalExpression ) |
| ; |
| |
| |
| /** In Java, "if", "while", and "for" statements can take random, non-braced statements as their bodies. |
| * Support this practice, even though it isn't very Groovy. |
| */ |
| compatibleBodyStatement |
| : compoundStatement |
| | statement |
| ; |
| |
| |
| forStatement |
| : "for" LPAREN |
| ( traditionalForClause |
| | forInClause |
| ) |
| RPAREN nlsWarn compatibleBodyStatement |
| ; |
| |
| |
| /** Things that can show up as expressions, but only in strict |
| * contexts like inside parentheses, argument lists, and list constructors. |
| */ |
| strictContextExpression |
| : ( singleDeclaration |
| | expression |
| | branchStatement |
| | annotation |
| ) |
| |
| ; |
| |
| |
| casesGroup |
| : ( aCase )+ caseSList |
| ; |
| |
| |
| tryBlock |
| : "try" nlsWarn compoundStatement ( nls handler )* |
| ( nls finallyClause |
| | |
| ) |
| ; |
| |
| |
| /** In Groovy, return, break, continue, throw, and assert can be used in a parenthesized expression context. |
| * Example: println (x || (return)); println assert x, "won't print a false value!" |
| * If an optional expression is missing, its value is void (this coerces to null when a value is required). |
| */ |
| branchStatement |
| : "return" |
| ( expression |
| | |
| ) |
| | ( "break" |
| | "continue" |
| ) |
| ( statementLabelPrefix |
| | |
| ) |
| ( expression |
| | |
| ) |
| | "throw" expression |
| | "assert" assignmentLessExpression |
| ( ( COMMA |
| | COLON |
| ) |
| expression |
| | |
| ) |
| ; |
| |
| |
| forInit |
| : declaration |
| | ( controlExpressionList |
| | |
| ) |
| |
| ; |
| |
| |
| traditionalForClause |
| : forInit SEMI forCond SEMI forIter |
| ; |
| |
| |
| forInClause |
| : ( singleDeclarationNoInit |
| | IDENT |
| ) |
| ( "in" shiftExpression |
| | COLON expression |
| ) |
| ; |
| |
| |
| forCond |
| : ( strictContextExpression |
| | |
| ) |
| |
| ; |
| |
| |
| forIter |
| : ( controlExpressionList |
| | |
| ) |
| |
| ; |
| |
| |
| shiftExpression |
| : additiveExpression ( ( ( SL |
| | SR |
| | BSR |
| ) |
| | RANGE_INCLUSIVE |
| | RANGE_EXCLUSIVE |
| ) |
| nls additiveExpression )* |
| ; |
| |
| |
| /** Lookahead for suspicious statement warnings and errors. */ |
| suspiciousExpressionStatementStart |
| : ( ( PLUS |
| | MINUS |
| ) |
| | ( LBRACK |
| | LPAREN |
| | LCURLY |
| ) |
| ) |
| ; |
| |
| |
| /** |
| * If two statements are separated by newline (not SEMI), the second had |
| * better not look like the latter half of an expression. If it does, issue a warning. |
| * <p> |
| * Also, if the expression starts with a closure, it needs to |
| * have an explicit parameter list, in order to avoid the appearance of a |
| * compound statement. This is a hard error. |
| * <p> |
| * These rules are different from Java's "dumb expression" restriction. |
| * Unlike Java, Groovy blocks can end with arbitrary (even dumb) expressions, |
| * as a consequence of optional 'return' and 'continue' tokens. |
| * <p> |
| * To make the programmer's intention clear, a leading closure must have an |
| * explicit parameter list, and must not follow a previous statement separated |
| * only by newlines. |
| */ |
| checkSuspiciousExpressionStatement |
| : ( |
| | |
| ) |
| | |
| | |
| ; |
| |
| |
| /** A member name (x.y) or element name (x[y]) can serve as a command name, |
| * which may be followed by a list of arguments. |
| * Unlike parenthesized arguments, these must be plain expressions, |
| * without labels or spread operators. |
| */ |
| commandArguments |
| : expression ( COMMA nls expression )* |
| ; |
| |
| |
| aCase |
| : ( "case" expression |
| | "default" |
| ) |
| COLON nls |
| ; |
| |
| |
| caseSList |
| : statement ( sep |
| ( statement |
| | |
| ) )* |
| ; |
| |
| |
| controlExpressionList |
| : strictContextExpression ( COMMA nls strictContextExpression )* |
| ; |
| |
| |
| handler |
| : "catch" LPAREN parameterDeclaration RPAREN nlsWarn compoundStatement |
| ; |
| |
| |
| finallyClause |
| : "finally" nlsWarn compoundStatement |
| ; |
| |
| |
| assignmentExpression |
| : conditionalExpression |
| ( ( ASSIGN |
| | PLUS_ASSIGN |
| | MINUS_ASSIGN |
| | STAR_ASSIGN |
| | DIV_ASSIGN |
| | MOD_ASSIGN |
| | SR_ASSIGN |
| | BSR_ASSIGN |
| | SL_ASSIGN |
| | BAND_ASSIGN |
| | BXOR_ASSIGN |
| | BOR_ASSIGN |
| | STAR_STAR_ASSIGN |
| ) |
| nls assignmentExpression |
| | |
| ) |
| ; |
| |
| |
| /** A "path expression" is a name or other primary, possibly qualified by various |
| * forms of dot, and/or followed by various kinds of brackets. |
| * It can be used for value or assigned to, or else further qualified, indexed, or called. |
| * It is called a "path" because it looks like a linear path through a data structure. |
| * Examples: x.y, x?.y, x*.y, x.@y; x[], x[y], x[y,z]; x(), x(y), x(y,z); x{s}; a.b[n].c(x).d{s} |
| * (Compare to a C lvalue, or LeftHandSide in the JLS section 15.26.) |
| * General expressions are built up from path expressions, using operators like '+' and '='. |
| */ |
| pathExpression |
| : primaryExpression |
| ( nls pathElement |
| | nlsWarn appendedBlock |
| )* |
| |
| ; |
| |
| |
| primaryExpression |
| : IDENT |
| | constant |
| | newExpression |
| | "this" |
| | "super" |
| | parenthesizedExpression |
| | closableBlockConstructorExpression |
| | listOrMapConstructorExpression |
| | stringConstructorExpression |
| | scopeEscapeExpression |
| | builtInType |
| ; |
| |
| |
| pathElementStart |
| : ( nls DOT ) |
| | SPREAD_DOT |
| | OPTIONAL_DOT |
| | MEMBER_POINTER |
| | LBRACK |
| | LPAREN |
| | LCURLY |
| ; |
| |
| |
| pathElement |
| : |
| ( SPREAD_DOT |
| | OPTIONAL_DOT |
| | MEMBER_POINTER |
| | ( nls DOT ) |
| ) |
| nls |
| ( typeArguments |
| | |
| ) |
| namePart |
| | methodCallArgs |
| | appendedBlock |
| | indexPropertyArgs |
| ; |
| |
| |
| /** An appended block follows any expression. |
| * If the expression is not a method call, it is given an empty argument list. |
| */ |
| appendedBlock |
| : closableBlock |
| ; |
| |
| |
| /** This is the grammar for what can follow a dot: x.a, x.@a, x.&a, x.'a', etc. |
| * Note: <code>typeArguments</code> is handled by the caller of <code>namePart</code>. |
| */ |
| namePart |
| : ( AT |
| | |
| ) |
| ( IDENT |
| | STRING_LITERAL |
| | dynamicMemberName |
| | openBlock |
| | keywordPropertyNames |
| ) |
| ; |
| |
| |
| /** An expression may be followed by one or both of (...) and {...}. |
| * Note: If either is (...) or {...} present, it is a method call. |
| * The {...} is appended to the argument list, and matches a formal of type Closure. |
| * If there is no method member, a property (or field) is used instead, and must itself be callable. |
| * <p> |
| * If the methodCallArgs are absent, it is a property reference. |
| * If there is no property, it is treated as a field reference, but never a method reference. |
| * <p> |
| * Arguments in the (...) can be labeled, and the appended block can be labeled also. |
| * If there is a mix of unlabeled and labeled arguments, |
| * all the labeled arguments must follow the unlabeled arguments, |
| * except that the closure (labeled or not) is always a separate final argument. |
| * Labeled arguments are collected up and passed as a single argument to a formal of type Map. |
| * <p> |
| * Therefore, f(x,y, a:p, b:q) {s} is equivalent in all ways to f(x,y, [a:p,b:q], {s}). |
| * Spread arguments of sequence type count as unlabeled arguments, |
| * while spread arguments of map type count as labeled arguments. |
| * (This distinction must sometimes be checked dynamically.) |
| * |
| * A plain unlabeled argument is allowed to match a trailing Map or Closure argument: |
| * f(x, a:p) {s} === f(*[ x, [a:p], {s} ]) |
| */ |
| methodCallArgs |
| : LPAREN argList RPAREN |
| ; |
| |
| |
| /** An expression may be followed by [...]. |
| * Unlike Java, these brackets may contain a general argument list, |
| * which is passed to the array element operator, which can make of it what it wants. |
| * The brackets may also be empty, as in T[]. This is how Groovy names array types. |
| * <p>Returned AST is [INDEX_OP, indexee, ELIST]. |
| */ |
| indexPropertyArgs |
| : LBRACK argList RBRACK |
| ; |
| |
| |
| /** If a dot is followed by a parenthesized or quoted expression, the member is computed dynamically, |
| * and the member selection is done only at runtime. This forces a statically unchecked member access. |
| */ |
| dynamicMemberName |
| : ( parenthesizedExpression |
| | stringConstructorExpression |
| ) |
| |
| ; |
| |
| |
| /** Allowed keywords after dot (as a member name) and before colon (as a label). |
| * TODO: What's the rationale for these? |
| */ |
| keywordPropertyNames |
| : ( "class" |
| | "in" |
| | "as" |
| | "def" |
| | "if" |
| | "else" |
| | "for" |
| | "while" |
| | "do" |
| | "switch" |
| | "try" |
| | "catch" |
| | "finally" |
| | builtInType |
| ) |
| |
| ; |
| |
| |
| parenthesizedExpression |
| : LPAREN strictContextExpression RPAREN |
| ; |
| |
| |
| stringConstructorExpression |
| : STRING_CTOR_START stringConstructorValuePart ( STRING_CTOR_MIDDLE stringConstructorValuePart )* STRING_CTOR_END |
| ; |
| |
| |
| logicalOrExpression |
| : logicalAndExpression ( LOR nls logicalAndExpression )* |
| ; |
| |
| |
| logicalAndExpression |
| : inclusiveOrExpression ( LAND nls inclusiveOrExpression )* |
| ; |
| |
| |
| inclusiveOrExpression |
| : exclusiveOrExpression ( BOR nls exclusiveOrExpression )* |
| ; |
| |
| |
| exclusiveOrExpression |
| : andExpression ( BXOR nls andExpression )* |
| ; |
| |
| |
| andExpression |
| : regexExpression ( BAND nls regexExpression )* |
| ; |
| |
| |
| regexExpression |
| : equalityExpression ( ( REGEX_FIND |
| | REGEX_MATCH |
| ) |
| nls equalityExpression )* |
| ; |
| |
| |
| equalityExpression |
| : relationalExpression ( ( NOT_EQUAL |
| | EQUAL |
| | COMPARE_TO |
| ) |
| nls relationalExpression )* |
| ; |
| |
| |
| relationalExpression |
| : shiftExpression |
| ( ( ( LT |
| | GT |
| | LE |
| | GE |
| | "in" |
| ) |
| nls shiftExpression |
| | |
| ) |
| | "instanceof" nls typeSpec |
| | "as" nls typeSpec |
| ) |
| ; |
| |
| |
| additiveExpression |
| : multiplicativeExpression ( ( PLUS |
| | MINUS |
| ) |
| nls multiplicativeExpression )* |
| ; |
| |
| |
| multiplicativeExpression |
| : ( INC nls powerExpressionNotPlusMinus ( ( STAR |
| | DIV |
| | MOD |
| ) |
| nls powerExpression )* ) |
| | ( DEC nls powerExpressionNotPlusMinus ( ( STAR |
| | DIV |
| | MOD |
| ) |
| nls powerExpression )* ) |
| | ( MINUS nls powerExpressionNotPlusMinus ( ( STAR |
| | DIV |
| | MOD |
| ) |
| nls powerExpression )* ) |
| | ( PLUS nls powerExpressionNotPlusMinus ( ( STAR |
| | DIV |
| | MOD |
| ) |
| nls powerExpression )* ) |
| | ( powerExpressionNotPlusMinus ( ( STAR |
| | DIV |
| | MOD |
| ) |
| nls powerExpression )* ) |
| ; |
| |
| |
| powerExpressionNotPlusMinus |
| : unaryExpressionNotPlusMinus ( STAR_STAR nls unaryExpression )* |
| ; |
| |
| |
| powerExpression |
| : unaryExpression ( STAR_STAR nls unaryExpression )* |
| ; |
| |
| |
| unaryExpression |
| : INC nls unaryExpression |
| | DEC nls unaryExpression |
| | MINUS nls unaryExpression |
| | PLUS nls unaryExpression |
| | unaryExpressionNotPlusMinus |
| ; |
| |
| |
| unaryExpressionNotPlusMinus |
| : BNOT nls unaryExpression |
| | LNOT nls unaryExpression |
| | ( LPAREN builtInTypeSpec RPAREN unaryExpression |
| | LPAREN classTypeSpec RPAREN unaryExpressionNotPlusMinus |
| | postfixExpression |
| ) |
| ; |
| |
| |
| postfixExpression |
| : pathExpression |
| ( INC |
| | DEC |
| | |
| ) |
| ; |
| |
| |
| /** Numeric, string, regexp, boolean, or null constant. */ |
| constant |
| : constantNumber |
| | STRING_LITERAL |
| | "true" |
| | "false" |
| | "null" |
| ; |
| |
| |
| /** object instantiation. |
| * Trees are built as illustrated by the following input/tree pairs: |
| * |
| * new T() |
| * |
| * new |
| * | |
| * T -- ELIST |
| * | |
| * arg1 -- arg2 -- .. -- argn |
| * |
| * new int[] |
| * |
| * new |
| * | |
| * int -- ARRAY_DECLARATOR |
| * |
| * new int[] {1,2} |
| * |
| * new |
| * | |
| * int -- ARRAY_DECLARATOR -- ARRAY_INIT |
| * | |
| * EXPR -- EXPR |
| * | | |
| * 1 2 |
| * |
| * new int[3] |
| * new |
| * | |
| * int -- ARRAY_DECLARATOR |
| * | |
| * EXPR |
| * | |
| * 3 |
| * |
| * new int[1][2] |
| * |
| * new |
| * | |
| * int -- ARRAY_DECLARATOR |
| * | |
| * ARRAY_DECLARATOR -- EXPR |
| * | | |
| * EXPR 1 |
| * | |
| * 2 |
| * |
| */ |
| newExpression |
| : "new" nls |
| ( typeArguments |
| | |
| ) |
| type |
| ( nls methodCallArgs |
| ( appendedBlock |
| | |
| ) |
| |
| | newArrayDeclarator |
| ) |
| ; |
| |
| |
| closableBlockConstructorExpression |
| : closableBlock |
| ; |
| |
| |
| /** |
| * A list constructor is a argument list enclosed in square brackets, without labels. |
| * Any argument can be decorated with a spread operator (*x), but not a label (a:x). |
| * Examples: [], [1], [1,2], [1,*l1,2], [*l1,*l2]. |
| * (The l1, l2 must be a sequence or null.) |
| * <p> |
| * A map constructor is an argument list enclosed in square brackets, with labels everywhere, |
| * except on spread arguments, which stand for whole maps spliced in. |
| * A colon alone between the brackets also forces the expression to be an empty map constructor. |
| * Examples: [:], [a:1], [a:1,b:2], [a:1,*:m1,b:2], [*:m1,*:m2] |
| * (The m1, m2 must be a map or null.) |
| * Values associated with identical keys overwrite from left to right: |
| * [a:1,a:2] === [a:2] |
| * <p> |
| * Some malformed constructor expressions are not detected in the parser, but in a post-pass. |
| * Bad examples: [1,b:2], [a:1,2], [:1]. |
| * (Note that method call arguments, by contrast, can be a mix of keyworded and non-keyworded arguments.) |
| */ |
| listOrMapConstructorExpression |
| : LBRACK argList RBRACK |
| | LBRACK COLON RBRACK |
| ; |
| |
| |
| scopeEscapeExpression |
| : DOLLAR |
| ( IDENT |
| | scopeEscapeExpression |
| ) |
| ; |
| |
| |
| stringConstructorValuePart |
| : ( STAR |
| | |
| ) |
| ( identifier |
| | openOrClosableBlock |
| ) |
| ; |
| |
| |
| newArrayDeclarator |
| : ( LBRACK |
| ( expression |
| | |
| ) |
| RBRACK )+ |
| ; |
| |
| |
| /** A single argument in (...) or [...]. Corresponds to to a method or closure parameter. |
| * May be labeled. May be modified by the spread operator '*' ('*:' for keywords). |
| */ |
| argument |
| : ( argumentLabel COLON |
| | STAR |
| ( COLON |
| | |
| ) |
| | |
| ) |
| strictContextExpression |
| ; |
| |
| |
| /** For lookahead only. Fast approximate parse of an argumentLabel followed by a colon. */ |
| argumentLabelStart |
| : ( IDENT |
| | keywordPropertyNames |
| | constantNumber |
| | STRING_LITERAL |
| | balancedBrackets |
| ) |
| COLON |
| ; |
| |
| |
| /** A label for an argument is of the form a:b, 'a':b, "a":b, (a):b, etc.. |
| * The labels in (a:b), ('a':b), and ("a":b) are in all ways equivalent, |
| * except that the quotes allow more spellings. |
| * Equivalent dynamically computed labels are (('a'):b) and ("${'a'}":b) |
| * but not ((a):b) or "$a":b, since the latter cases evaluate (a) as a normal identifier. |
| * Bottom line: If you want a truly variable label, use parens and say ((a):b). |
| */ |
| argumentLabel |
| : IDENT |
| | keywordPropertyNames |
| | primaryExpression |
| ; |
| |
| |
| /** Numeric constant. */ |
| constantNumber |
| : NUM_INT |
| | NUM_FLOAT |
| | NUM_LONG |
| | NUM_DOUBLE |
| | NUM_BIG_INT |
| | NUM_BIG_DECIMAL |
| ; |
| |
| |
| /** Fast lookahead across balanced brackets of all sorts. */ |
| balancedBrackets |
| : LPAREN balancedTokens RPAREN |
| | LBRACK balancedTokens RBRACK |
| | LCURLY balancedTokens RCURLY |
| | STRING_CTOR_START balancedTokens STRING_CTOR_END |
| ; |
| |
| |