You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@groovy.apache.org by pa...@apache.org on 2017/09/12 13:14:09 UTC
[1/2] groovy git commit: minor build refactor
Repository: groovy
Updated Branches:
refs/heads/master 1186414b0 -> 74110e343
http://git-wip-us.apache.org/repos/asf/groovy/blob/74110e34/src/main/antlr/GroovyParser.g4
----------------------------------------------------------------------
diff --git a/src/main/antlr/GroovyParser.g4 b/src/main/antlr/GroovyParser.g4
deleted file mode 100644
index 009f415..0000000
--- a/src/main/antlr/GroovyParser.g4
+++ /dev/null
@@ -1,1265 +0,0 @@
-/*
- * 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;
- import org.apache.groovy.parser.antlr4.SemanticPredicates;
-}
-
-@members {
-
- 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 | EOF))? (statement (sep | EOF))* EOF
- ;
-
-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
- )
- ;
-
-modifiersOpt
- : modifiers?
- ;
-
-modifiers
- : (modifier nls)+
- ;
-
-classOrInterfaceModifiersOpt
- : classOrInterfaceModifiers?
- ;
-
-classOrInterfaceModifiers
- : (classOrInterfaceModifier nls)+
- ;
-
-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
- | 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
- // 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?
- ;
-
-variableModifiers
- : (variableModifier nls)+
- ;
-
-typeParameters
- : LT nls typeParameter (COMMA nls typeParameter)* nls GT
- ;
-
-typeParameter
- : 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
- */
-classDeclaration
-locals[ int t ]
- : ( CLASS { $t = 0; }
- | INTERFACE { $t = 1; }
- | ENUM { $t = 2; }
- | AT INTERFACE { $t = 3; }
- | TRAIT { $t = 4; }
- )
- identifier nls
-
- (
- { 3 != $t }?
- typeParameters? nls
- (
- { 2 != $t }?
- (EXTENDS nls
- (
- // Only interface can extend more than one super class
- {1 == $t}? scs=typeList
- |
- sc=type
- )
- nls)?
- |
- /* enum should not have type parameters and extends */
- )
-
- (
- {1 != $t}?
- (IMPLEMENTS nls is=typeList nls)?
- |
- /* interface should not implement other interfaces */
- )
- |
- /* annotation should not have implements and extends*/
- )
-
- classBody[$t]
- ;
-
-// t see the comment of classDeclaration
-classBody[int t]
- : LBRACE nls
- (
- /* Only enum can have enum constants */
- { 2 == $t }?
- enumConstants? nls
- |
-
- )
- classBodyDeclaration[$t]? (sep classBodyDeclaration[$t])* sep? RBRACE
- ;
-
-enumConstants
- : enumConstant (nls COMMA nls enumConstant)* (nls COMMA)?
- ;
-
-enumConstant
- : annotationsOpt identifier arguments? anonymousInnerClassDeclaration[1]?
- ;
-
-classBodyDeclaration[int t]
- : SEMI
- | (STATIC nls)? block
- | memberDeclaration[$t]
- ;
-
-memberDeclaration[int t]
- : methodDeclaration[0, $t]
- | fieldDeclaration
- | modifiersOpt classDeclaration
- ;
-
-/**
- * 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]
- : { 3 == $ct }?
- returnType[$ct] methodName LPAREN RPAREN (DEFAULT nls elementValue)?
- |
- ( { 0 == $t }?
- modifiersOpt typeParameters?
- | modifiersOpt typeParameters? returnType[$ct]
- | modifiers typeParameters? returnType[$ct]?
- )
- methodName formalParameters (nls THROWS nls qualifiedClassNameList)?
- (
- { 0 == $t || 3 == $t || 1 == $t}?
- nls methodBody
- |
- { 0 == $t || 3 == $t || 2 == $t }?
- /* no method body */
- )
- ;
-
-methodName
- : identifier
- | stringLiteral
- ;
-
-returnType[int ct]
- :
- standardType
- |
- // annotation method can not have void return type
- { 3 != $ct }? 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)* nls COMMA?
- ;
-
-dims
- : (annotationsOpt LBRACK RBRACK)+
- ;
-
-dimsOpt
- : dims?
- ;
-
-standardType
-options { baseContext = type; }
- : annotationsOpt
- (
- primitiveType
- |
- standardClassOrInterfaceType
- )
- dimsOpt
- ;
-
-type
- : annotationsOpt
- (
- (
- primitiveType
- |
- // !!! ERROR ALTERNATIVE !!!
- VOID { require(false, "void is not allowed here", -4); }
- )
- |
- generalClassOrInterfaceType
- )
- dimsOpt
- ;
-
-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
- ;
-
-qualifiedClassName
- : (qualifiedNameElement DOT)* identifier
- ;
-
-qualifiedStandardClassName
- : (qualifiedNameElement DOT)* (className DOT)* className
- ;
-
-literal
- : IntegerLiteral #integerLiteralAlt
- | FloatingPointLiteral #floatingPointLiteralAlt
- | stringLiteral #stringLiteralAlt
- | BooleanLiteral #booleanLiteralAlt
- | NullLiteral #nullLiteralAlt
- ;
-
-// GSTRING
-
-gstring
- : GStringBegin gstringValue (GStringPart gstringValue)* GStringEnd
- ;
-
-gstringValue
- : gstringPath
- | LBRACE statementExpression? RBRACE
- | closure
- ;
-
-gstringPath
- : identifier GStringPathPart*
- ;
-
-
-// LAMBDA EXPRESSION
-lambdaExpression
-options { baseContext = standardLambdaExpression; }
- : lambdaParameters nls ARROW nls lambdaBody
- ;
-
-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
-locals[ String footprint = "" ]
- : LBRACE nls (formalParameterList? nls ARROW nls)? blockStatementsOpt RBRACE
- ;
-
-blockStatementsOpt
- : blockStatements?
- ;
-
-blockStatements
- : blockStatement (sep blockStatement)* sep?
- ;
-
-// ANNOTATIONS
-
-annotationsOpt
- : (annotation nls)*
- ;
-
-annotation
- : AT annotationName ( 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 (nls | sep*) blockStatementsOpt RBRACE
- ;
-
-blockStatement
- : localVariableDeclaration
- | statement
- ;
-
-localVariableDeclaration
- : { !SemanticPredicates.isInvalidLocalVariableDeclaration(_input) }?
- variableDeclaration[0]
- ;
-
-/**
- * t 0: local variable declaration; 1: field declaration
- */
-variableDeclaration[int t]
- : ( { 0 == $t }? variableModifiers
- | { 1 == $t }? modifiers
- )
- type? variableDeclarators
- |
- ( { 0 == $t }? variableModifiersOpt
- | { 1 == $t }? modifiersOpt
- )
- type variableDeclarators
- |
- ( { 0 == $t }? variableModifiers
- | { 1 == $t }? modifiers
- )
- typeNamePairs nls ASSIGN nls variableInitializer
- ;
-
-typeNamePairs
- : LPAREN typeNamePair (COMMA typeNamePair)* RPAREN
- ;
-
-typeNamePair
- : type? variableDeclaratorId
- ;
-
-variableNames
- : LPAREN variableDeclaratorId (COMMA variableDeclaratorId)+ rparen
- ;
-
-switchStatement
-locals[ String footprint = "" ]
- : SWITCH expressionInPar nls LBRACE nls switchBlockStatementGroup* nls RBRACE
- ;
-
-loopStatement
-locals[ String footprint = "" ]
- : FOR LPAREN forControl rparen nls statement #forStmtAlt
- | WHILE expressionInPar nls statement #whileStmtAlt
- | DO nls statement nls WHILE expressionInPar #doWhileStmtAlt
- ;
-
-continueStatement
-locals[ boolean isInsideLoop ]
-@init {
- try {
- $isInsideLoop = null != $loopStatement::footprint;
- } catch(NullPointerException e) {
- $isInsideLoop = false;
- }
-}
- : CONTINUE
- { require($isInsideLoop, "the continue statement is only allowed inside loops", -8); }
- identifier?
- ;
-
-breakStatement
-locals[ boolean isInsideLoop, boolean isInsideSwitch ]
-@init {
- try {
- $isInsideLoop = null != $loopStatement::footprint;
- } catch(NullPointerException e) {
- $isInsideLoop = false;
- }
-
- try {
- $isInsideSwitch = null != $switchStatement::footprint;
- } catch(NullPointerException e) {
- $isInsideSwitch = false;
- }
-}
- : BREAK
- { require($isInsideLoop || $isInsideSwitch, "the break statement is only allowed inside loops or switches", -5); }
- identifier?
- ;
-
-tryCatchStatement
-locals[boolean resourcesExists = false]
- : TRY (resources { $resourcesExists = true; })? nls
- block
- (
- (nls catchClause)+
- (nls finallyBlock)?
- |
- nls finallyBlock
- |
- // catch and finally clauses required unless it's a try-with-resources block
- { require($resourcesExists, "either a catch or finally clause or both is required for a try-catch-finally statement"); }
- )
- ;
-
-assertStatement
-locals[ String footprint = "" ]
- : ASSERT ce=expression (nls (COLON | COMMA) nls me=expression)?
- ;
-
-statement
- : block #blockStmtAlt
- | IF expressionInPar nls tb=statement ((nls | sep) ELSE nls fb=statement)? #ifElseStmtAlt
- | loopStatement #loopStmtAlt
-
- | tryCatchStatement #tryCatchStmtAlt
-
- | switchStatement #switchStmtAlt
- | SYNCHRONIZED expressionInPar nls block #synchronizedStmtAlt
- | RETURN expression? #returnStmtAlt
- | THROW expression #throwStmtAlt
-
- | breakStatement #breakStmtAlt
- | continueStatement #continueStmtAlt
-
- | identifier COLON nls statement #labeledStmtAlt
-
- // Import statement. Can be used in any scope. Has "import x as y" also.
- | importDeclaration #importStmtAlt
-
- | assertStatement #assertStmtAlt
-
- | typeDeclaration #typeDeclarationStmtAlt
- | localVariableDeclaration #localVariableDeclarationStmtAlt
-
- // validate the method in the AstBuilder#visitMethodDeclaration, e.g. method without method body is not allowed
- | { !SemanticPredicates.isInvalidMethodDeclaration(_input) }?
- methodDeclaration[3, 9] #methodDeclarationStmtAlt
-
- | 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)+ 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 expressionListElement[$canSpread])*
- ;
-
-expressionListElement[boolean canSpread]
- : ( MUL { require($canSpread, "spread operator is not allowed here", -1); }
- |
- ) expression
- ;
-
-enhancedStatementExpression
- : statementExpression
- | standardLambdaExpression
- ;
-
-/**
- * In order to resolve the syntactic ambiguities, e.g. (String)'abc' can be parsed as a cast expression or a parentheses-less method call(method name: (String), arguments: 'abc')
- * try to match expression first.
- * If it is not a normal expression, then try to match the command expression
- */
-statementExpression
- : expression #normalExprAlt
- | commandExpression #commandExprAlt
- ;
-
-postfixExpression
-locals[ boolean isInsideAssert ]
-@init {
- try {
- $isInsideAssert = null != $assertStatement::footprint;
- } catch(NullPointerException e) {
- $isInsideAssert = false;
- }
-}
- : pathExpression op=(INC | DEC)?
- ;
-
-expression
- // qualified names, array expressions, method invocation, post inc/dec, type casting (level 1)
- // The cast expression must be put before pathExpression to resovle the ambiguities between type casting and call on parentheses expression, e.g. (int)(1 / 2)
- : castParExpression expression #castExprAlt
- | postfixExpression #postfixExprAlt
-
- // ~(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
- )
- ) 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)
- | <assoc=right> 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
- | <assoc=right> left=variableNames nls op=ASSIGN nls right=statementExpression #multipleAssignmentExprAlt
- | <assoc=right> 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
- enhancedStatementExpression #assignmentExprAlt
- ;
-
-commandExpression
- : pathExpression
- (
- { SemanticPredicates.isFollowingMethodName($pathExpression.t) }?
- argumentList
- |
- /* if pathExpression is a method call, no need to have any more arguments */
- )
-
- commandArgument*
- ;
-
-commandArgument
- : primary
- // 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: closure, 4: indexPropertyArgs, 5: namedPropertyArgs
- */
-pathExpression returns [int t]
- : primary (pathElement { $t = $pathElement.t; })*
- ;
-
-pathElement returns [int t]
-locals[ boolean isInsideClosure ]
-@init {
- try {
- $isInsideClosure = null != $closure::footprint;
- } catch(NullPointerException e) {
- $isInsideClosure = false;
- }
-}
- : nls
-
- // AT: foo.@bar selects the field (or attribute), not property
- ( SPREAD_DOT nls (AT | nonWildcardTypeArguments)? // Spread operator: x*.y === x?.collect{it.y}
- | SAFE_DOT nls (AT | nonWildcardTypeArguments)? // Optional-null operator: x?.y === (x==null)?null:x.y
- | METHOD_POINTER nls // Method pointer operator: foo.&y == foo.metaClass.getMethodPointer(foo, "y")
- | METHOD_REFERENCE nls // Method reference: System.out::println
- | DOT nls (AT | nonWildcardTypeArguments)? // The all-powerful dot.
- )
- namePart
- { $t = 1; }
-
- | arguments
- { $t = 2; }
-
- // Can always append a block, as foo{bar}
- | nls closure
- { $t = 3; }
-
- // 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
- : QUESTION? LBRACK expressionList[true]? RBRACK
- ;
-
-namedPropertyArgs
- : LBRACK mapEntryList RBRACK
- ;
-
-primary
- : identifier #identifierPrmrAlt
- | literal #literalPrmrAlt
- | gstring #gstringPrmrAlt
- | NEW nls creator #newPrmrAlt
- | THIS #thisPrmrAlt
- | SUPER #superPrmrAlt
- | parExpression #parenPrmrAlt
- | closure #closurePrmrAlt
- | lambdaExpression #lambdaPrmrAlt
- | list #listPrmrAlt
- | map #mapPrmrAlt
- | builtInType #typePrmrAlt
- ;
-
-list
-locals[boolean empty = true]
- : LBRACK
- (
- expressionList[true]
- { $empty = false; }
- )?
- (
- COMMA
- { require(!$empty, "Empty list constructor should not contain any comma(,)", -1); }
- )?
- RBRACK
- ;
-
-map
- : LBRACK
- ( mapEntryList COMMA?
- | COLON
- )
- RBRACK
- ;
-
-mapEntryList
- : mapEntry (COMMA mapEntry)*
- ;
-
-mapEntry
- : mapEntryLabel COLON nls expression
- | MUL COLON nls expression
- ;
-
-mapEntryLabel
- : keywords
- | primary
- ;
-
-creator
- : createdName
- ( nls arguments anonymousInnerClassDeclaration[0]?
- | (annotationsOpt LBRACK expression RBRACK)+ dimsOpt
- | dims nls arrayInitializer
- )
- ;
-
-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
- ( enhancedArgumentList?
- | enhancedArgumentList COMMA
- )
- rparen
- ;
-
-argumentList
-options { baseContext = enhancedArgumentList; }
- : argumentListElement
- ( COMMA nls
- argumentListElement
- )*
- ;
-
-enhancedArgumentList
- : enhancedArgumentListElement
- ( COMMA nls
- enhancedArgumentListElement
- )*
- ;
-
-argumentListElement
-options { baseContext = enhancedArgumentListElement; }
- : expressionListElement[true]
- | mapEntry
- ;
-
-enhancedArgumentListElement
- : expressionListElement[true]
- | standardLambdaExpression
- | mapEntry
- ;
-
-stringLiteral
- : StringLiteral
- ;
-
-className
- : CapitalizedIdentifier
- ;
-
-identifier
- : Identifier
- | CapitalizedIdentifier
-
- |
- // if 'static' followed by DOT, we can treat them as identifiers, e.g. static.unused = { -> }
- { DOT == _input.LT(2).getType() }?
- STATIC
- ;
-
-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
- | PACKAGE
- | RETURN
- | STATIC
- | STRICTFP
- | SUPER
- | SWITCH
- | SYNCHRONIZED
- | THIS
- | THROW
- | THROWS
- | TRANSIENT
- | TRAIT
- | THREADSAFE
- | TRY
- | VOLATILE
- | WHILE
-
- | NullLiteral
- | BooleanLiteral
-
- | BuiltInPrimitiveType
- | VOID
-
- | PUBLIC
- | PROTECTED
- | PRIVATE
- ;
-
-rparen
- : RPAREN
- |
- // !!!Error Alternative, impact the performance of parsing
- { require(false, "Missing ')'"); }
- ;
-
-nls
- : NL*
- ;
-
-sep : SEMI NL*
- | NL+ (SEMI NL*)*
- ;
-
-
[2/2] groovy git commit: minor build refactor
Posted by pa...@apache.org.
minor build refactor
Project: http://git-wip-us.apache.org/repos/asf/groovy/repo
Commit: http://git-wip-us.apache.org/repos/asf/groovy/commit/74110e34
Tree: http://git-wip-us.apache.org/repos/asf/groovy/tree/74110e34
Diff: http://git-wip-us.apache.org/repos/asf/groovy/diff/74110e34
Branch: refs/heads/master
Commit: 74110e3436143c3c9630c6fe2427a6cbf81e0ebb
Parents: 1186414
Author: paulk <pa...@asert.com.au>
Authored: Tue Sep 12 23:13:19 2017 +1000
Committer: paulk <pa...@asert.com.au>
Committed: Tue Sep 12 23:14:02 2017 +1000
----------------------------------------------------------------------
build.gradle | 9 +-
src/antlr/GroovyLexer.g4 | 938 ++++++++++++++++++++++++++
src/antlr/GroovyParser.g4 | 1265 +++++++++++++++++++++++++++++++++++
src/main/antlr/GroovyLexer.g4 | 938 --------------------------
src/main/antlr/GroovyParser.g4 | 1265 -----------------------------------
5 files changed, 2211 insertions(+), 2204 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/groovy/blob/74110e34/build.gradle
----------------------------------------------------------------------
diff --git a/build.gradle b/build.gradle
index 050aa04..504ab57 100644
--- a/build.gradle
+++ b/build.gradle
@@ -290,7 +290,7 @@ sourceSets {
srcDirs = ['src/main', 'src/resources']
include 'META-INF/services/*',
'META-INF/groovy-release-info.properties',
- 'groovy/grape/*.xml',
+ 'groovy/grape/*.xml'
}
}
test {
@@ -321,6 +321,13 @@ sourceSets {
}
apply from: 'subprojects/parser-antlr4/build.gradle'
+sourceSets {
+ main {
+ antlr {
+ srcDirs = ['src/antlr']
+ }
+ }
+}
// make sure examples can be compiled, even if we don't run them
// todo: reorganize examples so that we can run them too
http://git-wip-us.apache.org/repos/asf/groovy/blob/74110e34/src/antlr/GroovyLexer.g4
----------------------------------------------------------------------
diff --git a/src/antlr/GroovyLexer.g4 b/src/antlr/GroovyLexer.g4
new file mode 100644
index 0000000..05fb767
--- /dev/null
+++ b/src/antlr/GroovyLexer.g4
@@ -0,0 +1,938 @@
+/*
+ * 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
+ */
+lexer grammar GroovyLexer;
+
+options {
+ superClass = AbstractLexer;
+}
+
+@header {
+ import static org.apache.groovy.parser.antlr4.SemanticPredicates.*;
+ import java.util.Deque;
+ import java.util.ArrayDeque;
+ import java.util.Map;
+ import java.util.HashMap;
+ import java.util.Set;
+ import java.util.HashSet;
+ import java.util.Collections;
+ import java.util.Arrays;
+}
+
+@members {
+ private long tokenIndex = 0;
+ private int lastTokenType = 0;
+ private int invalidDigitCount = 0;
+
+ /**
+ * Record the index and token type of the current token while emitting tokens.
+ */
+ @Override
+ public void emit(Token token) {
+ this.tokenIndex++;
+
+ int tokenType = token.getType();
+ if (Token.DEFAULT_CHANNEL == token.getChannel()) {
+ this.lastTokenType = tokenType;
+ }
+
+ if (RollBackOne == tokenType) {
+ this.rollbackOneChar();
+ }
+
+ super.emit(token);
+ }
+
+ private static final Set<Integer> REGEX_CHECK_SET =
+ Collections.unmodifiableSet(
+ new HashSet<>(Arrays.asList(Identifier, CapitalizedIdentifier, NullLiteral, BooleanLiteral, THIS, RPAREN, RBRACK, RBRACE, IntegerLiteral, FloatingPointLiteral, StringLiteral, GStringEnd, INC, DEC)));
+ private boolean isRegexAllowed() {
+ if (REGEX_CHECK_SET.contains(this.lastTokenType)) {
+ return false;
+ }
+
+ return true;
+ }
+
+ /**
+ * just a hook, which will be overrided by GroovyLangLexer
+ */
+ protected void rollbackOneChar() {}
+
+ private static class Paren {
+ private String text;
+ private int lastTokenType;
+ private int line;
+ private int column;
+
+ public Paren(String text, int lastTokenType, int line, int column) {
+ this.text = text;
+ this.lastTokenType = lastTokenType;
+ this.line = line;
+ this.column = column;
+ }
+
+ public String getText() {
+ return this.text;
+ }
+
+ public int getLastTokenType() {
+ return this.lastTokenType;
+ }
+
+ public int getLine() {
+ return line;
+ }
+
+ public int getColumn() {
+ return column;
+ }
+
+ @Override
+ public int hashCode() {
+ return (int) (text.hashCode() * line + column);
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (!(obj instanceof Paren)) {
+ return false;
+ }
+
+ Paren other = (Paren) obj;
+
+ return this.text.equals(other.text) && (this.line == other.line && this.column == other.column);
+ }
+ }
+
+ private static final Map<String, String> PAREN_MAP = Collections.unmodifiableMap(new HashMap<String, String>() {
+ {
+ put("(", ")");
+ put("[", "]");
+ put("{", "}");
+ }
+ });
+
+ private final Deque<Paren> parenStack = new ArrayDeque<>(32);
+ private void enterParen() {
+ parenStack.push(new Paren(getText(), this.lastTokenType, getLine(), getCharPositionInLine()));
+ }
+ private void exitParen() {
+ Paren paren = parenStack.peek();
+ String text = getText();
+
+ require(null != paren, "Too many '" + text + "'");
+ require(text.equals(PAREN_MAP.get(paren.getText())),
+ "'" + paren.getText() + "'" + new PositionInfo(paren.getLine(), paren.getColumn()) + " can not match '" + text + "'", -1);
+
+ parenStack.pop();
+ }
+ private boolean isInsideParens() {
+ Paren paren = parenStack.peek();
+
+ // We just care about "(" and "[", inside which the new lines will be ignored.
+ // Notice: the new lines between "{" and "}" can not be ignored.
+ if (null == paren) {
+ return false;
+ }
+ return ("(".equals(paren.getText()) && TRY != paren.getLastTokenType()) // we don't treat try-paren(i.e. try (....)) as parenthesis
+ || "[".equals(paren.getText());
+ }
+ private void ignoreTokenInsideParens() {
+ if (!this.isInsideParens()) {
+ return;
+ }
+
+ this.setChannel(Token.HIDDEN_CHANNEL);
+ }
+ private void ignoreMultiLineCommentConditionally() {
+ if (!this.isInsideParens() && isFollowedByWhiteSpaces(_input)) {
+ return;
+ }
+
+ this.setChannel(Token.HIDDEN_CHANNEL);
+ }
+
+ @Override
+ public int getSyntaxErrorSource() {
+ return GroovySyntaxError.LEXER;
+ }
+
+ @Override
+ public int getErrorLine() {
+ return getLine();
+ }
+
+ @Override
+ public int getErrorColumn() {
+ return getCharPositionInLine() + 1;
+ }
+}
+
+
+// §3.10.5 String Literals
+StringLiteral
+ : GStringQuotationMark DqStringCharacter*? GStringQuotationMark
+ | SqStringQuotationMark SqStringCharacter*? SqStringQuotationMark
+
+ | Slash { this.isRegexAllowed() && _input.LA(1) != '*' }?
+ SlashyStringCharacter+? Slash
+
+ | TdqStringQuotationMark TdqStringCharacter*? TdqStringQuotationMark
+ | TsqStringQuotationMark TsqStringCharacter*? TsqStringQuotationMark
+ | DollarSlashyGStringQuotationMarkBegin DollarSlashyStringCharacter+? DollarSlashyGStringQuotationMarkEnd
+ ;
+
+// Groovy gstring
+GStringBegin
+ : GStringQuotationMark DqStringCharacter*? Dollar -> pushMode(DQ_GSTRING_MODE), pushMode(GSTRING_TYPE_SELECTOR_MODE)
+ ;
+TdqGStringBegin
+ : TdqStringQuotationMark TdqStringCharacter*? Dollar -> type(GStringBegin), pushMode(TDQ_GSTRING_MODE), pushMode(GSTRING_TYPE_SELECTOR_MODE)
+ ;
+SlashyGStringBegin
+ : Slash { this.isRegexAllowed() && _input.LA(1) != '*' }? SlashyStringCharacter*? Dollar { isFollowedByJavaLetterInGString(_input) }? -> type(GStringBegin), pushMode(SLASHY_GSTRING_MODE), pushMode(GSTRING_TYPE_SELECTOR_MODE)
+ ;
+DollarSlashyGStringBegin
+ : DollarSlashyGStringQuotationMarkBegin DollarSlashyStringCharacter*? Dollar { isFollowedByJavaLetterInGString(_input) }? -> type(GStringBegin), pushMode(DOLLAR_SLASHY_GSTRING_MODE), pushMode(GSTRING_TYPE_SELECTOR_MODE)
+ ;
+
+mode DQ_GSTRING_MODE;
+GStringEnd
+ : GStringQuotationMark -> popMode
+ ;
+GStringPart
+ : Dollar -> pushMode(GSTRING_TYPE_SELECTOR_MODE)
+ ;
+GStringCharacter
+ : DqStringCharacter -> more
+ ;
+
+mode TDQ_GSTRING_MODE;
+TdqGStringEnd
+ : TdqStringQuotationMark -> type(GStringEnd), popMode
+ ;
+TdqGStringPart
+ : Dollar -> type(GStringPart), pushMode(GSTRING_TYPE_SELECTOR_MODE)
+ ;
+TdqGStringCharacter
+ : TdqStringCharacter -> more
+ ;
+
+mode SLASHY_GSTRING_MODE;
+SlashyGStringEnd
+ : Dollar? Slash -> type(GStringEnd), popMode
+ ;
+SlashyGStringPart
+ : Dollar { isFollowedByJavaLetterInGString(_input) }? -> type(GStringPart), pushMode(GSTRING_TYPE_SELECTOR_MODE)
+ ;
+SlashyGStringCharacter
+ : SlashyStringCharacter -> more
+ ;
+
+mode DOLLAR_SLASHY_GSTRING_MODE;
+DollarSlashyGStringEnd
+ : DollarSlashyGStringQuotationMarkEnd -> type(GStringEnd), popMode
+ ;
+DollarSlashyGStringPart
+ : Dollar { isFollowedByJavaLetterInGString(_input) }? -> type(GStringPart), pushMode(GSTRING_TYPE_SELECTOR_MODE)
+ ;
+DollarSlashyGStringCharacter
+ : DollarSlashyStringCharacter -> more
+ ;
+
+mode GSTRING_TYPE_SELECTOR_MODE;
+GStringLBrace
+ : '{' { this.enterParen(); } -> type(LBRACE), popMode, pushMode(DEFAULT_MODE)
+ ;
+GStringIdentifier
+ : IdentifierInGString -> type(Identifier), popMode, pushMode(GSTRING_PATH_MODE)
+ ;
+
+
+mode GSTRING_PATH_MODE;
+GStringPathPart
+ : Dot IdentifierInGString
+ ;
+RollBackOne
+ : . {
+ // a trick to handle GStrings followed by EOF properly
+ if (EOF == _input.LA(1) && ('"' == _input.LA(-1) || '/' == _input.LA(-1))) {
+ setType(GStringEnd);
+ } else {
+ setChannel(HIDDEN);
+ }
+ } -> popMode
+ ;
+
+
+mode DEFAULT_MODE;
+// character in the double quotation string. e.g. "a"
+fragment
+DqStringCharacter
+ : ~["\\$]
+ | EscapeSequence
+ ;
+
+// character in the single quotation string. e.g. 'a'
+fragment
+SqStringCharacter
+ : ~['\\]
+ | EscapeSequence
+ ;
+
+// character in the triple double quotation string. e.g. """a"""
+fragment TdqStringCharacter
+ : ~["\\$]
+ | GStringQuotationMark { !(_input.LA(1) == '"' && _input.LA(2) == '"') }?
+ | EscapeSequence
+ ;
+
+// character in the triple single quotation string. e.g. '''a'''
+fragment TsqStringCharacter
+ : ~['\\]
+ | SqStringQuotationMark { !(_input.LA(1) == '\'' && _input.LA(2) == '\'') }?
+ | EscapeSequence
+ ;
+
+// character in the slashy string. e.g. /a/
+fragment SlashyStringCharacter
+ : SlashEscape
+ | Dollar { !isFollowedByJavaLetterInGString(_input) }?
+ | ~[/$\u0000]
+ ;
+
+// character in the collar slashy string. e.g. $/a/$
+fragment DollarSlashyStringCharacter
+ : SlashEscape | DollarSlashEscape | DollarDollarEscape
+ | Slash { _input.LA(1) != '$' }?
+ | Dollar { !isFollowedByJavaLetterInGString(_input) }?
+ | ~[/$\u0000]
+ ;
+
+// Groovy keywords
+AS : 'as';
+DEF : 'def';
+IN : 'in';
+TRAIT : 'trait';
+THREADSAFE : 'threadsafe'; // reserved keyword
+
+
+// §3.9 Keywords
+BuiltInPrimitiveType
+ : BOOLEAN
+ | CHAR
+ | BYTE
+ | SHORT
+ | INT
+ | LONG
+ | FLOAT
+ | DOUBLE
+ ;
+
+ABSTRACT : 'abstract';
+ASSERT : 'assert';
+
+fragment
+BOOLEAN : 'boolean';
+
+BREAK : 'break';
+
+fragment
+BYTE : 'byte';
+
+CASE : 'case';
+CATCH : 'catch';
+
+fragment
+CHAR : 'char';
+
+CLASS : 'class';
+CONST : 'const';
+CONTINUE : 'continue';
+DEFAULT : 'default';
+DO : 'do';
+
+fragment
+DOUBLE : 'double';
+
+ELSE : 'else';
+ENUM : 'enum';
+EXTENDS : 'extends';
+FINAL : 'final';
+FINALLY : 'finally';
+
+fragment
+FLOAT : 'float';
+
+
+FOR : 'for';
+IF : 'if';
+GOTO : 'goto';
+IMPLEMENTS : 'implements';
+IMPORT : 'import';
+INSTANCEOF : 'instanceof';
+
+fragment
+INT : 'int';
+
+INTERFACE : 'interface';
+
+fragment
+LONG : 'long';
+
+NATIVE : 'native';
+NEW : 'new';
+PACKAGE : 'package';
+PRIVATE : 'private';
+PROTECTED : 'protected';
+PUBLIC : 'public';
+RETURN : 'return';
+
+fragment
+SHORT : 'short';
+
+
+STATIC : 'static';
+STRICTFP : 'strictfp';
+SUPER : 'super';
+SWITCH : 'switch';
+SYNCHRONIZED : 'synchronized';
+THIS : 'this';
+THROW : 'throw';
+THROWS : 'throws';
+TRANSIENT : 'transient';
+TRY : 'try';
+VOID : 'void';
+VOLATILE : 'volatile';
+WHILE : 'while';
+
+
+// §3.10.1 Integer Literals
+
+IntegerLiteral
+ : ( DecimalIntegerLiteral
+ | HexIntegerLiteral
+ | OctalIntegerLiteral
+ | BinaryIntegerLiteral
+ ) (Underscore { require(false, "Number ending with underscores is invalid", -1, true); })?
+
+ // !!! Error Alternative !!!
+ | Zero ([0-9] { invalidDigitCount++; })+ { require(false, "Invalid octal number", -(invalidDigitCount + 1), true); } IntegerTypeSuffix?
+ ;
+
+fragment
+Zero
+ : '0'
+ ;
+
+fragment
+DecimalIntegerLiteral
+ : DecimalNumeral IntegerTypeSuffix?
+ ;
+
+fragment
+HexIntegerLiteral
+ : HexNumeral IntegerTypeSuffix?
+ ;
+
+fragment
+OctalIntegerLiteral
+ : OctalNumeral IntegerTypeSuffix?
+ ;
+
+fragment
+BinaryIntegerLiteral
+ : BinaryNumeral IntegerTypeSuffix?
+ ;
+
+fragment
+IntegerTypeSuffix
+ : [lLiIgG]
+ ;
+
+fragment
+DecimalNumeral
+ : Zero
+ | NonZeroDigit (Digits? | Underscores Digits)
+ ;
+
+fragment
+Digits
+ : Digit (DigitOrUnderscore* Digit)?
+ ;
+
+fragment
+Digit
+ : Zero
+ | NonZeroDigit
+ ;
+
+fragment
+NonZeroDigit
+ : [1-9]
+ ;
+
+fragment
+DigitOrUnderscore
+ : Digit
+ | Underscore
+ ;
+
+fragment
+Underscores
+ : Underscore+
+ ;
+
+fragment
+Underscore
+ : '_'
+ ;
+
+fragment
+HexNumeral
+ : Zero [xX] HexDigits
+ ;
+
+fragment
+HexDigits
+ : HexDigit (HexDigitOrUnderscore* HexDigit)?
+ ;
+
+fragment
+HexDigit
+ : [0-9a-fA-F]
+ ;
+
+fragment
+HexDigitOrUnderscore
+ : HexDigit
+ | Underscore
+ ;
+
+fragment
+OctalNumeral
+ : Zero Underscores? OctalDigits
+ ;
+
+fragment
+OctalDigits
+ : OctalDigit (OctalDigitOrUnderscore* OctalDigit)?
+ ;
+
+fragment
+OctalDigit
+ : [0-7]
+ ;
+
+fragment
+OctalDigitOrUnderscore
+ : OctalDigit
+ | Underscore
+ ;
+
+fragment
+BinaryNumeral
+ : Zero [bB] BinaryDigits
+ ;
+
+fragment
+BinaryDigits
+ : BinaryDigit (BinaryDigitOrUnderscore* BinaryDigit)?
+ ;
+
+fragment
+BinaryDigit
+ : [01]
+ ;
+
+fragment
+BinaryDigitOrUnderscore
+ : BinaryDigit
+ | Underscore
+ ;
+
+// §3.10.2 Floating-Point Literals
+
+FloatingPointLiteral
+ : ( DecimalFloatingPointLiteral
+ | HexadecimalFloatingPointLiteral
+ ) (Underscore { require(false, "Number ending with underscores is invalid", -1, true); })?
+ ;
+
+fragment
+DecimalFloatingPointLiteral
+ : Digits Dot Digits ExponentPart? FloatTypeSuffix?
+ | Digits ExponentPart FloatTypeSuffix?
+ | Digits FloatTypeSuffix
+ ;
+
+fragment
+ExponentPart
+ : ExponentIndicator SignedInteger
+ ;
+
+fragment
+ExponentIndicator
+ : [eE]
+ ;
+
+fragment
+SignedInteger
+ : Sign? Digits
+ ;
+
+fragment
+Sign
+ : [+\-]
+ ;
+
+fragment
+FloatTypeSuffix
+ : [fFdDgG]
+ ;
+
+fragment
+HexadecimalFloatingPointLiteral
+ : HexSignificand BinaryExponent FloatTypeSuffix?
+ ;
+
+fragment
+HexSignificand
+ : HexNumeral Dot?
+ | Zero [xX] HexDigits? Dot HexDigits
+ ;
+
+fragment
+BinaryExponent
+ : BinaryExponentIndicator SignedInteger
+ ;
+
+fragment
+BinaryExponentIndicator
+ : [pP]
+ ;
+
+fragment
+Dot : '.'
+ ;
+
+// §3.10.3 Boolean Literals
+
+BooleanLiteral
+ : 'true'
+ | 'false'
+ ;
+
+
+// §3.10.6 Escape Sequences for Character and String Literals
+
+fragment
+EscapeSequence
+ : Backslash [btnfr"'\\]
+ | OctalEscape
+ | UnicodeEscape
+ | DollarEscape
+ | LineEscape
+ ;
+
+
+fragment
+OctalEscape
+ : Backslash OctalDigit
+ | Backslash OctalDigit OctalDigit
+ | Backslash ZeroToThree OctalDigit OctalDigit
+ ;
+
+// Groovy allows 1 or more u's after the backslash
+fragment
+UnicodeEscape
+ : Backslash 'u' HexDigit HexDigit HexDigit HexDigit
+ ;
+
+fragment
+ZeroToThree
+ : [0-3]
+ ;
+
+// Groovy Escape Sequences
+
+fragment
+DollarEscape
+ : Backslash Dollar
+ ;
+
+fragment
+LineEscape
+ : Backslash '\r'? '\n'
+ ;
+
+fragment
+SlashEscape
+ : Backslash Slash
+ ;
+
+fragment
+Backslash
+ : '\\'
+ ;
+
+fragment
+Slash
+ : '/'
+ ;
+
+fragment
+Dollar
+ : '$'
+ ;
+
+fragment
+GStringQuotationMark
+ : '"'
+ ;
+
+fragment
+SqStringQuotationMark
+ : '\''
+ ;
+
+fragment
+TdqStringQuotationMark
+ : '"""'
+ ;
+
+fragment
+TsqStringQuotationMark
+ : '\'\'\''
+ ;
+
+fragment
+DollarSlashyGStringQuotationMarkBegin
+ : '$/'
+ ;
+
+fragment
+DollarSlashyGStringQuotationMarkEnd
+ : '/$'
+ ;
+
+fragment
+DollarSlashEscape
+ : '$/$'
+ ;
+
+fragment
+DollarDollarEscape
+ : '$$'
+ ;
+
+// §3.10.7 The Null Literal
+NullLiteral
+ : 'null'
+ ;
+
+// Groovy Operators
+
+RANGE_INCLUSIVE : '..';
+RANGE_EXCLUSIVE : '..<';
+SPREAD_DOT : '*.';
+SAFE_DOT : '?.';
+ELVIS : '?:';
+METHOD_POINTER : '.&';
+METHOD_REFERENCE : '::';
+REGEX_FIND : '=~';
+REGEX_MATCH : '==~';
+POWER : '**';
+POWER_ASSIGN : '**=';
+SPACESHIP : '<=>';
+IDENTICAL : '===';
+NOT_IDENTICAL : '!==';
+ARROW : '->';
+
+// !internalPromise will be parsed as !in ternalPromise, so semantic predicates are necessary
+NOT_INSTANCEOF : '!instanceof' { isFollowedBy(_input, ' ', '\t', '\r', '\n') }?;
+NOT_IN : '!in' { isFollowedBy(_input, ' ', '\t', '\r', '\n', '[', '(', '{') }?;
+
+
+// §3.11 Separators
+
+LPAREN : '(' { this.enterParen(); } -> pushMode(DEFAULT_MODE);
+RPAREN : ')' { this.exitParen(); } -> popMode;
+LBRACE : '{' { this.enterParen(); } -> pushMode(DEFAULT_MODE);
+RBRACE : '}' { this.exitParen(); } -> popMode;
+LBRACK : '[' { this.enterParen(); } -> pushMode(DEFAULT_MODE);
+RBRACK : ']' { this.exitParen(); } -> popMode;
+
+SEMI : ';';
+COMMA : ',';
+DOT : Dot;
+
+// §3.12 Operators
+
+ASSIGN : '=';
+GT : '>';
+LT : '<';
+NOT : '!';
+BITNOT : '~';
+QUESTION : '?';
+COLON : ':';
+EQUAL : '==';
+LE : '<=';
+GE : '>=';
+NOTEQUAL : '!=';
+AND : '&&';
+OR : '||';
+INC : '++';
+DEC : '--';
+ADD : '+';
+SUB : '-';
+MUL : '*';
+DIV : Slash;
+BITAND : '&';
+BITOR : '|';
+XOR : '^';
+MOD : '%';
+
+
+ADD_ASSIGN : '+=';
+SUB_ASSIGN : '-=';
+MUL_ASSIGN : '*=';
+DIV_ASSIGN : '/=';
+AND_ASSIGN : '&=';
+OR_ASSIGN : '|=';
+XOR_ASSIGN : '^=';
+MOD_ASSIGN : '%=';
+LSHIFT_ASSIGN : '<<=';
+RSHIFT_ASSIGN : '>>=';
+URSHIFT_ASSIGN : '>>>=';
+ELVIS_ASSIGN : '?=';
+
+
+// §3.8 Identifiers (must appear after all keywords in the grammar)
+CapitalizedIdentifier
+ : [A-Z] JavaLetterOrDigit*
+ ;
+
+Identifier
+ : JavaLetter JavaLetterOrDigit*
+ ;
+
+fragment
+IdentifierInGString
+ : JavaLetterInGString JavaLetterOrDigitInGString*
+ ;
+
+fragment
+JavaLetterInGString
+ : [a-zA-Z_] // these are the "java letters" below 0x7F, except for $
+ | // covers all characters above 0x7F which are not a surrogate
+ ~[\u0000-\u007F\uD800-\uDBFF]
+ {Character.isJavaIdentifierStart(_input.LA(-1))}?
+ | // covers UTF-16 surrogate pairs encodings for U+10000 to U+10FFFF
+ [\uD800-\uDBFF] [\uDC00-\uDFFF]
+ {Character.isJavaIdentifierStart(Character.toCodePoint((char)_input.LA(-2), (char)_input.LA(-1)))}?
+ ;
+
+fragment
+JavaLetterOrDigitInGString
+ : [a-zA-Z0-9_] // these are the "java letters or digits" below 0x7F, except for $
+ | // covers all characters above 0x7F which are not a surrogate
+ ~[\u0000-\u007F\uD800-\uDBFF]
+ {Character.isJavaIdentifierPart(_input.LA(-1))}?
+ | // covers UTF-16 surrogate pairs encodings for U+10000 to U+10FFFF
+ [\uD800-\uDBFF] [\uDC00-\uDFFF]
+ {Character.isJavaIdentifierPart(Character.toCodePoint((char)_input.LA(-2), (char)_input.LA(-1)))}?
+ ;
+
+
+fragment
+JavaLetter
+ : [a-zA-Z$_] // these are the "java letters" below 0x7F
+ | // covers all characters above 0x7F which are not a surrogate
+ ~[\u0000-\u007F\uD800-\uDBFF]
+ {Character.isJavaIdentifierStart(_input.LA(-1))}?
+ | // covers UTF-16 surrogate pairs encodings for U+10000 to U+10FFFF
+ [\uD800-\uDBFF] [\uDC00-\uDFFF]
+ {Character.isJavaIdentifierStart(Character.toCodePoint((char)_input.LA(-2), (char)_input.LA(-1)))}?
+ ;
+
+fragment
+JavaLetterOrDigit
+ : [a-zA-Z0-9$_] // these are the "java letters or digits" below 0x7F
+ | // covers all characters above 0x7F which are not a surrogate
+ ~[\u0000-\u007F\uD800-\uDBFF]
+ {Character.isJavaIdentifierPart(_input.LA(-1))}?
+ | // covers UTF-16 surrogate pairs encodings for U+10000 to U+10FFFF
+ [\uD800-\uDBFF] [\uDC00-\uDFFF]
+ {Character.isJavaIdentifierPart(Character.toCodePoint((char)_input.LA(-2), (char)_input.LA(-1)))}?
+ ;
+
+//
+// Additional symbols not defined in the lexical specification
+//
+
+AT : '@';
+ELLIPSIS : '...';
+
+//
+// Whitespace, line escape and comments
+//
+WS : ([ \t\u000C]+ | LineEscape+) -> skip
+ ;
+
+
+// Inside (...) and [...] but not {...}, ignore newlines.
+NL : '\r'? '\n' { this.ignoreTokenInsideParens(); }
+ ;
+
+// Multiple-line comments(including groovydoc comments)
+ML_COMMENT
+ : '/*' .*? '*/' { this.ignoreMultiLineCommentConditionally(); } -> type(NL)
+ ;
+
+// Single-line comments
+SL_COMMENT
+ : '//' ~[\r\n\uFFFF]* { this.ignoreTokenInsideParens(); } -> type(NL)
+ ;
+
+// Script-header comments.
+// The very first characters of the file may be "#!". If so, ignore the first line.
+SH_COMMENT
+ : '#!' { require(0 == this.tokenIndex, "Shebang comment should appear at the first line", -2, true); } ~[\r\n\uFFFF]* -> skip
+ ;
+
+// Unexpected characters will be handled by groovy parser later.
+UNEXPECTED_CHAR
+ : .
+ ;
http://git-wip-us.apache.org/repos/asf/groovy/blob/74110e34/src/antlr/GroovyParser.g4
----------------------------------------------------------------------
diff --git a/src/antlr/GroovyParser.g4 b/src/antlr/GroovyParser.g4
new file mode 100644
index 0000000..009f415
--- /dev/null
+++ b/src/antlr/GroovyParser.g4
@@ -0,0 +1,1265 @@
+/*
+ * 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;
+ import org.apache.groovy.parser.antlr4.SemanticPredicates;
+}
+
+@members {
+
+ 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 | EOF))? (statement (sep | EOF))* EOF
+ ;
+
+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
+ )
+ ;
+
+modifiersOpt
+ : modifiers?
+ ;
+
+modifiers
+ : (modifier nls)+
+ ;
+
+classOrInterfaceModifiersOpt
+ : classOrInterfaceModifiers?
+ ;
+
+classOrInterfaceModifiers
+ : (classOrInterfaceModifier nls)+
+ ;
+
+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
+ | 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
+ // 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?
+ ;
+
+variableModifiers
+ : (variableModifier nls)+
+ ;
+
+typeParameters
+ : LT nls typeParameter (COMMA nls typeParameter)* nls GT
+ ;
+
+typeParameter
+ : 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
+ */
+classDeclaration
+locals[ int t ]
+ : ( CLASS { $t = 0; }
+ | INTERFACE { $t = 1; }
+ | ENUM { $t = 2; }
+ | AT INTERFACE { $t = 3; }
+ | TRAIT { $t = 4; }
+ )
+ identifier nls
+
+ (
+ { 3 != $t }?
+ typeParameters? nls
+ (
+ { 2 != $t }?
+ (EXTENDS nls
+ (
+ // Only interface can extend more than one super class
+ {1 == $t}? scs=typeList
+ |
+ sc=type
+ )
+ nls)?
+ |
+ /* enum should not have type parameters and extends */
+ )
+
+ (
+ {1 != $t}?
+ (IMPLEMENTS nls is=typeList nls)?
+ |
+ /* interface should not implement other interfaces */
+ )
+ |
+ /* annotation should not have implements and extends*/
+ )
+
+ classBody[$t]
+ ;
+
+// t see the comment of classDeclaration
+classBody[int t]
+ : LBRACE nls
+ (
+ /* Only enum can have enum constants */
+ { 2 == $t }?
+ enumConstants? nls
+ |
+
+ )
+ classBodyDeclaration[$t]? (sep classBodyDeclaration[$t])* sep? RBRACE
+ ;
+
+enumConstants
+ : enumConstant (nls COMMA nls enumConstant)* (nls COMMA)?
+ ;
+
+enumConstant
+ : annotationsOpt identifier arguments? anonymousInnerClassDeclaration[1]?
+ ;
+
+classBodyDeclaration[int t]
+ : SEMI
+ | (STATIC nls)? block
+ | memberDeclaration[$t]
+ ;
+
+memberDeclaration[int t]
+ : methodDeclaration[0, $t]
+ | fieldDeclaration
+ | modifiersOpt classDeclaration
+ ;
+
+/**
+ * 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]
+ : { 3 == $ct }?
+ returnType[$ct] methodName LPAREN RPAREN (DEFAULT nls elementValue)?
+ |
+ ( { 0 == $t }?
+ modifiersOpt typeParameters?
+ | modifiersOpt typeParameters? returnType[$ct]
+ | modifiers typeParameters? returnType[$ct]?
+ )
+ methodName formalParameters (nls THROWS nls qualifiedClassNameList)?
+ (
+ { 0 == $t || 3 == $t || 1 == $t}?
+ nls methodBody
+ |
+ { 0 == $t || 3 == $t || 2 == $t }?
+ /* no method body */
+ )
+ ;
+
+methodName
+ : identifier
+ | stringLiteral
+ ;
+
+returnType[int ct]
+ :
+ standardType
+ |
+ // annotation method can not have void return type
+ { 3 != $ct }? 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)* nls COMMA?
+ ;
+
+dims
+ : (annotationsOpt LBRACK RBRACK)+
+ ;
+
+dimsOpt
+ : dims?
+ ;
+
+standardType
+options { baseContext = type; }
+ : annotationsOpt
+ (
+ primitiveType
+ |
+ standardClassOrInterfaceType
+ )
+ dimsOpt
+ ;
+
+type
+ : annotationsOpt
+ (
+ (
+ primitiveType
+ |
+ // !!! ERROR ALTERNATIVE !!!
+ VOID { require(false, "void is not allowed here", -4); }
+ )
+ |
+ generalClassOrInterfaceType
+ )
+ dimsOpt
+ ;
+
+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
+ ;
+
+qualifiedClassName
+ : (qualifiedNameElement DOT)* identifier
+ ;
+
+qualifiedStandardClassName
+ : (qualifiedNameElement DOT)* (className DOT)* className
+ ;
+
+literal
+ : IntegerLiteral #integerLiteralAlt
+ | FloatingPointLiteral #floatingPointLiteralAlt
+ | stringLiteral #stringLiteralAlt
+ | BooleanLiteral #booleanLiteralAlt
+ | NullLiteral #nullLiteralAlt
+ ;
+
+// GSTRING
+
+gstring
+ : GStringBegin gstringValue (GStringPart gstringValue)* GStringEnd
+ ;
+
+gstringValue
+ : gstringPath
+ | LBRACE statementExpression? RBRACE
+ | closure
+ ;
+
+gstringPath
+ : identifier GStringPathPart*
+ ;
+
+
+// LAMBDA EXPRESSION
+lambdaExpression
+options { baseContext = standardLambdaExpression; }
+ : lambdaParameters nls ARROW nls lambdaBody
+ ;
+
+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
+locals[ String footprint = "" ]
+ : LBRACE nls (formalParameterList? nls ARROW nls)? blockStatementsOpt RBRACE
+ ;
+
+blockStatementsOpt
+ : blockStatements?
+ ;
+
+blockStatements
+ : blockStatement (sep blockStatement)* sep?
+ ;
+
+// ANNOTATIONS
+
+annotationsOpt
+ : (annotation nls)*
+ ;
+
+annotation
+ : AT annotationName ( 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 (nls | sep*) blockStatementsOpt RBRACE
+ ;
+
+blockStatement
+ : localVariableDeclaration
+ | statement
+ ;
+
+localVariableDeclaration
+ : { !SemanticPredicates.isInvalidLocalVariableDeclaration(_input) }?
+ variableDeclaration[0]
+ ;
+
+/**
+ * t 0: local variable declaration; 1: field declaration
+ */
+variableDeclaration[int t]
+ : ( { 0 == $t }? variableModifiers
+ | { 1 == $t }? modifiers
+ )
+ type? variableDeclarators
+ |
+ ( { 0 == $t }? variableModifiersOpt
+ | { 1 == $t }? modifiersOpt
+ )
+ type variableDeclarators
+ |
+ ( { 0 == $t }? variableModifiers
+ | { 1 == $t }? modifiers
+ )
+ typeNamePairs nls ASSIGN nls variableInitializer
+ ;
+
+typeNamePairs
+ : LPAREN typeNamePair (COMMA typeNamePair)* RPAREN
+ ;
+
+typeNamePair
+ : type? variableDeclaratorId
+ ;
+
+variableNames
+ : LPAREN variableDeclaratorId (COMMA variableDeclaratorId)+ rparen
+ ;
+
+switchStatement
+locals[ String footprint = "" ]
+ : SWITCH expressionInPar nls LBRACE nls switchBlockStatementGroup* nls RBRACE
+ ;
+
+loopStatement
+locals[ String footprint = "" ]
+ : FOR LPAREN forControl rparen nls statement #forStmtAlt
+ | WHILE expressionInPar nls statement #whileStmtAlt
+ | DO nls statement nls WHILE expressionInPar #doWhileStmtAlt
+ ;
+
+continueStatement
+locals[ boolean isInsideLoop ]
+@init {
+ try {
+ $isInsideLoop = null != $loopStatement::footprint;
+ } catch(NullPointerException e) {
+ $isInsideLoop = false;
+ }
+}
+ : CONTINUE
+ { require($isInsideLoop, "the continue statement is only allowed inside loops", -8); }
+ identifier?
+ ;
+
+breakStatement
+locals[ boolean isInsideLoop, boolean isInsideSwitch ]
+@init {
+ try {
+ $isInsideLoop = null != $loopStatement::footprint;
+ } catch(NullPointerException e) {
+ $isInsideLoop = false;
+ }
+
+ try {
+ $isInsideSwitch = null != $switchStatement::footprint;
+ } catch(NullPointerException e) {
+ $isInsideSwitch = false;
+ }
+}
+ : BREAK
+ { require($isInsideLoop || $isInsideSwitch, "the break statement is only allowed inside loops or switches", -5); }
+ identifier?
+ ;
+
+tryCatchStatement
+locals[boolean resourcesExists = false]
+ : TRY (resources { $resourcesExists = true; })? nls
+ block
+ (
+ (nls catchClause)+
+ (nls finallyBlock)?
+ |
+ nls finallyBlock
+ |
+ // catch and finally clauses required unless it's a try-with-resources block
+ { require($resourcesExists, "either a catch or finally clause or both is required for a try-catch-finally statement"); }
+ )
+ ;
+
+assertStatement
+locals[ String footprint = "" ]
+ : ASSERT ce=expression (nls (COLON | COMMA) nls me=expression)?
+ ;
+
+statement
+ : block #blockStmtAlt
+ | IF expressionInPar nls tb=statement ((nls | sep) ELSE nls fb=statement)? #ifElseStmtAlt
+ | loopStatement #loopStmtAlt
+
+ | tryCatchStatement #tryCatchStmtAlt
+
+ | switchStatement #switchStmtAlt
+ | SYNCHRONIZED expressionInPar nls block #synchronizedStmtAlt
+ | RETURN expression? #returnStmtAlt
+ | THROW expression #throwStmtAlt
+
+ | breakStatement #breakStmtAlt
+ | continueStatement #continueStmtAlt
+
+ | identifier COLON nls statement #labeledStmtAlt
+
+ // Import statement. Can be used in any scope. Has "import x as y" also.
+ | importDeclaration #importStmtAlt
+
+ | assertStatement #assertStmtAlt
+
+ | typeDeclaration #typeDeclarationStmtAlt
+ | localVariableDeclaration #localVariableDeclarationStmtAlt
+
+ // validate the method in the AstBuilder#visitMethodDeclaration, e.g. method without method body is not allowed
+ | { !SemanticPredicates.isInvalidMethodDeclaration(_input) }?
+ methodDeclaration[3, 9] #methodDeclarationStmtAlt
+
+ | 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)+ 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 expressionListElement[$canSpread])*
+ ;
+
+expressionListElement[boolean canSpread]
+ : ( MUL { require($canSpread, "spread operator is not allowed here", -1); }
+ |
+ ) expression
+ ;
+
+enhancedStatementExpression
+ : statementExpression
+ | standardLambdaExpression
+ ;
+
+/**
+ * In order to resolve the syntactic ambiguities, e.g. (String)'abc' can be parsed as a cast expression or a parentheses-less method call(method name: (String), arguments: 'abc')
+ * try to match expression first.
+ * If it is not a normal expression, then try to match the command expression
+ */
+statementExpression
+ : expression #normalExprAlt
+ | commandExpression #commandExprAlt
+ ;
+
+postfixExpression
+locals[ boolean isInsideAssert ]
+@init {
+ try {
+ $isInsideAssert = null != $assertStatement::footprint;
+ } catch(NullPointerException e) {
+ $isInsideAssert = false;
+ }
+}
+ : pathExpression op=(INC | DEC)?
+ ;
+
+expression
+ // qualified names, array expressions, method invocation, post inc/dec, type casting (level 1)
+ // The cast expression must be put before pathExpression to resovle the ambiguities between type casting and call on parentheses expression, e.g. (int)(1 / 2)
+ : castParExpression expression #castExprAlt
+ | postfixExpression #postfixExprAlt
+
+ // ~(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
+ )
+ ) 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)
+ | <assoc=right> 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
+ | <assoc=right> left=variableNames nls op=ASSIGN nls right=statementExpression #multipleAssignmentExprAlt
+ | <assoc=right> 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
+ enhancedStatementExpression #assignmentExprAlt
+ ;
+
+commandExpression
+ : pathExpression
+ (
+ { SemanticPredicates.isFollowingMethodName($pathExpression.t) }?
+ argumentList
+ |
+ /* if pathExpression is a method call, no need to have any more arguments */
+ )
+
+ commandArgument*
+ ;
+
+commandArgument
+ : primary
+ // 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: closure, 4: indexPropertyArgs, 5: namedPropertyArgs
+ */
+pathExpression returns [int t]
+ : primary (pathElement { $t = $pathElement.t; })*
+ ;
+
+pathElement returns [int t]
+locals[ boolean isInsideClosure ]
+@init {
+ try {
+ $isInsideClosure = null != $closure::footprint;
+ } catch(NullPointerException e) {
+ $isInsideClosure = false;
+ }
+}
+ : nls
+
+ // AT: foo.@bar selects the field (or attribute), not property
+ ( SPREAD_DOT nls (AT | nonWildcardTypeArguments)? // Spread operator: x*.y === x?.collect{it.y}
+ | SAFE_DOT nls (AT | nonWildcardTypeArguments)? // Optional-null operator: x?.y === (x==null)?null:x.y
+ | METHOD_POINTER nls // Method pointer operator: foo.&y == foo.metaClass.getMethodPointer(foo, "y")
+ | METHOD_REFERENCE nls // Method reference: System.out::println
+ | DOT nls (AT | nonWildcardTypeArguments)? // The all-powerful dot.
+ )
+ namePart
+ { $t = 1; }
+
+ | arguments
+ { $t = 2; }
+
+ // Can always append a block, as foo{bar}
+ | nls closure
+ { $t = 3; }
+
+ // 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
+ : QUESTION? LBRACK expressionList[true]? RBRACK
+ ;
+
+namedPropertyArgs
+ : LBRACK mapEntryList RBRACK
+ ;
+
+primary
+ : identifier #identifierPrmrAlt
+ | literal #literalPrmrAlt
+ | gstring #gstringPrmrAlt
+ | NEW nls creator #newPrmrAlt
+ | THIS #thisPrmrAlt
+ | SUPER #superPrmrAlt
+ | parExpression #parenPrmrAlt
+ | closure #closurePrmrAlt
+ | lambdaExpression #lambdaPrmrAlt
+ | list #listPrmrAlt
+ | map #mapPrmrAlt
+ | builtInType #typePrmrAlt
+ ;
+
+list
+locals[boolean empty = true]
+ : LBRACK
+ (
+ expressionList[true]
+ { $empty = false; }
+ )?
+ (
+ COMMA
+ { require(!$empty, "Empty list constructor should not contain any comma(,)", -1); }
+ )?
+ RBRACK
+ ;
+
+map
+ : LBRACK
+ ( mapEntryList COMMA?
+ | COLON
+ )
+ RBRACK
+ ;
+
+mapEntryList
+ : mapEntry (COMMA mapEntry)*
+ ;
+
+mapEntry
+ : mapEntryLabel COLON nls expression
+ | MUL COLON nls expression
+ ;
+
+mapEntryLabel
+ : keywords
+ | primary
+ ;
+
+creator
+ : createdName
+ ( nls arguments anonymousInnerClassDeclaration[0]?
+ | (annotationsOpt LBRACK expression RBRACK)+ dimsOpt
+ | dims nls arrayInitializer
+ )
+ ;
+
+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
+ ( enhancedArgumentList?
+ | enhancedArgumentList COMMA
+ )
+ rparen
+ ;
+
+argumentList
+options { baseContext = enhancedArgumentList; }
+ : argumentListElement
+ ( COMMA nls
+ argumentListElement
+ )*
+ ;
+
+enhancedArgumentList
+ : enhancedArgumentListElement
+ ( COMMA nls
+ enhancedArgumentListElement
+ )*
+ ;
+
+argumentListElement
+options { baseContext = enhancedArgumentListElement; }
+ : expressionListElement[true]
+ | mapEntry
+ ;
+
+enhancedArgumentListElement
+ : expressionListElement[true]
+ | standardLambdaExpression
+ | mapEntry
+ ;
+
+stringLiteral
+ : StringLiteral
+ ;
+
+className
+ : CapitalizedIdentifier
+ ;
+
+identifier
+ : Identifier
+ | CapitalizedIdentifier
+
+ |
+ // if 'static' followed by DOT, we can treat them as identifiers, e.g. static.unused = { -> }
+ { DOT == _input.LT(2).getType() }?
+ STATIC
+ ;
+
+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
+ | PACKAGE
+ | RETURN
+ | STATIC
+ | STRICTFP
+ | SUPER
+ | SWITCH
+ | SYNCHRONIZED
+ | THIS
+ | THROW
+ | THROWS
+ | TRANSIENT
+ | TRAIT
+ | THREADSAFE
+ | TRY
+ | VOLATILE
+ | WHILE
+
+ | NullLiteral
+ | BooleanLiteral
+
+ | BuiltInPrimitiveType
+ | VOID
+
+ | PUBLIC
+ | PROTECTED
+ | PRIVATE
+ ;
+
+rparen
+ : RPAREN
+ |
+ // !!!Error Alternative, impact the performance of parsing
+ { require(false, "Missing ')'"); }
+ ;
+
+nls
+ : NL*
+ ;
+
+sep : SEMI NL*
+ | NL+ (SEMI NL*)*
+ ;
+
+
http://git-wip-us.apache.org/repos/asf/groovy/blob/74110e34/src/main/antlr/GroovyLexer.g4
----------------------------------------------------------------------
diff --git a/src/main/antlr/GroovyLexer.g4 b/src/main/antlr/GroovyLexer.g4
deleted file mode 100644
index 05fb767..0000000
--- a/src/main/antlr/GroovyLexer.g4
+++ /dev/null
@@ -1,938 +0,0 @@
-/*
- * 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
- */
-lexer grammar GroovyLexer;
-
-options {
- superClass = AbstractLexer;
-}
-
-@header {
- import static org.apache.groovy.parser.antlr4.SemanticPredicates.*;
- import java.util.Deque;
- import java.util.ArrayDeque;
- import java.util.Map;
- import java.util.HashMap;
- import java.util.Set;
- import java.util.HashSet;
- import java.util.Collections;
- import java.util.Arrays;
-}
-
-@members {
- private long tokenIndex = 0;
- private int lastTokenType = 0;
- private int invalidDigitCount = 0;
-
- /**
- * Record the index and token type of the current token while emitting tokens.
- */
- @Override
- public void emit(Token token) {
- this.tokenIndex++;
-
- int tokenType = token.getType();
- if (Token.DEFAULT_CHANNEL == token.getChannel()) {
- this.lastTokenType = tokenType;
- }
-
- if (RollBackOne == tokenType) {
- this.rollbackOneChar();
- }
-
- super.emit(token);
- }
-
- private static final Set<Integer> REGEX_CHECK_SET =
- Collections.unmodifiableSet(
- new HashSet<>(Arrays.asList(Identifier, CapitalizedIdentifier, NullLiteral, BooleanLiteral, THIS, RPAREN, RBRACK, RBRACE, IntegerLiteral, FloatingPointLiteral, StringLiteral, GStringEnd, INC, DEC)));
- private boolean isRegexAllowed() {
- if (REGEX_CHECK_SET.contains(this.lastTokenType)) {
- return false;
- }
-
- return true;
- }
-
- /**
- * just a hook, which will be overrided by GroovyLangLexer
- */
- protected void rollbackOneChar() {}
-
- private static class Paren {
- private String text;
- private int lastTokenType;
- private int line;
- private int column;
-
- public Paren(String text, int lastTokenType, int line, int column) {
- this.text = text;
- this.lastTokenType = lastTokenType;
- this.line = line;
- this.column = column;
- }
-
- public String getText() {
- return this.text;
- }
-
- public int getLastTokenType() {
- return this.lastTokenType;
- }
-
- public int getLine() {
- return line;
- }
-
- public int getColumn() {
- return column;
- }
-
- @Override
- public int hashCode() {
- return (int) (text.hashCode() * line + column);
- }
-
- @Override
- public boolean equals(Object obj) {
- if (!(obj instanceof Paren)) {
- return false;
- }
-
- Paren other = (Paren) obj;
-
- return this.text.equals(other.text) && (this.line == other.line && this.column == other.column);
- }
- }
-
- private static final Map<String, String> PAREN_MAP = Collections.unmodifiableMap(new HashMap<String, String>() {
- {
- put("(", ")");
- put("[", "]");
- put("{", "}");
- }
- });
-
- private final Deque<Paren> parenStack = new ArrayDeque<>(32);
- private void enterParen() {
- parenStack.push(new Paren(getText(), this.lastTokenType, getLine(), getCharPositionInLine()));
- }
- private void exitParen() {
- Paren paren = parenStack.peek();
- String text = getText();
-
- require(null != paren, "Too many '" + text + "'");
- require(text.equals(PAREN_MAP.get(paren.getText())),
- "'" + paren.getText() + "'" + new PositionInfo(paren.getLine(), paren.getColumn()) + " can not match '" + text + "'", -1);
-
- parenStack.pop();
- }
- private boolean isInsideParens() {
- Paren paren = parenStack.peek();
-
- // We just care about "(" and "[", inside which the new lines will be ignored.
- // Notice: the new lines between "{" and "}" can not be ignored.
- if (null == paren) {
- return false;
- }
- return ("(".equals(paren.getText()) && TRY != paren.getLastTokenType()) // we don't treat try-paren(i.e. try (....)) as parenthesis
- || "[".equals(paren.getText());
- }
- private void ignoreTokenInsideParens() {
- if (!this.isInsideParens()) {
- return;
- }
-
- this.setChannel(Token.HIDDEN_CHANNEL);
- }
- private void ignoreMultiLineCommentConditionally() {
- if (!this.isInsideParens() && isFollowedByWhiteSpaces(_input)) {
- return;
- }
-
- this.setChannel(Token.HIDDEN_CHANNEL);
- }
-
- @Override
- public int getSyntaxErrorSource() {
- return GroovySyntaxError.LEXER;
- }
-
- @Override
- public int getErrorLine() {
- return getLine();
- }
-
- @Override
- public int getErrorColumn() {
- return getCharPositionInLine() + 1;
- }
-}
-
-
-// §3.10.5 String Literals
-StringLiteral
- : GStringQuotationMark DqStringCharacter*? GStringQuotationMark
- | SqStringQuotationMark SqStringCharacter*? SqStringQuotationMark
-
- | Slash { this.isRegexAllowed() && _input.LA(1) != '*' }?
- SlashyStringCharacter+? Slash
-
- | TdqStringQuotationMark TdqStringCharacter*? TdqStringQuotationMark
- | TsqStringQuotationMark TsqStringCharacter*? TsqStringQuotationMark
- | DollarSlashyGStringQuotationMarkBegin DollarSlashyStringCharacter+? DollarSlashyGStringQuotationMarkEnd
- ;
-
-// Groovy gstring
-GStringBegin
- : GStringQuotationMark DqStringCharacter*? Dollar -> pushMode(DQ_GSTRING_MODE), pushMode(GSTRING_TYPE_SELECTOR_MODE)
- ;
-TdqGStringBegin
- : TdqStringQuotationMark TdqStringCharacter*? Dollar -> type(GStringBegin), pushMode(TDQ_GSTRING_MODE), pushMode(GSTRING_TYPE_SELECTOR_MODE)
- ;
-SlashyGStringBegin
- : Slash { this.isRegexAllowed() && _input.LA(1) != '*' }? SlashyStringCharacter*? Dollar { isFollowedByJavaLetterInGString(_input) }? -> type(GStringBegin), pushMode(SLASHY_GSTRING_MODE), pushMode(GSTRING_TYPE_SELECTOR_MODE)
- ;
-DollarSlashyGStringBegin
- : DollarSlashyGStringQuotationMarkBegin DollarSlashyStringCharacter*? Dollar { isFollowedByJavaLetterInGString(_input) }? -> type(GStringBegin), pushMode(DOLLAR_SLASHY_GSTRING_MODE), pushMode(GSTRING_TYPE_SELECTOR_MODE)
- ;
-
-mode DQ_GSTRING_MODE;
-GStringEnd
- : GStringQuotationMark -> popMode
- ;
-GStringPart
- : Dollar -> pushMode(GSTRING_TYPE_SELECTOR_MODE)
- ;
-GStringCharacter
- : DqStringCharacter -> more
- ;
-
-mode TDQ_GSTRING_MODE;
-TdqGStringEnd
- : TdqStringQuotationMark -> type(GStringEnd), popMode
- ;
-TdqGStringPart
- : Dollar -> type(GStringPart), pushMode(GSTRING_TYPE_SELECTOR_MODE)
- ;
-TdqGStringCharacter
- : TdqStringCharacter -> more
- ;
-
-mode SLASHY_GSTRING_MODE;
-SlashyGStringEnd
- : Dollar? Slash -> type(GStringEnd), popMode
- ;
-SlashyGStringPart
- : Dollar { isFollowedByJavaLetterInGString(_input) }? -> type(GStringPart), pushMode(GSTRING_TYPE_SELECTOR_MODE)
- ;
-SlashyGStringCharacter
- : SlashyStringCharacter -> more
- ;
-
-mode DOLLAR_SLASHY_GSTRING_MODE;
-DollarSlashyGStringEnd
- : DollarSlashyGStringQuotationMarkEnd -> type(GStringEnd), popMode
- ;
-DollarSlashyGStringPart
- : Dollar { isFollowedByJavaLetterInGString(_input) }? -> type(GStringPart), pushMode(GSTRING_TYPE_SELECTOR_MODE)
- ;
-DollarSlashyGStringCharacter
- : DollarSlashyStringCharacter -> more
- ;
-
-mode GSTRING_TYPE_SELECTOR_MODE;
-GStringLBrace
- : '{' { this.enterParen(); } -> type(LBRACE), popMode, pushMode(DEFAULT_MODE)
- ;
-GStringIdentifier
- : IdentifierInGString -> type(Identifier), popMode, pushMode(GSTRING_PATH_MODE)
- ;
-
-
-mode GSTRING_PATH_MODE;
-GStringPathPart
- : Dot IdentifierInGString
- ;
-RollBackOne
- : . {
- // a trick to handle GStrings followed by EOF properly
- if (EOF == _input.LA(1) && ('"' == _input.LA(-1) || '/' == _input.LA(-1))) {
- setType(GStringEnd);
- } else {
- setChannel(HIDDEN);
- }
- } -> popMode
- ;
-
-
-mode DEFAULT_MODE;
-// character in the double quotation string. e.g. "a"
-fragment
-DqStringCharacter
- : ~["\\$]
- | EscapeSequence
- ;
-
-// character in the single quotation string. e.g. 'a'
-fragment
-SqStringCharacter
- : ~['\\]
- | EscapeSequence
- ;
-
-// character in the triple double quotation string. e.g. """a"""
-fragment TdqStringCharacter
- : ~["\\$]
- | GStringQuotationMark { !(_input.LA(1) == '"' && _input.LA(2) == '"') }?
- | EscapeSequence
- ;
-
-// character in the triple single quotation string. e.g. '''a'''
-fragment TsqStringCharacter
- : ~['\\]
- | SqStringQuotationMark { !(_input.LA(1) == '\'' && _input.LA(2) == '\'') }?
- | EscapeSequence
- ;
-
-// character in the slashy string. e.g. /a/
-fragment SlashyStringCharacter
- : SlashEscape
- | Dollar { !isFollowedByJavaLetterInGString(_input) }?
- | ~[/$\u0000]
- ;
-
-// character in the collar slashy string. e.g. $/a/$
-fragment DollarSlashyStringCharacter
- : SlashEscape | DollarSlashEscape | DollarDollarEscape
- | Slash { _input.LA(1) != '$' }?
- | Dollar { !isFollowedByJavaLetterInGString(_input) }?
- | ~[/$\u0000]
- ;
-
-// Groovy keywords
-AS : 'as';
-DEF : 'def';
-IN : 'in';
-TRAIT : 'trait';
-THREADSAFE : 'threadsafe'; // reserved keyword
-
-
-// §3.9 Keywords
-BuiltInPrimitiveType
- : BOOLEAN
- | CHAR
- | BYTE
- | SHORT
- | INT
- | LONG
- | FLOAT
- | DOUBLE
- ;
-
-ABSTRACT : 'abstract';
-ASSERT : 'assert';
-
-fragment
-BOOLEAN : 'boolean';
-
-BREAK : 'break';
-
-fragment
-BYTE : 'byte';
-
-CASE : 'case';
-CATCH : 'catch';
-
-fragment
-CHAR : 'char';
-
-CLASS : 'class';
-CONST : 'const';
-CONTINUE : 'continue';
-DEFAULT : 'default';
-DO : 'do';
-
-fragment
-DOUBLE : 'double';
-
-ELSE : 'else';
-ENUM : 'enum';
-EXTENDS : 'extends';
-FINAL : 'final';
-FINALLY : 'finally';
-
-fragment
-FLOAT : 'float';
-
-
-FOR : 'for';
-IF : 'if';
-GOTO : 'goto';
-IMPLEMENTS : 'implements';
-IMPORT : 'import';
-INSTANCEOF : 'instanceof';
-
-fragment
-INT : 'int';
-
-INTERFACE : 'interface';
-
-fragment
-LONG : 'long';
-
-NATIVE : 'native';
-NEW : 'new';
-PACKAGE : 'package';
-PRIVATE : 'private';
-PROTECTED : 'protected';
-PUBLIC : 'public';
-RETURN : 'return';
-
-fragment
-SHORT : 'short';
-
-
-STATIC : 'static';
-STRICTFP : 'strictfp';
-SUPER : 'super';
-SWITCH : 'switch';
-SYNCHRONIZED : 'synchronized';
-THIS : 'this';
-THROW : 'throw';
-THROWS : 'throws';
-TRANSIENT : 'transient';
-TRY : 'try';
-VOID : 'void';
-VOLATILE : 'volatile';
-WHILE : 'while';
-
-
-// §3.10.1 Integer Literals
-
-IntegerLiteral
- : ( DecimalIntegerLiteral
- | HexIntegerLiteral
- | OctalIntegerLiteral
- | BinaryIntegerLiteral
- ) (Underscore { require(false, "Number ending with underscores is invalid", -1, true); })?
-
- // !!! Error Alternative !!!
- | Zero ([0-9] { invalidDigitCount++; })+ { require(false, "Invalid octal number", -(invalidDigitCount + 1), true); } IntegerTypeSuffix?
- ;
-
-fragment
-Zero
- : '0'
- ;
-
-fragment
-DecimalIntegerLiteral
- : DecimalNumeral IntegerTypeSuffix?
- ;
-
-fragment
-HexIntegerLiteral
- : HexNumeral IntegerTypeSuffix?
- ;
-
-fragment
-OctalIntegerLiteral
- : OctalNumeral IntegerTypeSuffix?
- ;
-
-fragment
-BinaryIntegerLiteral
- : BinaryNumeral IntegerTypeSuffix?
- ;
-
-fragment
-IntegerTypeSuffix
- : [lLiIgG]
- ;
-
-fragment
-DecimalNumeral
- : Zero
- | NonZeroDigit (Digits? | Underscores Digits)
- ;
-
-fragment
-Digits
- : Digit (DigitOrUnderscore* Digit)?
- ;
-
-fragment
-Digit
- : Zero
- | NonZeroDigit
- ;
-
-fragment
-NonZeroDigit
- : [1-9]
- ;
-
-fragment
-DigitOrUnderscore
- : Digit
- | Underscore
- ;
-
-fragment
-Underscores
- : Underscore+
- ;
-
-fragment
-Underscore
- : '_'
- ;
-
-fragment
-HexNumeral
- : Zero [xX] HexDigits
- ;
-
-fragment
-HexDigits
- : HexDigit (HexDigitOrUnderscore* HexDigit)?
- ;
-
-fragment
-HexDigit
- : [0-9a-fA-F]
- ;
-
-fragment
-HexDigitOrUnderscore
- : HexDigit
- | Underscore
- ;
-
-fragment
-OctalNumeral
- : Zero Underscores? OctalDigits
- ;
-
-fragment
-OctalDigits
- : OctalDigit (OctalDigitOrUnderscore* OctalDigit)?
- ;
-
-fragment
-OctalDigit
- : [0-7]
- ;
-
-fragment
-OctalDigitOrUnderscore
- : OctalDigit
- | Underscore
- ;
-
-fragment
-BinaryNumeral
- : Zero [bB] BinaryDigits
- ;
-
-fragment
-BinaryDigits
- : BinaryDigit (BinaryDigitOrUnderscore* BinaryDigit)?
- ;
-
-fragment
-BinaryDigit
- : [01]
- ;
-
-fragment
-BinaryDigitOrUnderscore
- : BinaryDigit
- | Underscore
- ;
-
-// §3.10.2 Floating-Point Literals
-
-FloatingPointLiteral
- : ( DecimalFloatingPointLiteral
- | HexadecimalFloatingPointLiteral
- ) (Underscore { require(false, "Number ending with underscores is invalid", -1, true); })?
- ;
-
-fragment
-DecimalFloatingPointLiteral
- : Digits Dot Digits ExponentPart? FloatTypeSuffix?
- | Digits ExponentPart FloatTypeSuffix?
- | Digits FloatTypeSuffix
- ;
-
-fragment
-ExponentPart
- : ExponentIndicator SignedInteger
- ;
-
-fragment
-ExponentIndicator
- : [eE]
- ;
-
-fragment
-SignedInteger
- : Sign? Digits
- ;
-
-fragment
-Sign
- : [+\-]
- ;
-
-fragment
-FloatTypeSuffix
- : [fFdDgG]
- ;
-
-fragment
-HexadecimalFloatingPointLiteral
- : HexSignificand BinaryExponent FloatTypeSuffix?
- ;
-
-fragment
-HexSignificand
- : HexNumeral Dot?
- | Zero [xX] HexDigits? Dot HexDigits
- ;
-
-fragment
-BinaryExponent
- : BinaryExponentIndicator SignedInteger
- ;
-
-fragment
-BinaryExponentIndicator
- : [pP]
- ;
-
-fragment
-Dot : '.'
- ;
-
-// §3.10.3 Boolean Literals
-
-BooleanLiteral
- : 'true'
- | 'false'
- ;
-
-
-// §3.10.6 Escape Sequences for Character and String Literals
-
-fragment
-EscapeSequence
- : Backslash [btnfr"'\\]
- | OctalEscape
- | UnicodeEscape
- | DollarEscape
- | LineEscape
- ;
-
-
-fragment
-OctalEscape
- : Backslash OctalDigit
- | Backslash OctalDigit OctalDigit
- | Backslash ZeroToThree OctalDigit OctalDigit
- ;
-
-// Groovy allows 1 or more u's after the backslash
-fragment
-UnicodeEscape
- : Backslash 'u' HexDigit HexDigit HexDigit HexDigit
- ;
-
-fragment
-ZeroToThree
- : [0-3]
- ;
-
-// Groovy Escape Sequences
-
-fragment
-DollarEscape
- : Backslash Dollar
- ;
-
-fragment
-LineEscape
- : Backslash '\r'? '\n'
- ;
-
-fragment
-SlashEscape
- : Backslash Slash
- ;
-
-fragment
-Backslash
- : '\\'
- ;
-
-fragment
-Slash
- : '/'
- ;
-
-fragment
-Dollar
- : '$'
- ;
-
-fragment
-GStringQuotationMark
- : '"'
- ;
-
-fragment
-SqStringQuotationMark
- : '\''
- ;
-
-fragment
-TdqStringQuotationMark
- : '"""'
- ;
-
-fragment
-TsqStringQuotationMark
- : '\'\'\''
- ;
-
-fragment
-DollarSlashyGStringQuotationMarkBegin
- : '$/'
- ;
-
-fragment
-DollarSlashyGStringQuotationMarkEnd
- : '/$'
- ;
-
-fragment
-DollarSlashEscape
- : '$/$'
- ;
-
-fragment
-DollarDollarEscape
- : '$$'
- ;
-
-// §3.10.7 The Null Literal
-NullLiteral
- : 'null'
- ;
-
-// Groovy Operators
-
-RANGE_INCLUSIVE : '..';
-RANGE_EXCLUSIVE : '..<';
-SPREAD_DOT : '*.';
-SAFE_DOT : '?.';
-ELVIS : '?:';
-METHOD_POINTER : '.&';
-METHOD_REFERENCE : '::';
-REGEX_FIND : '=~';
-REGEX_MATCH : '==~';
-POWER : '**';
-POWER_ASSIGN : '**=';
-SPACESHIP : '<=>';
-IDENTICAL : '===';
-NOT_IDENTICAL : '!==';
-ARROW : '->';
-
-// !internalPromise will be parsed as !in ternalPromise, so semantic predicates are necessary
-NOT_INSTANCEOF : '!instanceof' { isFollowedBy(_input, ' ', '\t', '\r', '\n') }?;
-NOT_IN : '!in' { isFollowedBy(_input, ' ', '\t', '\r', '\n', '[', '(', '{') }?;
-
-
-// §3.11 Separators
-
-LPAREN : '(' { this.enterParen(); } -> pushMode(DEFAULT_MODE);
-RPAREN : ')' { this.exitParen(); } -> popMode;
-LBRACE : '{' { this.enterParen(); } -> pushMode(DEFAULT_MODE);
-RBRACE : '}' { this.exitParen(); } -> popMode;
-LBRACK : '[' { this.enterParen(); } -> pushMode(DEFAULT_MODE);
-RBRACK : ']' { this.exitParen(); } -> popMode;
-
-SEMI : ';';
-COMMA : ',';
-DOT : Dot;
-
-// §3.12 Operators
-
-ASSIGN : '=';
-GT : '>';
-LT : '<';
-NOT : '!';
-BITNOT : '~';
-QUESTION : '?';
-COLON : ':';
-EQUAL : '==';
-LE : '<=';
-GE : '>=';
-NOTEQUAL : '!=';
-AND : '&&';
-OR : '||';
-INC : '++';
-DEC : '--';
-ADD : '+';
-SUB : '-';
-MUL : '*';
-DIV : Slash;
-BITAND : '&';
-BITOR : '|';
-XOR : '^';
-MOD : '%';
-
-
-ADD_ASSIGN : '+=';
-SUB_ASSIGN : '-=';
-MUL_ASSIGN : '*=';
-DIV_ASSIGN : '/=';
-AND_ASSIGN : '&=';
-OR_ASSIGN : '|=';
-XOR_ASSIGN : '^=';
-MOD_ASSIGN : '%=';
-LSHIFT_ASSIGN : '<<=';
-RSHIFT_ASSIGN : '>>=';
-URSHIFT_ASSIGN : '>>>=';
-ELVIS_ASSIGN : '?=';
-
-
-// §3.8 Identifiers (must appear after all keywords in the grammar)
-CapitalizedIdentifier
- : [A-Z] JavaLetterOrDigit*
- ;
-
-Identifier
- : JavaLetter JavaLetterOrDigit*
- ;
-
-fragment
-IdentifierInGString
- : JavaLetterInGString JavaLetterOrDigitInGString*
- ;
-
-fragment
-JavaLetterInGString
- : [a-zA-Z_] // these are the "java letters" below 0x7F, except for $
- | // covers all characters above 0x7F which are not a surrogate
- ~[\u0000-\u007F\uD800-\uDBFF]
- {Character.isJavaIdentifierStart(_input.LA(-1))}?
- | // covers UTF-16 surrogate pairs encodings for U+10000 to U+10FFFF
- [\uD800-\uDBFF] [\uDC00-\uDFFF]
- {Character.isJavaIdentifierStart(Character.toCodePoint((char)_input.LA(-2), (char)_input.LA(-1)))}?
- ;
-
-fragment
-JavaLetterOrDigitInGString
- : [a-zA-Z0-9_] // these are the "java letters or digits" below 0x7F, except for $
- | // covers all characters above 0x7F which are not a surrogate
- ~[\u0000-\u007F\uD800-\uDBFF]
- {Character.isJavaIdentifierPart(_input.LA(-1))}?
- | // covers UTF-16 surrogate pairs encodings for U+10000 to U+10FFFF
- [\uD800-\uDBFF] [\uDC00-\uDFFF]
- {Character.isJavaIdentifierPart(Character.toCodePoint((char)_input.LA(-2), (char)_input.LA(-1)))}?
- ;
-
-
-fragment
-JavaLetter
- : [a-zA-Z$_] // these are the "java letters" below 0x7F
- | // covers all characters above 0x7F which are not a surrogate
- ~[\u0000-\u007F\uD800-\uDBFF]
- {Character.isJavaIdentifierStart(_input.LA(-1))}?
- | // covers UTF-16 surrogate pairs encodings for U+10000 to U+10FFFF
- [\uD800-\uDBFF] [\uDC00-\uDFFF]
- {Character.isJavaIdentifierStart(Character.toCodePoint((char)_input.LA(-2), (char)_input.LA(-1)))}?
- ;
-
-fragment
-JavaLetterOrDigit
- : [a-zA-Z0-9$_] // these are the "java letters or digits" below 0x7F
- | // covers all characters above 0x7F which are not a surrogate
- ~[\u0000-\u007F\uD800-\uDBFF]
- {Character.isJavaIdentifierPart(_input.LA(-1))}?
- | // covers UTF-16 surrogate pairs encodings for U+10000 to U+10FFFF
- [\uD800-\uDBFF] [\uDC00-\uDFFF]
- {Character.isJavaIdentifierPart(Character.toCodePoint((char)_input.LA(-2), (char)_input.LA(-1)))}?
- ;
-
-//
-// Additional symbols not defined in the lexical specification
-//
-
-AT : '@';
-ELLIPSIS : '...';
-
-//
-// Whitespace, line escape and comments
-//
-WS : ([ \t\u000C]+ | LineEscape+) -> skip
- ;
-
-
-// Inside (...) and [...] but not {...}, ignore newlines.
-NL : '\r'? '\n' { this.ignoreTokenInsideParens(); }
- ;
-
-// Multiple-line comments(including groovydoc comments)
-ML_COMMENT
- : '/*' .*? '*/' { this.ignoreMultiLineCommentConditionally(); } -> type(NL)
- ;
-
-// Single-line comments
-SL_COMMENT
- : '//' ~[\r\n\uFFFF]* { this.ignoreTokenInsideParens(); } -> type(NL)
- ;
-
-// Script-header comments.
-// The very first characters of the file may be "#!". If so, ignore the first line.
-SH_COMMENT
- : '#!' { require(0 == this.tokenIndex, "Shebang comment should appear at the first line", -2, true); } ~[\r\n\uFFFF]* -> skip
- ;
-
-// Unexpected characters will be handled by groovy parser later.
-UNEXPECTED_CHAR
- : .
- ;