1/*
2 * Copyright (c) 1994, 2004, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation.  Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25
26package sun.tools.java;
27
28import sun.tools.tree.*;
29import java.io.IOException;
30import java.io.InputStream;
31import java.util.Enumeration;
32import java.util.Vector;
33
34/**
35 * This class is used to parse Java statements and expressions.
36 * The result is a parse tree.<p>
37 *
38 * This class implements an operator precedence parser. Errors are
39 * reported to the Environment object, if the error can't be
40 * resolved immediately, a SyntaxError exception is thrown.<p>
41 *
42 * Error recovery is implemented by catching SyntaxError exceptions
43 * and discarding input tokens until an input token is reached that
44 * is possibly a legal continuation.<p>
45 *
46 * The parse tree that is constructed represents the input
47 * exactly (no rewrites to simpler forms). This is important
48 * if the resulting tree is to be used for code formatting in
49 * a programming environment. Currently only documentation comments
50 * are retained.<p>
51 *
52 * The parsing algorithm does NOT use any type information. Changes
53 * in the type system do not affect the structure of the parse tree.
54 * This restriction does introduce an ambiguity an expression of the
55 * form: (e1) e2 is assumed to be a cast if e2 does not start with
56 * an operator. That means that (a) - b is interpreted as subtract
57 * b from a and not cast negative b to type a. However, if a is a
58 * simple type (byte, int, ...) then it is assumed to be a cast.<p>
59 *
60 * WARNING: The contents of this source file are not part of any
61 * supported API.  Code that depends on them does so at its own risk:
62 * they are subject to change or removal without notice.
63 *
64 * @author      Arthur van Hoff
65 */
66
67public
68class Parser extends Scanner implements ParserActions, Constants {
69    /**
70     * Create a parser
71     */
72    protected Parser(Environment env, InputStream in) throws IOException {
73        super(env, in);
74        this.scanner = this;
75        this.actions = this;
76    }
77
78    /**
79     * Create a parser, given a scanner.
80     */
81    protected Parser(Scanner scanner) throws IOException {
82        super(scanner.env);
83        this.scanner = scanner;
84        ((Scanner)this).env = scanner.env;
85        ((Scanner)this).token = scanner.token;
86        ((Scanner)this).pos = scanner.pos;
87        this.actions = this;
88    }
89
90    /**
91     * Create a parser, given a scanner and the semantic callback.
92     */
93    public Parser(Scanner scanner, ParserActions actions) throws IOException {
94        this(scanner);
95        this.actions = actions;
96    }
97
98    /**
99     * Usually <code>this.actions == (ParserActions)this</code>.
100     * However, a delegate scanner can produce tokens for this parser,
101     * in which case <code>(Scanner)this</code> is unused,
102     * except for <code>this.token</code> and <code>this.pos</code>
103     * instance variables which are filled from the real scanner
104     * by <code>this.scan()</code> and the constructor.
105     */
106    ParserActions actions;
107
108    // Note:  The duplication of methods allows pre-1.1 classes to
109    // be binary compatible with the new version of the parser,
110    // which now passes IdentifierTokens to the semantics phase,
111    // rather than just Identifiers.  This change is necessary,
112    // since the parser is no longer responsible for managing the
113    // resolution of type names.  (That caused the "Vector" bug.)
114    //
115    // In a future release, the old "plain-Identifier" methods will
116    // go away, and the corresponding "IdentifierToken" methods
117    // may become abstract.
118
119    /**
120     * package declaration
121     * @deprecated
122     */
123    @Deprecated
124    public void packageDeclaration(long off, IdentifierToken nm) {
125        // By default, call the deprecated version.
126        // Any application must override one of the packageDeclaration methods.
127        packageDeclaration(off, nm.id);
128    }
129    /**
130     * @deprecated
131     */
132    @Deprecated
133    protected void packageDeclaration(long off, Identifier nm) {
134        throw new RuntimeException("beginClass method is abstract");
135    }
136
137    /**
138     * import class
139     * @deprecated
140     */
141    @Deprecated
142    public void importClass(long off, IdentifierToken nm) {
143        // By default, call the deprecated version.
144        // Any application must override one of the packageDeclaration methods.
145        importClass(off, nm.id);
146    }
147    /**
148     * @deprecated Use the version with the IdentifierToken arguments.
149     */
150    @Deprecated
151    protected void importClass(long off, Identifier nm) {
152        throw new RuntimeException("importClass method is abstract");
153    }
154
155    /**
156     * import package
157     * @deprecated
158     */
159    @Deprecated
160    public void importPackage(long off, IdentifierToken nm) {
161        // By default, call the deprecated version.
162        // Any application must override one of the importPackage methods.
163        importPackage(off, nm.id);
164    }
165    /**
166     * @deprecated Use the version with the IdentifierToken arguments.
167     */
168    @Deprecated
169    protected void importPackage(long off, Identifier nm) {
170        throw new RuntimeException("importPackage method is abstract");
171    }
172
173    /**
174     * Define class
175     * @deprecated
176     */
177    @Deprecated
178    public ClassDefinition beginClass(long off, String doc,
179                                      int mod, IdentifierToken nm,
180                                      IdentifierToken sup,
181                                      IdentifierToken impl[]) {
182        // By default, call the deprecated version.
183        // Any application must override one of the beginClass methods.
184        Identifier supId = (sup == null) ? null : sup.id;
185        Identifier implIds[] = null;
186        if (impl != null) {
187            implIds = new Identifier[impl.length];
188            for (int i = 0; i < impl.length; i++) {
189                implIds[i] = impl[i].id;
190            }
191        }
192        beginClass(off, doc, mod, nm.id, supId, implIds);
193        return getCurrentClass();
194    }
195    /**
196     * @deprecated Use the version with the IdentifierToken arguments.
197     */
198    @Deprecated
199    protected void beginClass(long off, String doc, int mod, Identifier nm,
200                              Identifier sup, Identifier impl[]) {
201        throw new RuntimeException("beginClass method is abstract");
202    }
203
204    /**
205     * Report the current class under construction.
206     * By default, it's a no-op which returns null.
207     * It may only be called before the corresponding endClass().
208     */
209    protected ClassDefinition getCurrentClass() {
210        return null;
211    }
212
213    /**
214     * End class
215     * @deprecated
216     */
217    @Deprecated
218    public void endClass(long off, ClassDefinition c) {
219        // By default, call the deprecated version.
220        // Any application must override one of the beginClass methods.
221        endClass(off, c.getName().getFlatName().getName());
222    }
223    /**
224     * @deprecated Use the version with the IdentifierToken arguments.
225     */
226    @Deprecated
227    protected void endClass(long off, Identifier nm) {
228        throw new RuntimeException("endClass method is abstract");
229    }
230
231    /**
232     * Define a field
233     * @deprecated
234     */
235    @Deprecated
236    public void defineField(long where, ClassDefinition c,
237                            String doc, int mod, Type t,
238                            IdentifierToken nm, IdentifierToken args[],
239                            IdentifierToken exp[], Node val) {
240        // By default, call the deprecated version.
241        // Any application must override one of the defineField methods.
242        Identifier argIds[] = null;
243        Identifier expIds[] = null;
244        if (args != null) {
245            argIds = new Identifier[args.length];
246            for (int i = 0; i < args.length; i++) {
247                argIds[i] = args[i].id;
248            }
249        }
250        if (exp != null) {
251            expIds = new Identifier[exp.length];
252            for (int i = 0; i < exp.length; i++) {
253                expIds[i] = exp[i].id;
254            }
255        }
256        defineField(where, doc, mod, t, nm.id, argIds, expIds, val);
257    }
258
259    /**
260     * @deprecated Use the version with the IdentifierToken arguments.
261     */
262    @Deprecated
263    protected void defineField(long where, String doc, int mod, Type t,
264                               Identifier nm, Identifier args[],
265                               Identifier exp[], Node val) {
266        throw new RuntimeException("defineField method is abstract");
267    }
268
269    /*
270     * A growable array of nodes. It is used as a growable
271     * buffer to hold argument lists and expression lists.
272     * I'm not using Vector to make it more efficient.
273     */
274    private Node args[] = new Node[32];
275    protected int argIndex = 0;
276
277    protected final void addArgument(Node n) {
278        if (argIndex == args.length) {
279            Node newArgs[] = new Node[args.length * 2];
280            System.arraycopy(args, 0, newArgs, 0, args.length);
281            args = newArgs;
282        }
283        args[argIndex++] = n;
284    }
285    protected final Expression exprArgs(int index)[] {
286        Expression e[] = new Expression[argIndex - index];
287        System.arraycopy(args, index, e, 0, argIndex - index);
288        argIndex = index;
289        return e;
290    }
291    protected final Statement statArgs(int index)[] {
292        Statement s[] = new Statement[argIndex - index];
293        System.arraycopy(args, index, s, 0, argIndex - index);
294        argIndex = index;
295        return s;
296    }
297
298    /**
299     * Expect a token, return its value, scan the next token or
300     * throw an exception.
301     */
302    protected void expect(int t) throws SyntaxError, IOException {
303        if (token != t) {
304            switch (t) {
305              case IDENT:
306                env.error(scanner.prevPos, "identifier.expected");
307                break;
308              default:
309                env.error(scanner.prevPos, "token.expected", opNames[t]);
310                break;
311            }
312                throw new SyntaxError();
313        }
314        scan();
315    }
316
317    /**
318     * Parse a type expression. Does not parse the []'s.
319     */
320    protected Expression parseTypeExpression() throws SyntaxError, IOException {
321        switch (token) {
322          case VOID:
323            return new TypeExpression(scan(), Type.tVoid);
324          case BOOLEAN:
325            return new TypeExpression(scan(), Type.tBoolean);
326          case BYTE:
327            return new TypeExpression(scan(), Type.tByte);
328          case CHAR:
329            return new TypeExpression(scan(), Type.tChar);
330          case SHORT:
331            return new TypeExpression(scan(), Type.tShort);
332          case INT:
333            return new TypeExpression(scan(), Type.tInt);
334          case LONG:
335            return new TypeExpression(scan(), Type.tLong);
336          case FLOAT:
337            return new TypeExpression(scan(), Type.tFloat);
338          case DOUBLE:
339            return new TypeExpression(scan(), Type.tDouble);
340          case IDENT:
341            Expression e = new IdentifierExpression(pos, scanner.idValue);
342            scan();
343            while (token == FIELD) {
344                e = new FieldExpression(scan(), e, scanner.idValue);
345                expect(IDENT);
346            }
347            return e;
348        }
349
350        env.error(pos, "type.expected");
351        throw new SyntaxError();
352    }
353
354    /**
355     * Parse a method invocation. Should be called when the current
356     * then is the '(' of the argument list.
357     */
358    protected Expression parseMethodExpression(Expression e, Identifier id) throws SyntaxError, IOException {
359       long p = scan();
360       int i = argIndex;
361       if (token != RPAREN) {
362           addArgument(parseExpression());
363           while (token == COMMA) {
364               scan();
365               addArgument(parseExpression());
366           }
367       }
368       expect(RPAREN);
369       return new MethodExpression(p, e, id, exprArgs(i));
370    }
371
372    /**
373     * Parse a new instance expression.  Should be called when the current
374     * token is the '(' of the argument list.
375     */
376    protected Expression parseNewInstanceExpression(long p, Expression outerArg, Expression type) throws SyntaxError, IOException {
377        int i = argIndex;
378        expect(LPAREN);
379        if (token != RPAREN) {
380            addArgument(parseExpression());
381            while (token == COMMA) {
382                scan();
383                addArgument(parseExpression());
384            }
385        }
386        expect(RPAREN);
387        ClassDefinition body = null;
388        if (token == LBRACE && !(type instanceof TypeExpression)) {
389            long tp = pos;
390            // x = new Type(arg) { subclass body ... }
391            Identifier superName = FieldExpression.toIdentifier(type);
392            if (superName == null) {
393                env.error(type.getWhere(), "type.expected");
394            }
395            Vector<IdentifierToken> ext = new Vector<>(1);
396            Vector<IdentifierToken> impl = new Vector<>(0);
397            ext.addElement(new IdentifierToken(idNull));
398            if (token == IMPLEMENTS || token == EXTENDS) {
399                env.error(pos, "anonymous.extends");
400                parseInheritance(ext, impl); // error recovery
401            }
402            body = parseClassBody(new IdentifierToken(tp, idNull),
403                                  M_ANONYMOUS | M_LOCAL, EXPR, null,
404                                  ext, impl, type.getWhere());
405        }
406        if (outerArg == null && body == null) {
407            return new NewInstanceExpression(p, type, exprArgs(i));
408        }
409        return new NewInstanceExpression(p, type, exprArgs(i), outerArg, body);
410    }
411
412    /**
413     * Parse a primary expression.
414     */
415    protected Expression parseTerm() throws SyntaxError, IOException {
416        switch (token) {
417          case CHARVAL: {
418            char v = scanner.charValue;
419            return new CharExpression(scan(), v);
420          }
421          case INTVAL: {
422            int v = scanner.intValue;
423            long q = scan();
424            if (v < 0 && radix == 10) env.error(q, "overflow.int.dec");
425            return new IntExpression(q, v);
426          }
427          case LONGVAL: {
428            long v = scanner.longValue;
429            long q = scan();
430            if (v < 0 && radix == 10) env.error(q, "overflow.long.dec");
431            return new LongExpression(q, v);
432          }
433          case FLOATVAL: {
434            float v = scanner.floatValue;
435            return new FloatExpression(scan(), v);
436          }
437          case DOUBLEVAL: {
438            double v = scanner.doubleValue;
439            return new DoubleExpression(scan(), v);
440          }
441          case STRINGVAL: {
442            String v = scanner.stringValue;
443            return new StringExpression(scan(), v);
444          }
445          case IDENT: {
446            Identifier v = scanner.idValue;
447            long p = scan();
448            return (token == LPAREN) ?
449                        parseMethodExpression(null, v) : new IdentifierExpression(p, v);
450          }
451
452          case TRUE:
453            return new BooleanExpression(scan(), true);
454          case FALSE:
455            return new BooleanExpression(scan(), false);
456          case NULL:
457            return new NullExpression(scan());
458
459          case THIS: {
460            Expression e = new ThisExpression(scan());
461            return (token == LPAREN) ? parseMethodExpression(e, idInit) : e;
462          }
463          case SUPER: {
464            Expression e = new SuperExpression(scan());
465            return (token == LPAREN) ? parseMethodExpression(e, idInit) : e;
466          }
467
468          case VOID:
469          case BOOLEAN:
470          case BYTE:
471          case CHAR:
472          case SHORT:
473          case INT:
474          case LONG:
475          case FLOAT:
476          case DOUBLE:
477            return parseTypeExpression();
478
479          case ADD: {
480            long p = scan();
481            switch (token) {
482              case INTVAL: {
483                int v = scanner.intValue;
484                long q = scan();
485                if (v < 0 && radix == 10) env.error(q, "overflow.int.dec");
486                return new IntExpression(q, v);
487              }
488              case LONGVAL: {
489                long v = scanner.longValue;
490                long q = scan();
491                if (v < 0 && radix == 10) env.error(q, "overflow.long.dec");
492                return new LongExpression(q, v);
493              }
494              case FLOATVAL: {
495                float v = scanner.floatValue;
496                return new FloatExpression(scan(), v);
497              }
498              case DOUBLEVAL: {
499                double v = scanner.doubleValue;
500                return new DoubleExpression(scan(), v);
501              }
502            }
503            return new PositiveExpression(p, parseTerm());
504          }
505          case SUB: {
506            long p = scan();
507            switch (token) {
508              case INTVAL: {
509                int v = -scanner.intValue;
510                return new IntExpression(scan(), v);
511              }
512              case LONGVAL: {
513                long v = -scanner.longValue;
514                return new LongExpression(scan(), v);
515              }
516              case FLOATVAL: {
517                float v = -scanner.floatValue;
518                return new FloatExpression(scan(), v);
519              }
520              case DOUBLEVAL: {
521                double v = -scanner.doubleValue;
522                return new DoubleExpression(scan(), v);
523              }
524            }
525            return new NegativeExpression(p, parseTerm());
526          }
527          case NOT:
528            return new NotExpression(scan(), parseTerm());
529          case BITNOT:
530            return new BitNotExpression(scan(), parseTerm());
531          case INC:
532            return new PreIncExpression(scan(), parseTerm());
533          case DEC:
534            return new PreDecExpression(scan(), parseTerm());
535
536          case LPAREN: {
537            // bracketed-expr: (expr)
538            long p = scan();
539            Expression e = parseExpression();
540            expect(RPAREN);
541
542            if (e.getOp() == TYPE) {
543                // cast-expr: (simple-type) expr
544                return new CastExpression(p, e, parseTerm());
545            }
546
547            switch (token) {
548
549                // We handle INC and DEC specially.
550                // See the discussion in JLS section 15.14.1.
551                // (Part of fix for 4044502.)
552
553              case INC:
554                  // We know this must be a postfix increment.
555                  return new PostIncExpression(scan(), e);
556
557              case DEC:
558                  // We know this must be a postfix decrement.
559                  return new PostDecExpression(scan(), e);
560
561              case LPAREN:
562              case CHARVAL:
563              case INTVAL:
564              case LONGVAL:
565              case FLOATVAL:
566              case DOUBLEVAL:
567              case STRINGVAL:
568              case IDENT:
569              case TRUE:
570              case FALSE:
571              case NOT:
572              case BITNOT:
573              case THIS:
574              case SUPER:
575              case NULL:
576              case NEW:
577                // cast-expr: (expr) expr
578                return new CastExpression(p, e, parseTerm());
579            }
580            return new ExprExpression(p, e);
581          }
582
583          case LBRACE: {
584            // array initializer: {expr1, expr2, ... exprn}
585            long p = scan();
586            int i = argIndex;
587            if (token != RBRACE) {
588                addArgument(parseExpression());
589                while (token == COMMA) {
590                    scan();
591                    if (token == RBRACE) {
592                        break;
593                    }
594                    addArgument(parseExpression());
595                }
596            }
597            expect(RBRACE);
598            return new ArrayExpression(p, exprArgs(i));
599          }
600
601          case NEW: {
602            long p = scan();
603            int i = argIndex;
604
605            if (token == LPAREN) {
606                scan();
607                Expression e = parseExpression();
608                expect(RPAREN);
609                env.error(p, "not.supported", "new(...)");
610                return new NullExpression(p);
611            }
612
613            Expression e = parseTypeExpression();
614
615            if (token == LSQBRACKET) {
616                while (token == LSQBRACKET) {
617                    scan();
618                    addArgument((token != RSQBRACKET) ? parseExpression() : null);
619                    expect(RSQBRACKET);
620                }
621                Expression[] dims = exprArgs(i);
622                if (token == LBRACE) {
623                    return new NewArrayExpression(p, e, dims, parseTerm());
624                }
625                return new NewArrayExpression(p, e, dims);
626            } else {
627                return parseNewInstanceExpression(p, null, e);
628            }
629          }
630        }
631
632        // System.err.println("NEAR: " + opNames[token]);
633        env.error(scanner.prevPos, "missing.term");
634        return new IntExpression(pos, 0);
635    }
636
637    /**
638     * Parse an expression.
639     */
640    protected Expression parseExpression() throws SyntaxError, IOException {
641        for (Expression e = parseTerm() ; e != null ; e = e.order()) {
642            Expression more = parseBinaryExpression(e);
643            if (more == null)
644                return e;
645            e = more;
646        }
647        // this return is bogus
648        return null;
649    }
650
651    /**
652     * Given a left-hand term, parse an operator and right-hand term.
653     */
654    protected Expression parseBinaryExpression(Expression e) throws SyntaxError, IOException {
655        if (e != null) {
656            switch (token) {
657              case LSQBRACKET: {
658                // index: expr1[expr2]
659                long p = scan();
660                Expression index = (token != RSQBRACKET) ? parseExpression() : null;
661                expect(RSQBRACKET);
662                e = new ArrayAccessExpression(p, e, index);
663                break;
664              }
665
666              case INC:
667                e = new PostIncExpression(scan(), e);
668                break;
669              case DEC:
670                e = new PostDecExpression(scan(), e);
671                break;
672              case FIELD: {
673                long p = scan();
674                if (token == THIS) {
675                    // class C { class N { ... C.this ... } }
676                    // class C { class N { N(C c){ ... c.this() ... } } }
677                    long q = scan();
678                    if (token == LPAREN) {
679                        e = new ThisExpression(q, e);
680                        e = parseMethodExpression(e, idInit);
681                    } else {
682                        e = new FieldExpression(p, e, idThis);
683                    }
684                    break;
685                }
686                if (token == SUPER) {
687                    // class D extends C.N { D(C.N n) { n.super(); } }
688                    // Also, 'C.super', as in:
689                    // class C extends CS { class N { ... C.super.foo ... } }
690                    // class C extends CS { class N { ... C.super.foo() ... } }
691                    long q = scan();
692                    if (token == LPAREN) {
693                        e = new SuperExpression(q, e);
694                        e = parseMethodExpression(e, idInit);
695                    } else {
696                        // We must check elsewhere that this expression
697                        // does not stand alone, but qualifies a member name.
698                        e = new FieldExpression(p, e, idSuper);
699                    }
700                    break;
701                }
702                if (token == NEW) {
703                    // new C().new N()
704                    scan();
705                    if (token != IDENT)
706                        expect(IDENT);
707                    e = parseNewInstanceExpression(p, e, parseTypeExpression());
708                    break;
709                }
710                if (token == CLASS) {
711                    // just class literals, really
712                    // Class c = C.class;
713                    scan();
714                    e = new FieldExpression(p, e, idClass);
715                    break;
716                }
717                Identifier id = scanner.idValue;
718                expect(IDENT);
719                if (token == LPAREN) {
720                    e = parseMethodExpression(e, id);
721                } else {
722                    e = new FieldExpression(p, e, id);
723                }
724                break;
725              }
726              case INSTANCEOF:
727                e = new InstanceOfExpression(scan(), e, parseTerm());
728                break;
729              case ADD:
730                e = new AddExpression(scan(), e, parseTerm());
731                break;
732              case SUB:
733                e = new SubtractExpression(scan(), e, parseTerm());
734                break;
735              case MUL:
736                e = new MultiplyExpression(scan(), e, parseTerm());
737                break;
738              case DIV:
739                e = new DivideExpression(scan(), e, parseTerm());
740                break;
741              case REM:
742                e = new RemainderExpression(scan(), e, parseTerm());
743                break;
744              case LSHIFT:
745                e = new ShiftLeftExpression(scan(), e, parseTerm());
746                break;
747              case RSHIFT:
748                e = new ShiftRightExpression(scan(), e, parseTerm());
749                break;
750              case URSHIFT:
751                e = new UnsignedShiftRightExpression(scan(), e, parseTerm());
752                break;
753              case LT:
754                e = new LessExpression(scan(), e, parseTerm());
755                break;
756              case LE:
757                e = new LessOrEqualExpression(scan(), e, parseTerm());
758                break;
759              case GT:
760                e = new GreaterExpression(scan(), e, parseTerm());
761                break;
762              case GE:
763                e = new GreaterOrEqualExpression(scan(), e, parseTerm());
764                break;
765              case EQ:
766                e = new EqualExpression(scan(), e, parseTerm());
767                break;
768              case NE:
769                e = new NotEqualExpression(scan(), e, parseTerm());
770                break;
771              case BITAND:
772                e = new BitAndExpression(scan(), e, parseTerm());
773                break;
774              case BITXOR:
775                e = new BitXorExpression(scan(), e, parseTerm());
776                break;
777              case BITOR:
778                e = new BitOrExpression(scan(), e, parseTerm());
779                break;
780              case AND:
781                e = new AndExpression(scan(), e, parseTerm());
782                break;
783              case OR:
784                e = new OrExpression(scan(), e, parseTerm());
785                break;
786              case ASSIGN:
787                e = new AssignExpression(scan(), e, parseTerm());
788                break;
789              case ASGMUL:
790                e = new AssignMultiplyExpression(scan(), e, parseTerm());
791                break;
792              case ASGDIV:
793                e = new AssignDivideExpression(scan(), e, parseTerm());
794                break;
795              case ASGREM:
796                e = new AssignRemainderExpression(scan(), e, parseTerm());
797                break;
798              case ASGADD:
799                e = new AssignAddExpression(scan(), e, parseTerm());
800                break;
801              case ASGSUB:
802                e = new AssignSubtractExpression(scan(), e, parseTerm());
803                break;
804              case ASGLSHIFT:
805                e = new AssignShiftLeftExpression(scan(), e, parseTerm());
806                break;
807              case ASGRSHIFT:
808                e = new AssignShiftRightExpression(scan(), e, parseTerm());
809                break;
810              case ASGURSHIFT:
811                e = new AssignUnsignedShiftRightExpression(scan(), e, parseTerm());
812                break;
813              case ASGBITAND:
814                e = new AssignBitAndExpression(scan(), e, parseTerm());
815                break;
816              case ASGBITOR:
817                e = new AssignBitOrExpression(scan(), e, parseTerm());
818                break;
819              case ASGBITXOR:
820                e = new AssignBitXorExpression(scan(), e, parseTerm());
821                break;
822              case QUESTIONMARK: {
823                long p = scan();
824                Expression second = parseExpression();
825                expect(COLON);
826                Expression third = parseExpression();
827
828                // The grammar in the JLS does not allow assignment
829                // expressions as the third part of a ?: expression.
830                // Even though javac has no trouble parsing this,
831                // check for this case and signal an error.
832                // (fix for bug 4092958)
833                if (third instanceof AssignExpression
834                    || third instanceof AssignOpExpression) {
835                    env.error(third.getWhere(), "assign.in.conditionalexpr");
836                }
837
838                e = new ConditionalExpression(p, e, second, third);
839                break;
840              }
841
842              default:
843                return null; // mark end of binary expressions
844            }
845        }
846        return e;           // return more binary expression stuff
847    }
848
849    /**
850     * Recover after a syntax error in a statement. This involves
851     * discarding tokens until EOF or a possible continuation is
852     * encountered.
853     */
854    protected boolean recoverStatement() throws SyntaxError, IOException {
855        while (true) {
856            switch (token) {
857              case EOF:
858              case RBRACE:
859              case LBRACE:
860              case IF:
861              case FOR:
862              case WHILE:
863              case DO:
864              case TRY:
865              case CATCH:
866              case FINALLY:
867              case BREAK:
868              case CONTINUE:
869              case RETURN:
870                // begin of a statement, return
871                return true;
872
873              case VOID:
874              case STATIC:
875              case PUBLIC:
876              case PRIVATE:
877              case SYNCHRONIZED:
878              case INTERFACE:
879              case CLASS:
880              case TRANSIENT:
881                // begin of something outside a statement, panic some more
882                expect(RBRACE);
883                return false;
884
885              case LPAREN:
886                match(LPAREN, RPAREN);
887                scan();
888                break;
889
890              case LSQBRACKET:
891                match(LSQBRACKET, RSQBRACKET);
892                scan();
893                break;
894
895              default:
896                // don't know what to do, skip
897                scan();
898                break;
899            }
900        }
901    }
902
903    /**
904     * Parse declaration, called after the type expression
905     * has been parsed and the current token is IDENT.
906     */
907    protected Statement parseDeclaration(long p, int mod, Expression type) throws SyntaxError, IOException {
908        int i = argIndex;
909        if (token == IDENT) {
910            addArgument(new VarDeclarationStatement(pos, parseExpression()));
911            while (token == COMMA) {
912                scan();
913                addArgument(new VarDeclarationStatement(pos, parseExpression()));
914            }
915        }
916        return new DeclarationStatement(p, mod, type, statArgs(i));
917    }
918
919    /**
920     * Check if an expression is a legal toplevel expression.
921     * Only method, inc, dec, and new expression are allowed.
922     */
923    protected void topLevelExpression(Expression e) {
924        switch (e.getOp()) {
925          case ASSIGN:
926          case ASGMUL:
927          case ASGDIV:
928          case ASGREM:
929          case ASGADD:
930          case ASGSUB:
931          case ASGLSHIFT:
932          case ASGRSHIFT:
933          case ASGURSHIFT:
934          case ASGBITAND:
935          case ASGBITOR:
936          case ASGBITXOR:
937          case PREINC:
938          case PREDEC:
939          case POSTINC:
940          case POSTDEC:
941          case METHOD:
942          case NEWINSTANCE:
943            return;
944        }
945        env.error(e.getWhere(), "invalid.expr");
946    }
947
948    /**
949     * Parse a statement.
950     */
951    protected Statement parseStatement() throws SyntaxError, IOException {
952        switch (token) {
953          case SEMICOLON:
954            return new CompoundStatement(scan(), new Statement[0]);
955
956          case LBRACE:
957              return parseBlockStatement();
958
959          case IF: {
960            // if-statement: if (expr) stat
961            // if-statement: if (expr) stat else stat
962            long p = scan();
963
964            expect(LPAREN);
965            Expression c = parseExpression();
966            expect(RPAREN);
967            Statement t = parseStatement();
968            if (token == ELSE) {
969                scan();
970                return new IfStatement(p, c, t, parseStatement());
971            } else {
972                return new IfStatement(p, c, t, null);
973            }
974          }
975
976          case ELSE: {
977            // else-statement: else stat
978            env.error(scan(), "else.without.if");
979            return parseStatement();
980          }
981
982          case FOR: {
983            // for-statement: for (decl-expr? ; expr? ; expr?) stat
984            long p = scan();
985            Statement init = null;
986            Expression cond = null, inc = null;
987
988            expect(LPAREN);
989            if (token != SEMICOLON) {
990                long p2 = pos;
991                int mod = parseModifiers(M_FINAL);
992                Expression e = parseExpression();
993
994                if (token == IDENT) {
995                    init = parseDeclaration(p2, mod, e);
996                } else {
997                    if (mod != 0) {
998                        expect(IDENT); // should have been a declaration
999                    }
1000                    topLevelExpression(e);
1001                    while (token == COMMA) {
1002                        long p3 = scan();
1003                        Expression e2 = parseExpression();
1004                        topLevelExpression(e2);
1005                        e = new CommaExpression(p3, e, e2);
1006                    }
1007                    init = new ExpressionStatement(p2, e);
1008                }
1009            }
1010            expect(SEMICOLON);
1011            if (token != SEMICOLON) {
1012                cond = parseExpression();
1013            }
1014            expect(SEMICOLON);
1015            if (token != RPAREN) {
1016                inc = parseExpression();
1017                topLevelExpression(inc);
1018                while (token == COMMA) {
1019                    long p2 = scan();
1020                    Expression e2 = parseExpression();
1021                    topLevelExpression(e2);
1022                    inc = new CommaExpression(p2, inc, e2);
1023                }
1024            }
1025            expect(RPAREN);
1026            return new ForStatement(p, init, cond, inc, parseStatement());
1027          }
1028
1029          case WHILE: {
1030            // while-statement: while (expr) stat
1031            long p = scan();
1032
1033            expect(LPAREN);
1034            Expression cond = parseExpression();
1035            expect(RPAREN);
1036            return new WhileStatement(p, cond, parseStatement());
1037          }
1038
1039          case DO: {
1040            // do-statement: do stat while (expr)
1041            long p = scan();
1042
1043            Statement body = parseStatement();
1044            expect(WHILE);
1045            expect(LPAREN);
1046            Expression cond = parseExpression();
1047            expect(RPAREN);
1048            expect(SEMICOLON);
1049            return new DoStatement(p, body, cond);
1050          }
1051
1052          case BREAK: {
1053            // break-statement: break ;
1054            long p = scan();
1055            Identifier label = null;
1056
1057            if (token == IDENT) {
1058                label = scanner.idValue;
1059                scan();
1060            }
1061            expect(SEMICOLON);
1062            return new BreakStatement(p, label);
1063          }
1064
1065          case CONTINUE: {
1066            // continue-statement: continue ;
1067            long p = scan();
1068            Identifier label = null;
1069
1070            if (token == IDENT) {
1071                label = scanner.idValue;
1072                scan();
1073            }
1074            expect(SEMICOLON);
1075            return new ContinueStatement(p, label);
1076          }
1077
1078          case RETURN: {
1079            // return-statement: return ;
1080            // return-statement: return expr ;
1081            long p = scan();
1082            Expression e = null;
1083
1084            if (token != SEMICOLON) {
1085                e = parseExpression();
1086            }
1087            expect(SEMICOLON);
1088            return new ReturnStatement(p, e);
1089          }
1090
1091          case SWITCH: {
1092            // switch statement: switch ( expr ) stat
1093            long p = scan();
1094            int i = argIndex;
1095
1096            expect(LPAREN);
1097            Expression e = parseExpression();
1098            expect(RPAREN);
1099            expect(LBRACE);
1100
1101            while ((token != EOF) && (token != RBRACE)) {
1102                int j = argIndex;
1103                try {
1104                    switch (token) {
1105                      case CASE:
1106                        // case-statement: case expr:
1107                        addArgument(new CaseStatement(scan(), parseExpression()));
1108                        expect(COLON);
1109                        break;
1110
1111                      case DEFAULT:
1112                        // default-statement: default:
1113                        addArgument(new CaseStatement(scan(), null));
1114                        expect(COLON);
1115                        break;
1116
1117                      default:
1118                        addArgument(parseStatement());
1119                        break;
1120                    }
1121                } catch (SyntaxError ee) {
1122                    argIndex = j;
1123                    if (!recoverStatement()) {
1124                        throw ee;
1125                    }
1126                }
1127            }
1128            expect(RBRACE);
1129            return new SwitchStatement(p, e, statArgs(i));
1130          }
1131
1132          case CASE: {
1133            // case-statement: case expr : stat
1134            env.error(pos, "case.without.switch");
1135            while (token == CASE) {
1136                scan();
1137                parseExpression();
1138                expect(COLON);
1139            }
1140            return parseStatement();
1141          }
1142
1143          case DEFAULT: {
1144            // default-statement: default : stat
1145            env.error(pos, "default.without.switch");
1146            scan();
1147            expect(COLON);
1148            return parseStatement();
1149          }
1150
1151          case TRY: {
1152            // try-statement: try stat catch (type-expr ident) stat finally stat
1153            long p = scan();
1154            Statement init = null;              // try-object specification
1155            int i = argIndex;
1156            boolean catches = false;
1157
1158            if (false && token == LPAREN) {
1159                expect(LPAREN);
1160                long p2 = pos;
1161                int mod = parseModifiers(M_FINAL);
1162                Expression e = parseExpression();
1163
1164                if (token == IDENT) {
1165                    init = parseDeclaration(p2, mod, e);
1166                    // leave check for try (T x, y) for semantic phase
1167                } else {
1168                    if (mod != 0) {
1169                        expect(IDENT); // should have been a declaration
1170                    }
1171                    init = new ExpressionStatement(p2, e);
1172                }
1173                expect(RPAREN);
1174            }
1175
1176            Statement s = parseBlockStatement();
1177
1178            if (init != null) {
1179                // s = new FinallyStatement(p, init, s, 0);
1180            }
1181
1182            while (token == CATCH) {
1183                long pp = pos;
1184                expect(CATCH);
1185                expect(LPAREN);
1186                int mod = parseModifiers(M_FINAL);
1187                Expression t = parseExpression();
1188                IdentifierToken id = scanner.getIdToken();
1189                expect(IDENT);
1190                id.modifiers = mod;
1191                // We only catch Throwable's, so this is no longer required
1192                // while (token == LSQBRACKET) {
1193                //    t = new ArrayAccessExpression(scan(), t, null);
1194                //    expect(RSQBRACKET);
1195                // }
1196                expect(RPAREN);
1197                addArgument(new CatchStatement(pp, t, id, parseBlockStatement()));
1198                catches = true;
1199            }
1200
1201            if (catches)
1202                s = new TryStatement(p, s, statArgs(i));
1203
1204            if (token == FINALLY) {
1205                scan();
1206                return new FinallyStatement(p, s, parseBlockStatement());
1207            } else if (catches || init != null) {
1208                return s;
1209            } else {
1210                env.error(pos, "try.without.catch.finally");
1211                return new TryStatement(p, s, null);
1212            }
1213          }
1214
1215          case CATCH: {
1216            // catch-statement: catch (expr ident) stat finally stat
1217            env.error(pos, "catch.without.try");
1218
1219            Statement s;
1220            do {
1221                scan();
1222                expect(LPAREN);
1223                parseModifiers(M_FINAL);
1224                parseExpression();
1225                expect(IDENT);
1226                expect(RPAREN);
1227                s = parseBlockStatement();
1228            } while (token == CATCH);
1229
1230            if (token == FINALLY) {
1231                scan();
1232                s = parseBlockStatement();
1233            }
1234            return s;
1235          }
1236
1237          case FINALLY: {
1238            // finally-statement: finally stat
1239            env.error(pos, "finally.without.try");
1240            scan();
1241            return parseBlockStatement();
1242          }
1243
1244          case THROW: {
1245            // throw-statement: throw expr;
1246            long p = scan();
1247            Expression e = parseExpression();
1248            expect(SEMICOLON);
1249            return new ThrowStatement(p, e);
1250          }
1251
1252          case GOTO: {
1253            long p = scan();
1254            expect(IDENT);
1255            expect(SEMICOLON);
1256            env.error(p, "not.supported", "goto");
1257            return new CompoundStatement(p, new Statement[0]);
1258          }
1259
1260          case SYNCHRONIZED: {
1261            // synchronized-statement: synchronized (expr) stat
1262            long p = scan();
1263            expect(LPAREN);
1264            Expression e = parseExpression();
1265            expect(RPAREN);
1266            return new SynchronizedStatement(p, e, parseBlockStatement());
1267          }
1268
1269          case INTERFACE:
1270          case CLASS:
1271            // Inner class.
1272            return parseLocalClass(0);
1273
1274          case CONST:
1275          case ABSTRACT:
1276          case FINAL:
1277          case STRICTFP: {
1278            // a declaration of some sort
1279            long p = pos;
1280
1281            // A class which is local to a block is not a member, and so
1282            // cannot be public, private, protected, or static. It is in
1283            // effect private to the block, since it cannot be used outside
1284            // its scope.
1285            //
1286            // However, any class (if it has a name) can be declared final,
1287            // abstract, or strictfp.
1288            int mod = parseModifiers(M_FINAL | M_ABSTRACT
1289                                             | M_STRICTFP );
1290
1291            switch (token) {
1292              case INTERFACE:
1293              case CLASS:
1294                return parseLocalClass(mod);
1295
1296              case BOOLEAN:
1297              case BYTE:
1298              case CHAR:
1299              case SHORT:
1300              case INT:
1301              case LONG:
1302              case FLOAT:
1303              case DOUBLE:
1304              case IDENT: {
1305                if ((mod & (M_ABSTRACT | M_STRICTFP )) != 0) {
1306                    mod &= ~ (M_ABSTRACT | M_STRICTFP );
1307                    expect(CLASS);
1308                }
1309                Expression e = parseExpression();
1310                if (token != IDENT) {
1311                    expect(IDENT);
1312                }
1313                // declaration: final expr expr
1314                Statement s = parseDeclaration(p, mod, e);
1315                expect(SEMICOLON);
1316                return s;
1317              }
1318
1319              default:
1320                env.error(pos, "type.expected");
1321                throw new SyntaxError();
1322            }
1323          }
1324
1325          case VOID:
1326          case STATIC:
1327          case PUBLIC:
1328          case PRIVATE:
1329          case TRANSIENT:
1330            // This is the start of something outside a statement
1331            env.error(pos, "statement.expected");
1332            throw new SyntaxError();
1333        }
1334
1335        long p = pos;
1336        Expression e = parseExpression();
1337
1338        if (token == IDENT) {
1339            // declaration: expr expr
1340            Statement s = parseDeclaration(p, 0, e);
1341            expect(SEMICOLON);
1342            return s;
1343        }
1344        if (token == COLON) {
1345            // label: id: stat
1346            scan();
1347            Statement s = parseStatement();
1348            s.setLabel(env, e);
1349            return s;
1350        }
1351
1352        // it was just an expression...
1353        topLevelExpression(e);
1354        expect(SEMICOLON);
1355        return new ExpressionStatement(p, e);
1356    }
1357
1358    protected Statement parseBlockStatement() throws SyntaxError, IOException {
1359        // compound statement: { stat1 stat2 ... statn }
1360        if (token != LBRACE) {
1361            // We're expecting a block statement.  But we'll probably do the
1362            // least damage if we try to parse a normal statement instead.
1363            env.error(scanner.prevPos, "token.expected", opNames[LBRACE]);
1364            return parseStatement();
1365        }
1366        long p = scan();
1367        int i = argIndex;
1368        while ((token != EOF) && (token != RBRACE)) {
1369            int j = argIndex;
1370            try {
1371                addArgument(parseStatement());
1372            } catch (SyntaxError e) {
1373                argIndex = j;
1374                if (!recoverStatement()) {
1375                    throw e;
1376                }
1377            }
1378        }
1379
1380        expect(RBRACE);
1381        return new CompoundStatement(p, statArgs(i));
1382    }
1383
1384
1385    /**
1386     * Parse an identifier. ie: a.b.c returns "a.b.c"
1387     * If star is true then "a.b.*" is allowed.
1388     * The return value encodes both the identifier and its location.
1389     */
1390    protected IdentifierToken parseName(boolean star) throws SyntaxError, IOException {
1391        IdentifierToken res = scanner.getIdToken();
1392        expect(IDENT);
1393
1394        if (token != FIELD) {
1395            return res;
1396        }
1397
1398        StringBuilder sb = new StringBuilder(res.id.toString());
1399
1400        while (token == FIELD) {
1401            scan();
1402            if ((token == MUL) && star) {
1403                scan();
1404                sb.append(".*");
1405                break;
1406            }
1407
1408            sb.append('.');
1409            if (token == IDENT) {
1410                sb.append(scanner.idValue);
1411            }
1412            expect(IDENT);
1413        }
1414
1415        res.id = Identifier.lookup(sb.toString());
1416        return res;
1417    }
1418    /**
1419     * @deprecated
1420     * @see #parseName
1421     */
1422    @Deprecated
1423    protected Identifier parseIdentifier(boolean star) throws SyntaxError, IOException {
1424        return parseName(star).id;
1425    }
1426
1427    /**
1428     * Parse a type expression, this results in a Type.
1429     * The parse includes trailing array brackets.
1430     */
1431    protected Type parseType() throws SyntaxError, IOException {
1432        Type t;
1433
1434        switch (token) {
1435          case IDENT:
1436            t = Type.tClass(parseName(false).id);
1437            break;
1438          case VOID:
1439            scan();
1440            t = Type.tVoid;
1441            break;
1442          case BOOLEAN:
1443            scan();
1444            t = Type.tBoolean;
1445            break;
1446          case BYTE:
1447            scan();
1448            t = Type.tByte;
1449            break;
1450          case CHAR:
1451            scan();
1452            t = Type.tChar;
1453            break;
1454          case SHORT:
1455            scan();
1456            t = Type.tShort;
1457            break;
1458          case INT:
1459            scan();
1460            t = Type.tInt;
1461            break;
1462          case FLOAT:
1463            scan();
1464            t = Type.tFloat;
1465            break;
1466          case LONG:
1467            scan();
1468            t = Type.tLong;
1469            break;
1470          case DOUBLE:
1471            scan();
1472            t = Type.tDouble;
1473            break;
1474          default:
1475            env.error(pos, "type.expected");
1476            throw new SyntaxError();
1477        }
1478        return parseArrayBrackets(t);
1479    }
1480
1481    /**
1482     * Parse the tail of a type expression, which might be array brackets.
1483     * Return the given type, as possibly modified by the suffix.
1484     */
1485    protected Type parseArrayBrackets(Type t) throws SyntaxError, IOException {
1486
1487        // Parse []'s
1488        while (token == LSQBRACKET) {
1489            scan();
1490            if (token != RSQBRACKET) {
1491                env.error(pos, "array.dim.in.decl");
1492                parseExpression();
1493            }
1494            expect(RSQBRACKET);
1495            t = Type.tArray(t);
1496        }
1497        return t;
1498    }
1499
1500    /*
1501     * Dealing with argument lists, I'm not using
1502     * Vector for efficiency.
1503     */
1504
1505    private int aCount = 0;
1506    private Type aTypes[] = new Type[8];
1507    private IdentifierToken aNames[] = new IdentifierToken[aTypes.length];
1508
1509    private void addArgument(int mod, Type t, IdentifierToken nm) {
1510        nm.modifiers = mod;
1511        if (aCount >= aTypes.length) {
1512            Type newATypes[] = new Type[aCount * 2];
1513            System.arraycopy(aTypes, 0, newATypes, 0, aCount);
1514            aTypes = newATypes;
1515            IdentifierToken newANames[] = new IdentifierToken[aCount * 2];
1516            System.arraycopy(aNames, 0, newANames, 0, aCount);
1517            aNames = newANames;
1518        }
1519        aTypes[aCount] = t;
1520        aNames[aCount++] = nm;
1521    }
1522
1523    /**
1524     * Parse a possibly-empty sequence of modifier keywords.
1525     * Return the resulting bitmask.
1526     * Diagnose repeated modifiers, but make no other checks.
1527     * Only modifiers mentioned in the given bitmask are scanned;
1528     * an unmatched modifier must be handled by the caller.
1529     */
1530    protected int parseModifiers(int mask) throws IOException {
1531        int mod = 0;
1532        while (true) {
1533            if (token==CONST) {
1534                // const isn't in java, but handle a common C++ usage gently
1535                env.error(pos, "not.supported", "const");
1536                scan();
1537            }
1538            int nextmod = 0;
1539            switch (token) {
1540               case PRIVATE:            nextmod = M_PRIVATE;      break;
1541               case PUBLIC:             nextmod = M_PUBLIC;       break;
1542               case PROTECTED:          nextmod = M_PROTECTED;    break;
1543               case STATIC:             nextmod = M_STATIC;       break;
1544               case TRANSIENT:          nextmod = M_TRANSIENT;    break;
1545               case FINAL:              nextmod = M_FINAL;        break;
1546               case ABSTRACT:           nextmod = M_ABSTRACT;     break;
1547               case NATIVE:             nextmod = M_NATIVE;       break;
1548               case VOLATILE:           nextmod = M_VOLATILE;     break;
1549               case SYNCHRONIZED:       nextmod = M_SYNCHRONIZED; break;
1550               case STRICTFP:           nextmod = M_STRICTFP;     break;
1551            }
1552            if ((nextmod & mask) == 0) {
1553                break;
1554            }
1555            if ((nextmod & mod) != 0) {
1556                env.error(pos, "repeated.modifier");
1557            }
1558            mod |= nextmod;
1559            scan();
1560        }
1561        return mod;
1562    }
1563
1564    private ClassDefinition curClass;
1565
1566    /**
1567     * Parse a field.
1568     */
1569    protected void parseField() throws SyntaxError, IOException {
1570
1571        // Empty fields are not allowed by the JLS but are accepted by
1572        // the compiler, and much code has come to rely on this.  It has
1573        // been decided that the language will be extended to legitimize them.
1574        if (token == SEMICOLON) {
1575            // empty field
1576            scan();
1577            return;
1578        }
1579
1580        // Optional doc comment
1581        String doc = scanner.docComment;
1582
1583        // The start of the field
1584        long p = pos;
1585
1586        // Parse the modifiers
1587        int mod = parseModifiers(MM_FIELD | MM_METHOD);
1588
1589        // Check for static initializer
1590        // ie: static { ... }
1591        // or an instance initializer (w/o the static).
1592        if ((mod == (mod & M_STATIC)) && (token == LBRACE)) {
1593            // static initializer
1594            actions.defineField(p, curClass, doc, mod,
1595                                Type.tMethod(Type.tVoid),
1596                                new IdentifierToken(idClassInit), null, null,
1597                                parseStatement());
1598            return;
1599        }
1600
1601        // Check for inner class
1602        if (token == CLASS || token == INTERFACE) {
1603            parseNamedClass(mod, CLASS, doc);
1604            return;
1605        }
1606
1607        // Parse the type
1608        p = pos;
1609        Type t = parseType();
1610        IdentifierToken id = null;
1611
1612        // Check that the type is followed by an Identifier
1613        // (the name of the method or the first variable),
1614        // otherwise it is a constructor.
1615        switch (token) {
1616          case IDENT:
1617            id = scanner.getIdToken();
1618            p = scan();
1619            break;
1620
1621          case LPAREN:
1622            // It is a constructor
1623            id = new IdentifierToken(idInit);
1624            if ((mod & M_STRICTFP) != 0)
1625                env.error(pos, "bad.constructor.modifier");
1626            break;
1627
1628          default:
1629            expect(IDENT);
1630        }
1631
1632        // If the next token is a left-bracket then we
1633        // are dealing with a method or constructor, otherwise it is
1634        // a list of variables
1635        if (token == LPAREN) {
1636            // It is a method or constructor declaration
1637            scan();
1638            aCount = 0;
1639
1640            if (token != RPAREN) {
1641                // Parse argument type and identifier
1642                // (arguments (like locals) are allowed to be final)
1643                int am = parseModifiers(M_FINAL);
1644                Type at = parseType();
1645                IdentifierToken an = scanner.getIdToken();
1646                expect(IDENT);
1647
1648                // Parse optional array specifier, ie: a[][]
1649                at = parseArrayBrackets(at);
1650                addArgument(am, at, an);
1651
1652                // If the next token is a comma then there are
1653                // more arguments
1654                while (token == COMMA) {
1655                    // Parse argument type and identifier
1656                    scan();
1657                    am = parseModifiers(M_FINAL);
1658                    at = parseType();
1659                    an = scanner.getIdToken();
1660                    expect(IDENT);
1661
1662                    // Parse optional array specifier, ie: a[][]
1663                    at = parseArrayBrackets(at);
1664                    addArgument(am, at, an);
1665                }
1666            }
1667            expect(RPAREN);
1668
1669            // Parse optional array sepecifier, ie: foo()[][]
1670            t = parseArrayBrackets(t);
1671
1672            // copy arguments
1673            Type atypes[] = new Type[aCount];
1674            System.arraycopy(aTypes, 0, atypes, 0, aCount);
1675
1676            IdentifierToken anames[] = new IdentifierToken[aCount];
1677            System.arraycopy(aNames, 0, anames, 0, aCount);
1678
1679            // Construct the type signature
1680            t = Type.tMethod(t, atypes);
1681
1682            // Parse and ignore throws clause
1683            IdentifierToken exp[] = null;
1684            if (token == THROWS) {
1685                Vector<IdentifierToken> v = new Vector<>();
1686                scan();
1687                v.addElement(parseName(false));
1688                while (token == COMMA) {
1689                    scan();
1690                    v.addElement(parseName(false));
1691                }
1692
1693                exp = new IdentifierToken[v.size()];
1694                v.copyInto(exp);
1695            }
1696
1697            // Check if it is a method definition or a method declaration
1698            // ie: foo() {...} or foo();
1699            switch (token) {
1700              case LBRACE:      // It's a method definition
1701
1702                // Set the state of FP strictness for the body of the method
1703                int oldFPstate = FPstate;
1704                if ((mod & M_STRICTFP)!=0) {
1705                    FPstate = M_STRICTFP;
1706                } else {
1707                    mod |= FPstate & M_STRICTFP;
1708                }
1709
1710                actions.defineField(p, curClass, doc, mod, t, id,
1711                                    anames, exp, parseStatement());
1712
1713                FPstate = oldFPstate;
1714
1715                break;
1716
1717              case SEMICOLON:
1718                scan();
1719                actions.defineField(p, curClass, doc, mod, t, id,
1720                                    anames, exp, null);
1721                break;
1722
1723              default:
1724                // really expected a statement body here
1725                if ((mod & (M_NATIVE | M_ABSTRACT)) == 0) {
1726                    expect(LBRACE);
1727                } else {
1728                    expect(SEMICOLON);
1729                }
1730            }
1731            return;
1732        }
1733
1734        // It is a list of instance variables
1735        while (true) {
1736            p = pos;            // get the current position
1737            // parse the array brackets (if any)
1738            // ie: var[][][]
1739            Type vt = parseArrayBrackets(t);
1740
1741            // Parse the optional initializer
1742            Node init = null;
1743            if (token == ASSIGN) {
1744                scan();
1745                init = parseExpression();
1746            }
1747
1748            // Define the variable
1749            actions.defineField(p, curClass, doc, mod, vt, id,
1750                                null, null, init);
1751
1752            // If the next token is a comma, then there is more
1753            if (token != COMMA) {
1754                expect(SEMICOLON);
1755                return;
1756            }
1757            scan();
1758
1759            // The next token must be an identifier
1760            id = scanner.getIdToken();
1761            expect(IDENT);
1762        }
1763    }
1764
1765    /**
1766     * Recover after a syntax error in a field. This involves
1767     * discarding tokens until an EOF or a possible legal
1768     * continuation is encountered.
1769     */
1770    protected void recoverField(ClassDefinition newClass) throws SyntaxError, IOException {
1771        while (true) {
1772            switch (token) {
1773              case EOF:
1774              case STATIC:
1775              case FINAL:
1776              case PUBLIC:
1777              case PRIVATE:
1778              case SYNCHRONIZED:
1779              case TRANSIENT:
1780
1781              case VOID:
1782              case BOOLEAN:
1783              case BYTE:
1784              case CHAR:
1785              case SHORT:
1786              case INT:
1787              case FLOAT:
1788              case LONG:
1789              case DOUBLE:
1790                // possible begin of a field, continue
1791                return;
1792
1793              case LBRACE:
1794                match(LBRACE, RBRACE);
1795                scan();
1796                break;
1797
1798              case LPAREN:
1799                match(LPAREN, RPAREN);
1800                scan();
1801                break;
1802
1803              case LSQBRACKET:
1804                match(LSQBRACKET, RSQBRACKET);
1805                scan();
1806                break;
1807
1808              case RBRACE:
1809              case INTERFACE:
1810              case CLASS:
1811              case IMPORT:
1812              case PACKAGE:
1813                // begin of something outside a class, panic more
1814                actions.endClass(pos, newClass);
1815                throw new SyntaxError();
1816
1817              default:
1818                // don't know what to do, skip
1819                scan();
1820                break;
1821            }
1822        }
1823    }
1824
1825    /**
1826     * Parse a top-level class or interface declaration.
1827     */
1828    protected void parseClass() throws SyntaxError, IOException {
1829        String doc = scanner.docComment;
1830
1831        // Parse the modifiers.
1832        int mod = parseModifiers(MM_CLASS | MM_MEMBER);
1833
1834        parseNamedClass(mod, PACKAGE, doc);
1835    }
1836
1837    // Current strict/default state of floating point.  This is
1838    // set and reset with a stack discipline around methods and named
1839    // classes.  Only M_STRICTFP may be set in this word.  try...
1840    // finally is not needed to protect setting and resetting because
1841    // there are no error messages based on FPstate.
1842    private int FPstate = 0;
1843
1844    /**
1845     * Parse a block-local class or interface declaration.
1846     */
1847    protected Statement parseLocalClass(int mod) throws SyntaxError, IOException {
1848        long p = pos;
1849        ClassDefinition body = parseNamedClass(M_LOCAL | mod, STAT, null);
1850        Statement ds[] = {
1851            new VarDeclarationStatement(p, new LocalMember(body), null)
1852        };
1853        Expression type = new TypeExpression(p, body.getType());
1854        return new DeclarationStatement(p, 0, type, ds);
1855    }
1856
1857    /**
1858     * Parse a named class or interface declaration,
1859     * starting at "class" or "interface".
1860     * @arg ctx Syntactic context of the class, one of {PACKAGE CLASS STAT EXPR}.
1861     */
1862    protected ClassDefinition parseNamedClass(int mod, int ctx, String doc) throws SyntaxError, IOException {
1863        // Parse class/interface
1864        switch (token) {
1865          case INTERFACE:
1866            scan();
1867            mod |= M_INTERFACE;
1868            break;
1869
1870          case CLASS:
1871            scan();
1872            break;
1873
1874          default:
1875            env.error(pos, "class.expected");
1876            break;
1877        }
1878
1879        int oldFPstate = FPstate;
1880        if ((mod & M_STRICTFP)!=0) {
1881            FPstate = M_STRICTFP;
1882        } else {
1883            // The & (...) isn't really necessary here because we do maintain
1884            // the invariant that FPstate has no extra bits set.
1885            mod |= FPstate & M_STRICTFP;
1886        }
1887
1888        // Parse the class name
1889        IdentifierToken nm = scanner.getIdToken();
1890        long p = pos;
1891        expect(IDENT);
1892
1893        Vector<IdentifierToken> ext = new Vector<>();
1894        Vector<IdentifierToken> impl = new Vector<>();
1895        parseInheritance(ext, impl);
1896
1897        ClassDefinition tmp = parseClassBody(nm, mod, ctx, doc, ext, impl, p);
1898
1899        FPstate = oldFPstate;
1900
1901        return tmp;
1902    }
1903
1904    protected void parseInheritance(Vector<IdentifierToken> ext, Vector<IdentifierToken> impl) throws SyntaxError, IOException {
1905        // Parse extends clause
1906        if (token == EXTENDS) {
1907            scan();
1908            ext.addElement(parseName(false));
1909            while (token == COMMA) {
1910                scan();
1911                ext.addElement(parseName(false));
1912            }
1913        }
1914
1915        // Parse implements clause
1916        if (token == IMPLEMENTS) {
1917            scan();
1918            impl.addElement(parseName(false));
1919            while (token == COMMA) {
1920                scan();
1921                impl.addElement(parseName(false));
1922            }
1923        }
1924    }
1925
1926    /**
1927     * Parse the body of a class or interface declaration,
1928     * starting at the left brace.
1929     */
1930    protected ClassDefinition parseClassBody(IdentifierToken nm, int mod,
1931                                             int ctx, String doc,
1932                                             Vector<IdentifierToken> ext, Vector<IdentifierToken> impl, long p
1933                                             ) throws SyntaxError, IOException {
1934        // Decide which is the super class
1935        IdentifierToken sup = null;
1936        if ((mod & M_INTERFACE) != 0) {
1937            if (impl.size() > 0) {
1938                env.error(impl.elementAt(0).getWhere(),
1939                          "intf.impl.intf");
1940            }
1941            impl = ext;
1942        } else {
1943            if (ext.size() > 0) {
1944                if (ext.size() > 1) {
1945                    env.error(ext.elementAt(1).getWhere(),
1946                              "multiple.inherit");
1947                }
1948                sup = ext.elementAt(0);
1949            }
1950        }
1951
1952        ClassDefinition oldClass = curClass;
1953
1954        // Begin a new class
1955        IdentifierToken implids[] = new IdentifierToken[impl.size()];
1956        impl.copyInto(implids);
1957        ClassDefinition newClass =
1958            actions.beginClass(p, doc, mod, nm, sup, implids);
1959
1960        // Parse fields
1961        expect(LBRACE);
1962        while ((token != EOF) && (token != RBRACE)) {
1963            try {
1964                curClass = newClass;
1965                parseField();
1966            } catch (SyntaxError e) {
1967                recoverField(newClass);
1968            } finally {
1969                curClass = oldClass;
1970            }
1971        }
1972        expect(RBRACE);
1973
1974        // End the class
1975        actions.endClass(scanner.prevPos, newClass);
1976        return newClass;
1977    }
1978
1979    /**
1980     * Recover after a syntax error in the file.
1981     * This involves discarding tokens until an EOF
1982     * or a possible legal continuation is encountered.
1983     */
1984    protected void recoverFile() throws IOException {
1985        while (true) {
1986            switch (token) {
1987              case CLASS:
1988              case INTERFACE:
1989                // Start of a new source file statement, continue
1990                return;
1991
1992              case LBRACE:
1993                match(LBRACE, RBRACE);
1994                scan();
1995                break;
1996
1997              case LPAREN:
1998                match(LPAREN, RPAREN);
1999                scan();
2000                break;
2001
2002              case LSQBRACKET:
2003                match(LSQBRACKET, RSQBRACKET);
2004                scan();
2005                break;
2006
2007              case EOF:
2008                return;
2009
2010              default:
2011                // Don't know what to do, skip
2012                scan();
2013                break;
2014            }
2015        }
2016    }
2017
2018    /**
2019     * Parse an Java file.
2020     */
2021    public void parseFile() {
2022        try {
2023            try {
2024                if (token == PACKAGE) {
2025                    // Package statement
2026                    long p = scan();
2027                    IdentifierToken id = parseName(false);
2028                    expect(SEMICOLON);
2029                    actions.packageDeclaration(p, id);
2030                }
2031            } catch (SyntaxError e) {
2032                recoverFile();
2033            }
2034            while (token == IMPORT) {
2035                try{
2036                    // Import statement
2037                    long p = scan();
2038                    IdentifierToken id = parseName(true);
2039                    expect(SEMICOLON);
2040                    if (id.id.getName().equals(idStar)) {
2041                        id.id = id.id.getQualifier();
2042                        actions.importPackage(p, id);
2043                    } else {
2044                        actions.importClass(p, id);
2045                    }
2046                } catch (SyntaxError e) {
2047                    recoverFile();
2048                }
2049            }
2050
2051            while (token != EOF) {
2052                try {
2053                    switch (token) {
2054                      case FINAL:
2055                      case PUBLIC:
2056                      case PRIVATE:
2057                      case ABSTRACT:
2058                      case CLASS:
2059                      case INTERFACE:
2060                      case STRICTFP:
2061                        // Start of a class
2062                        parseClass();
2063                        break;
2064
2065                      case SEMICOLON:
2066                        // Bogus semicolon.
2067                        // According to the JLS (7.6,19.6), a TypeDeclaration
2068                        // may consist of a single semicolon, however, this
2069                        // usage is discouraged (JLS 7.6).  In contrast,
2070                        // a FieldDeclaration may not be empty, and is flagged
2071                        // as an error.  See parseField above.
2072                        scan();
2073                        break;
2074
2075                      case EOF:
2076                        // The end
2077                        return;
2078
2079                      default:
2080                        // Oops
2081                        env.error(pos, "toplevel.expected");
2082                        throw new SyntaxError();
2083                    }
2084                } catch (SyntaxError e) {
2085                    recoverFile();
2086                }
2087            }
2088        } catch (IOException e) {
2089            env.error(pos, "io.exception", env.getSource());
2090            return;
2091        }
2092    }
2093
2094    /**
2095     * Usually <code>this.scanner == (Scanner)this</code>.
2096     * However, a delegate scanner can produce tokens for this parser,
2097     * in which case <code>(Scanner)this</code> is unused,
2098     * except for <code>this.token</code> and <code>this.pos</code>
2099     * instance variables which are filled from the real scanner
2100     * by <code>this.scan()</code> and the constructor.
2101     */
2102    protected Scanner scanner;
2103
2104    // Design Note: We ought to disinherit Parser from Scanner.
2105    // We also should split out the interface ParserActions from
2106    // Parser, and make BatchParser implement ParserActions,
2107    // not extend Parser.  This would split scanning, parsing,
2108    // and class building into distinct responsibility areas.
2109    // (Perhaps tree building could be virtualized too.)
2110
2111    public long scan() throws IOException {
2112        if (scanner != this && scanner != null) {
2113            long result = scanner.scan();
2114            ((Scanner)this).token = scanner.token;
2115            ((Scanner)this).pos = scanner.pos;
2116            return result;
2117        }
2118        return super.scan();
2119    }
2120
2121    public void match(int open, int close) throws IOException {
2122        if (scanner != this) {
2123            scanner.match(open, close);
2124            ((Scanner)this).token = scanner.token;
2125            ((Scanner)this).pos = scanner.pos;
2126            return;
2127        }
2128        super.match(open, close);
2129    }
2130}
2131