/* * This file is adapted from the Antlr4 Java grammar which has the following license * * Copyright (c) 2013 Terence Parr, Sam Harwell * All rights reserved. * [The "BSD licence"] * * http://www.opensource.org/licenses/bsd-license.php * * Subsequent modifications by the Groovy community have been done under the Apache License v2: * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ /** * The Groovy grammar is based on the official grammar for Java: * https://github.com/antlr/grammars-v4/blob/master/java/Java.g4 */ parser grammar GroovyParser; options { tokenVocab = GroovyLexer; contextSuperClass = GroovyParserRuleContext; superClass = AbstractParser; } @header { import java.util.Map; import org.codehaus.groovy.ast.NodeMetaDataHandler; } @members { private int inSwitchExpressionLevel = 0; public static class GroovyParserRuleContext extends ParserRuleContext implements NodeMetaDataHandler { private Map metaDataMap = null; public GroovyParserRuleContext() {} public GroovyParserRuleContext(ParserRuleContext parent, int invokingStateNumber) { super(parent, invokingStateNumber); } @Override public Map getMetaDataMap() { return this.metaDataMap; } @Override public void setMetaDataMap(Map metaDataMap) { this.metaDataMap = metaDataMap; } } @Override public int getSyntaxErrorSource() { return GroovySyntaxError.PARSER; } @Override public int getErrorLine() { Token token = _input.LT(-1); if (null == token) { return -1; } return token.getLine(); } @Override public int getErrorColumn() { Token token = _input.LT(-1); if (null == token) { return -1; } return token.getCharPositionInLine() + 1 + token.getText().length(); } } // starting point for parsing a groovy file compilationUnit : nls (packageDeclaration sep?)? scriptStatements? EOF ; scriptStatements : scriptStatement (sep scriptStatement)* sep? ; scriptStatement : importDeclaration // Import statement. Can be used in any scope. Has "import x as y" also. | typeDeclaration // validate the method in the AstBuilder#visitMethodDeclaration, e.g. method without method body is not allowed | { !SemanticPredicates.isInvalidMethodDeclaration(_input) }? methodDeclaration[3, 9] | statement ; packageDeclaration : annotationsOpt PACKAGE qualifiedName ; importDeclaration : annotationsOpt IMPORT STATIC? qualifiedName (DOT MUL | AS alias=identifier)? ; typeDeclaration : classOrInterfaceModifiersOpt classDeclaration ; modifier : classOrInterfaceModifier | m=( NATIVE | SYNCHRONIZED | TRANSIENT | VOLATILE | DEF | VAR ) ; modifiersOpt : (modifiers nls)? ; modifiers : modifier (nls modifier)* ; classOrInterfaceModifiersOpt : (classOrInterfaceModifiers NL* /* Use `NL*` here for better performance, so DON'T replace it with `nls` */ )? ; classOrInterfaceModifiers : classOrInterfaceModifier (nls classOrInterfaceModifier)* ; classOrInterfaceModifier : annotation // class or interface | m=( PUBLIC // class or interface | PROTECTED // class or interface | PRIVATE // class or interface | STATIC // class or interface | ABSTRACT // class or interface | SEALED // class or interface | NON_SEALED // class or interface | FINAL // class only -- does not apply to interfaces | STRICTFP // class or interface | DEFAULT // interface only -- does not apply to classes ) ; variableModifier : annotation | m=( FINAL | DEF | VAR // Groovy supports declaring local variables as instance/class fields, // e.g. import groovy.transform.*; @Field static List awe = [1, 2, 3] // e.g. import groovy.transform.*; def a = { @Field public List awe = [1, 2, 3] } // Notice: Groovy 2.4.7 just allows to declare local variables with the following modifiers when using annotations(e.g. @Field) // TODO check whether the following modifiers accompany annotations or not. Because the legacy codes(e.g. benchmark/bench/heapsort.groovy) allow to declare the special instance/class fields without annotations, we leave it as it is for the time being | PUBLIC | PROTECTED | PRIVATE | STATIC | ABSTRACT | STRICTFP ) ; variableModifiersOpt : (variableModifiers nls)? ; variableModifiers : variableModifier (nls variableModifier)* ; typeParameters : LT nls typeParameter (COMMA nls typeParameter)* nls GT ; typeParameter : annotationsOpt className (EXTENDS nls typeBound)? ; typeBound : type (BITAND nls type)* ; typeList : type (COMMA nls type)* ; /** * t 0: class; 1: interface; 2: enum; 3: annotation; 4: trait; 5: record */ classDeclaration locals[ int t ] : ( CLASS { $t = 0; } | INTERFACE { $t = 1; } | ENUM { $t = 2; } | AT INTERFACE { $t = 3; } | TRAIT { $t = 4; } | RECORD { $t = 5; } ) identifier (nls typeParameters)? (nls formalParameters)? (nls EXTENDS nls scs=typeList)? (nls IMPLEMENTS nls is=typeList)? (nls PERMITS nls ps=typeList)? nls classBody[$t] ; // t see the comment of classDeclaration classBody[int t] : LBRACE nls ( /* Only enum can have enum constants */ { 2 == $t }? enumConstants (nls COMMA)? sep? | ) (classBodyDeclaration[$t] (sep classBodyDeclaration[$t])*)? sep? RBRACE ; enumConstants : enumConstant (nls COMMA nls enumConstant)* ; enumConstant : annotationsOpt identifier arguments? anonymousInnerClassDeclaration[1]? ; classBodyDeclaration[int t] : (STATIC nls)? block | memberDeclaration[$t] ; memberDeclaration[int t] : methodDeclaration[0, $t] | fieldDeclaration | modifiersOpt ( classDeclaration | compactConstructorDeclaration ) ; /** * t 0: *class member* all kinds of method declaration AND constructor declaration, * 1: normal method declaration, 2: abstract method declaration * 3: normal method declaration OR abstract method declaration * ct 9: script, other see the comment of classDeclaration */ methodDeclaration[int t, int ct] : modifiersOpt typeParameters? (returnType[$ct] nls)? methodName formalParameters ( DEFAULT nls elementValue | (nls THROWS nls qualifiedClassNameList)? (nls methodBody)? )? ; compactConstructorDeclaration : methodName nls methodBody ; methodName : identifier | stringLiteral ; returnType[int ct] : standardType | VOID ; fieldDeclaration : variableDeclaration[1] ; variableDeclarators : variableDeclarator (COMMA nls variableDeclarator)* ; variableDeclarator : variableDeclaratorId (nls ASSIGN nls variableInitializer)? ; variableDeclaratorId : identifier ; variableInitializer : enhancedStatementExpression ; variableInitializers : variableInitializer (nls COMMA nls variableInitializer)* nls COMMA? ; emptyDims : (annotationsOpt LBRACK RBRACK)+ ; emptyDimsOpt : emptyDims? ; standardType options { baseContext = type; } : annotationsOpt ( primitiveType | standardClassOrInterfaceType ) emptyDimsOpt ; type : annotationsOpt ( ( primitiveType | // !!! Error Alternative !!! VOID ) | generalClassOrInterfaceType ) emptyDimsOpt ; classOrInterfaceType : ( qualifiedClassName | qualifiedStandardClassName ) typeArguments? ; generalClassOrInterfaceType options { baseContext = classOrInterfaceType; } : qualifiedClassName typeArguments? ; standardClassOrInterfaceType options { baseContext = classOrInterfaceType; } : qualifiedStandardClassName typeArguments? ; primitiveType : BuiltInPrimitiveType ; typeArguments : LT nls typeArgument (COMMA nls typeArgument)* nls GT ; typeArgument : type | annotationsOpt QUESTION ((EXTENDS | SUPER) nls type)? ; annotatedQualifiedClassName : annotationsOpt qualifiedClassName ; qualifiedClassNameList : annotatedQualifiedClassName (COMMA nls annotatedQualifiedClassName)* ; formalParameters : LPAREN formalParameterList? rparen ; formalParameterList : (formalParameter | thisFormalParameter) (COMMA nls formalParameter)* ; thisFormalParameter : type THIS ; formalParameter : variableModifiersOpt type? ELLIPSIS? variableDeclaratorId (nls ASSIGN nls expression)? ; methodBody : block ; qualifiedName : qualifiedNameElement (DOT qualifiedNameElement)* ; /** * Java doesn't have the keywords 'as', 'in', 'def', 'trait' so we make some allowances * for them in package names for better integration with existing Java packages */ qualifiedNameElement : identifier | DEF | IN | AS | TRAIT ; qualifiedNameElements : (qualifiedNameElement DOT)* ; qualifiedClassName : qualifiedNameElements identifier ; qualifiedStandardClassName : qualifiedNameElements className (DOT className)* ; literal : IntegerLiteral #integerLiteralAlt | FloatingPointLiteral #floatingPointLiteralAlt | stringLiteral #stringLiteralAlt | BooleanLiteral #booleanLiteralAlt | NullLiteral #nullLiteralAlt ; // GSTRING gstring : GStringBegin gstringValue (GStringPart gstringValue)* GStringEnd ; gstringValue : gstringPath | closure ; gstringPath : identifier GStringPathPart* ; // LAMBDA EXPRESSION lambdaExpression options { baseContext = standardLambdaExpression; } : lambdaParameters nls ARROW nls lambdaBody ; // JAVA STANDARD LAMBDA EXPRESSION standardLambdaExpression : standardLambdaParameters nls ARROW nls lambdaBody ; lambdaParameters options { baseContext = standardLambdaParameters; } : formalParameters // { a -> a * 2 } can be parsed as a lambda expression in a block, but we expect a closure. // So it is better to put parameters in the parentheses and the following single parameter without parentheses is limited // | variableDeclaratorId ; standardLambdaParameters : formalParameters | variableDeclaratorId ; lambdaBody : block | statementExpression ; // CLOSURE closure : LBRACE (nls (formalParameterList nls)? ARROW)? sep? blockStatementsOpt RBRACE ; // GROOVY-8991: Difference in behaviour with closure and lambda closureOrLambdaExpression : closure | lambdaExpression ; blockStatementsOpt : blockStatements? ; blockStatements : blockStatement (sep blockStatement)* sep? ; // ANNOTATIONS annotationsOpt : (annotation (nls annotation)* nls)? ; annotation : AT annotationName (nls LPAREN elementValues? rparen)? ; elementValues : elementValuePairs | elementValue ; annotationName : qualifiedClassName ; elementValuePairs : elementValuePair (COMMA elementValuePair)* ; elementValuePair : elementValuePairName nls ASSIGN nls elementValue ; elementValuePairName : identifier | keywords ; // TODO verify the potential performance issue because rule expression contains sub-rule assignments(https://github.com/antlr/grammars-v4/issues/215) elementValue : elementValueArrayInitializer | annotation | expression ; elementValueArrayInitializer : LBRACK (elementValue (COMMA elementValue)* COMMA?)? RBRACK ; // STATEMENTS / BLOCKS block : LBRACE sep? blockStatementsOpt RBRACE ; blockStatement : localVariableDeclaration | statement ; localVariableDeclaration : { !SemanticPredicates.isInvalidLocalVariableDeclaration(_input) }? variableDeclaration[0] ; /** * t 0: local variable declaration; 1: field declaration */ variableDeclaration[int t] : modifiers nls ( type? variableDeclarators | typeNamePairs nls ASSIGN nls variableInitializer ) | type variableDeclarators ; typeNamePairs : LPAREN typeNamePair (COMMA typeNamePair)* rparen ; typeNamePair : type? variableDeclaratorId ; variableNames : LPAREN variableDeclaratorId (COMMA variableDeclaratorId)+ rparen ; conditionalStatement : ifElseStatement | switchStatement ; ifElseStatement : IF expressionInPar nls tb=statement ((nls | sep) ELSE nls fb=statement)? ; switchStatement : SWITCH expressionInPar nls LBRACE nls (switchBlockStatementGroup+ nls)? RBRACE ; loopStatement : FOR LPAREN forControl rparen nls statement #forStmtAlt | WHILE expressionInPar nls statement #whileStmtAlt | DO nls statement nls WHILE expressionInPar #doWhileStmtAlt ; continueStatement : CONTINUE identifier? ; breakStatement : BREAK identifier? ; yieldStatement : YIELD expression ; tryCatchStatement : TRY resources? nls block (nls catchClause)* (nls finallyBlock)? ; assertStatement : ASSERT ce=expression (nls (COLON | COMMA) nls me=expression)? ; statement : block #blockStmtAlt | conditionalStatement #conditionalStmtAlt | loopStatement #loopStmtAlt | tryCatchStatement #tryCatchStmtAlt | SYNCHRONIZED expressionInPar nls block #synchronizedStmtAlt | RETURN expression? #returnStmtAlt | THROW expression #throwStmtAlt | breakStatement #breakStmtAlt | continueStatement #continueStmtAlt | { inSwitchExpressionLevel > 0 }? yieldStatement #yieldStmtAlt | identifier COLON nls statement #labeledStmtAlt | assertStatement #assertStmtAlt | localVariableDeclaration #localVariableDeclarationStmtAlt | statementExpression #expressionStmtAlt | SEMI #emptyStmtAlt ; catchClause : CATCH LPAREN variableModifiersOpt catchType? identifier rparen nls block ; catchType : qualifiedClassName (BITOR qualifiedClassName)* ; finallyBlock : FINALLY nls block ; resources : LPAREN nls resourceList sep? rparen ; resourceList : resource (sep resource)* ; resource : localVariableDeclaration | expression ; /** Matches cases then statements, both of which are mandatory. * To handle empty cases at the end, we add switchLabel* to statement. */ switchBlockStatementGroup : switchLabel (nls switchLabel)* nls blockStatements ; switchLabel : CASE expression COLON | DEFAULT COLON ; forControl : enhancedForControl | classicalForControl ; enhancedForControl : variableModifiersOpt type? variableDeclaratorId (COLON | IN) expression ; classicalForControl : forInit? SEMI expression? SEMI forUpdate? ; forInit : localVariableDeclaration | expressionList[false] ; forUpdate : expressionList[false] ; // EXPRESSIONS castParExpression : LPAREN type rparen ; parExpression : expressionInPar ; expressionInPar : LPAREN enhancedStatementExpression rparen ; expressionList[boolean canSpread] : expressionListElement[$canSpread] (COMMA nls expressionListElement[$canSpread])* ; expressionListElement[boolean canSpread] : MUL? expression ; enhancedStatementExpression : statementExpression | standardLambdaExpression ; statementExpression : commandExpression #commandExprAlt ; postfixExpression : pathExpression op=(INC | DEC)? ; switchExpression @init { inSwitchExpressionLevel++; } @after { inSwitchExpressionLevel--; } : SWITCH expressionInPar nls LBRACE nls switchBlockStatementExpressionGroup* nls RBRACE ; switchBlockStatementExpressionGroup : (switchExpressionLabel nls)+ blockStatements ; switchExpressionLabel : ( CASE expressionList[true] | DEFAULT ) ac=(ARROW | COLON) ; expression // must come before postfixExpression to resovle the ambiguities between casting and call on parentheses expression, e.g. (int)(1 / 2) : castParExpression castOperandExpression #castExprAlt // qualified names, array expressions, method invocation, post inc/dec | postfixExpression #postfixExprAlt | switchExpression #switchExprAlt // ~(BNOT)/!(LNOT) (level 1) | (BITNOT | NOT) nls expression #unaryNotExprAlt // math power operator (**) (level 2) | left=expression op=POWER nls right=expression #powerExprAlt // ++(prefix)/--(prefix)/+(unary)/-(unary) (level 3) | op=(INC | DEC | ADD | SUB) expression #unaryAddExprAlt // multiplication/division/modulo (level 4) | left=expression nls op=(MUL | DIV | MOD) nls right=expression #multiplicativeExprAlt // binary addition/subtraction (level 5) | left=expression op=(ADD | SUB) nls right=expression #additiveExprAlt // bit shift expressions (level 6) | left=expression nls ( ( dlOp=LT LT | tgOp=GT GT GT | dgOp=GT GT ) | rangeOp=( RANGE_INCLUSIVE | RANGE_EXCLUSIVE_LEFT | RANGE_EXCLUSIVE_RIGHT | RANGE_EXCLUSIVE_FULL ) ) nls right=expression #shiftExprAlt // boolean relational expressions (level 7) | left=expression nls op=(AS | INSTANCEOF | NOT_INSTANCEOF) nls type #relationalExprAlt | left=expression nls op=(LE | GE | GT | LT | IN | NOT_IN) nls right=expression #relationalExprAlt // equality/inequality (==/!=) (level 8) | left=expression nls op=( IDENTICAL | NOT_IDENTICAL | EQUAL | NOTEQUAL | SPACESHIP ) nls right=expression #equalityExprAlt // regex find and match (=~ and ==~) (level 8.5) // jez: moved =~ closer to precedence of == etc, as... // 'if (foo =~ "a.c")' is very close in intent to 'if (foo == "abc")' | left=expression nls op=(REGEX_FIND | REGEX_MATCH) nls right=expression #regexExprAlt // bitwise or non-short-circuiting and (&) (level 9) | left=expression nls op=BITAND nls right=expression #andExprAlt // exclusive or (^) (level 10) | left=expression nls op=XOR nls right=expression #exclusiveOrExprAlt // bitwise or non-short-circuiting or (|) (level 11) | left=expression nls op=BITOR nls right=expression #inclusiveOrExprAlt // logical and (&&) (level 12) | left=expression nls op=AND nls right=expression #logicalAndExprAlt // logical or (||) (level 13) | left=expression nls op=OR nls right=expression #logicalOrExprAlt // conditional test (level 14) | con=expression nls ( QUESTION nls tb=expression nls COLON nls | ELVIS nls ) fb=expression #conditionalExprAlt // assignment expression (level 15) // "(a) = [1]" is a special case of multipleAssignmentExprAlt, it will be handle by assignmentExprAlt | left=variableNames nls op=ASSIGN nls right=statementExpression #multipleAssignmentExprAlt | left=expression nls op=( ASSIGN | ADD_ASSIGN | SUB_ASSIGN | MUL_ASSIGN | DIV_ASSIGN | AND_ASSIGN | OR_ASSIGN | XOR_ASSIGN | RSHIFT_ASSIGN | URSHIFT_ASSIGN | LSHIFT_ASSIGN | MOD_ASSIGN | POWER_ASSIGN | ELVIS_ASSIGN ) nls right=enhancedStatementExpression #assignmentExprAlt ; castOperandExpression options { baseContext = expression; } : castParExpression castOperandExpression #castExprAlt | postfixExpression #postfixExprAlt // ~(BNOT)/!(LNOT) | (BITNOT | NOT) nls castOperandExpression #unaryNotExprAlt // ++(prefix)/--(prefix)/+(unary)/-(unary) | op=(INC | DEC | ADD | SUB) castOperandExpression #unaryAddExprAlt ; commandExpression : expression ( { !SemanticPredicates.isFollowingArgumentsOrClosure($expression.ctx) }? argumentList | /* if pathExpression is a method call, no need to have any more arguments */ ) commandArgument* ; commandArgument : commandPrimary // what follows is either a normal argument, parens, // an appended block, an index operation, or nothing // parens (a b already processed): // a b c() d e -> a(b).c().d(e) // a b c()() d e -> a(b).c().call().d(e) // index (a b already processed): // a b c[x] d e -> a(b).c[x].d(e) // a b c[x][y] d e -> a(b).c[x][y].d(e) // block (a b already processed): // a b c {x} d e -> a(b).c({x}).d(e) // // parens/block completes method call // index makes method call to property get with index // ( pathElement+ | argumentList )? ; /** * 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 '='. * * t 0: primary, 1: namePart, 2: arguments, 3: closureOrLambdaExpression, 4: indexPropertyArgs, 5: namedPropertyArgs, * 6: non-static inner class creator */ pathExpression returns [int t] : ( primary | // if 'static' followed by DOT, we can treat them as identifiers, e.g. static.unused = { -> } { _input.LT(2).getType() == DOT }? STATIC ) (pathElement { $t = $pathElement.t; })* ; pathElement returns [int t] : nls ( DOT nls NEW creator[1] { $t = 6; } | // AT: foo.@bar selects the field (or attribute), not property ( ( DOT // The all-powerful dot. | SPREAD_DOT // Spread operator: x*.y === x?.collect{it.y} | SAFE_DOT // Optional-null operator: x?.y === (x==null)?null:x.y | SAFE_CHAIN_DOT // Optional-null chain operator: x??.y.z === x?.y?.z ) nls (AT | nonWildcardTypeArguments)? | METHOD_POINTER nls // Method pointer operator: foo.&y == foo.metaClass.getMethodPointer(foo, "y") | METHOD_REFERENCE nls // Method reference: System.out::println ) namePart { $t = 1; } // Can always append a block, as foo{bar} | closureOrLambdaExpression { $t = 3; } ) | arguments { $t = 2; } // Element selection is always an option, too. // In Groovy, the stuff between brackets is a general argument list, // since the bracket operator is transformed into a method call. | indexPropertyArgs { $t = 4; } | namedPropertyArgs { $t = 5; } ; /** * This is the grammar for what can follow a dot: x.a, x.@a, x.&a, x.'a', etc. */ namePart : ( identifier // foo.'bar' is in all ways same as foo.bar, except that bar can have an arbitrary spelling | stringLiteral | dynamicMemberName /* just a PROPOSAL, which has not been implemented yet! // PROPOSAL, DECIDE: Is this inline form of the 'with' statement useful? // Definition: a.{foo} === {with(a) {foo}} // May cover some path expression use-cases previously handled by dynamic scoping (closure delegates). | block */ // let's allow common keywords as property names | keywords ) ; /** * 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 : parExpression | gstring ; /** 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. */ indexPropertyArgs : (SAFE_INDEX | LBRACK) expressionList[true]? RBRACK ; namedPropertyArgs : (SAFE_INDEX | LBRACK) (namedPropertyArgList | COLON) RBRACK ; primary : // Append `typeArguments?` to `identifier` to support constructor reference with generics, e.g. HashMap::new // Though this is not a graceful solution, it is much faster than replacing `builtInType` with `type` identifier typeArguments? #identifierPrmrAlt | literal #literalPrmrAlt | gstring #gstringPrmrAlt | NEW nls creator[0] #newPrmrAlt | THIS #thisPrmrAlt | SUPER #superPrmrAlt | parExpression #parenPrmrAlt | closureOrLambdaExpression #closureOrLambdaExpressionPrmrAlt | list #listPrmrAlt | map #mapPrmrAlt | builtInType #builtInTypePrmrAlt ; namedPropertyArgPrimary options { baseContext = primary; } : identifier #identifierPrmrAlt | literal #literalPrmrAlt | gstring #gstringPrmrAlt | parExpression #parenPrmrAlt | list #listPrmrAlt | map #mapPrmrAlt ; namedArgPrimary options { baseContext = primary; } : identifier #identifierPrmrAlt | literal #literalPrmrAlt | gstring #gstringPrmrAlt ; commandPrimary options { baseContext = primary; } : identifier #identifierPrmrAlt | literal #literalPrmrAlt | gstring #gstringPrmrAlt ; list : LBRACK expressionList[true]? COMMA? RBRACK ; map : LBRACK ( mapEntryList COMMA? | COLON ) RBRACK ; mapEntryList : mapEntry (COMMA mapEntry)* ; namedPropertyArgList options { baseContext = mapEntryList; } : namedPropertyArg (COMMA namedPropertyArg)* ; mapEntry : mapEntryLabel COLON nls expression | MUL COLON nls expression ; namedPropertyArg options { baseContext = mapEntry; } : namedPropertyArgLabel COLON nls expression | MUL COLON nls expression ; namedArg options { baseContext = mapEntry; } : namedArgLabel COLON nls expression | MUL COLON nls expression ; mapEntryLabel : keywords | primary ; namedPropertyArgLabel options { baseContext = mapEntryLabel; } : keywords | namedPropertyArgPrimary ; namedArgLabel options { baseContext = mapEntryLabel; } : keywords | namedArgPrimary ; /** * t 0: general creation; 1: non-static inner class creation */ creator[int t] : createdName ( nls arguments anonymousInnerClassDeclaration[0]? | dim+ (nls arrayInitializer)? ) ; dim : annotationsOpt LBRACK expression? RBRACK ; arrayInitializer : LBRACE nls (variableInitializers nls)? RBRACE ; /** * t 0: anonymous inner class; 1: anonymous enum */ anonymousInnerClassDeclaration[int t] : classBody[0] ; createdName : annotationsOpt ( primitiveType | qualifiedClassName typeArgumentsOrDiamond? ) ; nonWildcardTypeArguments : LT nls typeList nls GT ; typeArgumentsOrDiamond : LT GT | typeArguments ; arguments : LPAREN enhancedArgumentListInPar? COMMA? rparen ; argumentList options { baseContext = enhancedArgumentListInPar; } : firstArgumentListElement ( COMMA nls argumentListElement )* ; enhancedArgumentListInPar : enhancedArgumentListElement ( COMMA nls enhancedArgumentListElement )* ; firstArgumentListElement options { baseContext = enhancedArgumentListElement; } : expressionListElement[true] | namedArg ; argumentListElement options { baseContext = enhancedArgumentListElement; } : expressionListElement[true] | namedPropertyArg ; enhancedArgumentListElement : expressionListElement[true] | standardLambdaExpression | namedPropertyArg ; stringLiteral : StringLiteral ; className : CapitalizedIdentifier ; identifier : Identifier | CapitalizedIdentifier | VAR | IN // | DEF | TRAIT | AS | YIELD | PERMITS | SEALED | RECORD ; builtInType : BuiltInPrimitiveType | VOID ; keywords : ABSTRACT | AS | ASSERT | BREAK | CASE | CATCH | CLASS | CONST | CONTINUE | DEF | DEFAULT | DO | ELSE | ENUM | EXTENDS | FINAL | FINALLY | FOR | GOTO | IF | IMPLEMENTS | IMPORT | IN | INSTANCEOF | INTERFACE | NATIVE | NEW | NON_SEALED | PACKAGE | PERMITS | RECORD | RETURN | SEALED | STATIC | STRICTFP | SUPER | SWITCH | SYNCHRONIZED | THIS | THROW | THROWS | TRANSIENT | TRAIT | THREADSAFE | TRY | VAR | VOLATILE | WHILE | YIELD | NullLiteral | BooleanLiteral | BuiltInPrimitiveType | VOID | PUBLIC | PROTECTED | PRIVATE ; rparen : RPAREN ; nls : NL* ; sep : (NL | SEMI)+ ;