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