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

📄 groovy.g

📁 Groovy动态语言 运行在JVM中的动态语言 可以方便的处理业务逻辑变化大的业务
💻 G
📖 第 1 页 / 共 5 页
字号:
        )?
        RCURLY!
    ;
*OBS*/

/*OBS*  // Use [...] for initializing all sorts of sequences, including arrays.
// The two "things" that can initialize an array element are an expression
// and another (nested) array initializer.
initializer
    :   expression
    |   arrayInitializer
    ;
*OBS*/

/*OBS???
// This is the header of a method. It includes the name and parameters
// for the method.
// This also watches for a list of exception classes in a "throws" clause.
ctorHead
    :   IDENT // the name of the method

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

        // get the list of exceptions that this method is declared to throw
        (throwsClause)?
    ;
*OBS*/

// This is a list of exception classes that the method is declared to throw
throwsClause
    :   nls! "throws"^ nls! identifier ( COMMA! nls! identifier )* 
    ;

/** A list of zero or more formal parameters.
 *  If a parameter is variable length (e.g. String... myArg) it should be
 *  to the right of any other parameters of the same kind.
 *  General form:  (req, ..., opt, ..., [rest], key, ..., [restKeys], [block]
 *  This must be sorted out after parsing, since the various declaration forms
 *  are impossible to tell apart without backtracking.
 */
parameterDeclarationList  {Token first = LT(1);}
    :
        (
            parameterDeclaration
            (   COMMA! nls!
                parameterDeclaration
            )*
        )?
        {#parameterDeclarationList = #(create(PARAMETERS,"PARAMETERS",first,LT(1)),
                                       #parameterDeclarationList);}
    ;

/** A formal parameter for a method or closure. */
parameterDeclaration!
        { Token first = LT(1);boolean spreadParam = false; }
    :
        pm:parameterModifiersOpt
        (   options {greedy=true;} :
            t:typeSpec[false]
        )?

        // TODO:  What do formal parameters for keyword arguments look like?

        // TODO:  Should this be SPREAD_ARG instead?
        ( TRIPLE_DOT! { spreadParam = true; } )?

        id:IDENT

        // allow an optional default value expression
        (exp:varInitializer)?

        /*OBS*pd:declaratorBrackets[#t]*/
        {
            if (spreadParam) {
                #parameterDeclaration = #(create(VARIABLE_PARAMETER_DEF,"VARIABLE_PARAMETER_DEF",first,LT(1)),
                      pm, #(create(TYPE,"TYPE",first,LT(1)),t), id, exp);
            } else {
                #parameterDeclaration = #(create(PARAMETER_DEF,"PARAMETER_DEF",first,LT(1)),
                      pm, #(create(TYPE,"TYPE",first,LT(1)),t), id, exp);
            }
        }
    ;

/*OBS*
variableLengthParameterDeclaration!  {Token first = LT(1);}
    :   pm:parameterModifier t:typeSpec[false] TRIPLE_DOT! id:IDENT

        /*OBS* pd:declaratorBrackets[#t]* /
        {#variableLengthParameterDeclaration = #(create(VARIABLE_PARAMETER_DEF,"VARIABLE_PARAMETER_DEF",first,LT(1)),
                                                                                            pm, #(create(TYPE,"TYPE",first,LT(1)),t), id);}
    ;
*OBS*/

parameterModifiersOpt
        { Token first = LT(1);int seenDef = 0; }
        //final and/or def can appear amongst annotations in any order
    :   (   {seenDef++ == 0}?       // do not allow multiple "def" tokens
            "def"!  nls!            // redundant, but allowed for symmetry
        |   "final" nls!
        |   annotation nls!
        )*
        {#parameterModifiersOpt = #(create(MODIFIERS,"MODIFIERS",first,LT(1)), #parameterModifiersOpt);}
    ;

/** Closure parameters are exactly like method parameters,
 *  except that they are not enclosed in parentheses, but rather
 *  are prepended to the front of a block, just after the brace.
 *  They are separated from the closure body by a CLOSABLE_BLOCK_OP token '->'.
 */
// With '|' there would be restrictions on bitwise-or expressions.
closableBlockParamsOpt[boolean addImplicit]
    :   (parameterDeclarationList nls CLOSABLE_BLOCK_OP)=>
        parameterDeclarationList nls! CLOSABLE_BLOCK_OP! nls!
    |   {addImplicit}?
        implicitParameters
    |
        /* else do not parse any parameters at all */
    ;

/** Lookahead to check whether a block begins with explicit closure arguments. */
closableBlockParamsStart!
    :
        parameterDeclarationList nls CLOSABLE_BLOCK_OP
    ;

/** Simple names, as in {x|...}, are completely equivalent to {(def x)|...}.  Build the right AST. */
closableBlockParam!  {Token first = LT(1);}
    :   id:IDENT!
        {#closableBlockParam = #(create(PARAMETER_DEF,"PARAMETER_DEF",first,LT(1)),
                               #(create(MODIFIERS,"MODIFIERS",first,LT(1))), #(create(TYPE,"TYPE",first,LT(1))),
                               id);}
    ;

// Compound statement. This is used in many contexts:
// Inside a class definition prefixed with "static":
// it is a class initializer
// Inside a class definition without "static":
// it is an instance initializer
// As the body of a method
// As a completely indepdent braced block of code inside a method
// it starts a new scope for variable definitions
// In Groovy, this is called an "open block".  It cannot have closure arguments.

compoundStatement
    :   openBlock
    ;

/** An open block is not allowed to have closure arguments. */
openBlock
    :   lc:LCURLY^ nls!     {#lc.setType(SLIST);}
        // AST type of SLIST means "never gonna be a closure"
        blockBody[EOF]
        RCURLY!
    ;

/** A block body is a parade of zero or more statements or expressions. */
blockBody[int prevToken]
    :   
        (statement[prevToken])? (sep! (statement[sepToken])?)*
    ;

/** A block which is known to be a closure, even if it has no apparent arguments.
 *  A block inside an expression or after a method call is always assumed to be a closure.
 *  Only labeled, unparameterized blocks which occur directly as substatements are kept open.
 */
closableBlock
    :   lc:LCURLY^ nls!     {#lc.setType(CLOSABLE_BLOCK);}
        closableBlockParamsOpt[true]
        blockBody[EOF]
        RCURLY!
    ;

/** A block known to be a closure, but which omits its arguments, is given this placeholder.
 *  A subsequent pass is responsible for deciding if there is an implicit 'it' parameter,
 *  or if the parameter list should be empty.
 */
implicitParameters  {Token first = LT(1);}
    :   {   #implicitParameters = #(create(IMPLICIT_PARAMETERS,"IMPLICIT_PARAMETERS",first,LT(1)));  }
    ;

/** A sub-block of a block can be either open or closable.
 *  It is closable if and only if there are explicit closure arguments.
 *  Compare this to a block which is appended to a method call,
 *  which is given closure arguments, even if they are not explicit in the code.
 */
openOrClosableBlock
    :   lc:LCURLY^ nls!
        cp:closableBlockParamsOpt[false]
        {   if (#cp == null)    #lc.setType(SLIST);
            else                #lc.setType(CLOSABLE_BLOCK);
        }
        blockBody[EOF]
        RCURLY!
    ;

/** A statement is an element of a block.
 *  Typical statements are declarations (which are scoped to the block)
 *  and expressions.
 */
statement[int prevToken]
    // prevToken is NLS if previous statement is separated only by a newline

    // declarations are ambiguous with "ID DOT" relative to expression
    // statements. Must backtrack to be sure. Could use a semantic
    // predicate to test symbol table to see what the type was coming
    // up, but that's pretty hard without a symbol table ;)
    :   (declarationStart)=>
        declaration

    // Attach a label to the front of a statement
    // This block is executed for effect, unless it has an explicit closure argument.
    |
        (IDENT COLON)=>
        pfx:statementLabelPrefix!
        {#statement = #pfx;}  // nest it all under the label prefix
        (   (LCURLY) => openOrClosableBlock
        |   statement[COLON]
        )

    // An expression statement. This could be a method call,
    // assignment statement, or any other expression evaluated for
    // side-effects.
    // The prevToken is used to check for dumb expressions like +1.
    |    expressionStatement[prevToken]

    // class definition
    |    m:modifiersOpt! typeDefinitionInternal[#m]

    // If-else statement
    |   "if"^ LPAREN! assignmentLessExpression RPAREN! nlsWarn! compatibleBodyStatement
        (
            // CONFLICT: the old "dangling-else" problem...
            //           ANTLR generates proper code matching
            //                       as soon as possible.  Hush warning.
            options {
                    warnWhenFollowAmbig = false;
            }
        :   // lookahead to check if we're entering an 'else' clause
            ( (sep!)? "else"! )=>
            (sep!)?  // allow SEMI here for compatibility with Java
            "else"! nlsWarn! compatibleBodyStatement
        )?

    // For statement
    |   forStatement

    // While statement
    |   "while"^ LPAREN! strictContextExpression RPAREN! nlsWarn! compatibleBodyStatement

    /*OBS* no do-while statement in Groovy (too ambiguous)
    // do-while statement
    |   "do"^ statement "while"! LPAREN! strictContextExpression RPAREN! SEMI!
    *OBS*/
    // With statement
    // (This is the Groovy scope-shift mechanism, used for builders.)
    |   "with"^ LPAREN! strictContextExpression RPAREN! nlsWarn! compoundStatement

    // Splice statement, meaningful only inside a "with" expression.
    // PROPOSED, DECIDE.  Prevents the namespace pollution of a "text" method or some such.
    |   sp:STAR^ nls!                       {#sp.setType(SPREAD_ARG);}
        expressionStatement[EOF]
    // Example:  with(htmlbuilder) { head{} body{ *"some text" } }
    // Equivalent to:  { htmlbuilder.head{} htmlbuilder.body{ (htmlbuilder as Collection).add("some text") } }

    // Import statement.  Can be used in any scope.  Has "import x as y" also.
    |   importStatement

    // switch/case statement
    |   "switch"^ LPAREN! strictContextExpression RPAREN! nlsWarn! LCURLY! nls!
        ( casesGroup )*
        RCURLY!

    // exception try-catch block
    |   tryBlock

    // synchronize a statement
    |   "synchronized"^ LPAREN! strictContextExpression RPAREN! nlsWarn! compoundStatement


    /*OBS*
    // empty statement
    |   s:SEMI {#s.setType(EMPTY_STAT);}
    *OBS*/

    |   branchStatement
    ;

forStatement
    :   f:"for"^
        LPAREN!
        (   (forInit SEMI)=>traditionalForClause
            // *OBS*
            // There's no need at all for squeezing in the new Java 5 "for"
            // syntax, since Groovy's is a suitable alternative.
            // |   (parameterDeclaration COLON)=> forEachClause
            // *OBS*
        |   // the coast is clear; it's a modern Groovy for statement
            forInClause
        )
        RPAREN! nlsWarn!
        compatibleBodyStatement                                  // statement to loop over
    ;

traditionalForClause
    :
        forInit SEMI!   // initializer
        forCond SEMI!   // condition test
        forIter         // updater
    ;

/*OBS*
forEachClause  {Token first = LT(1);}
    :
        p:parameterDeclaration COLON! expression
        {#forEachClause = #(create(FOR_EACH_CLAUSE,"FOR_EACH_CLAUSE",first,LT(1)), #forEachClause);}
    ;
*OBS*/

forInClause
    :   (   (declarationStart)=>
            decl:singleDeclarationNoInit
        |   IDENT
        )
        (
            i:"in"^         {#i.setType(FOR_IN_ITERABLE);}
            shiftExpression[0]
        |
            { addWa

⌨️ 快捷键说明

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