Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/openjdk-multiarch-jdk8u
Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/src/share/classes/sun/tools/java/Parser.java
38918 views
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
}
2131
2132