/Users/lyon/j4p/src/javassist/compiler/Parser.java
|
1 /*
2 * Javassist, a Java-bytecode translator toolkit.
3 * Copyright (C) 1999-2003 Shigeru Chiba. All Rights Reserved.
4 *
5 * The contents of this file are subject to the Mozilla Public License Version
6 * 1.1 (the "License"); you may not use this file except in compliance with
7 * the License. Alternatively, the contents of this file may be used under
8 * the terms of the GNU Lesser General Public License Version 2.1 or later.
9 *
10 * Software distributed under the License is distributed on an "AS IS" basis,
11 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
12 * for the specific language governing rights and limitations under the
13 * License.
14 */
15
16 package javassist.compiler;
17
18 import javassist.compiler.ast.*;
19
20 public final class Parser implements TokenId {
21 private Lex lex;
22
23 public Parser(Lex lex) {
24 this.lex = lex;
25 }
26
27 public boolean hasMore() {
28 return lex.lookAhead() >= 0;
29 }
30
31 /* member.declaration
32 * : method.declaration | field.declaration
33 */
34 public ASTList parseMember(SymbolTable tbl) throws CompileError {
35 ASTList mem = parseMember1(tbl);
36 if (mem instanceof MethodDecl)
37 return parseMethod2(tbl, (MethodDecl) mem);
38 else
39 return mem;
40 }
41
42 /* A method body is not parsed.
43 */
44 public ASTList parseMember1(SymbolTable tbl) throws CompileError {
45 ASTList mods = parseMemberMods();
46 Declarator d;
47 boolean isConstructor = false;
48 if (lex.lookAhead() == Identifier && lex.lookAhead(1) == '(') {
49 d = new Declarator(VOID, 0);
50 isConstructor = true;
51 } else
52 d = parseFormalType(tbl);
53
54 if (lex.get() != Identifier)
55 throw new SyntaxError(lex);
56
57 String name;
58 if (isConstructor)
59 name = MethodDecl.initName;
60 else
61 name = lex.getString();
62
63 d.setVariable(new Symbol(name));
64 if (isConstructor || lex.lookAhead() == '(')
65 return parseMethod1(tbl, isConstructor, mods, d);
66 else
67 return parseField(tbl, mods, d);
68 }
69
70 /* field.declaration
71 * : member.modifiers
72 * formal.type Identifier
73 * [ "=" expression ] ";"
74 */
75 private FieldDecl parseField(SymbolTable tbl, ASTList mods,
76 Declarator d) throws CompileError {
77 ASTree expr = null;
78 if (lex.lookAhead() == '=') {
79 lex.get();
80 expr = parseExpression(tbl);
81 }
82
83 int c = lex.get();
84 if (c == ';')
85 return new FieldDecl(mods, new ASTList(d, new ASTList(expr)));
86 else if (c == ',')
87 throw new CompileError(
88 "only one field can be declared in one declaration", lex);
89 else
90 throw new SyntaxError(lex);
91 }
92
93 /* method.declaration
94 * : member.modifiers
95 * [ formal.type ]
96 * Identifier "(" [ formal.parameter ( "," formal.parameter )* ] ")"
97 * array.dimension
98 * [ THROWS class.type ( "," class.type ) ]
99 * ( block.statement | ";" )
100 *
101 * Note that a method body is not parsed.
102 */
103 private MethodDecl parseMethod1(SymbolTable tbl, boolean isConstructor,
104 ASTList mods, Declarator d)
105 throws CompileError {
106 if (lex.get() != '(')
107 throw new SyntaxError(lex);
108
109 ASTList parms = null;
110 if (lex.lookAhead() != ')')
111 while (true) {
112 parms = ASTList.append(parms, parseFormalParam(tbl));
113 int t = lex.lookAhead();
114 if (t == ',')
115 lex.get();
116 else if (t == ')')
117 break;
118 }
119
120 lex.get(); // ')'
121 d.addArrayDim(parseArrayDimension());
122 if (isConstructor && d.getArrayDim() > 0)
123 throw new SyntaxError(lex);
124
125 ASTList throwsList = null;
126 if (lex.lookAhead() == THROWS) {
127 lex.get();
128 while (true) {
129 throwsList = ASTList.append(throwsList, parseClassType(tbl));
130 if (lex.lookAhead() == ',')
131 lex.get();
132 else
133 break;
134 }
135 }
136
137 return new MethodDecl(mods, new ASTList(d,
138 ASTList.make(parms, throwsList, null)));
139 }
140
141 /* Parses a method body.
142 */
143 public MethodDecl parseMethod2(SymbolTable tbl, MethodDecl md)
144 throws CompileError {
145 Stmnt body = null;
146 if (lex.lookAhead() == ';')
147 lex.get();
148 else {
149 body = parseBlock(tbl);
150 if (body == null)
151 body = new Stmnt(BLOCK);
152 }
153
154 md.sublist(4).setHead(body);
155 return md;
156 }
157
158 /* member.modifiers
159 * : ( FINAL | SYNCHRONIZED | ABSTRACT
160 * | PUBLIC | PROTECTED | PRIVATE | STATIC
161 * | VOLATILE | TRANSIENT | STRICT )*
162 */
163 private ASTList parseMemberMods() {
164 int t;
165 ASTList list = null;
166 while (true) {
167 t = lex.lookAhead();
168 if (t == ABSTRACT || t == FINAL || t == PUBLIC || t == PROTECTED
169 || t == PRIVATE || t == SYNCHRONIZED || t == STATIC
170 || t == VOLATILE || t == TRANSIENT || t == STRICT)
171 list = new ASTList(new Keyword(lex.get()), list);
172 else
173 break;
174 }
175
176 return list;
177 }
178
179 /* formal.type : ( build-in-type | class.type ) array.dimension
180 */
181 private Declarator parseFormalType(SymbolTable tbl) throws CompileError {
182 int t = lex.lookAhead();
183 if (isBuiltinType(t) || t == VOID) {
184 lex.get(); // primitive type
185 int dim = parseArrayDimension();
186 return new Declarator(t, dim);
187 } else {
188 ASTList name = parseClassType(tbl);
189 int dim = parseArrayDimension();
190 return new Declarator(name, dim);
191 }
192 }
193
194 private static boolean isBuiltinType(int t) {
195 return (t == BOOLEAN || t == BYTE || t == CHAR || t == SHORT
196 || t == INT || t == LONG || t == FLOAT || t == DOUBLE);
197 }
198
199 /* formal.parameter : formal.type Identifier array.dimension
200 */
201 private Declarator parseFormalParam(SymbolTable tbl)
202 throws CompileError {
203 Declarator d = parseFormalType(tbl);
204 if (lex.get() != Identifier)
205 throw new SyntaxError(lex);
206
207 String name = lex.getString();
208 d.setVariable(new Symbol(name));
209 d.addArrayDim(parseArrayDimension());
210 tbl.append(name, d);
211 return d;
212 }
213
214 /* statement : [ label ":" ]* labeled.statement
215 *
216 * labeled.statement
217 * : block.statement
218 * | if.statement
219 * | while.statement
220 * | do.statement
221 * | for.statement
222 * | switch.statement
223 * | try.statement
224 * | return.statement
225 * | thorw.statement
226 * | break.statement
227 * | continue.statement
228 * | declaration.or.expression
229 * | ";"
230 *
231 * This method may return null (empty statement).
232 */
233 public Stmnt parseStatement(SymbolTable tbl)
234 throws CompileError {
235 int t = lex.lookAhead();
236 if (t == '{')
237 return parseBlock(tbl);
238 else if (t == ';') {
239 lex.get();
240 return new Stmnt(BLOCK); // empty statement
241 } else if (t == Identifier && lex.lookAhead(1) == ':') {
242 lex.get(); // Identifier
243 String label = lex.getString();
244 lex.get(); // ':'
245 return Stmnt.make(LABEL, new Symbol(label), parseStatement(tbl));
246 } else if (t == IF)
247 return parseIf(tbl);
248 else if (t == WHILE)
249 return parseWhile(tbl);
250 else if (t == DO)
251 return parseDo(tbl);
252 else if (t == FOR)
253 return parseFor(tbl);
254 else if (t == TRY)
255 return parseTry(tbl);
256 else if (t == SWITCH)
257 return parseSwitch(tbl);
258 else if (t == SYNCHRONIZED)
259 return parseSynchronized(tbl);
260 else if (t == RETURN)
261 return parseReturn(tbl);
262 else if (t == THROW)
263 return parseThrow(tbl);
264 else if (t == BREAK)
265 return parseBreak(tbl);
266 else if (t == CONTINUE)
267 return parseContinue(tbl);
268 else
269 return parseDeclarationOrExpression(tbl, false);
270 }
271
272 /* block.statement : "{" statement* "}"
273 */
274 private Stmnt parseBlock(SymbolTable tbl) throws CompileError {
275 if (lex.get() != '{')
276 throw new SyntaxError(lex);
277
278 Stmnt body = null;
279 SymbolTable tbl2 = new SymbolTable(tbl);
280 while (lex.lookAhead() != '}') {
281 Stmnt s = parseStatement(tbl2);
282 if (s != null)
283 body = (Stmnt) ASTList.concat(body, new Stmnt(BLOCK, s));
284 }
285
286 lex.get(); // '}'
287 if (body == null)
288 return new Stmnt(BLOCK); // empty block
289 else
290 return body;
291 }
292
293 /* if.statement : IF "(" expression ")" statement
294 * [ ELSE statement ]
295 */
296 private Stmnt parseIf(SymbolTable tbl) throws CompileError {
297 int t = lex.get(); // IF
298 if (lex.get() != '(')
299 throw new SyntaxError(lex);
300
301 ASTree expr = parseExpression(tbl);
302 if (lex.get() != ')')
303 throw new SyntaxError(lex);
304
305 Stmnt thenp = parseStatement(tbl);
306 Stmnt elsep;
307 if (lex.lookAhead() == ELSE) {
308 lex.get();
309 elsep = parseStatement(tbl);
310 } else
311 elsep = null;
312
313 return new Stmnt(t, expr, new ASTList(thenp, new ASTList(elsep)));
314 }
315
316 /* while.statement : WHILE "(" expression ")" statement
317 */
318 private Stmnt parseWhile(SymbolTable tbl)
319 throws CompileError {
320 int t = lex.get(); // WHILE
321 if (lex.get() != '(')
322 throw new SyntaxError(lex);
323
324 ASTree expr = parseExpression(tbl);
325 if (lex.get() != ')')
326 throw new SyntaxError(lex);
327
328 Stmnt body = parseStatement(tbl);
329 return new Stmnt(t, expr, body);
330 }
331
332 /* do.statement : DO statement WHILE "(" expression ")" ";"
333 */
334 private Stmnt parseDo(SymbolTable tbl) throws CompileError {
335 int t = lex.get(); // DO
336 Stmnt body = parseStatement(tbl);
337 if (lex.get() != WHILE || lex.get() != '(')
338 throw new SyntaxError(lex);
339
340 ASTree expr = parseExpression(tbl);
341 if (lex.get() != ')' || lex.get() != ';')
342 throw new SyntaxError(lex);
343
344 return new Stmnt(t, expr, body);
345 }
346
347 /* for.statement : FOR "(" decl.or.expr expression ";" expression ")"
348 * statement
349 */
350 private Stmnt parseFor(SymbolTable tbl) throws CompileError {
351 Stmnt expr1, expr3;
352 ASTree expr2;
353 int t = lex.get(); // FOR
354
355 SymbolTable tbl2 = new SymbolTable(tbl);
356
357 if (lex.get() != '(')
358 throw new SyntaxError(lex);
359
360 if (lex.lookAhead() == ';') {
361 lex.get();
362 expr1 = null;
363 } else
364 expr1 = parseDeclarationOrExpression(tbl2, true);
365
366 if (lex.lookAhead() == ';')
367 expr2 = null;
368 else
369 expr2 = parseExpression(tbl2);
370
371 if (lex.get() != ';')
372 throw new CompileError("; is missing", lex);
373
374 if (lex.lookAhead() == ')')
375 expr3 = null;
376 else
377 expr3 = parseExprList(tbl2);
378
379 if (lex.get() != ')')
380 throw new CompileError(") is missing", lex);
381
382 Stmnt body = parseStatement(tbl2);
383 return new Stmnt(t, expr1, new ASTList(expr2,
384 new ASTList(expr3, body)));
385 }
386
387 /* switch.statement : SWITCH "(" expression ")" "{" switch.block "}"
388 *
389 * swtich.block : ( switch.label* statement )*
390 *
391 * swtich.label : DEFAULT ":"
392 * | CASE const.expression ":"
393 */
394 private Stmnt parseSwitch(SymbolTable tbl) throws CompileError {
395 throw new CompileError("switch is not supported", lex);
396 }
397
398 /* synchronized.statement :
399 * SYNCHRONIZED "(" expression ")" block.statement
400 */
401 private Stmnt parseSynchronized(SymbolTable tbl) throws CompileError {
402 throw new CompileError("synchronized is not supported", lex);
403 }
404
405 /* try.statement
406 * : TRY block.statement
407 * [ CATCH "(" class.type Identifier ")" block.statement ]*
408 * [ FINALLY block.statement ]*
409 */
410 private Stmnt parseTry(SymbolTable tbl) throws CompileError {
411 lex.get(); // TRY
412 Stmnt block = parseBlock(tbl);
413 ASTList catchList = null;
414 while (lex.lookAhead() == CATCH) {
415 lex.get(); // CATCH
416 if (lex.get() != '(')
417 throw new SyntaxError(lex);
418
419 SymbolTable tbl2 = new SymbolTable(tbl);
420 Declarator d = parseFormalParam(tbl2);
421 if (d.getArrayDim() > 0 || d.getType() != CLASS)
422 throw new SyntaxError(lex);
423
424 if (lex.get() != ')')
425 throw new SyntaxError(lex);
426
427 Stmnt b = parseBlock(tbl2);
428 catchList = ASTList.append(catchList, new Pair(d, b));
429 }
430
431 Stmnt finallyBlock = null;
432 if (lex.lookAhead() == FINALLY) {
433 lex.get(); // FINALLY
434 finallyBlock = parseBlock(tbl);
435 }
436
437 return Stmnt.make(TRY, block, catchList, finallyBlock);
438 }
439
440 /* return.statement : RETURN [ expression ] ";"
441 */
442 private Stmnt parseReturn(SymbolTable tbl) throws CompileError {
443 int t = lex.get(); // RETURN
444 Stmnt s = new Stmnt(t);
445 if (lex.lookAhead() != ';')
446 s.setLeft(parseExpression(tbl));
447
448 if (lex.get() != ';')
449 throw new CompileError("; is missing", lex);
450
451 return s;
452 }
453
454 /* throw.statement : THROW expression ";"
455 */
456 private Stmnt parseThrow(SymbolTable tbl) throws CompileError {
457 int t = lex.get(); // THROW
458 ASTree expr = parseExpression(tbl);
459 if (lex.get() != ';')
460 throw new CompileError("; is missing", lex);
461
462 return new Stmnt(t, expr);
463 }
464
465 /* break.statement : BREAK [ Identifier ] ";"
466 */
467 private Stmnt parseBreak(SymbolTable tbl)
468 throws CompileError {
469 return parseContinue(tbl);
470 }
471
472 /* continue.statement : CONTINUE [ Identifier ] ";"
473 */
474 private Stmnt parseContinue(SymbolTable tbl)
475 throws CompileError {
476 int t = lex.get(); // CONTINUE
477 Stmnt s = new Stmnt(t);
478 int t2 = lex.get();
479 if (t2 == Identifier) {
480 s.setLeft(new Symbol(lex.getString()));
481 t2 = lex.get();
482 }
483
484 if (t2 != ';')
485 throw new CompileError("; is missing", lex);
486
487 return s;
488 }
489
490 /* declaration.or.expression
491 * : [ FINAL ] built-in-type array.dimension declarators
492 * | [ FINAL ] class.type array.dimension declarators
493 * | expression ';'
494 * | expr.list ';' if exprList is true
495 *
496 * Note: FINAL is currently ignored. This must be fixed
497 * in future.
498 */
499 private Stmnt parseDeclarationOrExpression(SymbolTable tbl,
500 boolean exprList)
501 throws CompileError {
502 int t = lex.lookAhead();
503 while (t == FINAL) {
504 lex.get();
505 t = lex.lookAhead();
506 }
507
508 if (isBuiltinType(t)) {
509 t = lex.get();
510 int dim = parseArrayDimension();
511 return parseDeclarators(tbl, new Declarator(t, dim));
512 } else if (t == Identifier) {
513 int i = nextIsClassType(0);
514 if (i >= 0)
515 if (lex.lookAhead(i) == Identifier) {
516 ASTList name = parseClassType(tbl);
517 int dim = parseArrayDimension();
518 return parseDeclarators(tbl, new Declarator(name, dim));
519 }
520 }
521
522 Stmnt expr;
523 if (exprList)
524 expr = parseExprList(tbl);
525 else
526 expr = new Stmnt(EXPR, parseExpression(tbl));
527
528 if (lex.get() != ';')
529 throw new CompileError("; is missing", lex);
530
531 return expr;
532 }
533
534 /* expr.list : ( expression ',')* expression
535 */
536 private Stmnt parseExprList(SymbolTable tbl) throws CompileError {
537 Stmnt expr = null;
538 for (; ;) {
539 Stmnt e = new Stmnt(EXPR, parseExpression(tbl));
540 expr = (Stmnt) ASTList.concat(expr, new Stmnt(BLOCK, e));
541 if (lex.lookAhead() == ',')
542 lex.get();
543 else
544 return expr;
545 }
546 }
547
548 /* declarators : declarator [ ',' declarator ]* ';'
549 */
550 private Stmnt parseDeclarators(SymbolTable tbl, Declarator d)
551 throws CompileError {
552 Stmnt decl = null;
553 for (; ;) {
554 decl = (Stmnt) ASTList.concat(decl,
555 new Stmnt(DECL, parseDeclarator(tbl, d)));
556 int t = lex.get();
557 if (t == ';')
558 return decl;
559 else if (t != ',')
560 throw new CompileError("; is missing", lex);
561 }
562 }
563
564 /* declarator : Identifier array.dimension [ '=' initializer ]
565 */
566 private Declarator parseDeclarator(SymbolTable tbl, Declarator d)
567 throws CompileError {
568 if (lex.get() != Identifier || d.getType() == VOID)
569 throw new SyntaxError(lex);
570
571 String name = lex.getString();
572 Symbol symbol = new Symbol(name);
573 int dim = parseArrayDimension();
574 ASTree init = null;
575 if (lex.lookAhead() == '=') {
576 lex.get();
577 init = parseInitializer(tbl);
578 }
579
580 Declarator decl = d.make(symbol, dim, init);
581 tbl.append(name, decl);
582 return decl;
583 }
584
585 /* initializer : expression | array.initializer
586 */
587 private ASTree parseInitializer(SymbolTable tbl) throws CompileError {
588 if (lex.lookAhead() == '{')
589 return parseArrayInitializer(tbl);
590 else
591 return parseExpression(tbl);
592 }
593
594 /* array.initializer :
595 * '{' (( array.initializer | expression ) ',')* '}'
596 */
597 private ASTree parseArrayInitializer(SymbolTable tbl)
598 throws CompileError {
599 lex.get(); // '{'
600 throw new CompileError("array initializer is not supported", lex);
601 }
602
603 /* expression : conditional.expr
604 * | conditional.expr assign.op expression (right-to-left)
605 */
606 public ASTree parseExpression(SymbolTable tbl) throws CompileError {
607 ASTree left = parseConditionalExpr(tbl);
608 if (!isAssignOp(lex.lookAhead()))
609 return left;
610
611 int t = lex.get();
612 ASTree right = parseExpression(tbl);
613 return AssignExpr.makeAssign(t, left, right);
614 }
615
616 private static boolean isAssignOp(int t) {
617 return t == '=' || t == MOD_E || t == AND_E
618 || t == MUL_E || t == PLUS_E || t == MINUS_E || t == DIV_E
619 || t == EXOR_E || t == OR_E || t == LSHIFT_E
620 || t == RSHIFT_E || t == ARSHIFT_E;
621 }
622
623 /* conditional.expr (right-to-left)
624 * : logical.or.expr [ '?' expression ':' conditional.expr ]
625 */
626 private ASTree parseConditionalExpr(SymbolTable tbl) throws CompileError {
627 ASTree cond = parseBinaryExpr(tbl);
628 if (lex.lookAhead() == '?') {
629 lex.get();
630 ASTree thenExpr = parseExpression(tbl);
631 if (lex.get() != ':')
632 throw new CompileError(": is missing", lex);
633
634 ASTree elseExpr = parseExpression(tbl);
635 return new CondExpr(cond, thenExpr, elseExpr);
636 } else
637 return cond;
638 }
639
640 /* logical.or.expr 10 (operator precedence)
641 * : logical.and.expr
642 * | logical.or.expr OROR logical.and.expr left-to-right
643 *
644 * logical.and.expr 9
645 * : inclusive.or.expr
646 * | logical.and.expr ANDAND inclusive.or.expr
647 *
648 * inclusive.or.expr 8
649 * : exclusive.or.expr
650 * | inclusive.or.expr "|" exclusive.or.expr
651 *
652 * exclusive.or.expr 7
653 * : and.expr
654 * | exclusive.or.expr "^" and.expr
655 *
656 * and.expr 6
657 * : equality.expr
658 * | and.expr "&" equality.expr
659 *
660 * equality.expr 5
661 * : relational.expr
662 * | equality.expr (EQ | NEQ) relational.expr
663 *
664 * relational.expr 4
665 * : shift.expr
666 * | relational.expr (LE | GE | "<" | ">") shift.expr
667 * | relational.expr INSTANCEOF class.type ("[" "]")*
668 *
669 * shift.expr 3
670 * : additive.expr
671 * | shift.expr (LSHIFT | RSHIFT | ARSHIFT) additive.expr
672 *
673 * additive.expr 2
674 * : multiply.expr
675 * | additive.expr ("+" | "-") multiply.expr
676 *
677 * multiply.expr 1
678 * : unary.expr
679 * | multiply.expr ("*" | "/" | "%") unary.expr
680 */
681 private ASTree parseBinaryExpr(SymbolTable tbl) throws CompileError {
682 ASTree expr = parseUnaryExpr(tbl);
683 for (; ;) {
684 int t = lex.lookAhead();
685 int p = getOpPrecedence(t);
686 if (p == 0)
687 return expr;
688 else
689 expr = binaryExpr2(tbl, expr, p);
690 }
691 }
692
693 private ASTree parseInstanceOf(SymbolTable tbl, ASTree expr)
694 throws CompileError {
695 int t = lex.lookAhead();
696 if (isBuiltinType(t)) {
697 lex.get(); // primitive type
698 int dim = parseArrayDimension();
699 return new InstanceOfExpr(t, dim, expr);
700 } else {
701 ASTList name = parseClassType(tbl);
702 int dim = parseArrayDimension();
703 return new InstanceOfExpr(name, dim, expr);
704 }
705 }
706
707 private ASTree binaryExpr2(SymbolTable tbl, ASTree expr, int prec)
708 throws CompileError {
709 int t = lex.get();
710 if (t == INSTANCEOF)
711 return parseInstanceOf(tbl, expr);
712
713 ASTree expr2 = parseUnaryExpr(tbl);
714 for (; ;) {
715 int t2 = lex.lookAhead();
716 int p2 = getOpPrecedence(t2);
717 if (p2 != 0 && prec > p2)
718 expr2 = binaryExpr2(tbl, expr2, p2);
719 else
720 return BinExpr.makeBin(t, expr, expr2);
721 }
722 }
723
724 // !"#$%&'( )*+,-./0 12345678 9:;<=>?
725 private static final int[] binaryOpPrecedence
726 = {0, 0, 0, 0, 1, 6, 0, 0,
727 0, 1, 2, 0, 2, 0, 1, 0,
728 0, 0, 0, 0, 0, 0, 0, 0,
729 0, 0, 0, 4, 0, 4, 0};
730
731 private int getOpPrecedence(int c) {
732 if ('!' <= c && c <= '?')
733 return binaryOpPrecedence[c - '!'];
734 else if (c == '^')
735 return 7;
736 else if (c == '|')
737 return 8;
738 else if (c == ANDAND)
739 return 9;
740 else if (c == OROR)
741 return 10;
742 else if (c == EQ || c == NEQ)
743 return 5;
744 else if (c == LE || c == GE || c == INSTANCEOF)
745 return 4;
746 else if (c == LSHIFT || c == RSHIFT || c == ARSHIFT)
747 return 3;
748 else
749 return 0; // not a binary operator
750 }
751
752 /* unary.expr : "++"|"--" unary.expr
753 | "+"|"-" unary.expr
754 | "!"|"~" unary.expr
755 | cast.expr
756 | postfix.expr
757
758 unary.expr.not.plus.minus is a unary expression starting without
759 "+", "-", "++", or "--".
760 */
761 private ASTree parseUnaryExpr(SymbolTable tbl) throws CompileError {
762 int t;
763 switch (lex.lookAhead()) {
764 case '+':
765 case '-':
766 case PLUSPLUS:
767 case MINUSMINUS:
768 case '!':
769 case '~':
770 t = lex.get();
771 return new Expr(t, parseUnaryExpr(tbl));
772 case '(':
773 return parseCast(tbl);
774 default :
775 return parsePostfix(tbl);
776 }
777 }
778
779 /* cast.expr : "(" builtin.type ("[" "]")* ")" unary.expr
780 | "(" class.type ("[" "]")* ")" unary.expr2
781
782 unary.expr2 is a unary.expr begining with "(", NULL, StringL,
783 Identifier, THIS, SUPER, or NEW.
784 */
785 private ASTree parseCast(SymbolTable tbl) throws CompileError {
786 int t = lex.lookAhead(1);
787 if (isBuiltinType(t)) {
788 lex.get(); // '('
789 lex.get(); // primitive type
790 int dim = parseArrayDimension();
791 if (lex.get() != ')')
792 throw new CompileError(") is missing", lex);
793
794 return new CastExpr(t, dim, parseUnaryExpr(tbl));
795 } else if (t == Identifier && nextIsClassCast()) {
796 lex.get(); // '('
797 ASTList name = parseClassType(tbl);
798 int dim = parseArrayDimension();
799 if (lex.get() != ')')
800 throw new CompileError(") is missing", lex);
801
802 return new CastExpr(name, dim, parseUnaryExpr(tbl));
803 } else
804 return parsePostfix(tbl);
805 }
806
807 private boolean nextIsClassCast() {
808 int i = nextIsClassType(1);
809 if (i < 0)
810 return false;
811
812 int t = lex.lookAhead(i);
813 if (t != ')')
814 return false;
815
816 t = lex.lookAhead(i + 1);
817 return t == '(' || t == NULL || t == StringL
818 || t == Identifier || t == THIS || t == SUPER || t == NEW
819 || t == TRUE || t == FALSE || t == LongConstant
820 || t == IntConstant || t == CharConstant
821 || t == DoubleConstant || t == FloatConstant;
822 }
823
824 private int nextIsClassType(int i) {
825 int t;
826 while (lex.lookAhead(++i) == '.')
827 if (lex.lookAhead(++i) != Identifier)
828 return -1;
829
830 while ((t = lex.lookAhead(i++)) == '[')
831 if (lex.lookAhead(i++) != ']')
832 return -1;
833
834 return i - 1;
835 }
836
837 /* array.dimension : [ "[" "]" ]*
838 */
839 private int parseArrayDimension() throws CompileError {
840 int arrayDim = 0;
841 while (lex.lookAhead() == '[') {
842 ++arrayDim;
843 lex.get();
844 if (lex.get() != ']')
845 throw new CompileError("] is missing", lex);
846 }
847
848 return arrayDim;
849 }
850
851 /* class.type : Identifier ( "." Identifier )*
852 */
853 private ASTList parseClassType(SymbolTable tbl) throws CompileError {
854 ASTList list = null;
855 for (; ;) {
856 if (lex.get() != Identifier)
857 throw new SyntaxError(lex);
858
859 list = ASTList.append(list, new Symbol(lex.getString()));
860 if (lex.lookAhead() == '.')
861 lex.get();
862 else
863 break;
864 }
865
866 return list;
867 }
868
869 /* postfix.expr : number.literal
870 * | primary.expr
871 * | method.expr
872 * | postfix.expr "++" | "--"
873 * | postfix.expr "[" array.size "]"
874 * | postfix.expr "." Identifier
875 * | postfix.expr "#" Identifier
876 *
877 * "#" is not an operator of regular Java. It separates
878 * a class name and a member name in an expression for static member
879 * access. For example,
880 * java.lang.Integer.toString(3) in regular Java
881 * must be written like this:
882 * java.lang.Integer#toString(3) for this compiler.
883 */
884 private ASTree parsePostfix(SymbolTable tbl) throws CompileError {
885 int token = lex.lookAhead();
886 switch (token) {
887 case LongConstant:
888 case IntConstant:
889 case CharConstant:
890 lex.get();
891 return new IntConst(lex.getLong(), token);
892 case DoubleConstant:
893 case FloatConstant:
894 lex.get();
895 return new DoubleConst(lex.getDouble(), token);
896 default :
897 break;
898 }
899
900 String str;
901 ASTree index;
902 ASTree expr = parsePrimaryExpr(tbl);
903 int t;
904 while (true) {
905 switch (lex.lookAhead()) {
906 case '(':
907 expr = parseMethodCall(tbl, expr);
908 break;
909 case '[':
910 index = parseArrayIndex(tbl);
911 if (index == null)
912 throw new SyntaxError(lex);
913
914 expr = Expr.make(ARRAY, expr, index);
915 break;
916 case PLUSPLUS:
917 case MINUSMINUS:
918 t = lex.get();
919 expr = Expr.make(t, null, expr);
920 break;
921 case '.':
922 lex.get();
923 if (lex.get() != Identifier)
924 throw new CompileError("missing member name", lex);
925
926 expr = Expr.make('.', expr, new Member(lex.getString()));
927 break;
928 case '#':
929 lex.get();
930 t = lex.get();
931 if (t == CLASS)
932 str = "class";
933 else if (t == Identifier)
934 str = lex.getString();
935 else
936 throw new CompileError("missing static member name", lex);
937
938 expr = Expr.make(MEMBER, toClassName(expr, null),
939 new Member(str));
940 break;
941 default :
942 return expr;
943 }
944 }
945 }
946
947 /* method.call : method.expr "(" argument.list ")"
948 * method.expr : THIS | SUPER | Identifier
949 * | postfix.expr "." Identifier
950 * | postfix.expr "#" Identifier
951 */
952 private ASTree parseMethodCall(SymbolTable tbl, ASTree expr)
953 throws CompileError {
954 if (expr instanceof Keyword) {
955 int token = ((Keyword) expr).get();
956 if (token != THIS && token != SUPER)
957 throw new SyntaxError(lex);
958 } else if (expr instanceof Symbol) // Identifier
959 ;
960 else if (expr instanceof Expr) {
961 int op = ((Expr) expr).getOperator();
962 if (op != '.' && op != MEMBER)
963 throw new SyntaxError(lex);
964 }
965
966 return Expr.make(CALL, expr, parseArgumentList(tbl));
967 }
968
969
970 private ASTList toClassName(ASTree name, ASTList tail)
971 throws CompileError {
972 if (name instanceof Symbol)
973 return new ASTList(name, tail);
974 else if (name instanceof Expr) {
975 Expr expr = (Expr) name;
976 if (expr.getOperator() == '.')
977 return toClassName(expr.oprand1(),
978 new ASTList(expr.oprand2(), tail));
979 }
980
981 throw new CompileError("bad static member access", lex);
982 }
983
984 /* primary.expr : THIS | SUPER | TRUE | FALSE | NULL
985 * | StringL
986 * | Identifier
987 * | NEW new.expr
988 * | "(" expression ")"
989 *
990 * Identifier represents either a local variable name, a member name,
991 * or a class name.
992 */
993 private ASTree parsePrimaryExpr(SymbolTable tbl) throws CompileError {
994 int t;
995 String name;
996 Declarator decl;
997 ASTree expr;
998
999 switch (t = lex.get()) {
1000 case THIS:
1001 case SUPER:
1002 case TRUE:
1003 case FALSE:
1004 case NULL:
1005 return new Keyword(t);
1006 case Identifier:
1007 name = lex.getString();
1008 decl = tbl.lookup(name);
1009 if (decl == null)
1010 return new Member(name); // this or static member
1011 else
1012 return new Variable(name, decl); // local variable
1013 case StringL:
1014 return new StringL(lex.getString());
1015 case NEW:
1016 return parseNew(tbl);
1017 case '(':
1018 expr = parseExpression(tbl);
1019 if (lex.get() == ')')
1020 return expr;
1021 else
1022 throw new CompileError(") is missing", lex);
1023 default :
1024 throw new SyntaxError(lex);
1025 }
1026 }
1027
1028 /* new.expr : class.type "(" argument.list ")"
1029 * | class.type array.size [ array.initializer ]
1030 * | primitive.type array.size [ array.initializer ]
1031 */
1032 private NewExpr parseNew(SymbolTable tbl) throws CompileError {
1033 ASTree init = null;
1034 int t = lex.lookAhead();
1035 if (isBuiltinType(t)) {
1036 lex.get();
1037 ASTList size = parseArraySize(tbl);
1038 if (lex.lookAhead() == '{')
1039 init = parseArrayInitializer(tbl);
1040
1041 return new NewExpr(t, size, init);
1042 } else if (t == Identifier) {
1043 ASTList name = parseClassType(tbl);
1044 t = lex.lookAhead();
1045 if (t == '(') {
1046 ASTList args = parseArgumentList(tbl);
1047 return new NewExpr(name, args);
1048 } else if (t == '[') {
1049 ASTList size = parseArraySize(tbl);
1050 if (lex.lookAhead() == '{')
1051 init = parseArrayInitializer(tbl);
1052
1053 return NewExpr.makeObjectArray(name, size, init);
1054 }
1055 }
1056
1057 throw new SyntaxError(lex);
1058 }
1059
1060 /* array.size : [ array.index ]*
1061 */
1062 private ASTList parseArraySize(SymbolTable tbl) throws CompileError {
1063 ASTList list = null;
1064 while (lex.lookAhead() == '[')
1065 list = ASTList.append(list, parseArrayIndex(tbl));
1066
1067 return list;
1068 }
1069
1070 /* array.index : "[" [ expression ] "]"
1071 */
1072 private ASTree parseArrayIndex(SymbolTable tbl) throws CompileError {
1073 lex.get(); // '['
1074 if (lex.lookAhead() == ']') {
1075 lex.get();
1076 return null;
1077 } else {
1078 ASTree index = parseExpression(tbl);
1079 if (lex.get() != ']')
1080 throw new CompileError("] is missing", lex);
1081
1082 return index;
1083 }
1084 }
1085
1086 /* argument.list : "(" [ expression [ "," expression ]* ] ")"
1087 */
1088 private ASTList parseArgumentList(SymbolTable tbl) throws CompileError {
1089 if (lex.get() != '(')
1090 throw new CompileError("( is missing", lex);
1091
1092 ASTList list = null;
1093 if (lex.lookAhead() != ')')
1094 for (; ;) {
1095 list = ASTList.append(list, parseExpression(tbl));
1096 if (lex.lookAhead() == ',')
1097 lex.get();
1098 else
1099 break;
1100 }
1101
1102 if (lex.get() != ')')
1103 throw new CompileError(") is missing", lex);
1104
1105 return list;
1106 }
1107 }
1108
1109