EMMA Coverage Report (generated Thu Dec 06 15:24:05 GMT 2007)
[all classes][com.sun.tools.javac.parser]

COVERAGE SUMMARY FOR SOURCE FILE [Parser.java]

nameclass, %method, %block, %line, %
Parser.java100% (3/3)53%  (61/116)32%  (2470/7801)29%  (397.7/1392)

COVERAGE BREAKDOWN BY CLASS AND METHOD

nameclass, %method, %block, %line, %
     
class Parser100% (1/1)50%  (56/111)26%  (1818/7044)28%  (380.9/1375)
annotation (int): JCTree$JCAnnotation 0%   (0/1)0%   (0/24)0%   (0/6)
annotationFieldValue (): JCTree$JCExpression 0%   (0/1)0%   (0/44)0%   (0/9)
annotationFieldValues (): List 0%   (0/1)0%   (0/37)0%   (0/9)
annotationFieldValuesOpt (): List 0%   (0/1)0%   (0/10)0%   (0/1)
annotationValue (): JCTree$JCExpression 0%   (0/1)0%   (0/81)0%   (0/17)
annotationsOpt (): List 0%   (0/1)0%   (0/33)0%   (0/8)
arrayCreatorRest (int, JCTree$JCExpression): JCTree$JCExpression 0%   (0/1)0%   (0/91)0%   (0/19)
arrayInitializer (int, JCTree$JCExpression): JCTree$JCExpression 0%   (0/1)0%   (0/62)0%   (0/12)
basicType (): JCTree$JCPrimitiveTypeTree 0%   (0/1)0%   (0/20)0%   (0/3)
bracketsOptCont (JCTree$JCExpression, int): JCTree$JCArrayTypeTree 0%   (0/1)0%   (0/17)0%   (0/3)
bracketsSuffix (JCTree$JCExpression): JCTree$JCExpression 0%   (0/1)0%   (0/99)0%   (0/18)
catchClause (): JCTree$JCCatch 0%   (0/1)0%   (0/32)0%   (0/7)
checkAnnotations (): void 0%   (0/1)0%   (0/22)0%   (0/4)
checkForeach (): void 0%   (0/1)0%   (0/22)0%   (0/4)
checkGenerics (): void 0%   (0/1)0%   (0/22)0%   (0/4)
checkStaticImports (): void 0%   (0/1)0%   (0/22)0%   (0/4)
checkVarargs (): void 0%   (0/1)0%   (0/22)0%   (0/4)
enumBody (Name): List 0%   (0/1)0%   (0/147)0%   (0/21)
enumDeclaration (JCTree$JCModifiers, String): JCTree$JCClassDecl 0%   (0/1)0%   (0/61)0%   (0/12)
enumeratorDeclaration (Name): JCTree 0%   (0/1)0%   (0/153)0%   (0/28)
foldStrings (JCTree): StringBuffer 0%   (0/1)0%   (0/68)0%   (0/18)
forInit (): List 0%   (0/1)0%   (0/65)0%   (0/8)
forUpdate (): List 0%   (0/1)0%   (0/12)0%   (0/1)
getEndPos (JCTree): int 0%   (0/1)0%   (0/2)0%   (0/1)
getErrorEndPos (): int 0%   (0/1)0%   (0/3)0%   (0/1)
getStartPos (JCTree): int 0%   (0/1)0%   (0/3)0%   (0/1)
illegal (): JCTree$JCExpression 0%   (0/1)0%   (0/6)0%   (0/1)
illegal (int): JCTree$JCExpression 0%   (0/1)0%   (0/24)0%   (0/4)
importDeclaration (): JCTree 0%   (0/1)0%   (0/93)0%   (0/18)
innerCreator (int, List, JCTree$JCExpression): JCTree$JCExpression 0%   (0/1)0%   (0/31)0%   (0/5)
interfaceDeclaration (JCTree$JCModifiers, String): JCTree$JCClassDecl 0%   (0/1)0%   (0/52)0%   (0/12)
isZero (String): boolean 0%   (0/1)0%   (0/50)0%   (0/5)
literal (Name): JCTree$JCExpression 0%   (0/1)0%   (0/304)0%   (0/49)
makeOp (int, Token, JCTree$JCExpression, JCTree$JCExpression): JCTree$JCExpre... 0%   (0/1)0%   (0/21)0%   (0/3)
moreStatementExpressions (int, JCTree$JCExpression, ListBuffer): ListBuffer 0%   (0/1)0%   (0/44)0%   (0/8)
parExpression (): JCTree$JCExpression 0%   (0/1)0%   (0/11)0%   (0/4)
qualidentList (): List 0%   (0/1)0%   (0/26)0%   (0/6)
skip (boolean, boolean, boolean, boolean): void 0%   (0/1)0%   (0/28)0%   (0/13)
strval (Name): String 0%   (0/1)0%   (0/18)0%   (0/2)
switchBlockStatementGroups (): List 0%   (0/1)0%   (0/115)0%   (0/24)
syntaxError (String): JCTree$JCErroneous 0%   (0/1)0%   (0/9)0%   (0/1)
syntaxError (String, String): JCTree$JCErroneous 0%   (0/1)0%   (0/13)0%   (0/1)
syntaxError (int, List, String, Object []): JCTree$JCErroneous 0%   (0/1)0%   (0/18)0%   (0/3)
syntaxError (int, String, Object []): JCTree$JCErroneous 0%   (0/1)0%   (0/7)0%   (0/1)
typeArgument (): JCTree$JCExpression 0%   (0/1)0%   (0/165)0%   (0/19)
typeArguments (): List 0%   (0/1)0%   (0/100)0%   (0/22)
typeArguments (JCTree$JCExpression): JCTree$JCTypeApply 0%   (0/1)0%   (0/18)0%   (0/3)
typeArgumentsOpt (): List 0%   (0/1)0%   (0/4)0%   (0/1)
typeList (): List 0%   (0/1)0%   (0/26)0%   (0/6)
typeParameter (): JCTree$JCTypeParameter 0%   (0/1)0%   (0/50)0%   (0/10)
typetag (Token): int 0%   (0/1)0%   (0/23)0%   (0/10)
unoptag (Token): int 0%   (0/1)0%   (0/19)0%   (0/8)
variableDeclarator (JCTree$JCModifiers, JCTree$JCExpression, boolean, String)... 0%   (0/1)0%   (0/12)0%   (0/1)
variableDeclarators (JCTree$JCModifiers, JCTree$JCExpression, ListBuffer): Li... 0%   (0/1)0%   (0/13)0%   (0/1)
variableInitializer (): JCTree$JCExpression 0%   (0/1)0%   (0/15)0%   (0/1)
classOrInterfaceOrEnumDeclaration (JCTree$JCModifiers, String): JCTree$JCStat... 100% (1/1)5%   (10/184)9%   (2/23)
statement (): JCTree$JCStatement 100% (1/1)7%   (37/559)7%   (6.9/106)
optag (Token): int 100% (1/1)10%  (7/69)6%   (2/33)
typeParametersOpt (): List 100% (1/1)17%  (7/41)18%  (2/11)
checkNoMods (long): void 100% (1/1)20%  (5/25)50%  (2/4)
term1Rest (JCTree$JCExpression): JCTree$JCExpression 100% (1/1)22%  (7/32)25%  (2/8)
checkExprStat (JCTree$JCExpression): JCTree$JCExpression 100% (1/1)23%  (5/22)50%  (2/4)
creator (int, List): JCTree$JCExpression 100% (1/1)25%  (46/186)30%  (10/33)
typeArgumentsOpt (int): List 100% (1/1)25%  (7/28)29%  (2/7)
blockStatements (): List 100% (1/1)26%  (75/290)31%  (15.9/52)
typeArgumentsOpt (JCTree$JCExpression): JCTree$JCExpression 100% (1/1)27%  (7/26)27%  (1.3/5)
term3 (): JCTree$JCExpression 100% (1/1)29%  (284/988)28%  (54.3/196)
bracketsOpt (JCTree$JCExpression): JCTree$JCExpression 100% (1/1)29%  (7/24)33%  (2/6)
ident (): Name 100% (1/1)30%  (31/105)33%  (8/24)
superSuffix (List, JCTree$JCExpression): JCTree$JCExpression 100% (1/1)31%  (16/52)42%  (3.8/9)
modifiersOpt (JCTree$JCModifiers): JCTree$JCModifiers 100% (1/1)32%  (59/186)30%  (13.4/45)
attach (JCTree, String): void 100% (1/1)33%  (4/12)53%  (1.6/3)
term2Rest (JCTree$JCExpression, int): JCTree$JCExpression 100% (1/1)38%  (52/136)49%  (14.2/29)
formalParameter (): JCTree$JCVariableDecl 100% (1/1)42%  (17/40)50%  (4/8)
variableDeclaratorsRest (int, JCTree$JCModifiers, JCTree$JCExpression, Name, ... 100% (1/1)45%  (18/40)50%  (3/6)
classCreatorRest (int, JCTree$JCExpression, List, JCTree$JCExpression): JCTre... 100% (1/1)45%  (24/53)50%  (4/8)
qualident (): JCTree$JCExpression 100% (1/1)50%  (20/40)43%  (3/7)
termRest (JCTree$JCExpression): JCTree$JCExpression 100% (1/1)55%  (33/60)54%  (7/13)
arguments (): List 100% (1/1)56%  (32/57)73%  (8/11)
variableDeclaratorRest (int, JCTree$JCModifiers, JCTree$JCExpression, Name, b... 100% (1/1)58%  (32/55)68%  (6.1/9)
argumentsOpt (List, JCTree$JCExpression): JCTree$JCExpression 100% (1/1)64%  (14/22)50%  (2/4)
classOrInterfaceBody (Name, boolean): List 100% (1/1)67%  (42/63)67%  (8/12)
compilationUnit (): JCTree$JCCompilationUnit 100% (1/1)67%  (98/147)64%  (24.4/38)
term2 (): JCTree$JCExpression 100% (1/1)67%  (16/24)60%  (3/5)
typeDeclaration (JCTree$JCModifiers): JCTree 100% (1/1)67%  (22/33)67%  (4/6)
term1 (): JCTree$JCExpression 100% (1/1)68%  (15/22)60%  (3/5)
classOrInterfaceBodyDeclaration (Name, boolean): List 100% (1/1)69%  (187/271)75%  (28.6/38)
prec (Token): int 100% (1/1)70%  (7/10)85%  (1.7/2)
methodDeclaratorRest (int, JCTree$JCModifiers, JCTree$JCExpression, Name, Lis... 100% (1/1)72%  (68/95)68%  (15/22)
block (int, long): JCTree$JCBlock 100% (1/1)73%  (37/51)78%  (7/9)
formalParameters (): List 100% (1/1)78%  (40/51)80%  (8/10)
term (): JCTree$JCExpression 100% (1/1)81%  (25/31)94%  (3.8/4)
reportSyntaxError (int, String, Object []): void 100% (1/1)83%  (38/46)89%  (8/9)
<static initializer> 100% (1/1)88%  (7/8)87%  (0.9/1)
classDeclaration (JCTree$JCModifiers, String): JCTree$JCClassDecl 100% (1/1)91%  (59/65)88%  (14/16)
Parser (Parser$Factory, Lexer, boolean): void 100% (1/1)95%  (98/103)100% (25.9/26)
accept (Token): void 100% (1/1)100% (30/30)100% (5/5)
arguments (List, JCTree$JCExpression): JCTree$JCMethodInvocation 100% (1/1)100% (19/19)100% (3/3)
block (): JCTree$JCBlock 100% (1/1)100% (7/7)100% (1/1)
expression (): JCTree$JCExpression 100% (1/1)100% (4/4)100% (1/1)
modifiersOpt (): JCTree$JCModifiers 100% (1/1)100% (4/4)100% (1/1)
newOdStack (): JCTree$JCExpression [] 100% (1/1)100% (28/28)100% (5/5)
newOpStack (): Token [] 100% (1/1)100% (28/28)100% (5/5)
optFinal (long): JCTree$JCModifiers 100% (1/1)100% (17/17)100% (4/4)
setErrorEndPos (int): void 100% (1/1)100% (8/8)100% (3/3)
storeEnd (JCTree, int): void 100% (1/1)100% (1/1)100% (1/1)
term (int): JCTree$JCExpression 100% (1/1)100% (18/18)100% (6/6)
to (JCTree): JCTree 100% (1/1)100% (2/2)100% (1/1)
toP (JCTree): JCTree 100% (1/1)100% (2/2)100% (1/1)
type (): JCTree$JCExpression 100% (1/1)100% (4/4)100% (1/1)
variableDeclaratorId (JCTree$JCModifiers, JCTree$JCExpression): JCTree$JCVari... 100% (1/1)100% (31/31)100% (5/5)
     
class Parser$1100% (1/1)100% (1/1)86%  (593/691)85%  (0.8/1)
<static initializer> 100% (1/1)86%  (593/691)85%  (0.8/1)
     
class Parser$Factory100% (1/1)100% (4/4)89%  (59/66)94%  (16/17)
newParser (Lexer, boolean, boolean): Parser 100% (1/1)56%  (9/16)67%  (2/3)
<static initializer> 100% (1/1)100% (5/5)100% (1/1)
Parser$Factory (Context): void 100% (1/1)100% (31/31)100% (9/9)
instance (Context): Parser$Factory 100% (1/1)100% (14/14)100% (4/4)

1/*
2 * Copyright 1999-2006 Sun Microsystems, Inc.  All Rights Reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation.  Sun designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Sun in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
22 * CA 95054 USA or visit www.sun.com if you need additional information or
23 * have any questions.
24 */
25 
26package com.sun.tools.javac.parser;
27 
28import java.util.*;
29 
30import com.sun.tools.javac.tree.*;
31import com.sun.tools.javac.code.*;
32import com.sun.tools.javac.util.*;
33import com.sun.tools.javac.util.List;
34import static com.sun.tools.javac.util.ListBuffer.lb;
35 
36import com.sun.tools.javac.tree.JCTree.*;
37 
38import static com.sun.tools.javac.parser.Token.*;
39 
40/** The parser maps a token sequence into an abstract syntax
41 *  tree. It operates by recursive descent, with code derived
42 *  systematically from an LL(1) grammar. For efficiency reasons, an
43 *  operator precedence scheme is used for parsing binary operation
44 *  expressions.
45 *
46 *  <p><b>This is NOT part of any API supported by Sun Microsystems.  If
47 *  you write code that depends on this, you do so at your own risk.
48 *  This code and its internal interfaces are subject to change or
49 *  deletion without notice.</b>
50 */
51public class Parser {
52 
53    /** A factory for creating parsers. */
54    public static class Factory {
55        /** The context key for the parser factory. */
56        protected static final Context.Key<Parser.Factory> parserFactoryKey =
57            new Context.Key<Parser.Factory>();
58 
59        /** Get the Factory instance for this context. */
60        public static Factory instance(Context context) {
61            Factory instance = context.get(parserFactoryKey);
62            if (instance == null)
63                instance = new Factory(context);
64            return instance;
65        }
66 
67        final TreeMaker F;
68        final Log log;
69        final Keywords keywords;
70        final Source source;
71        final Name.Table names;
72        final Options options;
73 
74        /** Create a new parser factory. */
75        protected Factory(Context context) {
76            context.put(parserFactoryKey, this);
77            this.F = TreeMaker.instance(context);
78            this.log = Log.instance(context);
79            this.names = Name.Table.instance(context);
80            this.keywords = Keywords.instance(context);
81            this.source = Source.instance(context);
82            this.options = Options.instance(context);
83        }
84 
85        /**
86         * Create a new Parser.
87         * @param S Lexer for getting tokens while parsing
88         * @param keepDocComments true if javadoc comments should be kept
89         * @param genEndPos true if end positions should be generated
90         */
91        public Parser newParser(Lexer S, boolean keepDocComments, boolean genEndPos) {
92            if (!genEndPos)
93                return new Parser(this, S, keepDocComments);
94            else
95                return new EndPosParser(this, S, keepDocComments);
96        }
97    }
98 
99    /** The number of precedence levels of infix operators.
100     */
101    private static final int infixPrecedenceLevels = 10;
102 
103    /** The scanner used for lexical analysis.
104     */
105    private Lexer S;
106 
107    /** The factory to be used for abstract syntax tree construction.
108     */
109    protected TreeMaker F;
110 
111    /** The log to be used for error diagnostics.
112     */
113    private Log log;
114 
115    /** The keyword table. */
116    private Keywords keywords;
117 
118    /** The Source language setting. */
119    private Source source;
120 
121    /** The name table. */
122    private Name.Table names;
123 
124    /** Construct a parser from a given scanner, tree factory and log.
125     */
126    protected Parser(Factory fac,
127                     Lexer S,
128                     boolean keepDocComments) {
129        this.S = S;
130        S.nextToken(); // prime the pump
131        this.F = fac.F;
132        this.log = fac.log;
133        this.names = fac.names;
134        this.keywords = fac.keywords;
135        this.source = fac.source;
136        Options options = fac.options;
137        this.allowGenerics = source.allowGenerics();
138        this.allowVarargs = source.allowVarargs();
139        this.allowAsserts = source.allowAsserts();
140        this.allowEnums = source.allowEnums();
141        this.allowForeach = source.allowForeach();
142        this.allowStaticImport = source.allowStaticImport();
143        this.allowAnnotations = source.allowAnnotations();
144        this.keepDocComments = keepDocComments;
145        if (keepDocComments) docComments = new HashMap<JCTree,String>();
146        this.errorTree = F.Erroneous();
147    }
148 
149    /** Switch: Should generics be recognized?
150     */
151    boolean allowGenerics;
152 
153    /** Switch: Should varargs be recognized?
154     */
155    boolean allowVarargs;
156 
157    /** Switch: should we recognize assert statements, or just give a warning?
158     */
159    boolean allowAsserts;
160 
161    /** Switch: should we recognize enums, or just give a warning?
162     */
163    boolean allowEnums;
164 
165    /** Switch: should we recognize foreach?
166     */
167    boolean allowForeach;
168 
169    /** Switch: should we recognize foreach?
170     */
171    boolean allowStaticImport;
172 
173    /** Switch: should we recognize annotations?
174     */
175    boolean allowAnnotations;
176 
177    /** Switch: should we keep docComments?
178     */
179    boolean keepDocComments;
180 
181    /** When terms are parsed, the mode determines which is expected:
182     *     mode = EXPR        : an expression
183     *     mode = TYPE        : a type
184     *     mode = NOPARAMS    : no parameters allowed for type
185     *     mode = TYPEARG     : type argument
186     */
187    static final int EXPR = 1;
188    static final int TYPE = 2;
189    static final int NOPARAMS = 4;
190    static final int TYPEARG = 8;
191 
192    /** The current mode.
193     */
194    private int mode = 0;
195 
196    /** The mode of the term that was parsed last.
197     */
198    private int lastmode = 0;
199 
200/* ---------- error recovery -------------- */
201 
202    private JCErroneous errorTree;
203 
204    /** Skip forward until a suitable stop token is found.
205     */
206    private void skip(boolean stopAtImport, boolean stopAtMemberDecl, boolean stopAtIdentifier, boolean stopAtStatement) {
207         while (true) {
208             switch (S.token()) {
209                case SEMI:
210                    S.nextToken();
211                    return;
212                case PUBLIC:
213                case FINAL:
214                case ABSTRACT:
215                case MONKEYS_AT:
216                case EOF:
217                case CLASS:
218                case INTERFACE:
219                case ENUM:
220                    return;
221                case IMPORT:
222                    if (stopAtImport)
223                        return;
224                    break;
225                case LBRACE:
226                case RBRACE:
227                case PRIVATE:
228                case PROTECTED:
229                case STATIC:
230                case TRANSIENT:
231                case NATIVE:
232                case VOLATILE:
233                case SYNCHRONIZED:
234                case STRICTFP:
235                case LT:
236                case BYTE:
237                case SHORT:
238                case CHAR:
239                case INT:
240                case LONG:
241                case FLOAT:
242                case DOUBLE:
243                case BOOLEAN:
244                case VOID:
245                    if (stopAtMemberDecl)
246                        return;
247                    break;
248                case IDENTIFIER:
249                   if (stopAtIdentifier)
250                        return;
251                    break;
252                case CASE:
253                case DEFAULT:
254                case IF:
255                case FOR:
256                case WHILE:
257                case DO:
258                case TRY:
259                case SWITCH:
260                case RETURN:
261                case THROW:
262                case BREAK:
263                case CONTINUE:
264                case ELSE:
265                case FINALLY:
266                case CATCH:
267                    if (stopAtStatement)
268                        return;
269                    break;
270            }
271            S.nextToken();
272        }
273    }
274 
275    private JCErroneous syntaxError(int pos, String key, Object... arg) {
276        return syntaxError(pos, null, key, arg);
277    }
278 
279    private JCErroneous syntaxError(int pos, List<JCTree> errs, String key, Object... arg) {
280        setErrorEndPos(pos);
281        reportSyntaxError(pos, key, arg);
282        return toP(F.at(pos).Erroneous(errs));
283    }
284 
285    private int errorPos = Position.NOPOS;
286    /**
287     * Report a syntax error at given position using the given
288     * argument unless one was already reported at the same position.
289     */
290    private void reportSyntaxError(int pos, String key, Object... arg) {
291        if (pos > S.errPos() || pos == Position.NOPOS) {
292            if (S.token() == EOF)
293                log.error(pos, "premature.eof");
294            else
295                log.error(pos, key, arg);
296        }
297        S.errPos(pos);
298        if (S.pos() == errorPos)
299            S.nextToken(); // guarantee progress
300        errorPos = S.pos();
301    }
302 
303 
304    /** Generate a syntax error at current position unless one was already
305     *  reported at the same position.
306     */
307    private JCErroneous syntaxError(String key) {
308        return syntaxError(S.pos(), key);
309    }
310 
311    /** Generate a syntax error at current position unless one was
312     *  already reported at the same position.
313     */
314    private JCErroneous syntaxError(String key, String arg) {
315        return syntaxError(S.pos(), key, arg);
316    }
317 
318    /** If next input token matches given token, skip it, otherwise report
319     *  an error.
320     */
321    public void accept(Token token) {
322        if (S.token() == token) {
323            S.nextToken();
324        } else {
325            setErrorEndPos(S.pos());
326            reportSyntaxError(S.prevEndPos(), "expected", keywords.token2string(token));
327        }
328    }
329 
330    /** Report an illegal start of expression/type error at given position.
331     */
332    JCExpression illegal(int pos) {
333        setErrorEndPos(S.pos());
334        if ((mode & EXPR) != 0)
335            return syntaxError(pos, "illegal.start.of.expr");
336        else
337            return syntaxError(pos, "illegal.start.of.type");
338 
339    }
340 
341    /** Report an illegal start of expression/type error at current position.
342     */
343    JCExpression illegal() {
344        return illegal(S.pos());
345    }
346 
347    /** Diagnose a modifier flag from the set, if any. */
348    void checkNoMods(long mods) {
349        if (mods != 0) {
350            long lowestMod = mods & -mods;
351            log.error(S.pos(), "mod.not.allowed.here",
352                      Flags.toString(lowestMod).trim());
353        }
354    }
355 
356/* ---------- doc comments --------- */
357 
358    /** A hashtable to store all documentation comments
359     *  indexed by the tree nodes they refer to.
360     *  defined only if option flag keepDocComment is set.
361     */
362    Map<JCTree, String> docComments;
363 
364    /** Make an entry into docComments hashtable,
365     *  provided flag keepDocComments is set and given doc comment is non-null.
366     *  @param tree   The tree to be used as index in the hashtable
367     *  @param dc     The doc comment to associate with the tree, or null.
368     */
369    void attach(JCTree tree, String dc) {
370        if (keepDocComments && dc != null) {
371//          System.out.println("doc comment = ");System.out.println(dc);//DEBUG
372            docComments.put(tree, dc);
373        }
374    }
375 
376/* -------- source positions ------- */
377 
378    private int errorEndPos = -1;
379 
380    private void setErrorEndPos(int errPos) {
381        if (errPos > errorEndPos)
382            errorEndPos = errPos;
383    }
384 
385    protected int getErrorEndPos() {
386        return errorEndPos;
387    }
388 
389    /**
390     * Store ending position for a tree.
391     * @param tree   The tree.
392     * @param endpos The ending position to associate with the tree.
393     */
394    protected void storeEnd(JCTree tree, int endpos) {}
395 
396    /**
397     * Store ending position for a tree.  The ending position should
398     * be the ending position of the current token.
399     * @param t The tree.
400     */
401    protected <T extends JCTree> T to(T t) { return t; }
402 
403    /**
404     * Store ending position for a tree.  The ending position should
405     * be greater of the ending position of the previous token and errorEndPos.
406     * @param t The tree.
407     */
408    protected <T extends JCTree> T toP(T t) { return t; }
409 
410    /** Get the start position for a tree node.  The start position is
411     * defined to be the position of the first character of the first
412     * token of the node's source text.
413     * @param tree  The tree node
414     */
415    public int getStartPos(JCTree tree) {
416        return TreeInfo.getStartPos(tree);
417    }
418 
419    /**
420     * Get the end position for a tree node.  The end position is
421     * defined to be the position of the last character of the last
422     * token of the node's source text.  Returns Position.NOPOS if end
423     * positions are not generated or the position is otherwise not
424     * found.
425     * @param tree  The tree node
426     */
427    public int getEndPos(JCTree tree) {
428        return Position.NOPOS;
429    }
430 
431 
432 
433/* ---------- parsing -------------- */
434 
435    /**
436     * Ident = IDENTIFIER
437     */
438    Name ident() {
439        if (S.token() == IDENTIFIER) {
440            Name name = S.name();
441            S.nextToken();
442            return name;
443        } else if (S.token() == ASSERT) {
444            if (allowAsserts) {
445                log.error(S.pos(), "assert.as.identifier");
446                S.nextToken();
447                return names.error;
448            } else {
449                log.warning(S.pos(), "assert.as.identifier");
450                Name name = S.name();
451                S.nextToken();
452                return name;
453            }
454        } else if (S.token() == ENUM) {
455            if (allowEnums) {
456                log.error(S.pos(), "enum.as.identifier");
457                S.nextToken();
458                return names.error;
459            } else {
460                log.warning(S.pos(), "enum.as.identifier");
461                Name name = S.name();
462                S.nextToken();
463                return name;
464            }
465        } else {
466            accept(IDENTIFIER);
467            return names.error;
468        }
469}
470 
471    /**
472     * Qualident = Ident { DOT Ident }
473     */
474    public JCExpression qualident() {
475        JCExpression t = toP(F.at(S.pos()).Ident(ident()));
476        while (S.token() == DOT) {
477            int pos = S.pos();
478            S.nextToken();
479            t = toP(F.at(pos).Select(t, ident()));
480        }
481        return t;
482    }
483 
484    /**
485     * Literal =
486     *     INTLITERAL
487     *   | LONGLITERAL
488     *   | FLOATLITERAL
489     *   | DOUBLELITERAL
490     *   | CHARLITERAL
491     *   | STRINGLITERAL
492     *   | TRUE
493     *   | FALSE
494     *   | NULL
495     */
496    JCExpression literal(Name prefix) {
497        int pos = S.pos();
498        JCExpression t = errorTree;
499        switch (S.token()) {
500        case INTLITERAL:
501            try {
502                t = F.at(pos).Literal(
503                    TypeTags.INT,
504                    Convert.string2int(strval(prefix), S.radix()));
505            } catch (NumberFormatException ex) {
506                log.error(S.pos(), "int.number.too.large", strval(prefix));
507            }
508            break;
509        case LONGLITERAL:
510            try {
511                t = F.at(pos).Literal(
512                    TypeTags.LONG,
513                    new Long(Convert.string2long(strval(prefix), S.radix())));
514            } catch (NumberFormatException ex) {
515                log.error(S.pos(), "int.number.too.large", strval(prefix));
516            }
517            break;
518        case FLOATLITERAL: {
519            String proper = (S.radix() == 16 ? ("0x"+ S.stringVal()) : S.stringVal());
520            Float n;
521            try {
522                n = Float.valueOf(proper);
523            } catch (NumberFormatException ex) {
524                // error already repoted in scanner
525                n = Float.NaN;
526            }
527            if (n.floatValue() == 0.0f && !isZero(proper))
528                log.error(S.pos(), "fp.number.too.small");
529            else if (n.floatValue() == Float.POSITIVE_INFINITY)
530                log.error(S.pos(), "fp.number.too.large");
531            else
532                t = F.at(pos).Literal(TypeTags.FLOAT, n);
533            break;
534        }
535        case DOUBLELITERAL: {
536            String proper = (S.radix() == 16 ? ("0x"+ S.stringVal()) : S.stringVal());
537            Double n;
538            try {
539                n = Double.valueOf(proper);
540            } catch (NumberFormatException ex) {
541                // error already reported in scanner
542                n = Double.NaN;
543            }
544            if (n.doubleValue() == 0.0d && !isZero(proper))
545                log.error(S.pos(), "fp.number.too.small");
546            else if (n.doubleValue() == Double.POSITIVE_INFINITY)
547                log.error(S.pos(), "fp.number.too.large");
548            else
549                t = F.at(pos).Literal(TypeTags.DOUBLE, n);
550            break;
551        }
552        case CHARLITERAL:
553            t = F.at(pos).Literal(
554                TypeTags.CHAR,
555                S.stringVal().charAt(0) + 0);
556            break;
557        case STRINGLITERAL:
558            t = F.at(pos).Literal(
559                TypeTags.CLASS,
560                S.stringVal());
561            break;
562        case TRUE: case FALSE:
563            t = F.at(pos).Literal(
564                TypeTags.BOOLEAN,
565                (S.token() == TRUE ? 1 : 0));
566            break;
567        case NULL:
568            t = F.at(pos).Literal(
569                TypeTags.BOT,
570                null);
571            break;
572        default:
573            assert false;
574        }
575        if (t == errorTree)
576            t = F.at(pos).Erroneous();
577        storeEnd(t, S.endPos());
578        S.nextToken();
579        return t;
580    }
581//where
582        boolean isZero(String s) {
583            char[] cs = s.toCharArray();
584            int base = ((Character.toLowerCase(s.charAt(1)) == 'x') ? 16 : 10);
585            int i = ((base==16) ? 2 : 0);
586            while (i < cs.length && (cs[i] == '0' || cs[i] == '.')) i++;
587            return !(i < cs.length && (Character.digit(cs[i], base) > 0));
588        }
589 
590        String strval(Name prefix) {
591            String s = S.stringVal();
592            return (prefix.len == 0) ? s : prefix + s;
593        }
594 
595    /** terms can be either expressions or types.
596     */
597    public JCExpression expression() {
598        return term(EXPR);
599    }
600 
601    public JCExpression type() {
602        return term(TYPE);
603    }
604 
605    JCExpression term(int newmode) {
606        int prevmode = mode;
607        mode = newmode;
608        JCExpression t = term();
609        lastmode = mode;
610        mode = prevmode;
611        return t;
612    }
613 
614    /**
615     *  Expression = Expression1 [ExpressionRest]
616     *  ExpressionRest = [AssignmentOperator Expression1]
617     *  AssignmentOperator = "=" | "+=" | "-=" | "*=" | "/=" |
618     *                       "&=" | "|=" | "^=" |
619     *                       "%=" | "<<=" | ">>=" | ">>>="
620     *  Type = Type1
621     *  TypeNoParams = TypeNoParams1
622     *  StatementExpression = Expression
623     *  ConstantExpression = Expression
624     */
625    JCExpression term() {
626        JCExpression t = term1();
627        if ((mode & EXPR) != 0 &&
628            S.token() == EQ || PLUSEQ.compareTo(S.token()) <= 0 && S.token().compareTo(GTGTGTEQ) <= 0)
629            return termRest(t);
630        else
631            return t;
632    }
633 
634    JCExpression termRest(JCExpression t) {
635        switch (S.token()) {
636        case EQ: {
637            int pos = S.pos();
638            S.nextToken();
639            mode = EXPR;
640            JCExpression t1 = term();
641            return toP(F.at(pos).Assign(t, t1));
642        }
643        case PLUSEQ:
644        case SUBEQ:
645        case STAREQ:
646        case SLASHEQ:
647        case PERCENTEQ:
648        case AMPEQ:
649        case BAREQ:
650        case CARETEQ:
651        case LTLTEQ:
652        case GTGTEQ:
653        case GTGTGTEQ:
654            int pos = S.pos();
655            Token token = S.token();
656            S.nextToken();
657            mode = EXPR;
658            JCExpression t1 = term();
659            return F.at(pos).Assignop(optag(token), t, t1);
660        default:
661            return t;
662        }
663    }
664 
665    /** Expression1   = Expression2 [Expression1Rest]
666     *  Type1         = Type2
667     *  TypeNoParams1 = TypeNoParams2
668     */
669    JCExpression term1() {
670        JCExpression t = term2();
671        if ((mode & EXPR) != 0 && S.token() == QUES) {
672            mode = EXPR;
673            return term1Rest(t);
674        } else {
675            return t;
676        }
677    }
678 
679    /** Expression1Rest = ["?" Expression ":" Expression1]
680     */
681    JCExpression term1Rest(JCExpression t) {
682        if (S.token() == QUES) {
683            int pos = S.pos();
684            S.nextToken();
685            JCExpression t1 = term();
686            accept(COLON);
687            JCExpression t2 = term1();
688            return F.at(pos).Conditional(t, t1, t2);
689        } else {
690            return t;
691        }
692    }
693 
694    /** Expression2   = Expression3 [Expression2Rest]
695     *  Type2         = Type3
696     *  TypeNoParams2 = TypeNoParams3
697     */
698    JCExpression term2() {
699        JCExpression t = term3();
700        if ((mode & EXPR) != 0 && prec(S.token()) >= TreeInfo.orPrec) {
701            mode = EXPR;
702            return term2Rest(t, TreeInfo.orPrec);
703        } else {
704            return t;
705        }
706    }
707 
708    /*  Expression2Rest = {infixop Expression3}
709     *                  | Expression3 instanceof Type
710     *  infixop         = "||"
711     *                  | "&&"
712     *                  | "|"
713     *                  | "^"
714     *                  | "&"
715     *                  | "==" | "!="
716     *                  | "<" | ">" | "<=" | ">="
717     *                  | "<<" | ">>" | ">>>"
718     *                  | "+" | "-"
719     *                  | "*" | "/" | "%"
720     */
721    JCExpression term2Rest(JCExpression t, int minprec) {
722        List<JCExpression[]> savedOd = odStackSupply.elems;
723        JCExpression[] odStack = newOdStack();
724        List<Token[]> savedOp = opStackSupply.elems;
725        Token[] opStack = newOpStack();
726        // optimization, was odStack = new Tree[...]; opStack = new Tree[...];
727        int top = 0;
728        odStack[0] = t;
729        int startPos = S.pos();
730        Token topOp = ERROR;
731        while (prec(S.token()) >= minprec) {
732            opStack[top] = topOp;
733            top++;
734            topOp = S.token();
735            int pos = S.pos();
736            S.nextToken();
737            odStack[top] = topOp == INSTANCEOF ? type() : term3();
738            while (top > 0 && prec(topOp) >= prec(S.token())) {
739                odStack[top-1] = makeOp(pos, topOp, odStack[top-1],
740                                        odStack[top]);
741                top--;
742                topOp = opStack[top];
743            }
744        }
745        assert top == 0;
746        t = odStack[0];
747 
748        if (t.getTag() == JCTree.PLUS) {
749            StringBuffer buf = foldStrings(t);
750            if (buf != null) {
751                t = toP(F.at(startPos).Literal(TypeTags.CLASS, buf.toString()));
752            }
753        }
754 
755        odStackSupply.elems = savedOd; // optimization
756        opStackSupply.elems = savedOp; // optimization
757        return t;
758    }
759//where
760        /** Construct a binary or type test node.
761         */
762        private JCExpression makeOp(int pos,
763                                    Token topOp,
764                                    JCExpression od1,
765                                    JCExpression od2)
766        {
767            if (topOp == INSTANCEOF) {
768                return F.at(pos).TypeTest(od1, od2);
769            } else {
770                return F.at(pos).Binary(optag(topOp), od1, od2);
771            }
772        }
773        /** If tree is a concatenation of string literals, replace it
774         *  by a single literal representing the concatenated string.
775         */
776        protected StringBuffer foldStrings(JCTree tree) {
777            List<String> buf = List.nil();
778            while (true) {
779                if (tree.getTag() == JCTree.LITERAL) {
780                    JCLiteral lit = (JCLiteral) tree;
781                    if (lit.typetag == TypeTags.CLASS) {
782                        StringBuffer sbuf =
783                            new StringBuffer((String)lit.value);
784                        while (buf.nonEmpty()) {
785                            sbuf.append(buf.head);
786                            buf = buf.tail;
787                        }
788                        return sbuf;
789                    }
790                } else if (tree.getTag() == JCTree.PLUS) {
791                    JCBinary op = (JCBinary)tree;
792                    if (op.rhs.getTag() == JCTree.LITERAL) {
793                        JCLiteral lit = (JCLiteral) op.rhs;
794                        if (lit.typetag == TypeTags.CLASS) {
795                            buf = buf.prepend((String) lit.value);
796                            tree = op.lhs;
797                            continue;
798                        }
799                    }
800                }
801                return null;
802            }
803        }
804 
805        /** optimization: To save allocating a new operand/operator stack
806         *  for every binary operation, we use supplys.
807         */
808        ListBuffer<JCExpression[]> odStackSupply = new ListBuffer<JCExpression[]>();
809        ListBuffer<Token[]> opStackSupply = new ListBuffer<Token[]>();
810 
811        private JCExpression[] newOdStack() {
812            if (odStackSupply.elems == odStackSupply.last)
813                odStackSupply.append(new JCExpression[infixPrecedenceLevels + 1]);
814            JCExpression[] odStack = odStackSupply.elems.head;
815            odStackSupply.elems = odStackSupply.elems.tail;
816            return odStack;
817        }
818 
819        private Token[] newOpStack() {
820            if (opStackSupply.elems == opStackSupply.last)
821                opStackSupply.append(new Token[infixPrecedenceLevels + 1]);
822            Token[] opStack = opStackSupply.elems.head;
823            opStackSupply.elems = opStackSupply.elems.tail;
824            return opStack;
825        }
826 
827    /** Expression3    = PrefixOp Expression3
828     *                 | "(" Expr | TypeNoParams ")" Expression3
829     *                 | Primary {Selector} {PostfixOp}
830     *  Primary        = "(" Expression ")"
831     *                 | Literal
832     *                 | [TypeArguments] THIS [Arguments]
833     *                 | [TypeArguments] SUPER SuperSuffix
834     *                 | NEW [TypeArguments] Creator
835     *                 | Ident { "." Ident }
836     *                   [ "[" ( "]" BracketsOpt "." CLASS | Expression "]" )
837     *                   | Arguments
838     *                   | "." ( CLASS | THIS | [TypeArguments] SUPER Arguments | NEW [TypeArguments] InnerCreator )
839     *                   ]
840     *                 | BasicType BracketsOpt "." CLASS
841     *  PrefixOp       = "++" | "--" | "!" | "~" | "+" | "-"
842     *  PostfixOp      = "++" | "--"
843     *  Type3          = Ident { "." Ident } [TypeArguments] {TypeSelector} BracketsOpt
844     *                 | BasicType
845     *  TypeNoParams3  = Ident { "." Ident } BracketsOpt
846     *  Selector       = "." [TypeArguments] Ident [Arguments]
847     *                 | "." THIS
848     *                 | "." [TypeArguments] SUPER SuperSuffix
849     *                 | "." NEW [TypeArguments] InnerCreator
850     *                 | "[" Expression "]"
851     *  TypeSelector   = "." Ident [TypeArguments]
852     *  SuperSuffix    = Arguments | "." Ident [Arguments]
853     */
854    protected JCExpression term3() {
855        int pos = S.pos();
856        JCExpression t;
857        List<JCExpression> typeArgs = typeArgumentsOpt(EXPR);
858        switch (S.token()) {
859        case QUES:
860            if ((mode & TYPE) != 0 && (mode & (TYPEARG|NOPARAMS)) == TYPEARG) {
861                mode = TYPE;
862                return typeArgument();
863            } else
864                return illegal();
865        case PLUSPLUS: case SUBSUB: case BANG: case TILDE: case PLUS: case SUB:
866            if (typeArgs == null && (mode & EXPR) != 0) {
867                Token token = S.token();
868                S.nextToken();
869                mode = EXPR;
870                if (token == SUB &&
871                    (S.token() == INTLITERAL || S.token() == LONGLITERAL) &&
872                    S.radix() == 10) {
873                    mode = EXPR;
874                    t = literal(names.hyphen);
875                } else {
876                    t = term3();
877                    return F.at(pos).Unary(unoptag(token), t);
878                }
879            } else return illegal();
880            break;
881        case LPAREN:
882            if (typeArgs == null && (mode & EXPR) != 0) {
883                S.nextToken();
884                mode = EXPR | TYPE | NOPARAMS;
885                t = term3();
886                if ((mode & TYPE) != 0 && S.token() == LT) {
887                    // Could be a cast to a parameterized type
888                    int op = JCTree.LT;
889                    int pos1 = S.pos();
890                    S.nextToken();
891                    mode &= (EXPR | TYPE);
892                    mode |= TYPEARG;
893                    JCExpression t1 = term3();
894                    if ((mode & TYPE) != 0 &&
895                        (S.token() == COMMA || S.token() == GT)) {
896                        mode = TYPE;
897                        ListBuffer<JCExpression> args = new ListBuffer<JCExpression>();
898                        args.append(t1);
899                        while (S.token() == COMMA) {
900                            S.nextToken();
901                            args.append(typeArgument());
902                        }
903                        accept(GT);
904                        t = F.at(pos1).TypeApply(t, args.toList());
905                        checkGenerics();
906                        t = bracketsOpt(toP(t));
907                    } else if ((mode & EXPR) != 0) {
908                        mode = EXPR;
909                        t = F.at(pos1).Binary(op, t, term2Rest(t1, TreeInfo.shiftPrec));
910                        t = termRest(term1Rest(term2Rest(t, TreeInfo.orPrec)));
911                    } else {
912                        accept(GT);
913                    }
914                } else {
915                    t = termRest(term1Rest(term2Rest(t, TreeInfo.orPrec)));
916                }
917                accept(RPAREN);
918                lastmode = mode;
919                mode = EXPR;
920                if ((lastmode & EXPR) == 0) {
921                    JCExpression t1 = term3();
922                    return F.at(pos).TypeCast(t, t1);
923                } else if ((lastmode & TYPE) != 0) {
924                    switch (S.token()) {
925                    /*case PLUSPLUS: case SUBSUB: */
926                    case BANG: case TILDE:
927                    case LPAREN: case THIS: case SUPER:
928                    case INTLITERAL: case LONGLITERAL: case FLOATLITERAL:
929                    case DOUBLELITERAL: case CHARLITERAL: case STRINGLITERAL:
930                    case TRUE: case FALSE: case NULL:
931                    case NEW: case IDENTIFIER: case ASSERT: case ENUM:
932                    case BYTE: case SHORT: case CHAR: case INT:
933                    case LONG: case FLOAT: case DOUBLE: case BOOLEAN: case VOID:
934                        JCExpression t1 = term3();
935                        return F.at(pos).TypeCast(t, t1);
936                    }
937                }
938            } else return illegal();
939            t = toP(F.at(pos).Parens(t));
940            break;
941        case THIS:
942            if ((mode & EXPR) != 0) {
943                mode = EXPR;
944                t = to(F.at(pos).Ident(names._this));
945                S.nextToken();
946                if (typeArgs == null)
947                    t = argumentsOpt(null, t);
948                else
949                    t = arguments(typeArgs, t);
950                typeArgs = null;
951            } else return illegal();
952            break;
953        case SUPER:
954            if ((mode & EXPR) != 0) {
955                mode = EXPR;
956                t = to(superSuffix(typeArgs, F.at(pos).Ident(names._super)));
957                typeArgs = null;
958            } else return illegal();
959            break;
960        case INTLITERAL: case LONGLITERAL: case FLOATLITERAL: case DOUBLELITERAL:
961        case CHARLITERAL: case STRINGLITERAL:
962        case TRUE: case FALSE: case NULL:
963            if (typeArgs == null && (mode & EXPR) != 0) {
964                mode = EXPR;
965                t = literal(names.empty);
966            } else return illegal();
967            break;
968        case NEW:
969            if (typeArgs != null) return illegal();
970            if ((mode & EXPR) != 0) {
971                mode = EXPR;
972                S.nextToken();
973                if (S.token() == LT) typeArgs = typeArguments();
974                t = creator(pos, typeArgs);
975                typeArgs = null;
976            } else return illegal();
977            break;
978        case IDENTIFIER: case ASSERT: case ENUM:
979            if (typeArgs != null) return illegal();
980            t = toP(F.at(S.pos()).Ident(ident()));
981            loop: while (true) {
982                pos = S.pos();
983                switch (S.token()) {
984                case LBRACKET:
985                    S.nextToken();
986                    if (S.token() == RBRACKET) {
987                        S.nextToken();
988                        t = bracketsOpt(t);
989                        t = toP(F.at(pos).TypeArray(t));
990                        t = bracketsSuffix(t);
991                    } else {
992                        if ((mode & EXPR) != 0) {
993                            mode = EXPR;
994                            JCExpression t1 = term();
995                            t = to(F.at(pos).Indexed(t, t1));
996                        }
997                        accept(RBRACKET);
998                    }
999                    break loop;
1000                case LPAREN:
1001                    if ((mode & EXPR) != 0) {
1002                        mode = EXPR;
1003                        t = arguments(typeArgs, t);
1004                        typeArgs = null;
1005                    }
1006                    break loop;
1007                case DOT:
1008                    S.nextToken();
1009                    typeArgs = typeArgumentsOpt(EXPR);
1010                    if ((mode & EXPR) != 0) {
1011                        switch (S.token()) {
1012                        case CLASS:
1013                            if (typeArgs != null) return illegal();
1014                            mode = EXPR;
1015                            t = to(F.at(pos).Select(t, names._class));
1016                            S.nextToken();
1017                            break loop;
1018                        case THIS:
1019                            if (typeArgs != null) return illegal();
1020                            mode = EXPR;
1021                            t = to(F.at(pos).Select(t, names._this));
1022                            S.nextToken();
1023                            break loop;
1024                        case SUPER:
1025                            mode = EXPR;
1026                            t = to(F.at(pos).Select(t, names._super));
1027                            t = superSuffix(typeArgs, t);
1028                            typeArgs = null;
1029                            break loop;
1030                        case NEW:
1031                            if (typeArgs != null) return illegal();
1032                            mode = EXPR;
1033                            int pos1 = S.pos();
1034                            S.nextToken();
1035                            if (S.token() == LT) typeArgs = typeArguments();
1036                            t = innerCreator(pos1, typeArgs, t);
1037                            typeArgs = null;
1038                            break loop;
1039                        }
1040                    }
1041                    // typeArgs saved for next loop iteration.
1042                    t = toP(F.at(pos).Select(t, ident()));
1043                    break;
1044                default:
1045                    break loop;
1046                }
1047            }
1048            if (typeArgs != null) illegal();
1049            t = typeArgumentsOpt(t);
1050            break;
1051        case BYTE: case SHORT: case CHAR: case INT: case LONG: case FLOAT:
1052        case DOUBLE: case BOOLEAN:
1053            if (typeArgs != null) illegal();
1054            t = bracketsSuffix(bracketsOpt(basicType()));
1055            break;
1056        case VOID:
1057            if (typeArgs != null) illegal();
1058            if ((mode & EXPR) != 0) {
1059                S.nextToken();
1060                if (S.token() == DOT) {
1061                    JCPrimitiveTypeTree ti = toP(F.at(pos).TypeIdent(TypeTags.VOID));
1062                    t = bracketsSuffix(ti);
1063                } else {
1064                    return illegal(pos);
1065                }
1066            } else {
1067                return illegal();
1068            }
1069            break;
1070        default:
1071            return illegal();
1072        }
1073        if (typeArgs != null) illegal();
1074        while (true) {
1075            int pos1 = S.pos();
1076            if (S.token() == LBRACKET) {
1077                S.nextToken();
1078                if ((mode & TYPE) != 0) {
1079                    int oldmode = mode;
1080                    mode = TYPE;
1081                    if (S.token() == RBRACKET) {
1082                        S.nextToken();
1083                        t = bracketsOpt(t);
1084                        t = toP(F.at(pos1).TypeArray(t));
1085                        return t;
1086                    }
1087                    mode = oldmode;
1088                }
1089                if ((mode & EXPR) != 0) {
1090                    mode = EXPR;
1091                    JCExpression t1 = term();
1092                    t = to(F.at(pos1).Indexed(t, t1));
1093                }
1094                accept(RBRACKET);
1095            } else if (S.token() == DOT) {
1096                S.nextToken();
1097                typeArgs = typeArgumentsOpt(EXPR);
1098                if (S.token() == SUPER && (mode & EXPR) != 0) {
1099                    mode = EXPR;
1100                    t = to(F.at(pos1).Select(t, names._super));
1101                    S.nextToken();
1102                    t = arguments(typeArgs, t);
1103                    typeArgs = null;
1104                } else if (S.token() == NEW && (mode & EXPR) != 0) {
1105                    if (typeArgs != null) return illegal();
1106                    mode = EXPR;
1107                    int pos2 = S.pos();
1108                    S.nextToken();
1109                    if (S.token() == LT) typeArgs = typeArguments();
1110                    t = innerCreator(pos2, typeArgs, t);
1111                    typeArgs = null;
1112                } else {
1113                    t = toP(F.at(pos1).Select(t, ident()));
1114                    t = argumentsOpt(typeArgs, typeArgumentsOpt(t));
1115                    typeArgs = null;
1116                }
1117            } else {
1118                break;
1119            }
1120        }
1121        while ((S.token() == PLUSPLUS || S.token() == SUBSUB) && (mode & EXPR) != 0) {
1122            mode = EXPR;
1123            t = to(F.at(S.pos()).Unary(
1124                  S.token() == PLUSPLUS ? JCTree.POSTINC : JCTree.POSTDEC, t));
1125            S.nextToken();
1126        }
1127        return toP(t);
1128    }
1129 
1130    /** SuperSuffix = Arguments | "." [TypeArguments] Ident [Arguments]
1131     */
1132    JCExpression superSuffix(List<JCExpression> typeArgs, JCExpression t) {
1133        S.nextToken();
1134        if (S.token() == LPAREN || typeArgs != null) {
1135            t = arguments(typeArgs, t);
1136        } else {
1137            int pos = S.pos();
1138            accept(DOT);
1139            typeArgs = (S.token() == LT) ? typeArguments() : null;
1140            t = toP(F.at(pos).Select(t, ident()));
1141            t = argumentsOpt(typeArgs, t);
1142        }
1143        return t;
1144    }
1145 
1146    /** BasicType = BYTE | SHORT | CHAR | INT | LONG | FLOAT | DOUBLE | BOOLEAN
1147     */
1148    JCPrimitiveTypeTree basicType() {
1149        JCPrimitiveTypeTree t = to(F.at(S.pos()).TypeIdent(typetag(S.token())));
1150        S.nextToken();
1151        return t;
1152    }
1153 
1154    /** ArgumentsOpt = [ Arguments ]
1155     */
1156    JCExpression argumentsOpt(List<JCExpression> typeArgs, JCExpression t) {
1157        if ((mode & EXPR) != 0 && S.token() == LPAREN || typeArgs != null) {
1158            mode = EXPR;
1159            return arguments(typeArgs, t);
1160        } else {
1161            return t;
1162        }
1163    }
1164 
1165    /** Arguments = "(" [Expression { COMMA Expression }] ")"
1166     */
1167    List<JCExpression> arguments() {
1168        ListBuffer<JCExpression> args = lb();
1169        if (S.token() == LPAREN) {
1170            S.nextToken();
1171            if (S.token() != RPAREN) {
1172                args.append(expression());
1173                while (S.token() == COMMA) {
1174                    S.nextToken();
1175                    args.append(expression());
1176                }
1177            }
1178            accept(RPAREN);
1179        } else {
1180            syntaxError(S.pos(), "expected", keywords.token2string(LPAREN));
1181        }
1182        return args.toList();
1183    }
1184 
1185    JCMethodInvocation arguments(List<JCExpression> typeArgs, JCExpression t) {
1186        int pos = S.pos();
1187        List<JCExpression> args = arguments();
1188        return toP(F.at(pos).Apply(typeArgs, t, args));
1189    }
1190 
1191    /**  TypeArgumentsOpt = [ TypeArguments ]
1192     */
1193    JCExpression typeArgumentsOpt(JCExpression t) {
1194        if (S.token() == LT &&
1195            (mode & TYPE) != 0 &&
1196            (mode & NOPARAMS) == 0) {
1197            mode = TYPE;
1198            checkGenerics();
1199            return typeArguments(t);
1200        } else {
1201            return t;
1202        }
1203    }
1204    List<JCExpression> typeArgumentsOpt() {
1205        return typeArgumentsOpt(TYPE);
1206    }
1207 
1208    List<JCExpression> typeArgumentsOpt(int useMode) {
1209        if (S.token() == LT) {
1210            checkGenerics();
1211            if ((mode & useMode) == 0 ||
1212                (mode & NOPARAMS) != 0) {
1213                illegal();
1214            }
1215            mode = useMode;
1216            return typeArguments();
1217        }
1218        return null;
1219    }
1220 
1221    /**  TypeArguments  = "<" TypeArgument {"," TypeArgument} ">"
1222     */
1223    List<JCExpression> typeArguments() {
1224        ListBuffer<JCExpression> args = lb();
1225        if (S.token() == LT) {
1226            S.nextToken();
1227            args.append(((mode & EXPR) == 0) ? typeArgument() : type());
1228            while (S.token() == COMMA) {
1229                S.nextToken();
1230                args.append(((mode & EXPR) == 0) ? typeArgument() : type());
1231            }
1232            switch (S.token()) {
1233            case GTGTGTEQ:
1234                S.token(GTGTEQ);
1235                break;
1236            case GTGTEQ:
1237                S.token(GTEQ);
1238                break;
1239            case GTEQ:
1240                S.token(EQ);
1241                break;
1242            case GTGTGT:
1243                S.token(GTGT);
1244                break;
1245            case GTGT:
1246                S.token(GT);
1247                break;
1248            default:
1249                accept(GT);
1250                break;
1251            }
1252        } else {
1253            syntaxError(S.pos(), "expected", keywords.token2string(LT));
1254        }
1255        return args.toList();
1256    }
1257 
1258    /** TypeArgument = Type
1259     *               | "?"
1260     *               | "?" EXTENDS Type {"&" Type}
1261     *               | "?" SUPER Type
1262     */
1263    JCExpression typeArgument() {
1264        if (S.token() != QUES) return type();
1265        int pos = S.pos();
1266        S.nextToken();
1267        if (S.token() == EXTENDS) {
1268            TypeBoundKind t = to(F.at(S.pos()).TypeBoundKind(BoundKind.EXTENDS));
1269            S.nextToken();
1270            return F.at(pos).Wildcard(t, type());
1271        } else if (S.token() == SUPER) {
1272            TypeBoundKind t = to(F.at(S.pos()).TypeBoundKind(BoundKind.SUPER));
1273            S.nextToken();
1274            return F.at(pos).Wildcard(t, type());
1275        } else if (S.token() == IDENTIFIER) {
1276            //error recovery
1277            reportSyntaxError(S.prevEndPos(), "expected3",
1278                    keywords.token2string(GT),
1279                    keywords.token2string(EXTENDS),
1280                    keywords.token2string(SUPER));
1281            TypeBoundKind t = F.at(Position.NOPOS).TypeBoundKind(BoundKind.UNBOUND);
1282            JCExpression wc = toP(F.at(pos).Wildcard(t, null));
1283            JCIdent id = toP(F.at(S.pos()).Ident(ident()));
1284            return F.at(pos).Erroneous(List.<JCTree>of(wc, id));
1285        } else {
1286            TypeBoundKind t = F.at(Position.NOPOS).TypeBoundKind(BoundKind.UNBOUND);
1287            return toP(F.at(pos).Wildcard(t, null));
1288        }
1289    }
1290 
1291    JCTypeApply typeArguments(JCExpression t) {
1292        int pos = S.pos();
1293        List<JCExpression> args = typeArguments();
1294        return toP(F.at(pos).TypeApply(t, args));
1295    }
1296 
1297    /** BracketsOpt = {"[" "]"}
1298     */
1299    private JCExpression bracketsOpt(JCExpression t) {
1300        if (S.token() == LBRACKET) {
1301            int pos = S.pos();
1302            S.nextToken();
1303            t = bracketsOptCont(t, pos);
1304            F.at(pos);
1305        }
1306        return t;
1307    }
1308 
1309    private JCArrayTypeTree bracketsOptCont(JCExpression t, int pos) {
1310        accept(RBRACKET);
1311        t = bracketsOpt(t);
1312        return toP(F.at(pos).TypeArray(t));
1313    }
1314 
1315    /** BracketsSuffixExpr = "." CLASS
1316     *  BracketsSuffixType =
1317     */
1318    JCExpression bracketsSuffix(JCExpression t) {
1319        if ((mode & EXPR) != 0 && S.token() == DOT) {
1320            mode = EXPR;
1321            int pos = S.pos();
1322            S.nextToken();
1323            accept(CLASS);
1324            if (S.pos() == errorEndPos) {
1325                // error recovery
1326                Name name = null;
1327                if (S.token() == IDENTIFIER) {
1328                    name = S.name();
1329                    S.nextToken();
1330                } else {
1331                    name = names.error;
1332                }
1333                t = F.at(pos).Erroneous(List.<JCTree>of(toP(F.at(pos).Select(t, name))));
1334            } else {
1335                t = toP(F.at(pos).Select(t, names._class));
1336            }
1337        } else if ((mode & TYPE) != 0) {
1338            mode = TYPE;
1339        } else {
1340            syntaxError(S.pos(), "dot.class.expected");
1341        }
1342        return t;
1343    }
1344 
1345    /** Creator = Qualident [TypeArguments] ( ArrayCreatorRest | ClassCreatorRest )
1346     */
1347    JCExpression creator(int newpos, List<JCExpression> typeArgs) {
1348        switch (S.token()) {
1349        case BYTE: case SHORT: case CHAR: case INT: case LONG: case FLOAT:
1350        case DOUBLE: case BOOLEAN:
1351            if (typeArgs == null)
1352                return arrayCreatorRest(newpos, basicType());
1353            break;
1354        default:
1355        }
1356        JCExpression t = qualident();
1357        int oldmode = mode;
1358        mode = TYPE;
1359        if (S.token() == LT) {
1360            checkGenerics();
1361            t = typeArguments(t);
1362        }
1363        while (S.token() == DOT) {
1364            int pos = S.pos();
1365            S.nextToken();
1366            t = toP(F.at(pos).Select(t, ident()));
1367            if (S.token() == LT) {
1368                checkGenerics();
1369                t = typeArguments(t);
1370            }
1371        }
1372        mode = oldmode;
1373        if (S.token() == LBRACKET) {
1374            JCExpression e = arrayCreatorRest(newpos, t);
1375            if (typeArgs != null) {
1376                int pos = newpos;
1377                if (!typeArgs.isEmpty() && typeArgs.head.pos != Position.NOPOS) {
1378                    // note: this should always happen but we should
1379                    // not rely on this as the parser is continuously
1380                    // modified to improve error recovery.
1381                    pos = typeArgs.head.pos;
1382                }
1383                setErrorEndPos(S.prevEndPos());
1384                reportSyntaxError(pos, "cannot.create.array.with.type.arguments");
1385                return toP(F.at(newpos).Erroneous(typeArgs.prepend(e)));
1386            }
1387            return e;
1388        } else if (S.token() == LPAREN) {
1389            return classCreatorRest(newpos, null, typeArgs, t);
1390        } else {
1391            reportSyntaxError(S.pos(), "expected2",
1392                               keywords.token2string(LPAREN),
1393                               keywords.token2string(LBRACKET));
1394            t = toP(F.at(newpos).NewClass(null, typeArgs, t, List.<JCExpression>nil(), null));
1395            return toP(F.at(newpos).Erroneous(List.<JCTree>of(t)));
1396        }
1397    }
1398 
1399    /** InnerCreator = Ident [TypeArguments] ClassCreatorRest
1400     */
1401    JCExpression innerCreator(int newpos, List<JCExpression> typeArgs, JCExpression encl) {
1402        JCExpression t = toP(F.at(S.pos()).Ident(ident()));
1403        if (S.token() == LT) {
1404            checkGenerics();
1405            t = typeArguments(t);
1406        }
1407        return classCreatorRest(newpos, encl, typeArgs, t);
1408    }
1409 
1410    /** ArrayCreatorRest = "[" ( "]" BracketsOpt ArrayInitializer
1411     *                         | Expression "]" {"[" Expression "]"} BracketsOpt )
1412     */
1413    JCExpression arrayCreatorRest(int newpos, JCExpression elemtype) {
1414        accept(LBRACKET);
1415        if (S.token() == RBRACKET) {
1416            accept(RBRACKET);
1417            elemtype = bracketsOpt(elemtype);
1418            if (S.token() == LBRACE) {
1419                return arrayInitializer(newpos, elemtype);
1420            } else {
1421                return syntaxError(S.pos(), "array.dimension.missing");
1422            }
1423        } else {
1424            ListBuffer<JCExpression> dims = new ListBuffer<JCExpression>();
1425            dims.append(expression());
1426            accept(RBRACKET);
1427            while (S.token() == LBRACKET) {
1428                int pos = S.pos();
1429                S.nextToken();
1430                if (S.token() == RBRACKET) {
1431                    elemtype = bracketsOptCont(elemtype, pos);
1432                } else {
1433                    dims.append(expression());
1434                    accept(RBRACKET);
1435                }
1436            }
1437            return toP(F.at(newpos).NewArray(elemtype, dims.toList(), null));
1438        }
1439    }
1440 
1441    /** ClassCreatorRest = Arguments [ClassBody]
1442     */
1443    JCExpression classCreatorRest(int newpos,
1444                                  JCExpression encl,
1445                                  List<JCExpression> typeArgs,
1446                                  JCExpression t)
1447    {
1448        List<JCExpression> args = arguments();
1449        JCClassDecl body = null;
1450        if (S.token() == LBRACE) {
1451            int pos = S.pos();
1452            List<JCTree> defs = classOrInterfaceBody(names.empty, false);
1453            JCModifiers mods = F.at(Position.NOPOS).Modifiers(0);
1454            body = toP(F.at(pos).AnonymousClassDef(mods, defs));
1455        }
1456        return toP(F.at(newpos).NewClass(encl, typeArgs, t, args, body));
1457    }
1458 
1459    /** ArrayInitializer = "{" [VariableInitializer {"," VariableInitializer}] [","] "}"
1460     */
1461    JCExpression arrayInitializer(int newpos, JCExpression t) {
1462        accept(LBRACE);
1463        ListBuffer<JCExpression> elems = new ListBuffer<JCExpression>();
1464        if (S.token() == COMMA) {
1465            S.nextToken();
1466        } else if (S.token() != RBRACE) {
1467            elems.append(variableInitializer());
1468            while (S.token() == COMMA) {
1469                S.nextToken();
1470                if (S.token() == RBRACE) break;
1471                elems.append(variableInitializer());
1472            }
1473        }
1474        accept(RBRACE);
1475        return toP(F.at(newpos).NewArray(t, List.<JCExpression>nil(), elems.toList()));
1476    }
1477 
1478    /** VariableInitializer = ArrayInitializer | Expression
1479     */
1480    public JCExpression variableInitializer() {
1481        return S.token() == LBRACE ? arrayInitializer(S.pos(), null) : expression();
1482    }
1483 
1484    /** ParExpression = "(" Expression ")"
1485     */
1486    JCExpression parExpression() {
1487        accept(LPAREN);
1488        JCExpression t = expression();
1489        accept(RPAREN);
1490        return t;
1491    }
1492 
1493    /** Block = "{" BlockStatements "}"
1494     */
1495    JCBlock block(int pos, long flags) {
1496        accept(LBRACE);
1497        List<JCStatement> stats = blockStatements();
1498        JCBlock t = F.at(pos).Block(flags, stats);
1499        while (S.token() == CASE || S.token() == DEFAULT) {
1500            syntaxError("orphaned", keywords.token2string(S.token()));
1501            switchBlockStatementGroups();
1502        }
1503        // the Block node has a field "endpos" for first char of last token, which is
1504        // usually but not necessarily the last char of the last token.
1505        t.endpos = S.pos();
1506        accept(RBRACE);
1507        return toP(t);
1508    }
1509 
1510    public JCBlock block() {
1511        return block(S.pos(), 0);
1512    }
1513 
1514    /** BlockStatements = { BlockStatement }
1515     *  BlockStatement  = LocalVariableDeclarationStatement
1516     *                  | ClassOrInterfaceOrEnumDeclaration
1517     *                  | [Ident ":"] Statement
1518     *  LocalVariableDeclarationStatement
1519     *                  = { FINAL | '@' Annotation } Type VariableDeclarators ";"
1520     */
1521    @SuppressWarnings("fallthrough")
1522    List<JCStatement> blockStatements() {
1523//todo: skip to anchor on error(?)
1524        int lastErrPos = -1;
1525        ListBuffer<JCStatement> stats = new ListBuffer<JCStatement>();
1526        while (true) {
1527            int pos = S.pos();
1528            switch (S.token()) {
1529            case RBRACE: case CASE: case DEFAULT: case EOF:
1530                return stats.toList();
1531            case LBRACE: case IF: case FOR: case WHILE: case DO: case TRY:
1532            case SWITCH: case SYNCHRONIZED: case RETURN: case THROW: case BREAK:
1533            case CONTINUE: case SEMI: case ELSE: case FINALLY: case CATCH:
1534                stats.append(statement());
1535                break;
1536            case MONKEYS_AT:
1537            case FINAL: {
1538                String dc = S.docComment();
1539                JCModifiers mods = modifiersOpt();
1540                if (S.token() == INTERFACE ||
1541                    S.token() == CLASS ||
1542                    allowEnums && S.token() == ENUM) {
1543                    stats.append(classOrInterfaceOrEnumDeclaration(mods, dc));
1544                } else {
1545                    JCExpression t = type();
1546                    stats.appendList(variableDeclarators(mods, t,
1547                                                         new ListBuffer<JCStatement>()));
1548                    // A "LocalVariableDeclarationStatement" subsumes the terminating semicolon
1549                    storeEnd(stats.elems.last(), S.endPos());
1550                    accept(SEMI);
1551                }
1552                break;
1553            }
1554            case ABSTRACT: case STRICTFP: {
1555                String dc = S.docComment();
1556                JCModifiers mods = modifiersOpt();
1557                stats.append(classOrInterfaceOrEnumDeclaration(mods, dc));
1558                break;
1559            }
1560            case INTERFACE:
1561            case CLASS:
1562                stats.append(classOrInterfaceOrEnumDeclaration(modifiersOpt(),
1563                                                               S.docComment()));
1564                break;
1565            case ENUM:
1566            case ASSERT:
1567                if (allowEnums && S.token() == ENUM) {
1568                    log.error(S.pos(), "local.enum");
1569                    stats.
1570                        append(classOrInterfaceOrEnumDeclaration(modifiersOpt(),
1571                                                                 S.docComment()));
1572                    break;
1573                } else if (allowAsserts && S.token() == ASSERT) {
1574                    stats.append(statement());
1575                    break;
1576                }
1577                /* fall through to default */
1578            default:
1579                Name name = S.name();
1580                JCExpression t = term(EXPR | TYPE);
1581                if (S.token() == COLON && t.getTag() == JCTree.IDENT) {
1582                    S.nextToken();
1583                    JCStatement stat = statement();
1584                    stats.append(F.at(pos).Labelled(name, stat));
1585                } else if ((lastmode & TYPE) != 0 &&
1586                           (S.token() == IDENTIFIER ||
1587                            S.token() == ASSERT ||
1588                            S.token() == ENUM)) {
1589                    pos = S.pos();
1590                    JCModifiers mods = F.at(Position.NOPOS).Modifiers(0);
1591                    F.at(pos);
1592                    stats.appendList(variableDeclarators(mods, t,
1593                                                         new ListBuffer<JCStatement>()));
1594                    // A "LocalVariableDeclarationStatement" subsumes the terminating semicolon
1595                    storeEnd(stats.elems.last(), S.endPos());
1596                    accept(SEMI);
1597                } else {
1598                    // This Exec is an "ExpressionStatement"; it subsumes the terminating semicolon
1599                    stats.append(to(F.at(pos).Exec(checkExprStat(t))));
1600                    accept(SEMI);
1601                }
1602            }
1603 
1604            // error recovery
1605            if (S.pos() == lastErrPos)
1606                return stats.toList();
1607            if (S.pos() <= errorEndPos) {
1608                skip(false, true, true, true);
1609                lastErrPos = S.pos();
1610            }
1611 
1612            // ensure no dangling /** @deprecated */ active
1613            S.resetDeprecatedFlag();
1614        }
1615    }
1616 
1617    /** Statement =
1618     *       Block
1619     *     | IF ParExpression Statement [ELSE Statement]
1620     *     | FOR "(" ForInitOpt ";" [Expression] ";" ForUpdateOpt ")" Statement
1621     *     | FOR "(" FormalParameter : Expression ")" Statement
1622     *     | WHILE ParExpression Statement
1623     *     | DO Statement WHILE ParExpression ";"
1624     *     | TRY Block ( Catches | [Catches] FinallyPart )
1625     *     | SWITCH ParExpression "{" SwitchBlockStatementGroups "}"
1626     *     | SYNCHRONIZED ParExpression Block
1627     *     | RETURN [Expression] ";"
1628     *     | THROW Expression ";"
1629     *     | BREAK [Ident] ";"
1630     *     | CONTINUE [Ident] ";"
1631     *     | ASSERT Expression [ ":" Expression ] ";"
1632     *     | ";"
1633     *     | ExpressionStatement
1634     *     | Ident ":" Statement
1635     */
1636    @SuppressWarnings("fallthrough")
1637    public JCStatement statement() {
1638        int pos = S.pos();
1639        switch (S.token()) {
1640        case LBRACE:
1641            return block();
1642        case IF: {
1643            S.nextToken();
1644            JCExpression cond = parExpression();
1645            JCStatement thenpart = statement();
1646            JCStatement elsepart = null;
1647            if (S.token() == ELSE) {
1648                S.nextToken();
1649                elsepart = statement();
1650            }
1651            return F.at(pos).If(cond, thenpart, elsepart);
1652        }
1653        case FOR: {
1654            S.nextToken();
1655            accept(LPAREN);
1656            List<JCStatement> inits = S.token() == SEMI ? List.<JCStatement>nil() : forInit();
1657            if (inits.length() == 1 &&
1658                inits.head.getTag() == JCTree.VARDEF &&
1659                ((JCVariableDecl) inits.head).init == null &&
1660                S.token() == COLON) {
1661                checkForeach();
1662                JCVariableDecl var = (JCVariableDecl)inits.head;
1663                accept(COLON);
1664                JCExpression expr = expression();
1665                accept(RPAREN);
1666                JCStatement body = statement();
1667                return F.at(pos).ForeachLoop(var, expr, body);
1668            } else {
1669                accept(SEMI);
1670                JCExpression cond = S.token() == SEMI ? null : expression();
1671                accept(SEMI);
1672                List<JCExpressionStatement> steps = S.token() == RPAREN ? List.<JCExpressionStatement>nil() : forUpdate();
1673                accept(RPAREN);
1674                JCStatement body = statement();
1675                return F.at(pos).ForLoop(inits, cond, steps, body);
1676            }
1677        }
1678        case WHILE: {
1679            S.nextToken();
1680            JCExpression cond = parExpression();
1681            JCStatement body = statement();
1682            return F.at(pos).WhileLoop(cond, body);
1683        }
1684        case DO: {
1685            S.nextToken();
1686            JCStatement body = statement();
1687            accept(WHILE);
1688            JCExpression cond = parExpression();
1689            JCDoWhileLoop t = to(F.at(pos).DoLoop(body, cond));
1690            accept(SEMI);
1691            return t;
1692        }
1693        case TRY: {
1694            S.nextToken();
1695            JCBlock body = block();
1696            ListBuffer<JCCatch> catchers = new ListBuffer<JCCatch>();
1697            JCBlock finalizer = null;
1698            if (S.token() == CATCH || S.token() == FINALLY) {
1699                while (S.token() == CATCH) catchers.append(catchClause());
1700                if (S.token() == FINALLY) {
1701                    S.nextToken();
1702                    finalizer = block();
1703                }
1704            } else {
1705                log.error(pos, "try.without.catch.or.finally");
1706            }
1707            return F.at(pos).Try(body, catchers.toList(), finalizer);
1708        }
1709        case SWITCH: {
1710            S.nextToken();
1711            JCExpression selector = parExpression();
1712            accept(LBRACE);
1713            List<JCCase> cases = switchBlockStatementGroups();
1714            JCSwitch t = to(F.at(pos).Switch(selector, cases));
1715            accept(RBRACE);
1716            return t;
1717        }
1718        case SYNCHRONIZED: {
1719            S.nextToken();
1720            JCExpression lock = parExpression();
1721            JCBlock body = block();
1722            return F.at(pos).Synchronized(lock, body);
1723        }
1724        case RETURN: {
1725            S.nextToken();
1726            JCExpression result = S.token() == SEMI ? null : expression();
1727            JCReturn t = to(F.at(pos).Return(result));
1728            accept(SEMI);
1729            return t;
1730        }
1731        case THROW: {
1732            S.nextToken();
1733            JCExpression exc = expression();
1734            JCThrow t = to(F.at(pos).Throw(exc));
1735            accept(SEMI);
1736            return t;
1737        }
1738        case BREAK: {
1739            S.nextToken();
1740            Name label = (S.token() == IDENTIFIER || S.token() == ASSERT || S.token() == ENUM) ? ident() : null;
1741            JCBreak t = to(F.at(pos).Break(label));
1742            accept(SEMI);
1743            return t;
1744        }
1745        case CONTINUE: {
1746            S.nextToken();
1747            Name label = (S.token() == IDENTIFIER || S.token() == ASSERT || S.token() == ENUM) ? ident() : null;
1748            JCContinue t =  to(F.at(pos).Continue(label));
1749            accept(SEMI);
1750            return t;
1751        }
1752        case SEMI:
1753            S.nextToken();
1754            return toP(F.at(pos).Skip());
1755        case ELSE:
1756            return toP(F.Exec(syntaxError("else.without.if")));
1757        case FINALLY:
1758            return toP(F.Exec(syntaxError("finally.without.try")));
1759        case CATCH:
1760            return toP(F.Exec(syntaxError("catch.without.try")));
1761        case ASSERT: {
1762            if (allowAsserts && S.token() == ASSERT) {
1763                S.nextToken();
1764                JCExpression assertion = expression();
1765                JCExpression message = null;
1766                if (S.token() == COLON) {
1767                    S.nextToken();
1768                    message = expression();
1769                }
1770                JCAssert t = to(F.at(pos).Assert(assertion, message));
1771                accept(SEMI);
1772                return t;
1773            }
1774            /* else fall through to default case */
1775        }
1776        case ENUM:
1777        default:
1778            Name name = S.name();
1779            JCExpression expr = expression();
1780            if (S.token() == COLON && expr.getTag() == JCTree.IDENT) {
1781                S.nextToken();
1782                JCStatement stat = statement();
1783                return F.at(pos).Labelled(name, stat);
1784            } else {
1785                // This Exec is an "ExpressionStatement"; it subsumes the terminating semicolon
1786                JCExpressionStatement stat = to(F.at(pos).Exec(checkExprStat(expr)));
1787                accept(SEMI);
1788                return stat;
1789            }
1790        }
1791    }
1792 
1793    /** CatchClause     = CATCH "(" FormalParameter ")" Block
1794     */
1795    JCCatch catchClause() {
1796        int pos = S.pos();
1797        accept(CATCH);
1798        accept(LPAREN);
1799        JCVariableDecl formal =
1800            variableDeclaratorId(optFinal(Flags.PARAMETER),
1801                                 qualident());
1802        accept(RPAREN);
1803        JCBlock body = block();
1804        return F.at(pos).Catch(formal, body);
1805    }
1806 
1807    /** SwitchBlockStatementGroups = { SwitchBlockStatementGroup }
1808     *  SwitchBlockStatementGroup = SwitchLabel BlockStatements
1809     *  SwitchLabel = CASE ConstantExpression ":" | DEFAULT ":"
1810     */
1811    List<JCCase> switchBlockStatementGroups() {
1812        ListBuffer<JCCase> cases = new ListBuffer<JCCase>();
1813        while (true) {
1814            int pos = S.pos();
1815            switch (S.token()) {
1816            case CASE: {
1817                S.nextToken();
1818                JCExpression pat = expression();
1819                accept(COLON);
1820                List<JCStatement> stats = blockStatements();
1821                JCCase c = F.at(pos).Case(pat, stats);
1822                if (stats.isEmpty())
1823                    storeEnd(c, S.prevEndPos());
1824                cases.append(c);
1825                break;
1826            }
1827            case DEFAULT: {
1828                S.nextToken();
1829                accept(COLON);
1830                List<JCStatement> stats = blockStatements();
1831                JCCase c = F.at(pos).Case(null, stats);
1832                if (stats.isEmpty())
1833                    storeEnd(c, S.prevEndPos());
1834                cases.append(c);
1835                break;
1836            }
1837            case RBRACE: case EOF:
1838                return cases.toList();
1839            default:
1840                S.nextToken(); // to ensure progress
1841                syntaxError(pos, "expected3",
1842                    keywords.token2string(CASE),
1843                    keywords.token2string(DEFAULT),
1844                    keywords.token2string(RBRACE));
1845            }
1846        }
1847    }
1848 
1849    /** MoreStatementExpressions = { COMMA StatementExpression }
1850     */
1851    <T extends ListBuffer<? super JCExpressionStatement>> T moreStatementExpressions(int pos,
1852                                                                    JCExpression first,
1853                                                                    T stats) {
1854        // This Exec is a "StatementExpression"; it subsumes no terminating token
1855        stats.append(toP(F.at(pos).Exec(checkExprStat(first))));
1856        while (S.token() == COMMA) {
1857            S.nextToken();
1858            pos = S.pos();
1859            JCExpression t = expression();
1860            // This Exec is a "StatementExpression"; it subsumes no terminating token
1861            stats.append(toP(F.at(pos).Exec(checkExprStat(t))));
1862        }
1863        return stats;
1864    }
1865 
1866    /** ForInit = StatementExpression MoreStatementExpressions
1867     *           |  { FINAL | '@' Annotation } Type VariableDeclarators
1868     */
1869    List<JCStatement> forInit() {
1870        ListBuffer<JCStatement> stats = lb();
1871        int pos = S.pos();
1872        if (S.token() == FINAL || S.token() == MONKEYS_AT) {
1873            return variableDeclarators(optFinal(0), type(), stats).toList();
1874        } else {
1875            JCExpression t = term(EXPR | TYPE);
1876            if ((lastmode & TYPE) != 0 &&
1877                (S.token() == IDENTIFIER || S.token() == ASSERT || S.token() == ENUM))
1878                return variableDeclarators(modifiersOpt(), t, stats).toList();
1879            else
1880                return moreStatementExpressions(pos, t, stats).toList();
1881        }
1882    }
1883 
1884    /** ForUpdate = StatementExpression MoreStatementExpressions
1885     */
1886    List<JCExpressionStatement> forUpdate() {
1887        return moreStatementExpressions(S.pos(),
1888                                        expression(),
1889                                        new ListBuffer<JCExpressionStatement>()).toList();
1890    }
1891 
1892    /** AnnotationsOpt = { '@' Annotation }
1893     */
1894    List<JCAnnotation> annotationsOpt() {
1895        if (S.token() != MONKEYS_AT) return List.nil(); // optimization
1896        ListBuffer<JCAnnotation> buf = new ListBuffer<JCAnnotation>();
1897        while (S.token() == MONKEYS_AT) {
1898            int pos = S.pos();
1899            S.nextToken();
1900            buf.append(annotation(pos));
1901        }
1902        return buf.toList();
1903    }
1904 
1905    /** ModifiersOpt = { Modifier }
1906     *  Modifier = PUBLIC | PROTECTED | PRIVATE | STATIC | ABSTRACT | FINAL
1907     *           | NATIVE | SYNCHRONIZED | TRANSIENT | VOLATILE | "@"
1908     *           | "@" Annotation
1909     */
1910    JCModifiers modifiersOpt() {
1911        return modifiersOpt(null);
1912    }
1913    JCModifiers modifiersOpt(JCModifiers partial) {
1914        long flags = (partial == null) ? 0 : partial.flags;
1915        if (S.deprecatedFlag()) {
1916            flags |= Flags.DEPRECATED;
1917            S.resetDeprecatedFlag();
1918        }
1919        ListBuffer<JCAnnotation> annotations = new ListBuffer<JCAnnotation>();
1920        if (partial != null) annotations.appendList(partial.annotations);
1921        int pos = S.pos();
1922        int lastPos = Position.NOPOS;
1923    loop:
1924        while (true) {
1925            long flag;
1926            switch (S.token()) {
1927            case PRIVATE     : flag = Flags.PRIVATE; break;
1928            case PROTECTED   : flag = Flags.PROTECTED; break;
1929            case PUBLIC      : flag = Flags.PUBLIC; break;
1930            case STATIC      : flag = Flags.STATIC; break;
1931            case TRANSIENT   : flag = Flags.TRANSIENT; break;
1932            case FINAL       : flag = Flags.FINAL; break;
1933            case ABSTRACT    : flag = Flags.ABSTRACT; break;
1934            case NATIVE      : flag = Flags.NATIVE; break;
1935            case VOLATILE    : flag = Flags.VOLATILE; break;
1936            case SYNCHRONIZED: flag = Flags.SYNCHRONIZED; break;
1937            case STRICTFP    : flag = Flags.STRICTFP; break;
1938            case MONKEYS_AT  : flag = Flags.ANNOTATION; break;
1939            default: break loop;
1940            }
1941            if ((flags & flag) != 0) log.error(S.pos(), "repeated.modifier");
1942            lastPos = S.pos();
1943            S.nextToken();
1944            if (flag == Flags.ANNOTATION) {
1945                checkAnnotations();
1946                if (S.token() != INTERFACE) {
1947                JCAnnotation ann = annotation(lastPos);
1948                // if first modifier is an annotation, set pos to annotation's.
1949                if (flags == 0 && annotations.isEmpty())
1950                    pos = ann.pos;
1951                annotations.append(ann);
1952                lastPos = ann.pos;
1953                    flag = 0;
1954                }
1955            }
1956            flags |= flag;
1957        }
1958        switch (S.token()) {
1959        case ENUM: flags |= Flags.ENUM; break;
1960        case INTERFACE: flags |= Flags.INTERFACE; break;
1961        default: break;
1962        }
1963 
1964        /* A modifiers tree with no modifier tokens or annotations
1965         * has no text position. */
1966        if (flags == 0 && annotations.isEmpty())
1967            pos = Position.NOPOS;
1968 
1969        JCModifiers mods = F.at(pos).Modifiers(flags, annotations.toList());
1970        if (pos != Position.NOPOS)
1971            storeEnd(mods, S.prevEndPos());
1972        return mods;
1973    }
1974 
1975    /** Annotation              = "@" Qualident [ "(" AnnotationFieldValues ")" ]
1976     * @param pos position of "@" token
1977     */
1978    JCAnnotation annotation(int pos) {
1979        // accept(AT); // AT consumed by caller
1980        checkAnnotations();
1981        JCTree ident = qualident();
1982        List<JCExpression> fieldValues = annotationFieldValuesOpt();
1983        JCAnnotation ann = F.at(pos).Annotation(ident, fieldValues);
1984        storeEnd(ann, S.prevEndPos());
1985        return ann;
1986    }
1987 
1988    List<JCExpression> annotationFieldValuesOpt() {
1989        return (S.token() == LPAREN) ? annotationFieldValues() : List.<JCExpression>nil();
1990    }
1991 
1992    /** AnnotationFieldValues   = "(" [ AnnotationFieldValue { "," AnnotationFieldValue } ] ")" */
1993    List<JCExpression> annotationFieldValues() {
1994        accept(LPAREN);
1995        ListBuffer<JCExpression> buf = new ListBuffer<JCExpression>();
1996        if (S.token() != RPAREN) {
1997            buf.append(annotationFieldValue());
1998            while (S.token() == COMMA) {
1999                S.nextToken();
2000                buf.append(annotationFieldValue());
2001            }
2002        }
2003        accept(RPAREN);
2004        return buf.toList();
2005    }
2006 
2007    /** AnnotationFieldValue    = AnnotationValue
2008     *                          | Identifier "=" AnnotationValue
2009     */
2010    JCExpression annotationFieldValue() {
2011        if (S.token() == IDENTIFIER) {
2012            mode = EXPR;
2013            JCExpression t1 = term1();
2014            if (t1.getTag() == JCTree.IDENT && S.token() == EQ) {
2015                int pos = S.pos();
2016                accept(EQ);
2017                return toP(F.at(pos).Assign(t1, annotationValue()));
2018            } else {
2019                return t1;
2020            }
2021        }
2022        return annotationValue();
2023    }
2024 
2025    /* AnnotationValue          = ConditionalExpression
2026     *                          | Annotation
2027     *                          | "{" [ AnnotationValue { "," AnnotationValue } ] "}"
2028     */
2029    JCExpression annotationValue() {
2030        int pos;
2031        switch (S.token()) {
2032        case MONKEYS_AT:
2033            pos = S.pos();
2034            S.nextToken();
2035            return annotation(pos);
2036        case LBRACE:
2037            pos = S.pos();
2038            accept(LBRACE);
2039            ListBuffer<JCExpression> buf = new ListBuffer<JCExpression>();
2040            if (S.token() != RBRACE) {
2041                buf.append(annotationValue());
2042                while (S.token() == COMMA) {
2043                    S.nextToken();
2044                    if (S.token() == RPAREN) break;
2045                    buf.append(annotationValue());
2046                }
2047            }
2048            accept(RBRACE);
2049            return toP(F.at(pos).NewArray(null, List.<JCExpression>nil(), buf.toList()));
2050        default:
2051            mode = EXPR;
2052            return term1();
2053        }
2054    }
2055 
2056    /** VariableDeclarators = VariableDeclarator { "," VariableDeclarator }
2057     */
2058    public <T extends ListBuffer<? super JCVariableDecl>> T variableDeclarators(JCModifiers mods,
2059                                                                         JCExpression type,
2060                                                                         T vdefs)
2061    {
2062        return variableDeclaratorsRest(S.pos(), mods, type, ident(), false, null, vdefs);
2063    }
2064 
2065    /** VariableDeclaratorsRest = VariableDeclaratorRest { "," VariableDeclarator }
2066     *  ConstantDeclaratorsRest = ConstantDeclaratorRest { "," ConstantDeclarator }
2067     *
2068     *  @param reqInit  Is an initializer always required?
2069     *  @param dc       The documentation comment for the variable declarations, or null.
2070     */
2071    <T extends ListBuffer<? super JCVariableDecl>> T variableDeclaratorsRest(int pos,
2072                                                                     JCModifiers mods,
2073                                                                     JCExpression type,
2074                                                                     Name name,
2075                                                                     boolean reqInit,
2076                                                                     String dc,
2077                                                                     T vdefs)
2078    {
2079        vdefs.append(variableDeclaratorRest(pos, mods, type, name, reqInit, dc));
2080        while (S.token() == COMMA) {
2081            // All but last of multiple declarators subsume a comma
2082            storeEnd((JCTree)vdefs.elems.last(), S.endPos());
2083            S.nextToken();
2084            vdefs.append(variableDeclarator(mods, type, reqInit, dc));
2085        }
2086        return vdefs;
2087    }
2088 
2089    /** VariableDeclarator = Ident VariableDeclaratorRest
2090     *  ConstantDeclarator = Ident ConstantDeclaratorRest
2091     */
2092    JCVariableDecl variableDeclarator(JCModifiers mods, JCExpression type, boolean reqInit, String dc) {
2093        return variableDeclaratorRest(S.pos(), mods, type, ident(), reqInit, dc);
2094    }
2095 
2096    /** VariableDeclaratorRest = BracketsOpt ["=" VariableInitializer]
2097     *  ConstantDeclaratorRest = BracketsOpt "=" VariableInitializer
2098     *
2099     *  @param reqInit  Is an initializer always required?
2100     *  @param dc       The documentation comment for the variable declarations, or null.
2101     */
2102    JCVariableDecl variableDeclaratorRest(int pos, JCModifiers mods, JCExpression type, Name name,
2103                                  boolean reqInit, String dc) {
2104        type = bracketsOpt(type);
2105        JCExpression init = null;
2106        if (S.token() == EQ) {
2107            S.nextToken();
2108            init = variableInitializer();
2109        }
2110        else if (reqInit) syntaxError(S.pos(), "expected", keywords.token2string(EQ));
2111        JCVariableDecl result =
2112            toP(F.at(pos).VarDef(mods, name, type, init));
2113        attach(result, dc);
2114        return result;
2115    }
2116 
2117    /** VariableDeclaratorId = Ident BracketsOpt
2118     */
2119    JCVariableDecl variableDeclaratorId(JCModifiers mods, JCExpression type) {
2120        int pos = S.pos();
2121        Name name = ident();
2122        if ((mods.flags & Flags.VARARGS) == 0)
2123            type = bracketsOpt(type);
2124        return toP(F.at(pos).VarDef(mods, name, type, null));
2125    }
2126 
2127    /** CompilationUnit = [ { "@" Annotation } PACKAGE Qualident ";"] {ImportDeclaration} {TypeDeclaration}
2128     */
2129    public JCTree.JCCompilationUnit compilationUnit() {
2130        int pos = S.pos();
2131        JCExpression pid = null;
2132        String dc = S.docComment();
2133        JCModifiers mods = null;
2134        List<JCAnnotation> packageAnnotations = List.nil();
2135        if (S.token() == MONKEYS_AT)
2136            mods = modifiersOpt();
2137 
2138        if (S.token() == PACKAGE) {
2139            if (mods != null) {
2140                checkNoMods(mods.flags);
2141                packageAnnotations = mods.annotations;
2142                mods = null;
2143            }
2144            S.nextToken();
2145            pid = qualident();
2146            accept(SEMI);
2147        }
2148        ListBuffer<JCTree> defs = new ListBuffer<JCTree>();
2149       boolean checkForImports = true;
2150        while (S.token() != EOF) {
2151            if (S.pos() <= errorEndPos) {
2152                // error recovery
2153                skip(checkForImports, false, false, false);
2154                if (S.token() == EOF)
2155                    break;
2156            }
2157            if (checkForImports && mods == null && S.token() == IMPORT) {
2158                defs.append(importDeclaration());
2159            } else {
2160                JCTree def = typeDeclaration(mods);
2161                if (def instanceof JCExpressionStatement)
2162                    def = ((JCExpressionStatement)def).expr;
2163                defs.append(def);
2164                if (def instanceof JCClassDecl)
2165                    checkForImports = false;
2166                mods = null;
2167            }
2168        }
2169        JCTree.JCCompilationUnit toplevel = F.at(pos).TopLevel(packageAnnotations, pid, defs.toList());
2170        attach(toplevel, dc);
2171        if (defs.elems.isEmpty())
2172            storeEnd(toplevel, S.prevEndPos());
2173        if (keepDocComments) toplevel.docComments = docComments;
2174        return toplevel;
2175    }
2176 
2177    /** ImportDeclaration = IMPORT [ STATIC ] Ident { "." Ident } [ "." "*" ] ";"
2178     */
2179    JCTree importDeclaration() {
2180        int pos = S.pos();
2181        S.nextToken();
2182        boolean importStatic = false;
2183        if (S.token() == STATIC) {
2184            checkStaticImports();
2185            importStatic = true;
2186            S.nextToken();
2187        }
2188        JCExpression pid = toP(F.at(S.pos()).Ident(ident()));
2189        do {
2190            int pos1 = S.pos();
2191            accept(DOT);
2192            if (S.token() == STAR) {
2193                pid = to(F.at(pos1).Select(pid, names.asterisk));
2194                S.nextToken();
2195                break;
2196            } else {
2197                pid = toP(F.at(pos1).Select(pid, ident()));
2198            }
2199        } while (S.token() == DOT);
2200        accept(SEMI);
2201        return toP(F.at(pos).Import(pid, importStatic));
2202    }
2203 
2204    /** TypeDeclaration = ClassOrInterfaceOrEnumDeclaration
2205     *                  | ";"
2206     */
2207    JCTree typeDeclaration(JCModifiers mods) {
2208        int pos = S.pos();
2209        if (mods == null && S.token() == SEMI) {
2210            S.nextToken();
2211            return toP(F.at(pos).Skip());
2212        } else {
2213            String dc = S.docComment();
2214            return classOrInterfaceOrEnumDeclaration(modifiersOpt(mods), dc);
2215        }
2216    }
2217 
2218    /** ClassOrInterfaceOrEnumDeclaration = ModifiersOpt
2219     *           (ClassDeclaration | InterfaceDeclaration | EnumDeclaration)
2220     *  @param mods     Any modifiers starting the class or interface declaration
2221     *  @param dc       The documentation comment for the class, or null.
2222     */
2223    JCStatement classOrInterfaceOrEnumDeclaration(JCModifiers mods, String dc) {
2224        if (S.token() == CLASS) {
2225            return classDeclaration(mods, dc);
2226        } else if (S.token() == INTERFACE) {
2227            return interfaceDeclaration(mods, dc);
2228        } else if (allowEnums) {
2229            if (S.token() == ENUM) {
2230                return enumDeclaration(mods, dc);
2231            } else {
2232                int pos = S.pos();
2233                List<JCTree> errs;
2234                if (S.token() == IDENTIFIER) {
2235                    errs = List.<JCTree>of(mods, toP(F.at(pos).Ident(ident())));
2236                    setErrorEndPos(S.pos());
2237                } else {
2238                    errs = List.<JCTree>of(mods);
2239                }
2240                return toP(F.Exec(syntaxError(pos, errs, "expected3",
2241                                              keywords.token2string(CLASS),
2242                                              keywords.token2string(INTERFACE),
2243                                              keywords.token2string(ENUM))));
2244            }
2245        } else {
2246            if (S.token() == ENUM) {
2247                log.error(S.pos(), "enums.not.supported.in.source", source.name);
2248                allowEnums = true;
2249                return enumDeclaration(mods, dc);
2250            }
2251            int pos = S.pos();
2252            List<JCTree> errs;
2253            if (S.token() == IDENTIFIER) {
2254                errs = List.<JCTree>of(mods, toP(F.at(pos).Ident(ident())));
2255                setErrorEndPos(S.pos());
2256            } else {
2257                errs = List.<JCTree>of(mods);
2258            }
2259            return toP(F.Exec(syntaxError(pos, errs, "expected2",
2260                                          keywords.token2string(CLASS),
2261                                          keywords.token2string(INTERFACE))));
2262        }
2263    }
2264 
2265    /** ClassDeclaration = CLASS Ident TypeParametersOpt [EXTENDS Type]
2266     *                     [IMPLEMENTS TypeList] ClassBody
2267     *  @param mods    The modifiers starting the class declaration
2268     *  @param dc       The documentation comment for the class, or null.
2269     */
2270    JCClassDecl classDeclaration(JCModifiers mods, String dc) {
2271        int pos = S.pos();
2272        accept(CLASS);
2273        Name name = ident();
2274 
2275        List<JCTypeParameter> typarams = typeParametersOpt();
2276 
2277        JCTree extending = null;
2278        if (S.token() == EXTENDS) {
2279            S.nextToken();
2280            extending = type();
2281        }
2282        List<JCExpression> implementing = List.nil();
2283        if (S.token() == IMPLEMENTS) {
2284            S.nextToken();
2285            implementing = typeList();
2286        }
2287        List<JCTree> defs = classOrInterfaceBody(name, false);
2288        JCClassDecl result = toP(F.at(pos).ClassDef(
2289            mods, name, typarams, extending, implementing, defs));
2290        attach(result, dc);
2291        return result;
2292    }
2293 
2294    /** InterfaceDeclaration = INTERFACE Ident TypeParametersOpt
2295     *                         [EXTENDS TypeList] InterfaceBody
2296     *  @param mods    The modifiers starting the interface declaration
2297     *  @param dc       The documentation comment for the interface, or null.
2298     */
2299    JCClassDecl interfaceDeclaration(JCModifiers mods, String dc) {
2300        int pos = S.pos();
2301        accept(INTERFACE);
2302        Name name = ident();
2303 
2304        List<JCTypeParameter> typarams = typeParametersOpt();
2305 
2306        List<JCExpression> extending = List.nil();
2307        if (S.token() == EXTENDS) {
2308            S.nextToken();
2309            extending = typeList();
2310        }
2311        List<JCTree> defs = classOrInterfaceBody(name, true);
2312        JCClassDecl result = toP(F.at(pos).ClassDef(
2313            mods, name, typarams, null, extending, defs));
2314        attach(result, dc);
2315        return result;
2316    }
2317 
2318    /** EnumDeclaration = ENUM Ident [IMPLEMENTS TypeList] EnumBody
2319     *  @param mods    The modifiers starting the enum declaration
2320     *  @param dc       The documentation comment for the enum, or null.
2321     */
2322    JCClassDecl enumDeclaration(JCModifiers mods, String dc) {
2323        int pos = S.pos();
2324        accept(ENUM);
2325        Name name = ident();
2326 
2327        List<JCExpression> implementing = List.nil();
2328        if (S.token() == IMPLEMENTS) {
2329            S.nextToken();
2330            implementing = typeList();
2331        }
2332 
2333        List<JCTree> defs = enumBody(name);
2334        JCModifiers newMods =
2335            F.at(mods.pos).Modifiers(mods.flags|Flags.ENUM, mods.annotations);
2336        JCClassDecl result = toP(F.at(pos).
2337            ClassDef(newMods, name, List.<JCTypeParameter>nil(),
2338                null, implementing, defs));
2339        attach(result, dc);
2340        return result;
2341    }
2342 
2343    /** EnumBody = "{" { EnumeratorDeclarationList } [","]
2344     *                  [ ";" {ClassBodyDeclaration} ] "}"
2345     */
2346    List<JCTree> enumBody(Name enumName) {
2347        accept(LBRACE);
2348        ListBuffer<JCTree> defs = new ListBuffer<JCTree>();
2349        if (S.token() == COMMA) {
2350            S.nextToken();
2351        } else if (S.token() != RBRACE && S.token() != SEMI) {
2352            defs.append(enumeratorDeclaration(enumName));
2353            while (S.token() == COMMA) {
2354                S.nextToken();
2355                if (S.token() == RBRACE || S.token() == SEMI) break;
2356                defs.append(enumeratorDeclaration(enumName));
2357            }
2358            if (S.token() != SEMI && S.token() != RBRACE) {
2359                defs.append(syntaxError(S.pos(), "expected3",
2360                                keywords.token2string(COMMA),
2361                                keywords.token2string(RBRACE),
2362                                keywords.token2string(SEMI)));
2363                S.nextToken();
2364            }
2365        }
2366        if (S.token() == SEMI) {
2367            S.nextToken();
2368            while (S.token() != RBRACE && S.token() != EOF) {
2369                defs.appendList(classOrInterfaceBodyDeclaration(enumName,
2370                                                                false));
2371                if (S.pos() <= errorEndPos) {
2372                    // error recovery
2373                   skip(false, true, true, false);
2374                }
2375            }
2376        }
2377        accept(RBRACE);
2378        return defs.toList();
2379    }
2380 
2381    /** EnumeratorDeclaration = AnnotationsOpt [TypeArguments] IDENTIFIER [ Arguments ] [ "{" ClassBody "}" ]
2382     */
2383    JCTree enumeratorDeclaration(Name enumName) {
2384        String dc = S.docComment();
2385        int flags = Flags.PUBLIC|Flags.STATIC|Flags.FINAL|Flags.ENUM;
2386        if (S.deprecatedFlag()) {
2387            flags |= Flags.DEPRECATED;
2388            S.resetDeprecatedFlag();
2389        }
2390        int pos = S.pos();
2391        List<JCAnnotation> annotations = annotationsOpt();
2392        JCModifiers mods = F.at(annotations.isEmpty() ? Position.NOPOS : pos).Modifiers(flags, annotations);
2393        List<JCExpression> typeArgs = typeArgumentsOpt();
2394        int identPos = S.pos();
2395        Name name = ident();
2396        int createPos = S.pos();
2397        List<JCExpression> args = (S.token() == LPAREN)
2398            ? arguments() : List.<JCExpression>nil();
2399        JCClassDecl body = null;
2400        if (S.token() == LBRACE) {
2401            JCModifiers mods1 = F.at(Position.NOPOS).Modifiers(Flags.ENUM | Flags.STATIC);
2402            List<JCTree> defs = classOrInterfaceBody(names.empty, false);
2403            body = toP(F.at(identPos).AnonymousClassDef(mods1, defs));
2404        }
2405        if (args.isEmpty() && body == null)
2406            createPos = Position.NOPOS;
2407        JCIdent ident = F.at(Position.NOPOS).Ident(enumName);
2408        JCNewClass create = F.at(createPos).NewClass(null, typeArgs, ident, args, body);
2409        if (createPos != Position.NOPOS)
2410            storeEnd(create, S.prevEndPos());
2411        ident = F.at(Position.NOPOS).Ident(enumName);
2412        JCTree result = toP(F.at(pos).VarDef(mods, name, ident, create));
2413        attach(result, dc);
2414        return result;
2415    }
2416 
2417    /** TypeList = Type {"," Type}
2418     */
2419    List<JCExpression> typeList() {
2420        ListBuffer<JCExpression> ts = new ListBuffer<JCExpression>();
2421        ts.append(type());
2422        while (S.token() == COMMA) {
2423            S.nextToken();
2424            ts.append(type());
2425        }
2426        return ts.toList();
2427    }
2428 
2429    /** ClassBody     = "{" {ClassBodyDeclaration} "}"
2430     *  InterfaceBody = "{" {InterfaceBodyDeclaration} "}"
2431     */
2432    List<JCTree> classOrInterfaceBody(Name className, boolean isInterface) {
2433        accept(LBRACE);
2434        if (S.pos() <= errorEndPos) {
2435            // error recovery
2436            skip(false, true, false, false);
2437            if (S.token() == LBRACE)
2438                S.nextToken();
2439        }
2440        ListBuffer<JCTree> defs = new ListBuffer<JCTree>();
2441        while (S.token() != RBRACE && S.token() != EOF) {
2442            defs.appendList(classOrInterfaceBodyDeclaration(className, isInterface));
2443            if (S.pos() <= errorEndPos) {
2444               // error recovery
2445               skip(false, true, true, false);
2446           }
2447        }
2448        accept(RBRACE);
2449        return defs.toList();
2450    }
2451 
2452    /** ClassBodyDeclaration =
2453     *      ";"
2454     *    | [STATIC] Block
2455     *    | ModifiersOpt
2456     *      ( Type Ident
2457     *        ( VariableDeclaratorsRest ";" | MethodDeclaratorRest )
2458     *      | VOID Ident MethodDeclaratorRest
2459     *      | TypeParameters (Type | VOID) Ident MethodDeclaratorRest
2460     *      | Ident ConstructorDeclaratorRest
2461     *      | TypeParameters Ident ConstructorDeclaratorRest
2462     *      | ClassOrInterfaceOrEnumDeclaration
2463     *      )
2464     *  InterfaceBodyDeclaration =
2465     *      ";"
2466     *    | ModifiersOpt Type Ident
2467     *      ( ConstantDeclaratorsRest | InterfaceMethodDeclaratorRest ";" )
2468     */
2469    List<JCTree> classOrInterfaceBodyDeclaration(Name className, boolean isInterface) {
2470        if (S.token() == SEMI) {
2471            S.nextToken();
2472            return List.<JCTree>of(F.at(Position.NOPOS).Block(0, List.<JCStatement>nil()));
2473        } else {
2474            String dc = S.docComment();
2475            int pos = S.pos();
2476            JCModifiers mods = modifiersOpt();
2477            if (S.token() == CLASS ||
2478                S.token() == INTERFACE ||
2479                allowEnums && S.token() == ENUM) {
2480                return List.<JCTree>of(classOrInterfaceOrEnumDeclaration(mods, dc));
2481            } else if (S.token() == LBRACE && !isInterface &&
2482                       (mods.flags & Flags.StandardFlags & ~Flags.STATIC) == 0 &&
2483                       mods.annotations.isEmpty()) {
2484                return List.<JCTree>of(block(pos, mods.flags));
2485            } else {
2486                pos = S.pos();
2487                List<JCTypeParameter> typarams = typeParametersOpt();
2488                // Hack alert:  if there are type arguments but no Modifiers, the start
2489                // position will be lost unless we set the Modifiers position.  There
2490                // should be an AST node for type parameters (BugId 5005090).
2491                if (typarams.length() > 0 && mods.pos == Position.NOPOS) {
2492                    mods.pos = pos;
2493                }
2494                Token token = S.token();
2495                Name name = S.name();
2496                pos = S.pos();
2497                JCExpression type;
2498                boolean isVoid = S.token() == VOID;
2499                if (isVoid) {
2500                    type = to(F.at(pos).TypeIdent(TypeTags.VOID));
2501                    S.nextToken();
2502                } else {
2503                    type = type();
2504                }
2505                if (S.token() == LPAREN && !isInterface && type.getTag() == JCTree.IDENT) {
2506                    if (isInterface || name != className)
2507                        log.error(pos, "invalid.meth.decl.ret.type.req");
2508                    return List.of(methodDeclaratorRest(
2509                        pos, mods, null, names.init, typarams,
2510                        isInterface, true, dc));
2511                } else {
2512                    pos = S.pos();
2513                    name = ident();
2514                    if (S.token() == LPAREN) {
2515                        return List.of(methodDeclaratorRest(
2516                            pos, mods, type, name, typarams,
2517                            isInterface, isVoid, dc));
2518                    } else if (!isVoid && typarams.isEmpty()) {
2519                        List<JCTree> defs =
2520                            variableDeclaratorsRest(pos, mods, type, name, isInterface, dc,
2521                                                    new ListBuffer<JCTree>()).toList();
2522                        storeEnd(defs.last(), S.endPos());
2523                        accept(SEMI);
2524                        return defs;
2525                    } else {
2526                        pos = S.pos();
2527                        List<JCTree> err = isVoid
2528                            ? List.<JCTree>of(toP(F.at(pos).MethodDef(mods, name, type, typarams,
2529                                List.<JCVariableDecl>nil(), List.<JCExpression>nil(), null, null)))
2530                            : null;
2531                        return List.<JCTree>of(syntaxError(S.pos(), err, "expected", keywords.token2string(LPAREN)));
2532                    }
2533                }
2534            }
2535        }
2536    }
2537 
2538    /** MethodDeclaratorRest =
2539     *      FormalParameters BracketsOpt [Throws TypeList] ( MethodBody | [DEFAULT AnnotationValue] ";")
2540     *  VoidMethodDeclaratorRest =
2541     *      FormalParameters [Throws TypeList] ( MethodBody | ";")
2542     *  InterfaceMethodDeclaratorRest =
2543     *      FormalParameters BracketsOpt [THROWS TypeList] ";"
2544     *  VoidInterfaceMethodDeclaratorRest =
2545     *      FormalParameters [THROWS TypeList] ";"
2546     *  ConstructorDeclaratorRest =
2547     *      "(" FormalParameterListOpt ")" [THROWS TypeList] MethodBody
2548     */
2549    JCTree methodDeclaratorRest(int pos,
2550                              JCModifiers mods,
2551                              JCExpression type,
2552                              Name name,
2553                              List<JCTypeParameter> typarams,
2554                              boolean isInterface, boolean isVoid,
2555                              String dc) {
2556        List<JCVariableDecl> params = formalParameters();
2557        if (!isVoid) type = bracketsOpt(type);
2558        List<JCExpression> thrown = List.nil();
2559        if (S.token() == THROWS) {
2560            S.nextToken();
2561            thrown = qualidentList();
2562        }
2563        JCBlock body = null;
2564        JCExpression defaultValue;
2565        if (S.token() == LBRACE) {
2566            body = block();
2567            defaultValue = null;
2568        } else {
2569            if (S.token() == DEFAULT) {
2570                accept(DEFAULT);
2571                defaultValue = annotationValue();
2572            } else {
2573                defaultValue = null;
2574            }
2575            accept(SEMI);
2576            if (S.pos() <= errorEndPos) {
2577                // error recovery
2578                skip(false, true, false, false);
2579                if (S.token() == LBRACE) {
2580                    body = block();
2581                }
2582            }
2583        }
2584        JCMethodDecl result =
2585            toP(F.at(pos).MethodDef(mods, name, type, typarams,
2586                                    params, thrown,
2587                                    body, defaultValue));
2588        attach(result, dc);
2589        return result;
2590    }
2591 
2592    /** QualidentList = Qualident {"," Qualident}
2593     */
2594    List<JCExpression> qualidentList() {
2595        ListBuffer<JCExpression> ts = new ListBuffer<JCExpression>();
2596        ts.append(qualident());
2597        while (S.token() == COMMA) {
2598            S.nextToken();
2599            ts.append(qualident());
2600        }
2601        return ts.toList();
2602    }
2603 
2604    /** TypeParametersOpt = ["<" TypeParameter {"," TypeParameter} ">"]
2605     */
2606    List<JCTypeParameter> typeParametersOpt() {
2607        if (S.token() == LT) {
2608            checkGenerics();
2609            ListBuffer<JCTypeParameter> typarams = new ListBuffer<JCTypeParameter>();
2610            S.nextToken();
2611            typarams.append(typeParameter());
2612            while (S.token() == COMMA) {
2613                S.nextToken();
2614                typarams.append(typeParameter());
2615            }
2616            accept(GT);
2617            return typarams.toList();
2618        } else {
2619            return List.nil();
2620        }
2621    }
2622 
2623    /** TypeParameter = TypeVariable [TypeParameterBound]
2624     *  TypeParameterBound = EXTENDS Type {"&" Type}
2625     *  TypeVariable = Ident
2626     */
2627    JCTypeParameter typeParameter() {
2628        int pos = S.pos();
2629        Name name = ident();
2630        ListBuffer<JCExpression> bounds = new ListBuffer<JCExpression>();
2631        if (S.token() == EXTENDS) {
2632            S.nextToken();
2633            bounds.append(type());
2634            while (S.token() == AMP) {
2635                S.nextToken();
2636                bounds.append(type());
2637            }
2638        }
2639        return toP(F.at(pos).TypeParameter(name, bounds.toList()));
2640    }
2641 
2642    /** FormalParameters = "(" [ FormalParameterList ] ")"
2643     *  FormalParameterList = [ FormalParameterListNovarargs , ] LastFormalParameter
2644     *  FormalParameterListNovarargs = [ FormalParameterListNovarargs , ] FormalParameter
2645     */
2646    List<JCVariableDecl> formalParameters() {
2647        ListBuffer<JCVariableDecl> params = new ListBuffer<JCVariableDecl>();
2648        JCVariableDecl lastParam = null;
2649        accept(LPAREN);
2650        if (S.token() != RPAREN) {
2651            params.append(lastParam = formalParameter());
2652            while ((lastParam.mods.flags & Flags.VARARGS) == 0 && S.token() == COMMA) {
2653                S.nextToken();
2654                params.append(lastParam = formalParameter());
2655            }
2656        }
2657        accept(RPAREN);
2658        return params.toList();
2659    }
2660 
2661    JCModifiers optFinal(long flags) {
2662        JCModifiers mods = modifiersOpt();
2663        checkNoMods(mods.flags & ~(Flags.FINAL | Flags.DEPRECATED));
2664        mods.flags |= flags;
2665        return mods;
2666    }
2667 
2668    /** FormalParameter = { FINAL | '@' Annotation } Type VariableDeclaratorId
2669     *  LastFormalParameter = { FINAL | '@' Annotation } Type '...' Ident | FormalParameter
2670     */
2671    JCVariableDecl formalParameter() {
2672        JCModifiers mods = optFinal(Flags.PARAMETER);
2673        JCExpression type = type();
2674        if (S.token() == ELLIPSIS) {
2675            checkVarargs();
2676            mods.flags |= Flags.VARARGS;
2677            type = to(F.at(S.pos()).TypeArray(type));
2678            S.nextToken();
2679        }
2680        return variableDeclaratorId(mods, type);
2681    }
2682 
2683/* ---------- auxiliary methods -------------- */
2684 
2685    /** Check that given tree is a legal expression statement.
2686     */
2687    protected JCExpression checkExprStat(JCExpression t) {
2688        switch(t.getTag()) {
2689        case JCTree.PREINC: case JCTree.PREDEC:
2690        case JCTree.POSTINC: case JCTree.POSTDEC:
2691        case JCTree.ASSIGN:
2692        case JCTree.BITOR_ASG: case JCTree.BITXOR_ASG: case JCTree.BITAND_ASG:
2693        case JCTree.SL_ASG: case JCTree.SR_ASG: case JCTree.USR_ASG:
2694        case JCTree.PLUS_ASG: case JCTree.MINUS_ASG:
2695        case JCTree.MUL_ASG: case JCTree.DIV_ASG: case JCTree.MOD_ASG:
2696        case JCTree.APPLY: case JCTree.NEWCLASS:
2697        case JCTree.ERRONEOUS:
2698            return t;
2699        default:
2700            log.error(t.pos, "not.stmt");
2701            return F.at(t.pos).Erroneous(List.<JCTree>of(t));
2702        }
2703    }
2704 
2705    /** Return precedence of operator represented by token,
2706     *  -1 if token is not a binary operator. @see TreeInfo.opPrec
2707     */
2708    static int prec(Token token) {
2709        int oc = optag(token);
2710        return (oc >= 0) ? TreeInfo.opPrec(oc) : -1;
2711    }
2712 
2713    /** Return operation tag of binary operator represented by token,
2714     *  -1 if token is not a binary operator.
2715     */
2716    static int optag(Token token) {
2717        switch (token) {
2718        case BARBAR:
2719            return JCTree.OR;
2720        case AMPAMP:
2721            return JCTree.AND;
2722        case BAR:
2723            return JCTree.BITOR;
2724        case BAREQ:
2725            return JCTree.BITOR_ASG;
2726        case CARET:
2727            return JCTree.BITXOR;
2728        case CARETEQ:
2729            return JCTree.BITXOR_ASG;
2730        case AMP:
2731            return JCTree.BITAND;
2732        case AMPEQ:
2733            return JCTree.BITAND_ASG;
2734        case EQEQ:
2735            return JCTree.EQ;
2736        case BANGEQ:
2737            return JCTree.NE;
2738        case LT:
2739            return JCTree.LT;
2740        case GT:
2741            return JCTree.GT;
2742        case LTEQ:
2743            return JCTree.LE;
2744        case GTEQ:
2745            return JCTree.GE;
2746        case LTLT:
2747            return JCTree.SL;
2748        case LTLTEQ:
2749            return JCTree.SL_ASG;
2750        case GTGT:
2751            return JCTree.SR;
2752        case GTGTEQ:
2753            return JCTree.SR_ASG;
2754        case GTGTGT:
2755            return JCTree.USR;
2756        case GTGTGTEQ:
2757            return JCTree.USR_ASG;
2758        case PLUS:
2759            return JCTree.PLUS;
2760        case PLUSEQ:
2761            return JCTree.PLUS_ASG;
2762        case SUB:
2763            return JCTree.MINUS;
2764        case SUBEQ:
2765            return JCTree.MINUS_ASG;
2766        case STAR:
2767            return JCTree.MUL;
2768        case STAREQ:
2769            return JCTree.MUL_ASG;
2770        case SLASH:
2771            return JCTree.DIV;
2772        case SLASHEQ:
2773            return JCTree.DIV_ASG;
2774        case PERCENT:
2775            return JCTree.MOD;
2776        case PERCENTEQ:
2777            return JCTree.MOD_ASG;
2778        case INSTANCEOF:
2779            return JCTree.TYPETEST;
2780        default:
2781            return -1;
2782        }
2783    }
2784 
2785    /** Return operation tag of unary operator represented by token,
2786     *  -1 if token is not a binary operator.
2787     */
2788    static int unoptag(Token token) {
2789        switch (token) {
2790        case PLUS:
2791            return JCTree.POS;
2792        case SUB:
2793            return JCTree.NEG;
2794        case BANG:
2795            return JCTree.NOT;
2796        case TILDE:
2797            return JCTree.COMPL;
2798        case PLUSPLUS:
2799            return JCTree.PREINC;
2800        case SUBSUB:
2801            return JCTree.PREDEC;
2802        default:
2803            return -1;
2804        }
2805    }
2806 
2807    /** Return type tag of basic type represented by token,
2808     *  -1 if token is not a basic type identifier.
2809     */
2810    static int typetag(Token token) {
2811        switch (token) {
2812        case BYTE:
2813            return TypeTags.BYTE;
2814        case CHAR:
2815            return TypeTags.CHAR;
2816        case SHORT:
2817            return TypeTags.SHORT;
2818        case INT:
2819            return TypeTags.INT;
2820        case LONG:
2821            return TypeTags.LONG;
2822        case FLOAT:
2823            return TypeTags.FLOAT;
2824        case DOUBLE:
2825            return TypeTags.DOUBLE;
2826        case BOOLEAN:
2827            return TypeTags.BOOLEAN;
2828        default:
2829            return -1;
2830        }
2831    }
2832 
2833    void checkGenerics() {
2834        if (!allowGenerics) {
2835            log.error(S.pos(), "generics.not.supported.in.source", source.name);
2836            allowGenerics = true;
2837        }
2838    }
2839    void checkVarargs() {
2840        if (!allowVarargs) {
2841            log.error(S.pos(), "varargs.not.supported.in.source", source.name);
2842            allowVarargs = true;
2843        }
2844    }
2845    void checkForeach() {
2846        if (!allowForeach) {
2847            log.error(S.pos(), "foreach.not.supported.in.source", source.name);
2848            allowForeach = true;
2849        }
2850    }
2851    void checkStaticImports() {
2852        if (!allowStaticImport) {
2853            log.error(S.pos(), "static.import.not.supported.in.source", source.name);
2854            allowStaticImport = true;
2855        }
2856    }
2857    void checkAnnotations() {
2858        if (!allowAnnotations) {
2859            log.error(S.pos(), "annotations.not.supported.in.source", source.name);
2860            allowAnnotations = true;
2861        }
2862    }
2863}

[all classes][com.sun.tools.javac.parser]
EMMA 2.0.5312 (C) Vladimir Roubtsov