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

📄 groovy.g

📁 Groovy动态语言 运行在JVM中的动态语言 可以方便的处理业务逻辑变化大的业务
💻 G
📖 第 1 页 / 共 5 页
字号:
/** Guard for enumConstants.  */
enumConstantsStart
    :   enumConstant (COMMA | SEMI | NLS | RCURLY)
    ;

/** Comma-separated list of one or more enum constant definitions.  */
enumConstants
    :
        enumConstant
        ( options{greedy=true;}: COMMA! nls! enumConstant )*
        ( COMMA! nls! )?            // trailing extra comma is OK
    ;

// An annotation field
annotationField!  {Token first = LT(1);}
    :   mods:modifiersOpt!
        (   td:typeDefinitionInternal[#mods]
            {#annotationField = #td;}
        |   t:typeSpec[false]               // annotation field
            (
                // Need a syntactic predicate, since variableDefinitions
                // can start with foo() also.  Since method defs are not legal
                // in this context, there's no harm done.
                (IDENT LPAREN)=>
                i:IDENT              // the name of the field
                LPAREN! RPAREN!

                /*OBS* rt:declaratorBrackets[#t] *OBS*/

                ( "default" nls! amvi:annotationMemberValueInitializer )?

                {#annotationField =
                        #(create(ANNOTATION_FIELD_DEF,"ANNOTATION_FIELD_DEF",first,LT(1)),
                                 mods,
                                 #(create(TYPE,"TYPE",first,LT(1)),t),
                                 i,amvi
                                 );}
            |   v:variableDefinitions[#mods,#t]    // variable
                {#annotationField = #v;}
            )
        )
    ;

//An enum constant may have optional parameters and may have a
//a class body
enumConstant!  {Token first = LT(1);}
    :   an:annotationsOpt // Note:  Cannot start with "def" or another modifier.
        i:IDENT
        (   LPAREN!
            a:argList
            RPAREN!
        )?
        ( b:enumConstantBlock )?
        {#enumConstant = #(create(ENUM_CONSTANT_DEF, "ENUM_CONSTANT_DEF",first,LT(1)), an, i, a, b);}
    ;

//The class-like body of an enum constant
enumConstantBlock  {Token first = LT(1);}
    :   LCURLY!
        (enumConstantField)? ( sep! (enumConstantField)? )*
        RCURLY!
        {#enumConstantBlock = #(create(OBJBLOCK, "OBJBLOCK",first,LT(1)), #enumConstantBlock);}
    ;

//An enum constant field is just like a class field but without
//the posibility of a constructor definition or a static initializer

// TODO - maybe allow 'declaration' production within this production, 
// but how to disallow constructors and static initializers...
enumConstantField!  {Token first = LT(1);}
    :   mods:modifiersOpt!
        (   td:typeDefinitionInternal[#mods]
            {#enumConstantField = #td;}
        |   // A generic method has the typeParameters before the return type.
            // This is not allowed for variable definitions, but this production
            // allows it, a semantic check could be used if you wanted.
            (tp:typeParameters)? t:typeSpec[false]          // method or variable declaration(s)
            (
                // Need a syntactic predicate, since variableDefinitions
                // can start with foo() also.  Since method defs are not legal
                // in this context, there's no harm done.
                (IDENT LPAREN)=>

                IDENT                                     // the name of the method

                // parse the formal parameter declarations.
                LPAREN! param:parameterDeclarationList RPAREN!

                /*OBS* rt:declaratorBrackets[#t] *OBS*/

                // get the list of exceptions that this method is
                // declared to throw
                ((nls "throws") => tc:throwsClause)?

                ( s2:compoundStatement )?
                // TODO - verify that 't' is useful/correct here, used to be 'rt'
                {#enumConstantField = #(create(METHOD_DEF,"METHOD_DEF",first,LT(1)),
                                         mods,
                                         tp,
                                         #(create(TYPE,"TYPE",first,LT(1)),t),
                                         IDENT,
                                         param,
                                         tc,
                                         s2);}

            |   v:variableDefinitions[#mods,#t]
                {#enumConstantField = #v;}
            )
        )

        // "{ ... }" instance initializer
    |   s4:compoundStatement
        {#enumConstantField = #(create(INSTANCE_INIT,"INSTANCE_INIT",first,LT(1)), s4);}
    ;

// An interface can extend several other interfaces...
interfaceExtends  {Token first = LT(1);}
    :   (
            e:"extends"! nls!
            classOrInterfaceType[false] ( COMMA! nls! classOrInterfaceType[false] )* nls!
        )?
        {#interfaceExtends = #(create(EXTENDS_CLAUSE,"EXTENDS_CLAUSE",first,LT(1)),
                               #interfaceExtends);}
    ;

// A class can implement several interfaces...
implementsClause  {Token first = LT(1);}
    :   (
            i:"implements"! nls!
            classOrInterfaceType[false] ( COMMA! nls! classOrInterfaceType[false] )* nls!
        )?
        {#implementsClause = #(create(IMPLEMENTS_CLAUSE,"IMPLEMENTS_CLAUSE",first,LT(1)),
                               #implementsClause);}
    ;

// Now the various things that can be defined inside a class
classField!  {Token first = LT(1);}
    :   // method, constructor, or variable declaration
        (constructorStart)=>
        mc:modifiersOpt! ctor:constructorDefinition[#mc]
        {#classField = #ctor;}
    |
        (declarationStart)=>
        d:declaration
        {#classField = #d;}
    |
        //TODO - unify typeDeclaration and typeDefinitionInternal names
        // type declaration
        (typeDeclarationStart)=>
        mods:modifiersOpt!
        (   td:typeDefinitionInternal[#mods]
                {#classField = #td;}
        )

    // "static { ... }" class initializer
    |   "static" s3:compoundStatement
        {#classField = #(create(STATIC_INIT,"STATIC_INIT",first,LT(1)), s3);}

    // "{ ... }" instance initializer
    |   s4:compoundStatement
        {#classField = #(create(INSTANCE_INIT,"INSTANCE_INIT",first,LT(1)), s4);}
    ;

// Now the various things that can be defined inside a interface
interfaceField!
    :   // method, constructor, or variable declaration
        (declarationStart)=>
        d:declaration
        {#interfaceField = #d;}
    |
        //TODO - unify typeDeclaration and typeDefinitionInternal names
        // type declaration
        (typeDeclarationStart)=>
        mods:modifiersOpt

        (   td:typeDefinitionInternal[#mods]
            {#interfaceField = #td;}
        )
    ;

constructorBody
    :   lc:LCURLY^ nls!         {#lc.setType(SLIST);}
        (   (explicitConstructorInvocation) =>   // Java compatibility hack
                explicitConstructorInvocation (sep! blockBody[sepToken])?
            |   blockBody[EOF]
        )
        RCURLY!
;


/** Catch obvious constructor calls, but not the expr.super(...) calls */
explicitConstructorInvocation
    :   (typeArguments)?
        (   "this"! lp1:LPAREN^ argList RPAREN!
            {#lp1.setType(CTOR_CALL);}
        |   "super"! lp2:LPAREN^ argList RPAREN!
            {#lp2.setType(SUPER_CTOR_CALL);}
        )
    ;

/** The tail of a declaration.
  * Either v1, v2, ... (with possible initializers) or else m(args){body}.
  * The two arguments are the modifier list (if any) and the declaration head (if any).
  * The declaration head is the variable type, or (for a method) the return type.
  * If it is missing, then the variable type is taken from its initializer (if there is one).
  * Otherwise, the variable type defaults to 'any'.
  * DECIDE:  Method return types default to the type of the method body, as an expression.
  */
variableDefinitions[AST mods, AST t]  {Token first = LT(1);}
    :   variableDeclarator[getASTFactory().dupTree(mods),
                           getASTFactory().dupTree(t)]
        (   COMMA! nls!
            variableDeclarator[getASTFactory().dupTree(mods),
                               getASTFactory().dupTree(t)]
        )*
    |
        // The parser allows a method definition anywhere a variable definition is accepted.

        (   id:IDENT
        |   qid:STRING_LITERAL          {#qid.setType(IDENT);}  // use for operator defintions, etc.
        )

        // parse the formal parameter declarations.
        LPAREN! param:parameterDeclarationList! RPAREN!

        /*OBS*rt:declaratorBrackets[#t]*/

        // get the list of exceptions that this method is
        // declared to throw
        ((nls "throws") =>  tc:throwsClause!  )? 

        // the method body is an open block
        // but, it may have an optional constructor call (for constructors only)
        // this constructor clause is only used for constructors using 'def'
        // which look like method declarations
        // since the block is optional and nls is part of sep we have to be sure
        // a newline is followed by a block or ignore the nls too
        ((nls! LCURLY) =>  (nlsWarn! mb:openBlock!))?

        {   if (#qid != null)  #id = #qid;
            #variableDefinitions =
                    #(create(METHOD_DEF,"METHOD_DEF",first,LT(1)),
                      mods, #(create(TYPE,"TYPE",first,LT(1)),t), id, param, tc, mb);
        }
    ;

/** I've split out constructors separately; we could maybe integrate back into variableDefinitions 
 *  later on if we maybe simplified 'def' to be a type declaration?
 */
constructorDefinition[AST mods]  {Token first = LT(1);}
    :
        id:IDENT

        // parse the formal parameter declarations.
        LPAREN! param:parameterDeclarationList! RPAREN!

        /*OBS*rt:declaratorBrackets[#t]*/

        // get the list of exceptions that this method is
        // declared to throw
        ((nls "throws") => tc:throwsClause!  )? nlsWarn!
        // the method body is an open block
        // but, it may have an optional constructor call (for constructors only)

        // TODO assert that the id matches the class
        { isConstructorIdent(id); }

        cb:constructorBody!
        {   #constructorDefinition =  #(create(CTOR_IDENT,"CTOR_IDENT",first,LT(1)),  mods, param, tc, cb);
        }
     ;

/** Declaration of a variable. This can be a class/instance variable,
 *  or a local variable in a method
 *  It can also include possible initialization.
 */
variableDeclarator![AST mods, AST t]  {Token first = LT(1);}
    :
        id:variableName
        /*OBS*d:declaratorBrackets[t]*/
        (v:varInitializer)?
        {#variableDeclarator = #(create(VARIABLE_DEF,"VARIABLE_DEF",first,LT(1)), mods, #(create(TYPE,"TYPE",first,LT(1)),t), id, v);}
    ;

/** Used in cases where a declaration cannot have commas, or ends with the "in" operator instead of '='. */
singleVariable![AST mods, AST t]  {Token first = LT(1);}
    :
        id:variableName
        {#singleVariable = #(create(VARIABLE_DEF,"VARIABLE_DEF",first,LT(1)), mods, #(create(TYPE,"TYPE",first,LT(1)),t), id);}
    ;

variableName
    :   IDENT
    ;

/** After some type names, where zero or more empty bracket pairs are allowed.
 *  We use ARRAY_DECLARATOR to represent this.
 *  TODO:  Is there some more Groovy way to view this in terms of the indexed property syntax?
 */
declaratorBrackets[AST typ]
    :   {#declaratorBrackets=typ;}
        (
            // A following list constructor might conflict with index brackets; prefer the declarator.
            options {greedy=true;} :
            lb:LBRACK^ {#lb.setType(ARRAY_DECLARATOR);} RBRACK!
        )*
    ;

/** An assignment operator '=' followed by an expression.  (Never empty.) */
varInitializer
    :   ASSIGN^ nls! expression[LC_INIT]
        // In {T x = y}, the left-context of y is that of an initializer.
    ;

/*OBS*
// This is an initializer used to set up an array.
arrayInitializer
    :   lc:LCURLY^ {#lc.setType(ARRAY_INIT);}
        (   initializer
            (
                // CONFLICT: does a COMMA after an initializer start a new
                // initializer or start the option ',' at end?
                // ANTLR generates proper code by matching
                // the comma as soon as possible.
                options {
                        warnWhenFollowAmbig = false;
                }
            :
                COMMA! initializer
            )*
            (COMMA!)?

⌨️ 快捷键说明

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