⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 groovy.g

📁 Groovy动态语言 运行在JVM中的动态语言 可以方便的处理业务逻辑变化大的业务
💻 G
📖 第 1 页 / 共 5 页
字号:
    // Query a name token to see if it is identical with the current class name.
    // This is used to distinguish constructors from other methods.
    private boolean isConstructorIdent(Token x) {
        if (currentClass == null)  return false;
        if (currentClass.getType() != IDENT)  return false;  // cannot happen?
        String cname = currentClass.getText();

        if (x == null || x.getType() != IDENT)  return false;  // cannot happen?
        return cname.equals(x.getText());
    }

    // Scratch variable for last 'sep' token.
    // Written by the 'sep' rule, read only by immediate callers of 'sep'.
    // (Not entirely clean, but better than a million xx=sep occurrences.)
    private int sepToken = EOF;

    // Scratch variable for last argument list; tells whether there was a label.
    // Written by 'argList' rule, read only by immediate callers of 'argList'.
    private boolean argListHasLabels = false;

    // Scratch variable, holds most recently completed pathExpression.
    // Read only by immediate callers of 'pathExpression' and 'expression'.
    private AST lastPathExpression = null;

    // Inherited attribute pushed into most expression rules.
    // If not zero, it means that the left context of the expression
    // being parsed is a statement boundary or an initializer sign '='.
    // Only such expressions are allowed to reach across newlines
    // to pull in an LCURLY and appended block.
    private final int LC_STMT = 1, LC_INIT = 2;

    /**
     * Counts the number of LT seen in the typeArguments production.
     * It is used in semantic predicates to ensure we have seen
     * enough closing '>' characters; which actually may have been
     * either GT, SR or BSR tokens.
     */
    private int ltCounter = 0;
    
    /* This symbol is used to work around a known ANTLR limitation.
     * In a loop with syntactic predicate, ANTLR needs help knowing
     * that the loop exit is a second alternative.
     * Example usage:  ( (LCURLY)=> block | {ANTLR_LOOP_EXIT}? )*
     * Probably should be an ANTLR RFE.
     */
    ////// Original comment in Java grammar:
    // Unfortunately a syntactic predicate can only select one of
    // multiple alternatives on the same level, not break out of
    // an enclosing loop, which is why this ugly hack (a fake
    // empty alternative with always-false semantic predicate)
    // is necessary.
    private static final boolean ANTLR_LOOP_EXIT = false;
}

// Compilation Unit: In Groovy, this is a single file or script. This is the start
// rule for this parser
compilationUnit
    :
        // The very first characters of the file may be "#!".  If so, ignore the first line.
        (SH_COMMENT!)?

        // we can have comments at the top of a file
        nls!

        // A compilation unit starts with an optional package definition
        (   (annotationsOpt "package")=> packageDefinition
        |   (statement[EOF])?
        )

        // The main part of the script is a sequence of any number of statements.
        // Semicolons and/or significant newlines serve as separators.
        ( sep! (statement[sepToken])? )*
        EOF!
    ;

/** A Groovy script or simple expression.  Can be anything legal inside {...}. */
snippetUnit
    :   nls! blockBody[EOF]
    ;


// Package statement: optional annotations followed by "package" then the package identifier.
packageDefinition
        //TODO? options {defaultErrorHandler = true;} // let ANTLR handle errors
    :   annotationsOpt p:"package"^ {#p.setType(PACKAGE_DEF);} identifier
    ;


// Import statement: import followed by a package or class name
importStatement
        //TODO? options {defaultErrorHandler = true;}
        { boolean isStatic = false; }
    :   i:"import"^ {#i.setType(IMPORT);} ( "static"! {#i.setType(STATIC_IMPORT);} )? identifierStar
    ;

// TODO REMOVE
// A type definition is either a class, interface, enum or annotation with possible additional semis.
//typeDefinition
//      options {defaultErrorHandler = true;}
//      :       m:modifiers!
//              typeDefinitionInternal[#m]
//      |       SEMI!
//      ;

// Added this production, even though 'typeDefinition' seems to be obsolete,
// as this is referenced by many other parts of the grammar.
// Protected type definitions production for reuse in other productions
protected typeDefinitionInternal[AST mods]
    :   cd:classDefinition[#mods]       // inner class
        {#typeDefinitionInternal = #cd;}
    |   id:interfaceDefinition[#mods]   // inner interface
        {#typeDefinitionInternal = #id;}
    |   ed:enumDefinition[#mods]        // inner enum
        {#typeDefinitionInternal = #ed;}
    |   ad:annotationDefinition[#mods]  // inner annotation
        {#typeDefinitionInternal = #ad;}
    ;

/** A declaration is the creation of a reference or primitive-type variable,
 *  or (if arguments are present) of a method.
 *  Generically, this is called a 'variable' definition, even in the case of a class field or method.
 *  It may start with the modifiers and/or a declaration keyword "def".
 *  It may also start with the modifiers and a capitalized type name.
 *  <p>
 *  AST effect: Create a separate Type/Var tree for each var in the var list.
 *  Must be guarded, as in (declarationStart) => declaration.
 */
declaration!
    :
        // method/variable using a 'def' or a modifier; type is optional
        m:modifiers
        (t:typeSpec[false])?
        v:variableDefinitions[#m, #t]
        {#declaration = #v;}
    |
        // method/variable using a type only
        t2:typeSpec[false]
        v2:variableDefinitions[null,#t2]
        {#declaration = #v2;}
    ;


// *TODO* We must also audit the various occurrences of warning
// suppressions like "options { greedy = true; }".

/** A declaration with one declarator and no initialization, like a parameterDeclaration.
 *  Used to parse loops like <code>for (int x in y)</code> (up to the <code>in</code> keyword).
 */
singleDeclarationNoInit!
    :
        // method/variable using a 'def' or a modifier; type is optional
        m:modifiers
        (t:typeSpec[false])?
        v:singleVariable[#m, #t]
        {#singleDeclarationNoInit = #v;}
    |
        // method/variable using a type only
        t2:typeSpec[false]
        v2:singleVariable[null,#t2]
        {#singleDeclarationNoInit = #v2;}
    ;

/** A declaration with one declarator and optional initialization, like a parameterDeclaration.
 *  Used to parse declarations used for both binding and effect, in places like argument
 *  lists and <code>while</code> statements.
 */
singleDeclaration
    :   sd:singleDeclarationNoInit!
        { #singleDeclaration = #sd; }
        (varInitializer)?
    ;

/** Used only as a lookahead predicate, before diving in and parsing a declaration.
 *  A declaration can be unambiguously introduced with "def", an annotation or a modifier token like "final".
 *  It may also be introduced by a simple identifier whose first character is an uppercase letter,
 *  as in {String x}.  A declaration can also be introduced with a built in type like 'int' or 'void'.
 *  Brackets (array and generic) are allowed, as in {List[] x} or {int[][] y}.
 *  Anything else is parsed as a statement of some sort (expression or command).
 *  <p>
 *  (In the absence of explicit method-call parens, we assume a capitalized name is a type name.
 *  Yes, this is a little hacky.  Alternatives are to complicate the declaration or command
 *  syntaxes, or to have the parser query the symbol table.  Parse-time queries are evil.
 *  And we want both {String x} and {println x}.  So we need a syntactic razor-edge to slip
 *  between 'println' and 'String'.)
 *  
 *   *TODO* The declarationStart production needs to be strengthened to recognize
 *  things like {List<String> foo}.
 *  Right now it only knows how to skip square brackets after the type, not
 *  angle brackets.
 *  This probably turns out to be tricky because of >> vs. > >. If so,
 *  just put a TODO comment in.
 */
declarationStart!
    :   "def"
    |   modifier
    |   AT IDENT  // IDENT != "interface"
    |   (   upperCaseIdent
        |   builtInType
        |   qualifiedTypeName
        ) (LBRACK balancedTokens RBRACK)* IDENT
    ;

/** Not yet used - but we could use something like this to look for fully qualified type names 
 */
qualifiedTypeName!
				 :
				 			 IDENT (DOT IDENT)* DOT upperCaseIdent
				 ;
	
/** Used to look ahead for a constructor 
 */
constructorStart!
    :
        modifiersOpt! id:IDENT! {isConstructorIdent(id)}? nls! LPAREN! //...
    ;


/** Used only as a lookahead predicate for nested type declarations. */

/*TODO* The lookahead in typeDeclarationStart needs to skip annotations, not
just stop at '@', because variable and method declarations can also be
annotated.
> typeDeclarationStart!
>     :   (modifier!)* ("class" | "interface" | "enum" | AT )
S.B. something like
>     :   (modifier! | annotationTokens!)* ("class" | "interface" |
> "enum" )
(And maybe @interface, if Java 5 allows nested annotation types? Don't
know offhand.)
Where annotationTokens can be a quick paren-skipper, as in other
places: '@' ident '(' balancedTokens ')'.
*/

typeDeclarationStart!
    :   modifiersOpt! ("class" | "interface" | "enum" | AT "interface")
    ;
    
/** An IDENT token whose spelling is required to start with an uppercase letter.
 *  In the case of a simple statement {UpperID name} the identifier is taken to be a type name, not a command name.
 */
upperCaseIdent
    :   {isUpperCase(LT(1))}?
        IDENT
    ;

// A type specification is a type name with possible brackets afterwards
// (which would make it an array type).
// Set addImagNode true for types inside expressions, not declarations.
typeSpec[boolean addImagNode]
    :    classTypeSpec[addImagNode]
    |    builtInTypeSpec[addImagNode]
    ;

// also check that 'classOrInterfaceType[false]' is a suitable substitution for 'identifier'

// A class type specification is a class type with either:
// - possible brackets afterwards
//   (which would make it an array type).
// - generic type arguments after
classTypeSpec[boolean addImagNode]  {Token first = LT(1);}
    :   ct:classOrInterfaceType[false]!
        declaratorBrackets[#ct]
        {
            if ( addImagNode ) {
                #classTypeSpec = #(create(TYPE,"TYPE",first,LT(1)), #classTypeSpec);
            }
        }
    ;

// A non-built in type name, with possible type parameters
classOrInterfaceType[boolean addImagNode]  {Token first = LT(1);}
    :   IDENT^ (typeArguments)?
        (   options{greedy=true;}: // match as many as possible
            DOT^
            IDENT (typeArguments)?
        )*
        {
            if ( addImagNode ) {
                #classOrInterfaceType = #(create(TYPE,"TYPE",first,LT(1)), #classOrInterfaceType);
            }
        }
    ;

// A specialised form of typeSpec where built in types must be arrays
typeArgumentSpec
    :   classTypeSpec[true]
    |   builtInTypeArraySpec[true]
    ;

// A generic type argument is a class type, a possibly bounded wildcard type or a built-in type array
typeArgument  {Token first = LT(1);}
    :   (   typeArgumentSpec
        |   wildcardType
        )
        {#typeArgument = #(create(TYPE_ARGUMENT,"TYPE_ARGUMENT",first,LT(1)), #typeArgument);}
    ;

// Wildcard type indicating all types (with possible constraint)
wildcardType
    :   q:QUESTION^ {#q.setType(WILDCARD_TYPE);}
        (("extends" | "super")=> typeArgumentBounds)?
    ;

// Type arguments to a class or interface type
typeArguments
{Token first = LT(1);
int currentLtLevel = 0;}
    :
        {currentLtLevel = ltCounter;}
        LT! {ltCounter++;} nls!
        typeArgument
        (   options{greedy=true;}: // match as many as possible
            {inputState.guessing !=0 || ltCounter == currentLtLevel + 1}?
            COMMA! nls! typeArgument
        )*
        nls!
        (   // turn warning off since Antlr generates the right code,
            // plus we have our semantic predicate below
            options{generateAmbigWarnings=false;}:
            typeArgumentsOrParametersEnd
        )?

        // make sure we have gobbled up enough '>' characters
        // if we are at the "top level" of nested typeArgument productions
        {(currentLtLevel != 0) || ltCounter == currentLtLevel}?

        {#typeArguments = #(create(TYPE_ARGUMENTS, "TYPE_ARGUMENTS",first,LT(1)), #typeArguments);}
    ;

// this gobbles up *some* amount of '>' characters, and counts how many
// it gobbled.

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -