📄 groovy.g
字号:
// 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 throwthrowsClause : 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*//** A simplified formal parameter for closures, can occur outside parens. * It is not confused by a lookahead of BOR. * DECIDE: Is thie necessary, or do we change the closure-bar syntax? */simpleParameterDeclaration! {Token first = LT(1);} : ( options {greedy=true;} : t:typeSpec[false])? id:IDENT {#simpleParameterDeclaration = #(create(PARAMETER_DEF,"PARAMETER_DEF",first,LT(1)), #(create(MODIFIERS,"MODIFIERS",first,LT(1))), #(create(TYPE,"TYPE",first,LT(1)),t), id);} ;/** Simplified formal parameter list for closures. Never empty. */simpleParameterDeclarationList {Token first = LT(1);} : simpleParameterDeclaration ( COMMA! nls! simpleParameterDeclaration )* {#simpleParameterDeclarationList = #(create(PARAMETERS,"PARAMETERS",first,LT(1)), #simpleParameterDeclarationList);} ;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 CLOSURE_OP token '->'. */// With '|' there would be restrictions on bitwise-or expressions.closureParametersOpt[boolean addImplicit] : (parameterDeclarationList nls CLOSURE_OP)=> parameterDeclarationList nls! CLOSURE_OP! nls! | {compatibilityMode}? (oldClosureParametersStart)=> oldClosureParameters | {addImplicit}? implicitParameters | /* else do not parse any parameters at all */ ;/** Lookahead to check whether a block begins with explicit closure arguments. */closureParametersStart! : {compatibilityMode}? (oldClosureParametersStart)=> oldClosureParametersStart | parameterDeclarationList nls CLOSURE_OP ;/** Provisional definition of old-style closure params based on BOR '|'. * Going away soon, perhaps... */oldClosureParameters {Token first = LT(1);} : LOR! nls! // '||' operator is a null param list {#oldClosureParameters = #(create(PARAMETERS,"PARAMETERS",first,LT(1)));} | (BOR nls BOR)=> BOR! nls! BOR! nls! {#oldClosureParameters = #(create(PARAMETERS,"PARAMETERS",first,LT(1)));} | ((BOR nls)? LPAREN parameterDeclarationList RPAREN nls BOR)=> (BOR! nls!)? LPAREN! parameterDeclarationList RPAREN! nls! BOR! nls! | ((BOR nls)? simpleParameterDeclarationList nls BOR)=> (BOR! nls!)? simpleParameterDeclarationList nls! BOR! nls! ;/** Lookahead for oldClosureParameters. */oldClosureParametersStart! : BOR | LOR // for empty parameter declaration | LPAREN balancedTokens RPAREN nls BOR //| (IDENT nls (BOR | COMMA))=> | simpleParameterDeclarationList BOR ;/** Simple names, as in {x|...}, are completely equivalent to {(def x)|...}. Build the right AST. */closureParameter! {Token first = LT(1);} : id:IDENT! {#closureParameter = #(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. */closedBlock : lc:LCURLY^ nls! {#lc.setType(CLOSED_BLOCK);} closureParametersOpt[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 closed. * It is closed 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. */openOrClosedBlock : lc:LCURLY^ nls! cp:closureParametersOpt[false] { if (#cp == null) #lc.setType(SLIST); else #lc.setType(CLOSED_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) => openOrClosedBlock | 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
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -