📄 groovy.g
字号:
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 bodyenumConstant! {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 constantenumConstantBlock {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 classclassField! {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 interfaceinterfaceField! : // 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!)? )? 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
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -