📄 groovy.g
字号:
/** 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 + -