/*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/** The parser maps a token sequence into an abstract syntax
* tree. It operates by recursive descent, with code derived
* systematically from an LL(1) grammar. For efficiency reasons, an
* operator precedence scheme is used for parsing binary operation
* expressions.
*
* <p><b>This is NOT part of any supported API.
* If you write code that depends on this, you do so at your own risk.
* This code and its internal interfaces are subject to change or
* deletion without notice.</b>
*/
/** The number of precedence levels of infix operators.
*/
/** The scanner used for lexical analysis.
*/
protected Lexer S;
/** The factory to be used for abstract syntax tree construction.
*/
protected TreeMaker F;
/** The log to be used for error diagnostics.
*/
/** The keyword table. */
/** The Source language setting. */
/** The name table. */
/** Construct a parser from a given scanner, tree factory and log.
*/
Lexer S,
boolean keepDocComments,
boolean keepLineMap) {
this.S = S;
S.nextToken(); // prime the pump
this.F = fac.F;
this.keepDocComments = keepDocComments;
this.keepLineMap = keepLineMap;
}
/** Switch: Should generics be recognized?
*/
boolean allowGenerics;
/** Switch: Should diamond operator be recognized?
*/
boolean allowDiamond;
/** Switch: Should multicatch clause be accepted?
*/
boolean allowMulticatch;
/** Switch: Should varargs be recognized?
*/
boolean allowVarargs;
/** Switch: should we recognize assert statements, or just give a warning?
*/
boolean allowAsserts;
/** Switch: should we recognize enums, or just give a warning?
*/
boolean allowEnums;
/** Switch: should we recognize foreach?
*/
boolean allowForeach;
/** Switch: should we recognize foreach?
*/
boolean allowStaticImport;
/** Switch: should we recognize annotations?
*/
boolean allowAnnotations;
/** Switch: should we recognize try-with-resources?
*/
boolean allowTWR;
/** Switch: should we fold strings?
*/
boolean allowStringFolding;
/** Switch: should we keep docComments?
*/
boolean keepDocComments;
/** Switch: should we keep line table?
*/
boolean keepLineMap;
/** When terms are parsed, the mode determines which is expected:
* mode = EXPR : an expression
* mode = TYPE : a type
* mode = NOPARAMS : no parameters allowed for type
* mode = TYPEARG : type argument
*/
/** The current mode.
*/
/** The mode of the term that was parsed last.
*/
/* ---------- error recovery -------------- */
/** Skip forward until a suitable stop token is found.
*/
private void skip(boolean stopAtImport, boolean stopAtMemberDecl, boolean stopAtIdentifier, boolean stopAtStatement) {
while (true) {
switch (S.token()) {
case SEMI:
S.nextToken();
return;
case PUBLIC:
case FINAL:
case ABSTRACT:
case MONKEYS_AT:
case EOF:
case CLASS:
case INTERFACE:
case ENUM:
return;
case IMPORT:
if (stopAtImport)
return;
break;
case LBRACE:
case RBRACE:
case PRIVATE:
case PROTECTED:
case STATIC:
case TRANSIENT:
case NATIVE:
case VOLATILE:
case SYNCHRONIZED:
case STRICTFP:
case LT:
case BYTE:
case SHORT:
case CHAR:
case INT:
case LONG:
case FLOAT:
case DOUBLE:
case BOOLEAN:
case VOID:
if (stopAtMemberDecl)
return;
break;
case IDENTIFIER:
if (stopAtIdentifier)
return;
break;
case CASE:
case DEFAULT:
case IF:
case FOR:
case WHILE:
case DO:
case TRY:
case SWITCH:
case RETURN:
case THROW:
case BREAK:
case CONTINUE:
case ELSE:
case FINALLY:
case CATCH:
if (stopAtStatement)
return;
break;
}
S.nextToken();
}
}
}
}
}
/**
* Report a syntax using the given the position parameter and arguments,
* unless one was already reported at the same position.
*/
}
/**
* Report a syntax error using the given DiagnosticPosition object and
* arguments, unless one was already reported at the same position.
*/
private void reportSyntaxError(JCDiagnostic.DiagnosticPosition diagPos, String key, Object... args) {
} else {
}
}
S.nextToken(); // guarantee progress
}
/** Generate a syntax error at current position unless one was already
* reported at the same position.
*/
}
/** Generate a syntax error at current position unless one was
* already reported at the same position.
*/
}
/** If next input token matches given token, skip it, otherwise report
* an error.
*/
S.nextToken();
} else {
setErrorEndPos(S.pos());
}
}
/** Report an illegal start of expression/type error at given position.
*/
else
}
/** Report an illegal start of expression/type error at current position.
*/
}
/** Diagnose a modifier flag from the set, if any. */
if (mods != 0) {
}
}
/* ---------- doc comments --------- */
/** A hashtable to store all documentation comments
* indexed by the tree nodes they refer to.
* defined only if option flag keepDocComment is set.
*/
/** Make an entry into docComments hashtable,
* provided flag keepDocComments is set and given doc comment is non-null.
* @param tree The tree to be used as index in the hashtable
* @param dc The doc comment to associate with the tree, or null.
*/
// System.out.println("doc comment = ");System.out.println(dc);//DEBUG
}
}
/* -------- source positions ------- */
if (errPos > errorEndPos)
}
protected int getErrorEndPos() {
return errorEndPos;
}
/**
* Store ending position for a tree.
* @param tree The tree.
* @param endpos The ending position to associate with the tree.
*/
/**
* Store ending position for a tree. The ending position should
* be the ending position of the current token.
* @param t The tree.
*/
/**
* Store ending position for a tree. The ending position should
* be greater of the ending position of the previous token and errorEndPos.
* @param t The tree.
*/
/** Get the start position for a tree node. The start position is
* defined to be the position of the first character of the first
* token of the node's source text.
* @param tree The tree node
*/
}
/**
* Get the end position for a tree node. The end position is
* defined to be the position of the last character of the last
* token of the node's source text. Returns Position.NOPOS if end
* positions are not generated or the position is otherwise not
* found.
* @param tree The tree node
*/
}
/* ---------- parsing -------------- */
/**
* Ident = IDENTIFIER
*/
if (S.token() == IDENTIFIER) {
S.nextToken();
return name;
if (allowAsserts) {
S.nextToken();
} else {
S.nextToken();
return name;
}
if (allowEnums) {
S.nextToken();
} else {
S.nextToken();
return name;
}
} else {
}
}
/**
* Qualident = Ident { DOT Ident }
*/
S.nextToken();
}
return t;
}
}
/**
* Literal =
* INTLITERAL
* | LONGLITERAL
* | FLOATLITERAL
* | DOUBLELITERAL
* | CHARLITERAL
* | STRINGLITERAL
* | TRUE
* | FALSE
* | NULL
*/
JCExpression t = errorTree;
switch (S.token()) {
case INTLITERAL:
try {
} catch (NumberFormatException ex) {
}
break;
case LONGLITERAL:
try {
} catch (NumberFormatException ex) {
}
break;
case FLOATLITERAL: {
Float n;
try {
} catch (NumberFormatException ex) {
// error already reported in scanner
}
else
break;
}
case DOUBLELITERAL: {
Double n;
try {
} catch (NumberFormatException ex) {
// error already reported in scanner
}
else
break;
}
case CHARLITERAL:
break;
case STRINGLITERAL:
S.stringVal());
break;
break;
case NULL:
null);
break;
default:
}
if (t == errorTree)
S.nextToken();
return t;
}
//where
char[] cs = s.toCharArray();
}
}
/** terms can be either expressions or types.
*/
}
}
JCExpression t = term();
return t;
}
/**
* Expression = Expression1 [ExpressionRest]
* ExpressionRest = [AssignmentOperator Expression1]
* AssignmentOperator = "=" | "+=" | "-=" | "*=" | "/=" |
* "&=" | "|=" | "^=" |
* "%=" | "<<=" | ">>=" | ">>>="
* Type = Type1
* TypeNoParams = TypeNoParams1
* StatementExpression = Expression
* ConstantExpression = Expression
*/
JCExpression t = term1();
return termRest(t);
else
return t;
}
switch (S.token()) {
case EQ: {
S.nextToken();
}
case PLUSEQ:
case SUBEQ:
case STAREQ:
case SLASHEQ:
case PERCENTEQ:
case AMPEQ:
case BAREQ:
case CARETEQ:
case LTLTEQ:
case GTGTEQ:
case GTGTGTEQ:
S.nextToken();
default:
return t;
}
}
/** Expression1 = Expression2 [Expression1Rest]
* Type1 = Type2
* TypeNoParams1 = TypeNoParams2
*/
JCExpression t = term2();
return term1Rest(t);
} else {
return t;
}
}
/** Expression1Rest = ["?" Expression ":" Expression1]
*/
S.nextToken();
} else {
return t;
}
}
/** Expression2 = Expression3 [Expression2Rest]
* Type2 = Type3
* TypeNoParams2 = TypeNoParams3
*/
JCExpression t = term3();
} else {
return t;
}
}
/* Expression2Rest = {infixop Expression3}
* | Expression3 instanceof Type
* infixop = "||"
* | "&&"
* | "|"
* | "^"
* | "&"
* | "==" | "!="
* | "<" | ">" | "<=" | ">="
* | "<<" | ">>" | ">>>"
* | "+" | "-"
* | "*" | "/" | "%"
*/
int[] posStack = newPosStack();
// optimization, was odStack = new Tree[...]; opStack = new Tree[...];
int top = 0;
odStack[0] = t;
top++;
S.nextToken();
top--;
}
}
t = odStack[0];
}
}
return t;
}
//where
/** Construct a binary or type test node.
*/
{
if (topOp == INSTANCEOF) {
} else {
}
}
/** If tree is a concatenation of string literals, replace it
* by a single literal representing the concatenated string.
*/
if (!allowStringFolding)
return null;
while (true) {
}
return sbuf;
}
continue;
}
}
}
return null;
}
}
* for every binary operation, we use supplys.
*/
return odStack;
}
return opStack;
}
private int[] newPosStack() {
return posStack;
}
/** Expression3 = PrefixOp Expression3
* | "(" Expr | TypeNoParams ")" Expression3
* | Primary {Selector} {PostfixOp}
* Primary = "(" Expression ")"
* | Literal
* | [TypeArguments] THIS [Arguments]
* | [TypeArguments] SUPER SuperSuffix
* | NEW [TypeArguments] Creator
* | Ident { "." Ident }
* [ "[" ( "]" BracketsOpt "." CLASS | Expression "]" )
* | Arguments
* | "." ( CLASS | THIS | [TypeArguments] SUPER Arguments | NEW [TypeArguments] InnerCreator )
* ]
* | BasicType BracketsOpt "." CLASS
* PrefixOp = "++" | "--" | "!" | "~" | "+" | "-"
* PostfixOp = "++" | "--"
* Type3 = Ident { "." Ident } [TypeArguments] {TypeSelector} BracketsOpt
* | BasicType
* TypeNoParams3 = Ident { "." Ident } BracketsOpt
* Selector = "." [TypeArguments] Ident [Arguments]
* | "." THIS
* | "." [TypeArguments] SUPER SuperSuffix
* | "." NEW [TypeArguments] InnerCreator
* | "[" Expression "]"
* TypeSelector = "." Ident [TypeArguments]
* SuperSuffix = Arguments | "." Ident [Arguments]
*/
JCExpression t;
switch (S.token()) {
case QUES:
return typeArgument();
} else
return illegal();
S.nextToken();
S.radix() == 10) {
} else {
t = term3();
}
} else return illegal();
break;
case LPAREN:
S.nextToken();
t = term3();
// Could be a cast to a parameterized type
S.nextToken();
S.nextToken();
}
S.nextToken();
t = typeArgumentsOpt(t);
}
t = bracketsOpt(toP(t));
} else {
}
}
else {
}
switch (S.token()) {
/*case PLUSPLUS: case SUBSUB: */
}
}
} else return illegal();
break;
case THIS:
S.nextToken();
t = argumentsOpt(null, t);
else
} else return illegal();
break;
case SUPER:
t = superSuffix(typeArgs, t);
} else return illegal();
break;
case CHARLITERAL: case STRINGLITERAL:
} else return illegal();
break;
case NEW:
S.nextToken();
} else return illegal();
break;
loop: while (true) {
switch (S.token()) {
case LBRACKET:
S.nextToken();
S.nextToken();
t = bracketsOpt(t);
t = bracketsSuffix(t);
} else {
}
}
break loop;
case LPAREN:
}
break loop;
case DOT:
S.nextToken();
switch (S.token()) {
case CLASS:
S.nextToken();
break loop;
case THIS:
S.nextToken();
break loop;
case SUPER:
t = superSuffix(typeArgs, t);
break loop;
case NEW:
S.nextToken();
break loop;
}
}
// typeArgs saved for next loop iteration.
break;
default:
break loop;
}
}
t = typeArgumentsOpt(t);
break;
break;
case VOID:
S.nextToken();
t = bracketsSuffix(ti);
} else {
}
} else {
// Support the corner case of myMethodHandle.<void>invoke() by passing
// a void type (like other primitive types) to the next phase.
// The error will be reported in Attr.attribTypes or Attr.visitApply.
S.nextToken();
return ti;
//return illegal();
}
break;
default:
return illegal();
}
while (true) {
S.nextToken();
S.nextToken();
t = bracketsOpt(t);
return t;
}
}
}
S.nextToken();
S.nextToken();
S.nextToken();
} else {
}
} else {
break;
}
}
S.nextToken();
}
return toP(t);
}
/** SuperSuffix = Arguments | "." [TypeArguments] Ident [Arguments]
*/
S.nextToken();
} else {
t = argumentsOpt(typeArgs, t);
}
return t;
}
/** BasicType = BYTE | SHORT | CHAR | INT | LONG | FLOAT | DOUBLE | BOOLEAN
*/
S.nextToken();
return t;
}
/** ArgumentsOpt = [ Arguments ]
*/
} else {
return t;
}
}
/** Arguments = "(" [Expression { COMMA Expression }] ")"
*/
S.nextToken();
S.nextToken();
}
}
} else {
}
}
}
/** TypeArgumentsOpt = [ TypeArguments ]
*/
return typeArguments(t, false);
} else {
return t;
}
}
return typeArgumentsOpt(TYPE);
}
illegal();
}
return typeArguments(false);
}
return null;
}
/** TypeArguments = "<" TypeArgument {"," TypeArgument} ">"
*/
S.nextToken();
checkDiamond();
S.nextToken();
} else {
S.nextToken();
}
switch (S.token()) {
case GTGTGTEQ:
break;
case GTGTEQ:
break;
case GTEQ:
break;
case GTGTGT:
break;
case GTGT:
break;
case GT:
S.nextToken();
break;
default:
break;
}
}
} else {
}
}
/** TypeArgument = Type
* | "?"
* | "?" EXTENDS Type {"&" Type}
* | "?" SUPER Type
*/
S.nextToken();
S.nextToken();
S.nextToken();
} else if (S.token() == IDENTIFIER) {
//error recovery
return err;
} else {
}
}
}
/** BracketsOpt = {"[" "]"}
*/
S.nextToken();
t = bracketsOptCont(t, pos);
}
return t;
}
t = bracketsOpt(t);
}
/** BracketsSuffixExpr = "." CLASS
* BracketsSuffixType =
*/
S.nextToken();
if (S.pos() == errorEndPos) {
// error recovery
if (S.token() == IDENTIFIER) {
S.nextToken();
} else {
}
} else {
}
} else {
}
return t;
}
/** Creator = Qualident [TypeArguments] ( ArrayCreatorRest | ClassCreatorRest )
*/
switch (S.token()) {
break;
default:
}
JCExpression t = qualident();
boolean diamondFound = false;
int lastTypeargsPos = -1;
lastTypeargsPos = S.pos();
t = typeArguments(t, true);
}
if (diamondFound) {
//cannot select after a diamond
illegal();
}
S.nextToken();
lastTypeargsPos = S.pos();
t = typeArguments(t, true);
}
}
if (diamondFound) {
}
// note: this should always happen but we should
// not rely on this as the parser is continuously
// modified to improve error recovery.
}
setErrorEndPos(S.prevEndPos());
}
return e;
} else {
setErrorEndPos(S.pos());
}
}
/** InnerCreator = Ident [TypeArguments] ClassCreatorRest
*/
t = typeArguments(t, true);
}
}
/** ArrayCreatorRest = "[" ( "]" BracketsOpt ArrayInitializer
* | Expression "]" {"[" Expression "]"} BracketsOpt )
*/
} else {
}
} else {
S.nextToken();
} else {
}
}
}
}
/** ClassCreatorRest = Arguments [ClassBody]
*/
JCExpression t)
{
}
}
/** ArrayInitializer = "{" [VariableInitializer {"," VariableInitializer}] [","] "}"
*/
S.nextToken();
S.nextToken();
}
}
}
/** VariableInitializer = ArrayInitializer | Expression
*/
}
/** ParExpression = "(" Expression ")"
*/
JCExpression t = parseExpression();
return t;
}
/** Block = "{" BlockStatements "}"
*/
}
// the Block node has a field "endpos" for first char of last token, which is
// usually but not necessarily the last char of the last token.
return toP(t);
}
}
/** BlockStatements = { BlockStatement }
* BlockStatement = LocalVariableDeclarationStatement
* | ClassOrInterfaceOrEnumDeclaration
* | [Ident ":"] Statement
* LocalVariableDeclarationStatement
* = { FINAL | '@' Annotation } Type VariableDeclarators ";"
*/
@SuppressWarnings("fallthrough")
//todo: skip to anchor on error(?)
int lastErrPos = -1;
while (true) {
switch (S.token()) {
break;
case MONKEYS_AT:
case FINAL: {
} else {
JCExpression t = parseType();
new ListBuffer<JCStatement>()));
// A "LocalVariableDeclarationStatement" subsumes the terminating semicolon
}
break;
}
break;
}
case INTERFACE:
case CLASS:
S.docComment()));
break;
case ENUM:
case ASSERT:
S.docComment()));
break;
break;
}
/* fall through to default */
default:
S.nextToken();
(S.token() == IDENTIFIER ||
new ListBuffer<JCStatement>()));
// A "LocalVariableDeclarationStatement" subsumes the terminating semicolon
} else {
// This Exec is an "ExpressionStatement"; it subsumes the terminating semicolon
}
}
// error recovery
if (S.pos() == lastErrPos)
if (S.pos() <= errorEndPos) {
skip(false, true, true, true);
lastErrPos = S.pos();
}
// ensure no dangling /** @deprecated */ active
S.resetDeprecatedFlag();
}
}
/** Statement =
* Block
* | IF ParExpression Statement [ELSE Statement]
* | FOR "(" ForInitOpt ";" [Expression] ";" ForUpdateOpt ")" Statement
* | FOR "(" FormalParameter : Expression ")" Statement
* | WHILE ParExpression Statement
* | DO Statement WHILE ParExpression ";"
* | TRY Block ( Catches | [Catches] FinallyPart )
* | TRY "(" ResourceSpecification ";"opt ")" Block [Catches] [FinallyPart]
* | SWITCH ParExpression "{" SwitchBlockStatementGroups "}"
* | SYNCHRONIZED ParExpression Block
* | RETURN [Expression] ";"
* | THROW Expression ";"
* | BREAK [Ident] ";"
* | CONTINUE [Ident] ";"
* | ASSERT Expression [ ":" Expression ] ";"
* | ";"
* | ExpressionStatement
* | Ident ":" Statement
*/
@SuppressWarnings("fallthrough")
switch (S.token()) {
case LBRACE:
return block();
case IF: {
S.nextToken();
S.nextToken();
elsepart = parseStatement();
}
}
case FOR: {
S.nextToken();
checkForeach();
} else {
List<JCExpressionStatement> steps = S.token() == RPAREN ? List.<JCExpressionStatement>nil() : forUpdate();
}
}
case WHILE: {
S.nextToken();
}
case DO: {
S.nextToken();
return t;
}
case TRY: {
S.nextToken();
S.nextToken();
}
S.nextToken();
}
} else {
if (allowTWR) {
} else
}
}
case SWITCH: {
S.nextToken();
return t;
}
case SYNCHRONIZED: {
S.nextToken();
}
case RETURN: {
S.nextToken();
return t;
}
case THROW: {
S.nextToken();
return t;
}
case BREAK: {
S.nextToken();
Name label = (S.token() == IDENTIFIER || S.token() == ASSERT || S.token() == ENUM) ? ident() : null;
return t;
}
case CONTINUE: {
S.nextToken();
Name label = (S.token() == IDENTIFIER || S.token() == ASSERT || S.token() == ENUM) ? ident() : null;
return t;
}
case SEMI:
S.nextToken();
case ELSE:
case FINALLY:
case CATCH:
case ASSERT: {
S.nextToken();
S.nextToken();
message = parseExpression();
}
return t;
}
/* else fall through to default case */
}
case ENUM:
default:
S.nextToken();
} else {
// This Exec is an "ExpressionStatement"; it subsumes the terminating semicolon
return stat;
}
}
}
/** CatchClause = CATCH "(" FormalParameter ")" Block
*/
}
S.nextToken();
}
return catchTypes.toList();
}
/** SwitchBlockStatementGroups = { SwitchBlockStatementGroup }
* SwitchBlockStatementGroup = SwitchLabel BlockStatements
* SwitchLabel = CASE ConstantExpression ":" | DEFAULT ":"
*/
while (true) {
switch (S.token()) {
case CASE: {
S.nextToken();
storeEnd(c, S.prevEndPos());
break;
}
case DEFAULT: {
S.nextToken();
storeEnd(c, S.prevEndPos());
break;
}
default:
S.nextToken(); // to ensure progress
}
}
}
/** MoreStatementExpressions = { COMMA StatementExpression }
*/
T stats) {
// This Exec is a "StatementExpression"; it subsumes no terminating token
S.nextToken();
JCExpression t = parseExpression();
// This Exec is a "StatementExpression"; it subsumes no terminating token
}
return stats;
}
/** ForInit = StatementExpression MoreStatementExpressions
* | { FINAL | '@' Annotation } Type VariableDeclarators
*/
} else {
else
}
}
/** ForUpdate = StatementExpression MoreStatementExpressions
*/
return moreStatementExpressions(S.pos(),
}
/** AnnotationsOpt = { '@' Annotation }
*/
while (S.token() == MONKEYS_AT) {
S.nextToken();
}
}
/** ModifiersOpt = { Modifier }
* Modifier = PUBLIC | PROTECTED | PRIVATE | STATIC | ABSTRACT | FINAL
* | NATIVE | SYNCHRONIZED | TRANSIENT | VOLATILE | "@"
* | "@" Annotation
*/
return modifiersOpt(null);
}
long flags;
int pos;
flags = 0;
} else {
}
if (S.deprecatedFlag()) {
S.resetDeprecatedFlag();
}
loop:
while (true) {
long flag;
switch (S.token()) {
default: break loop;
}
S.nextToken();
// if first modifier is an annotation, set pos to annotation's.
flag = 0;
}
}
}
switch (S.token()) {
default: break;
}
/* A modifiers tree with no modifier tokens or annotations
* has no text position. */
return mods;
}
/** Annotation = "@" Qualident [ "(" AnnotationFieldValues ")" ]
* @param pos position of "@" token
*/
// accept(AT); // AT consumed by caller
return ann;
}
}
/** AnnotationFieldValues = "(" [ AnnotationFieldValue { "," AnnotationFieldValue } ] ")" */
S.nextToken();
}
}
}
/** AnnotationFieldValue = AnnotationValue
* | Identifier "=" AnnotationValue
*/
if (S.token() == IDENTIFIER) {
JCExpression v = annotationValue();
} else {
return t1;
}
}
return annotationValue();
}
/* AnnotationValue = ConditionalExpression
* | Annotation
* | "{" [ AnnotationValue { "," AnnotationValue } ] [","] "}"
*/
int pos;
switch (S.token()) {
case MONKEYS_AT:
S.nextToken();
return annotation(pos);
case LBRACE:
S.nextToken();
}
}
default:
return term1();
}
}
/** VariableDeclarators = VariableDeclarator { "," VariableDeclarator }
*/
T vdefs)
{
}
/** VariableDeclaratorsRest = VariableDeclaratorRest { "," VariableDeclarator }
* ConstantDeclaratorsRest = ConstantDeclaratorRest { "," ConstantDeclarator }
*
* @param reqInit Is an initializer always required?
* @param dc The documentation comment for the variable declarations, or null.
*/
boolean reqInit,
T vdefs)
{
// All but last of multiple declarators subsume a comma
S.nextToken();
}
return vdefs;
}
/** VariableDeclarator = Ident VariableDeclaratorRest
* ConstantDeclarator = Ident ConstantDeclaratorRest
*/
JCVariableDecl variableDeclarator(JCModifiers mods, JCExpression type, boolean reqInit, String dc) {
}
/** VariableDeclaratorRest = BracketsOpt ["=" VariableInitializer]
* ConstantDeclaratorRest = BracketsOpt "=" VariableInitializer
*
* @param reqInit Is an initializer always required?
* @param dc The documentation comment for the variable declarations, or null.
*/
S.nextToken();
init = variableInitializer();
}
return result;
}
/** VariableDeclaratorId = Ident BracketsOpt
*/
}
}
/** Resources = Resource { ";" Resources }
*/
// All but last of multiple declarators must subsume a semicolon
int semiColonPos = S.pos();
S.nextToken();
// after last resource
break;
}
}
}
/** Resource = VariableModifiersOpt Type VariableDeclaratorId = Expression
*/
}
/** CompilationUnit = [ { "@" Annotation } PACKAGE Qualident ";"] {ImportDeclaration} {TypeDeclaration}
*/
if (S.token() == MONKEYS_AT)
mods = modifiersOpt();
}
S.nextToken();
}
boolean checkForImports = true;
if (S.pos() <= errorEndPos) {
// error recovery
skip(checkForImports, false, false, false);
break;
}
} else {
// If the first type declaration has consumed the first doc
// comment, then don't use it for the top level comment as well.
}
if (def instanceof JCExpressionStatement)
if (def instanceof JCClassDecl)
checkForImports = false;
}
}
if (keepDocComments)
if (keepLineMap)
return toplevel;
}
/** ImportDeclaration = IMPORT [ STATIC ] Ident { "." Ident } [ "." "*" ] ";"
*/
S.nextToken();
boolean importStatic = false;
importStatic = true;
S.nextToken();
}
do {
S.nextToken();
break;
} else {
}
}
/** TypeDeclaration = ClassOrInterfaceOrEnumDeclaration
* | ";"
*/
S.nextToken();
} else {
}
}
/** ClassOrInterfaceOrEnumDeclaration = ModifiersOpt
* (ClassDeclaration | InterfaceDeclaration | EnumDeclaration)
* @param mods Any modifiers starting the class or interface declaration
* @param dc The documentation comment for the class, or null.
*/
} else if (allowEnums) {
} else {
if (S.token() == IDENTIFIER) {
setErrorEndPos(S.pos());
} else {
}
}
} else {
allowEnums = true;
}
if (S.token() == IDENTIFIER) {
setErrorEndPos(S.pos());
} else {
}
}
}
/** ClassDeclaration = CLASS Ident TypeParametersOpt [EXTENDS Type]
* [IMPLEMENTS TypeList] ClassBody
* @param mods The modifiers starting the class declaration
* @param dc The documentation comment for the class, or null.
*/
S.nextToken();
}
if (S.token() == IMPLEMENTS) {
S.nextToken();
implementing = typeList();
}
return result;
}
/** InterfaceDeclaration = INTERFACE Ident TypeParametersOpt
* [EXTENDS TypeList] InterfaceBody
* @param mods The modifiers starting the interface declaration
* @param dc The documentation comment for the interface, or null.
*/
S.nextToken();
}
return result;
}
/** EnumDeclaration = ENUM Ident [IMPLEMENTS TypeList] EnumBody
* @param mods The modifiers starting the enum declaration
* @param dc The documentation comment for the enum, or null.
*/
if (S.token() == IMPLEMENTS) {
S.nextToken();
implementing = typeList();
}
return result;
}
/** EnumBody = "{" { EnumeratorDeclarationList } [","]
* [ ";" {ClassBodyDeclaration} ] "}"
*/
S.nextToken();
S.nextToken();
}
S.nextToken();
}
}
S.nextToken();
false));
if (S.pos() <= errorEndPos) {
// error recovery
skip(false, true, true, false);
}
}
}
}
/** EnumeratorDeclaration = AnnotationsOpt [TypeArguments] IDENTIFIER [ Arguments ] [ "{" ClassBody "}" ]
*/
if (S.deprecatedFlag()) {
S.resetDeprecatedFlag();
}
JCModifiers mods = F.at(annotations.isEmpty() ? Position.NOPOS : pos).Modifiers(flags, annotations);
}
return result;
}
/** TypeList = Type {"," Type}
*/
S.nextToken();
}
}
/** ClassBody = "{" {ClassBodyDeclaration} "}"
* InterfaceBody = "{" {InterfaceBodyDeclaration} "}"
*/
if (S.pos() <= errorEndPos) {
// error recovery
skip(false, true, false, false);
S.nextToken();
}
if (S.pos() <= errorEndPos) {
// error recovery
skip(false, true, true, false);
}
}
}
/** ClassBodyDeclaration =
* ";"
* | [STATIC] Block
* | ModifiersOpt
* ( Type Ident
* ( VariableDeclaratorsRest ";" | MethodDeclaratorRest )
* | VOID Ident MethodDeclaratorRest
* | TypeParameters (Type | VOID) Ident MethodDeclaratorRest
* | Ident ConstructorDeclaratorRest
* | TypeParameters Ident ConstructorDeclaratorRest
* | ClassOrInterfaceOrEnumDeclaration
* )
* InterfaceBodyDeclaration =
* ";"
* | ModifiersOpt Type Ident
* ( ConstantDeclaratorsRest | InterfaceMethodDeclaratorRest ";" )
*/
S.nextToken();
} else {
} else {
// if there are type parameters but no modifiers, save the start
// position of the method in the modifiers.
}
if (isVoid) {
S.nextToken();
} else {
}
isInterface, true, dc));
} else {
return defs;
} else {
: null;
}
}
}
}
}
/** MethodDeclaratorRest =
* FormalParameters BracketsOpt [Throws TypeList] ( MethodBody | [DEFAULT AnnotationValue] ";")
* VoidMethodDeclaratorRest =
* FormalParameters [Throws TypeList] ( MethodBody | ";")
* InterfaceMethodDeclaratorRest =
* FormalParameters BracketsOpt [THROWS TypeList] ";"
* VoidInterfaceMethodDeclaratorRest =
* FormalParameters [THROWS TypeList] ";"
* ConstructorDeclaratorRest =
* "(" FormalParameterListOpt ")" [THROWS TypeList] MethodBody
*/
boolean isInterface, boolean isVoid,
S.nextToken();
thrown = qualidentList();
}
defaultValue = null;
} else {
} else {
defaultValue = null;
}
if (S.pos() <= errorEndPos) {
// error recovery
skip(false, true, false, false);
}
}
}
body, defaultValue));
return result;
}
/** QualidentList = Qualident {"," Qualident}
*/
S.nextToken();
}
}
/** TypeParametersOpt = ["<" TypeParameter {"," TypeParameter} ">"]
*/
S.nextToken();
S.nextToken();
}
} else {
}
}
/** TypeParameter = TypeVariable [TypeParameterBound]
* TypeParameterBound = EXTENDS Type {"&" Type}
* TypeVariable = Ident
*/
S.nextToken();
S.nextToken();
}
}
}
/** FormalParameters = "(" [ FormalParameterList ] ")"
* FormalParameterList = [ FormalParameterListNovarargs , ] LastFormalParameter
* FormalParameterListNovarargs = [ FormalParameterListNovarargs , ] FormalParameter
*/
S.nextToken();
}
}
}
return mods;
}
/** FormalParameter = { FINAL | '@' Annotation } Type VariableDeclaratorId
* LastFormalParameter = { FINAL | '@' Annotation } Type '...' Ident | FormalParameter
*/
checkVarargs();
S.nextToken();
}
}
/* ---------- auxiliary methods -------------- */
}
}
}
/** Check that given tree is a legal expression statement.
*/
switch(t.getTag()) {
return t;
default:
return ret;
}
}
/** Return precedence of operator represented by token,
* -1 if token is not a binary operator. @see TreeInfo.opPrec
*/
}
/**
* Return the lesser of two positions, making allowance for either one
* being unset.
*/
return pos2;
return pos1;
}
/** Return operation tag of binary operator represented by token,
* -1 if token is not a binary operator.
*/
switch (token) {
case BARBAR:
case AMPAMP:
case BAR:
case BAREQ:
case CARET:
case CARETEQ:
return JCTree.BITXOR_ASG;
case AMP:
case AMPEQ:
return JCTree.BITAND_ASG;
case EQEQ:
case BANGEQ:
case LT:
case GT:
case LTEQ:
case GTEQ:
case LTLT:
case LTLTEQ:
case GTGT:
case GTGTEQ:
case GTGTGT:
case GTGTGTEQ:
case PLUS:
case PLUSEQ:
case SUB:
case SUBEQ:
case STAR:
case STAREQ:
case SLASH:
case SLASHEQ:
case PERCENT:
case PERCENTEQ:
case INSTANCEOF:
default:
return -1;
}
}
/** Return operation tag of unary operator represented by token,
* -1 if token is not a binary operator.
*/
switch (token) {
case PLUS:
case SUB:
case BANG:
case TILDE:
case PLUSPLUS:
case SUBSUB:
default:
return -1;
}
}
/** Return type tag of basic type represented by token,
* -1 if token is not a basic type identifier.
*/
switch (token) {
case BYTE:
case CHAR:
case SHORT:
case INT:
case LONG:
case FLOAT:
case DOUBLE:
case BOOLEAN:
default:
return -1;
}
}
void checkGenerics() {
if (!allowGenerics) {
allowGenerics = true;
}
}
void checkVarargs() {
if (!allowVarargs) {
allowVarargs = true;
}
}
void checkForeach() {
if (!allowForeach) {
allowForeach = true;
}
}
void checkStaticImports() {
if (!allowStaticImport) {
allowStaticImport = true;
}
}
void checkAnnotations() {
if (!allowAnnotations) {
allowAnnotations = true;
}
}
void checkDiamond() {
if (!allowDiamond) {
allowDiamond = true;
}
}
void checkMulticatch() {
if (!allowMulticatch) {
allowMulticatch = true;
}
}
void checkTryWithResources() {
if (!allowTWR) {
allowTWR = true;
}
}
}