History

My first initial commit with all of mine experimental changes.

Dmitry Kabak (userdima committed 13 years ago

Commit d37b88d1 parent 3f5b46618352 files · +2598093 −-8690Browse files

Showing the changes to java/pkg/sun/tools/java/Parser.java (1 of 18352 files). Show all

Unified · Split

java/pkg/sun/tools/java/Parser.java+2130−0
@@ -0,0 +1,2130 @@
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+ */
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+}