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 
26 package sun.tools.java;
27 
28 import sun.tools.tree.*;
29 import java.io.IOException;
30 import java.io.InputStream;
31 import java.util.Enumeration;
32 import 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 
67 public
68 class Parser extends Scanner implements ParserActions, Constants {
69     /**
70      * Create a parser
71      */
Parser(Environment env, InputStream in)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      */
Parser(Scanner scanner)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      */
Parser(Scanner scanner, ParserActions actions)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
packageDeclaration(long off, IdentifierToken nm)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
packageDeclaration(long off, Identifier nm)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
importClass(long off, IdentifierToken nm)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
importClass(long off, Identifier nm)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
importPackage(long off, IdentifierToken nm)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
importPackage(long off, Identifier nm)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
beginClass(long off, String doc, int mod, IdentifierToken nm, IdentifierToken sup, IdentifierToken impl[])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
beginClass(long off, String doc, int mod, Identifier nm, Identifier sup, Identifier impl[])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      */
getCurrentClass()209     protected ClassDefinition getCurrentClass() {
210         return null;
211     }
212 
213     /**
214      * End class
215      * @deprecated
216      */
217     @Deprecated
endClass(long off, ClassDefinition c)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
endClass(long off, Identifier nm)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
defineField(long where, ClassDefinition c, String doc, int mod, Type t, IdentifierToken nm, IdentifierToken args[], IdentifierToken exp[], Node val)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
defineField(long where, String doc, int mod, Type t, Identifier nm, Identifier args[], Identifier exp[], Node val)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 
addArgument(Node n)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     }
exprArgs(int index)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     }
statArgs(int index)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      */
expect(int t)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      */
parseTypeExpression()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      */
parseMethodExpression(Expression e, Identifier id)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      */
parseNewInstanceExpression(long p, Expression outerArg, Expression type)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      */
parseTerm()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      */
parseExpression()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      */
parseBinaryExpression(Expression e)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      */
recoverStatement()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      */
parseDeclaration(long p, int mod, Expression type)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      */
topLevelExpression(Expression e)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      */
parseStatement()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 
parseBlockStatement()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      */
parseName(boolean star)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
parseIdentifier(boolean star)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      */
parseType()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      */
parseArrayBrackets(Type t)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 
addArgument(int mod, Type t, IdentifierToken nm)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      */
parseModifiers(int mask)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      */
parseField()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      */
recoverField(ClassDefinition newClass)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      */
parseClass()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      */
parseLocalClass(int mod)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      */
parseNamedClass(int mod, int ctx, String doc)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 
parseInheritance(Vector<IdentifierToken> ext, Vector<IdentifierToken> impl)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      */
parseClassBody(IdentifierToken nm, int mod, int ctx, String doc, Vector<IdentifierToken> ext, Vector<IdentifierToken> impl, long p )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      */
recoverFile()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      */
parseFile()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 
scan()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 
match(int open, int close)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