Grammar GroovyRecognizer
ANTLR-generated HTML file from /home/users/jez/projects/groovy.head/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 
		(	openOrClosedBlock 
		|	statement 
		) 
	|	expressionStatement 
	|	modifiersOpt typeDefinitionInternal 
	|	"if" LPAREN strictContextExpression 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
	:	"throws" nls identifier ( COMMA nls identifier )* nls 
	;


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 
		)* 
		
	;


/** A simplified formal parameter for closures, can occur outside parens.
 *  It is not confused by a lookahead of BOR.
 *  DECIDE:  Is thie necessary, or do we change the closure-bar syntax?
 */
simpleParameterDeclaration
	:	(	typeSpec 
		|	
		) 
		IDENT 
	;


/** Simplified formal parameter list for closures.  Never empty. */
simpleParameterDeclarationList
	:	simpleParameterDeclaration ( COMMA nls simpleParameterDeclaration )* 
	;


/** 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 CLOSURE_OP token '->'.
 */
closureParametersOpt
	:	parameterDeclarationList nls CLOSURE_OP nls 
	|	oldClosureParameters 
	|	implicitParameters 
	|	
	;


/** Lookahead for oldClosureParameters. */
oldClosureParametersStart
	:	BOR 
	|	LOR 
	|	LPAREN balancedTokens RPAREN nls BOR 
	|	simpleParameterDeclarationList BOR 
	;


/** Provisional definition of old-style closure params based on BOR '|'.
 *  Going away soon, perhaps... */
oldClosureParameters
	:	LOR nls 
	|	BOR nls BOR nls 
	|	(	BOR nls 
		|	
		) 
		LPAREN parameterDeclarationList RPAREN nls BOR nls 
	|	(	BOR nls 
		|	
		) 
		simpleParameterDeclarationList nls BOR nls 
	;


/** 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. */
closureParametersStart
	:	oldClosureParametersStart 
	|	parameterDeclarationList nls CLOSURE_OP 
	;


/** Simple names, as in {x|...}, are completely equivalent to {(def x)|...}.  Build the right AST. */
closureParameter
	:	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.
 */
closedBlock
	:	LCURLY nls closureParametersOpt blockBody RCURLY 
	;


/** A sub-block of a block can be either open or closed.
 *  It is closed 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.
 */
openOrClosedBlock
	:	LCURLY nls closureParametersOpt blockBody RCURLY 
	;


/** A labeled statement, consisting of a vanilla identifier followed by a colon. */
statementLabelPrefix
	:	IDENT COLON 
	;


/** 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 
		|	
		) 
		
	;


/** 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 
		) 
		
	;


/** 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 
	;


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" expression 
		(	(	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 
			|	TRIPLE_DOT 
			) 
			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 
	|	closureConstructorExpression 
	|	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
	:	closedBlock 
	;


/** 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 powerExpression ( (	STAR 
				|	DIV 
				|	MOD 
				) 
				nls powerExpression )* ) 
	|	( DEC nls powerExpression ( (	STAR 
				|	DIV 
				|	MOD 
				) 
				nls powerExpression )* ) 
	|	( MINUS nls powerExpression ( (	STAR 
				|	DIV 
				|	MOD 
				) 
				nls powerExpression )* ) 
	|	( PLUS nls powerExpression ( (	STAR 
				|	DIV 
				|	MOD 
				) 
				nls powerExpression )* ) 
	|	( powerExpression ( (	STAR 
				|	DIV 
				|	MOD 
				) 
				nls powerExpression )* ) 
	;


powerExpression
	:	unaryExpressionNotPlusMinus ( STAR_STAR nls unaryExpression )* 
	;


unaryExpressionNotPlusMinus
	:	BNOT nls unaryExpression 
	|	LNOT nls unaryExpression 
	|	(	LPAREN builtInTypeSpec RPAREN unaryExpression 
		|	LPAREN classTypeSpec RPAREN unaryExpressionNotPlusMinus 
		|	postfixExpression 
		) 
	;


unaryExpression
	:	INC nls unaryExpression 
	|	DEC nls unaryExpression 
	|	MINUS nls unaryExpression 
	|	PLUS nls unaryExpression 
	|	unaryExpressionNotPlusMinus 
	;


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 
			|	
			) 
			
		|	appendedBlock 
		|	newArrayDeclarator 
		) 
	;


closureConstructorExpression
	:	closedBlock 
	;


/**
 * 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 
		|	openOrClosedBlock 
		) 
	;


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 
	;