blob: 316b62f7551e988b028d88e37f497b8d6aca6122 [file] [log] [blame]
J. Duke319a3b92007-12-01 00:00:00 +00001/*
2 * Copyright 1994-2004 Sun Microsystems, Inc. All Rights Reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. Sun designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Sun in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
22 * CA 95054 USA or visit www.sun.com if you need additional information or
23 * have any questions.
24 */
25
26package 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 ext = new Vector(1);
396 Vector 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 StringBuffer buf = new StringBuffer(res.id.toString());
1399
1400 while (token == FIELD) {
1401 scan();
1402 if ((token == MUL) && star) {
1403 scan();
1404 buf.append(".*");
1405 break;
1406 }
1407
1408 buf.append('.');
1409 if (token == IDENT) {
1410 buf.append(scanner.idValue);
1411 }
1412 expect(IDENT);
1413 }
1414
1415 res.id = Identifier.lookup(buf.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 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 ext = new Vector();
1894 Vector 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 ext, Vector 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 ext, Vector 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(((IdentifierToken)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(((IdentifierToken)ext.elementAt(1)).getWhere(),
1946 "multiple.inherit");
1947 }
1948 sup = (IdentifierToken)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}