📄 groovy.g
字号:
private boolean isConstructorIdent(Token x) { if (currentClass == null) return false; if (currentClass.getType() != IDENT) return false; // cannot happen? String cname = currentClass.getText(); if (x == null || x.getType() != IDENT) return false; // cannot happen? return cname.equals(x.getText()); } // Scratch variable for last 'sep' token. // Written by the 'sep' rule, read only by immediate callers of 'sep'. // (Not entirely clean, but better than a million xx=sep occurrences.) private int sepToken = EOF; // Scratch variable for last argument list; tells whether there was a label. // Written by 'argList' rule, read only by immediate callers of 'argList'. private boolean argListHasLabels = false; // Scratch variable, holds most recently completed pathExpression. // Read only by immediate callers of 'pathExpression' and 'expression'. private AST lastPathExpression = null; // Inherited attribute pushed into most expression rules. // If not zero, it means that the left context of the expression // being parsed is a statement boundary or an initializer sign '='. // Only such expressions are allowed to reach across newlines // to pull in an LCURLY and appended block. private final int LC_STMT = 1, LC_INIT = 2; /** * Counts the number of LT seen in the typeArguments production. * It is used in semantic predicates to ensure we have seen * enough closing '>' characters; which actually may have been * either GT, SR or BSR tokens. */ private int ltCounter = 0; /* This symbol is used to work around a known ANTLR limitation. * In a loop with syntactic predicate, ANTLR needs help knowing * that the loop exit is a second alternative. * Example usage: ( (LCURLY)=> block | {ANTLR_LOOP_EXIT}? )* * Probably should be an ANTLR RFE. */ ////// Original comment in Java grammar: // Unfortunately a syntactic predicate can only select one of // multiple alternatives on the same level, not break out of // an enclosing loop, which is why this ugly hack (a fake // empty alternative with always-false semantic predicate) // is necessary. private static final boolean ANTLR_LOOP_EXIT = false;}// Compilation Unit: In Groovy, this is a single file or script. This is the start// rule for this parsercompilationUnit : // The very first characters of the file may be "#!". If so, ignore the first line. (SH_COMMENT!)? // we can have comments at the top of a file nls! // A compilation unit starts with an optional package definition ( (annotationsOpt "package")=> packageDefinition | (statement[EOF])? ) // The main part of the script is a sequence of any number of statements. // Semicolons and/or significant newlines serve as separators. ( sep! (statement[sepToken])? )* EOF! ;/** A Groovy script or simple expression. Can be anything legal inside {...}. */snippetUnit : nls! blockBody[EOF] ;// Package statement: optional annotations followed by "package" then the package identifier.packageDefinition //TODO? options {defaultErrorHandler = true;} // let ANTLR handle errors : annotationsOpt p:"package"^ {#p.setType(PACKAGE_DEF);} identifier ;// Import statement: import followed by a package or class nameimportStatement //TODO? options {defaultErrorHandler = true;} { boolean isStatic = false; } : i:"import"^ {#i.setType(IMPORT);} ( "static"! {#i.setType(STATIC_IMPORT);} )? identifierStar ;// TODO REMOVE// A type definition is either a class, interface, enum or annotation with possible additional semis.//typeDefinition// options {defaultErrorHandler = true;}// : m:modifiers!// typeDefinitionInternal[#m]// | SEMI!// ;// Added this production, even though 'typeDefinition' seems to be obsolete,// as this is referenced by many other parts of the grammar.// Protected type definitions production for reuse in other productionsprotected typeDefinitionInternal[AST mods] : cd:classDefinition[#mods] // inner class {#typeDefinitionInternal = #cd;} | id:interfaceDefinition[#mods] // inner interface {#typeDefinitionInternal = #id;} | ed:enumDefinition[#mods] // inner enum {#typeDefinitionInternal = #ed;} | ad:annotationDefinition[#mods] // inner annotation {#typeDefinitionInternal = #ad;} ;/** A declaration is the creation of a reference or primitive-type variable, * or (if arguments are present) of a method. * Generically, this is called a 'variable' definition, even in the case of a class field or method. * It may start with the modifiers and/or a declaration keyword "def". * It may also start with the modifiers and a capitalized type name. * <p> * AST effect: Create a separate Type/Var tree for each var in the var list. * Must be guarded, as in (declarationStart) => declaration. */declaration! : // method/variable using a 'def' or a modifier; type is optional m:modifiers (t:typeSpec[false])? v:variableDefinitions[#m, #t] {#declaration = #v;} | // method/variable using a type only t2:typeSpec[false] v2:variableDefinitions[null,#t2] {#declaration = #v2;} ;// *TODO* We must also audit the various occurrences of warning// suppressions like "options { greedy = true; }"./** A declaration with one declarator and no initialization, like a parameterDeclaration. * Used to parse loops like <code>for (int x in y)</code> (up to the <code>in</code> keyword). */singleDeclarationNoInit! : // method/variable using a 'def' or a modifier; type is optional m:modifiers (t:typeSpec[false])? v:singleVariable[#m, #t] {#singleDeclarationNoInit = #v;} | // method/variable using a type only t2:typeSpec[false] v2:singleVariable[null,#t2] {#singleDeclarationNoInit = #v2;} ;/** A declaration with one declarator and optional initialization, like a parameterDeclaration. * Used to parse declarations used for both binding and effect, in places like argument * lists and <code>while</code> statements. */singleDeclaration : sd:singleDeclarationNoInit! { #singleDeclaration = #sd; } (varInitializer)? ;/** Used only as a lookahead predicate, before diving in and parsing a declaration. * A declaration can be unambiguously introduced with "def", an annotation or a modifier token like "final". * It may also be introduced by a simple identifier whose first character is an uppercase letter, * as in {String x}. A declaration can also be introduced with a built in type like 'int' or 'void'. * Brackets (array and generic) are allowed, as in {List[] x} or {int[][] y}. * Anything else is parsed as a statement of some sort (expression or command). * <p> * (In the absence of explicit method-call parens, we assume a capitalized name is a type name. * Yes, this is a little hacky. Alternatives are to complicate the declaration or command * syntaxes, or to have the parser query the symbol table. Parse-time queries are evil. * And we want both {String x} and {println x}. So we need a syntactic razor-edge to slip * between 'println' and 'String'.) * * *TODO* The declarationStart production needs to be strengthened to recognize * things like {List<String> foo}. * Right now it only knows how to skip square brackets after the type, not * angle brackets. * This probably turns out to be tricky because of >> vs. > >. If so, * just put a TODO comment in. */declarationStart! : "def" | modifier | AT IDENT // IDENT != "interface" | ( upperCaseIdent | builtInType | qualifiedTypeName ) (LBRACK balancedTokens RBRACK)* IDENT ;/** Not yet used - but we could use something like this to look for fully qualified type names */qualifiedTypeName! : IDENT (DOT IDENT)* DOT upperCaseIdent ; /** Used to look ahead for a constructor */constructorStart! : modifiersOpt! id:IDENT! {isConstructorIdent(id)}? nls! LPAREN! //... ;/** Used only as a lookahead predicate for nested type declarations. *//*TODO* The lookahead in typeDeclarationStart needs to skip annotations, notjust stop at '@', because variable and method declarations can also beannotated.> typeDeclarationStart!> : (modifier!)* ("class" | "interface" | "enum" | AT )S.B. something like> : (modifier! | annotationTokens!)* ("class" | "interface" |> "enum" )(And maybe @interface, if Java 5 allows nested annotation types? Don'tknow offhand.)Where annotationTokens can be a quick paren-skipper, as in otherplaces: '@' ident '(' balancedTokens ')'.*/typeDeclarationStart! : modifiersOpt! ("class" | "interface" | "enum" | AT "interface") ; /** An IDENT token whose spelling is required to start with an uppercase letter. * In the case of a simple statement {UpperID name} the identifier is taken to be a type name, not a command name. */upperCaseIdent : {isUpperCase(LT(1))}? IDENT ;// A type specification is a type name with possible brackets afterwards// (which would make it an array type).// Set addImagNode true for types inside expressions, not declarations.typeSpec[boolean addImagNode] : classTypeSpec[addImagNode] | builtInTypeSpec[addImagNode] ;// also check that 'classOrInterfaceType[false]' is a suitable substitution for 'identifier'// A class type specification is a class type with either:// - possible brackets afterwards// (which would make it an array type).// - generic type arguments afterclassTypeSpec[boolean addImagNode] {Token first = LT(1);} : ct:classOrInterfaceType[false]! declaratorBrackets[#ct] { if ( addImagNode ) { #classTypeSpec = #(create(TYPE,"TYPE",first,LT(1)), #classTypeSpec); } } ;// A non-built in type name, with possible type parametersclassOrInterfaceType[boolean addImagNode] {Token first = LT(1);} : IDENT^ (typeArguments)? ( options{greedy=true;}: // match as many as possible DOT^ IDENT (typeArguments)? )* { if ( addImagNode ) { #classOrInterfaceType = #(create(TYPE,"TYPE",first,LT(1)), #classOrInterfaceType); } } ;// A specialised form of typeSpec where built in types must be arraystypeArgumentSpec : classTypeSpec[true] | builtInTypeArraySpec[true] ;// A generic type argument is a class type, a possibly bounded wildcard type or a built-in type arraytypeArgument {Token first = LT(1);} : ( typeArgumentSpec | wildcardType ) {#typeArgument = #(create(TYPE_ARGUMENT,"TYPE_ARGUMENT",first,LT(1)), #typeArgument);} ;// Wildcard type indicating all types (with possible constraint)wildcardType : q:QUESTION^ {#q.setType(WILDCARD_TYPE);} (("extends" | "super")=> typeArgumentBounds)? ;// Type arguments to a class or interface typetypeArguments{Token first = LT(1);int currentLtLevel = 0;} : {currentLtLevel = ltCounter;} LT! {ltCounter++;} nls! typeArgument ( options{greedy=true;}: // match as many as possible {inputState.guessing !=0 || ltCounter == currentLtLevel + 1}? COMMA! nls! typeArgument )* nls! ( // turn warning off since Antlr generates the right code, // plus we have our semantic predicate below options{generateAmbigWarnings=false;}: typeArgumentsOrParametersEnd )? // make sure we have gobbled up enough '>' characters // if we are at the "top level" of nested typeArgument productions {(currentLtLevel != 0) || ltCounter == currentLtLevel}? {#typeArguments = #(create(TYPE_ARGUMENTS, "TYPE_ARGUMENTS",first,LT(1)), #typeArguments);} ;// this gobbles up *some* amount of '>' characters, and counts how many// it gobbled.protected typeArgumentsOrParametersEnd : GT! {ltCounter-=1;} nls! | SR! {ltCounter-=2;} nls! | BSR! {ltCounter-=3;} nls! ;// Restriction on wildcard types based on super class or derrived classtypeArgumentBounds
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -