KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > javassist > compiler > Parser


1 /*
2  * Javassist, a Java-bytecode translator toolkit.
3  * Copyright (C) 1999-2005 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() { return lex.lookAhead() >= 0; }
28
29     /* member.declaration
30      * : method.declaration | field.declaration
31      */

32     public ASTList parseMember(SymbolTable tbl) throws CompileError {
33         ASTList mem = parseMember1(tbl);
34         if (mem instanceof MethodDecl)
35             return parseMethod2(tbl, (MethodDecl)mem);
36         else
37             return mem;
38     }
39
40     /* A method body is not parsed.
41      */

42     public ASTList parseMember1(SymbolTable tbl) throws CompileError {
43         ASTList mods = parseMemberMods();
44         Declarator d;
45         boolean isConstructor = false;
46         if (lex.lookAhead() == Identifier && lex.lookAhead(1) == '(') {
47             d = new Declarator(VOID, 0);
48             isConstructor = true;
49         }
50         else
51             d = parseFormalType(tbl);
52
53         if (lex.get() != Identifier)
54             throw new SyntaxError(lex);
55
56         String JavaDoc name;
57         if (isConstructor)
58             name = MethodDecl.initName;
59         else
60             name = lex.getString();
61
62         d.setVariable(new Symbol(name));
63         if (isConstructor || lex.lookAhead() == '(')
64             return parseMethod1(tbl, isConstructor, mods, d);
65         else
66             return parseField(tbl, mods, d);
67     }
68
69     /* field.declaration
70      * : member.modifiers
71      * formal.type Identifier
72      * [ "=" expression ] ";"
73      */

74     private FieldDecl parseField(SymbolTable tbl, ASTList mods,
75                                 Declarator d) throws CompileError
76     {
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     {
107         if (lex.get() != '(')
108             throw new SyntaxError(lex);
109
110         ASTList parms = null;
111         if (lex.lookAhead() != ')')
112             while (true) {
113                 parms = ASTList.append(parms, parseFormalParam(tbl));
114                 int t = lex.lookAhead();
115                 if (t == ',')
116                     lex.get();
117                 else if (t == ')')
118                     break;
119             }
120
121         lex.get(); // ')'
122
d.addArrayDim(parseArrayDimension());
123         if (isConstructor && d.getArrayDim() > 0)
124             throw new SyntaxError(lex);
125
126         ASTList throwsList = null;
127         if (lex.lookAhead() == THROWS) {
128             lex.get();
129             while (true) {
130                 throwsList = ASTList.append(throwsList, parseClassType(tbl));
131                 if (lex.lookAhead() == ',')
132                     lex.get();
133                 else
134                     break;
135             }
136         }
137
138         return new MethodDecl(mods, new ASTList(d,
139                                 ASTList.make(parms, throwsList, null)));
140     }
141
142     /* Parses a method body.
143      */

144     public MethodDecl parseMethod2(SymbolTable tbl, MethodDecl md)
145         throws CompileError
146     {
147         Stmnt body = null;
148         if (lex.lookAhead() == ';')
149             lex.get();
150         else {
151             body = parseBlock(tbl);
152             if (body == null)
153                 body = new Stmnt(BLOCK);
154         }
155
156         md.sublist(4).setHead(body);
157         return md;
158     }
159
160     /* member.modifiers
161      * : ( FINAL | SYNCHRONIZED | ABSTRACT
162      * | PUBLIC | PROTECTED | PRIVATE | STATIC
163      * | VOLATILE | TRANSIENT | STRICT )*
164      */

165     private ASTList parseMemberMods() {
166         int t;
167         ASTList list = null;
168         while (true) {
169             t = lex.lookAhead();
170             if (t == ABSTRACT || t == FINAL || t == PUBLIC || t == PROTECTED
171                 || t == PRIVATE || t == SYNCHRONIZED || t == STATIC
172                 || t == VOLATILE || t == TRANSIENT || t == STRICT)
173                 list = new ASTList(new Keyword(lex.get()), list);
174             else
175                 break;
176         }
177
178         return list;
179     }
180
181     /* formal.type : ( build-in-type | class.type ) array.dimension
182      */

183     private Declarator parseFormalType(SymbolTable tbl) throws CompileError {
184         int t = lex.lookAhead();
185         if (isBuiltinType(t) || t == VOID) {
186             lex.get(); // primitive type
187
int dim = parseArrayDimension();
188             return new Declarator(t, dim);
189         }
190         else {
191             ASTList name = parseClassType(tbl);
192             int dim = parseArrayDimension();
193             return new Declarator(name, dim);
194         }
195     }
196
197     private static boolean isBuiltinType(int t) {
198         return (t == BOOLEAN || t == BYTE || t == CHAR || t == SHORT
199                 || t == INT || t == LONG || t == FLOAT || t == DOUBLE);
200     }
201
202     /* formal.parameter : formal.type Identifier array.dimension
203      */

204     private Declarator parseFormalParam(SymbolTable tbl)
205         throws CompileError
206     {
207         Declarator d = parseFormalType(tbl);
208         if (lex.get() != Identifier)
209             throw new SyntaxError(lex);
210
211         String JavaDoc name = lex.getString();
212         d.setVariable(new Symbol(name));
213         d.addArrayDim(parseArrayDimension());
214         tbl.append(name, d);
215         return d;
216     }
217
218     /* statement : [ label ":" ]* labeled.statement
219      *
220      * labeled.statement
221      * : block.statement
222      * | if.statement
223      * | while.statement
224      * | do.statement
225      * | for.statement
226      * | switch.statement
227      * | try.statement
228      * | return.statement
229      * | thorw.statement
230      * | break.statement
231      * | continue.statement
232      * | declaration.or.expression
233      * | ";"
234      *
235      * This method may return null (empty statement).
236      */

237     public Stmnt parseStatement(SymbolTable tbl)
238         throws CompileError
239     {
240         int t = lex.lookAhead();
241         if (t == '{')
242             return parseBlock(tbl);
243         else if (t == ';') {
244             lex.get();
245             return new Stmnt(BLOCK); // empty statement
246
}
247         else if (t == Identifier && lex.lookAhead(1) == ':') {
248             lex.get(); // Identifier
249
String JavaDoc label = lex.getString();
250             lex.get(); // ':'
251
return Stmnt.make(LABEL, new Symbol(label), parseStatement(tbl));
252         }
253         else if (t == IF)
254             return parseIf(tbl);
255         else if (t == WHILE)
256             return parseWhile(tbl);
257         else if (t == DO)
258             return parseDo(tbl);
259         else if (t == FOR)
260             return parseFor(tbl);
261         else if (t == TRY)
262             return parseTry(tbl);
263         else if (t == SWITCH)
264             return parseSwitch(tbl);
265         else if (t == SYNCHRONIZED)
266             return parseSynchronized(tbl);
267         else if (t == RETURN)
268             return parseReturn(tbl);
269         else if (t == THROW)
270             return parseThrow(tbl);
271         else if (t == BREAK)
272             return parseBreak(tbl);
273         else if (t == CONTINUE)
274             return parseContinue(tbl);
275         else
276             return parseDeclarationOrExpression(tbl, false);
277     }
278
279     /* block.statement : "{" statement* "}"
280      */

281     private Stmnt parseBlock(SymbolTable tbl) throws CompileError {
282         if (lex.get() != '{')
283             throw new SyntaxError(lex);
284
285         Stmnt body = null;
286         SymbolTable tbl2 = new SymbolTable(tbl);
287         while (lex.lookAhead() != '}') {
288             Stmnt s = parseStatement(tbl2);
289             if (s != null)
290                 body = (Stmnt)ASTList.concat(body, new Stmnt(BLOCK, s));
291         }
292
293         lex.get(); // '}'
294
if (body == null)
295             return new Stmnt(BLOCK); // empty block
296
else
297             return body;
298     }
299
300     /* if.statement : IF "(" expression ")" statement
301      * [ ELSE statement ]
302      */

303     private Stmnt parseIf(SymbolTable tbl) throws CompileError {
304         int t = lex.get(); // IF
305
ASTree expr = parseParExpression(tbl);
306         Stmnt thenp = parseStatement(tbl);
307         Stmnt elsep;
308         if (lex.lookAhead() == ELSE) {
309             lex.get();
310             elsep = parseStatement(tbl);
311         }
312         else
313             elsep = null;
314
315         return new Stmnt(t, expr, new ASTList(thenp, new ASTList(elsep)));
316     }
317
318     /* while.statement : WHILE "(" expression ")" statement
319      */

320     private Stmnt parseWhile(SymbolTable tbl)
321         throws CompileError
322     {
323         int t = lex.get(); // WHILE
324
ASTree expr = parseParExpression(tbl);
325         Stmnt body = parseStatement(tbl);
326         return new Stmnt(t, expr, body);
327     }
328
329     /* do.statement : DO statement WHILE "(" expression ")" ";"
330      */

331     private Stmnt parseDo(SymbolTable tbl) throws CompileError {
332         int t = lex.get(); // DO
333
Stmnt body = parseStatement(tbl);
334         if (lex.get() != WHILE || lex.get() != '(')
335             throw new SyntaxError(lex);
336
337         ASTree expr = parseExpression(tbl);
338         if (lex.get() != ')' || lex.get() != ';')
339             throw new SyntaxError(lex);
340
341         return new Stmnt(t, expr, body);
342     }
343
344     /* for.statement : FOR "(" decl.or.expr expression ";" expression ")"
345      * statement
346      */

347     private Stmnt parseFor(SymbolTable tbl) throws CompileError {
348         Stmnt expr1, expr3;
349         ASTree expr2;
350         int t = lex.get(); // FOR
351

352         SymbolTable tbl2 = new SymbolTable(tbl);
353
354         if (lex.get() != '(')
355             throw new SyntaxError(lex);
356
357         if (lex.lookAhead() == ';') {
358             lex.get();
359             expr1 = null;
360         }
361         else
362             expr1 = parseDeclarationOrExpression(tbl2, true);
363
364         if (lex.lookAhead() == ';')
365             expr2 = null;
366         else
367             expr2 = parseExpression(tbl2);
368
369         if (lex.get() != ';')
370             throw new CompileError("; is missing", lex);
371
372         if (lex.lookAhead() == ')')
373             expr3 = null;
374         else
375             expr3 = parseExprList(tbl2);
376
377         if (lex.get() != ')')
378             throw new CompileError(") is missing", lex);
379
380         Stmnt body = parseStatement(tbl2);
381         return new Stmnt(t, expr1, new ASTList(expr2,
382                                                new ASTList(expr3, body)));
383     }
384
385     /* switch.statement : SWITCH "(" expression ")" "{" switch.block "}"
386      *
387      * swtich.block : ( switch.label statement* )*
388      *
389      * swtich.label : DEFAULT ":"
390      * | CASE const.expression ":"
391      */

392     private Stmnt parseSwitch(SymbolTable tbl) throws CompileError {
393         int t = lex.get(); // SWITCH
394
ASTree expr = parseParExpression(tbl);
395         Stmnt body = parseSwitchBlock(tbl);
396         return new Stmnt(t, expr, body);
397     }
398
399     private Stmnt parseSwitchBlock(SymbolTable tbl) throws CompileError {
400         if (lex.get() != '{')
401             throw new SyntaxError(lex);
402
403         SymbolTable tbl2 = new SymbolTable(tbl);
404         Stmnt s = parseStmntOrCase(tbl2);
405         if (s == null)
406             throw new CompileError("empty switch block", lex);
407
408         int op = s.getOperator();
409         if (op != CASE && op != DEFAULT)
410             throw new CompileError("no case or default in a switch block",
411                                    lex);
412
413         Stmnt body = new Stmnt(BLOCK, s);
414         while (lex.lookAhead() != '}') {
415             Stmnt s2 = parseStmntOrCase(tbl2);
416             if (s2 != null) {
417                 int op2 = s2.getOperator();
418                 if (op2 == CASE || op2 == DEFAULT) {
419                     body = (Stmnt)ASTList.concat(body, new Stmnt(BLOCK, s2));
420                     s = s2;
421                 }
422                 else
423                     s = (Stmnt)ASTList.concat(s, new Stmnt(BLOCK, s2));
424             }
425         }
426
427         lex.get(); // '}'
428
return body;
429     }
430
431     private Stmnt parseStmntOrCase(SymbolTable tbl) throws CompileError {
432         int t = lex.lookAhead();
433         if (t != CASE && t != DEFAULT)
434             return parseStatement(tbl);
435
436         lex.get();
437         Stmnt s;
438         if (t == CASE)
439             s = new Stmnt(t, parseExpression(tbl));
440         else
441             s = new Stmnt(DEFAULT);
442
443         if (lex.get() != ':')
444             throw new CompileError(": is missing", lex);
445
446         return s;
447     }
448
449     /* synchronized.statement :
450      * SYNCHRONIZED "(" expression ")" block.statement
451      */

452     private Stmnt parseSynchronized(SymbolTable tbl) throws CompileError {
453         int t = lex.get(); // SYNCHRONIZED
454
if (lex.get() != '(')
455             throw new SyntaxError(lex);
456
457         ASTree expr = parseExpression(tbl);
458         if (lex.get() != ')')
459             throw new SyntaxError(lex);
460
461         Stmnt body = parseBlock(tbl);
462         return new Stmnt(t, expr, body);
463     }
464
465     /* try.statement
466      * : TRY block.statement
467      * [ CATCH "(" class.type Identifier ")" block.statement ]*
468      * [ FINALLY block.statement ]*
469      */

470     private Stmnt parseTry(SymbolTable tbl) throws CompileError {
471         lex.get(); // TRY
472
Stmnt block = parseBlock(tbl);
473         ASTList catchList = null;
474         while (lex.lookAhead() == CATCH) {
475             lex.get(); // CATCH
476
if (lex.get() != '(')
477                 throw new SyntaxError(lex);
478
479             SymbolTable tbl2 = new SymbolTable(tbl);
480             Declarator d = parseFormalParam(tbl2);
481             if (d.getArrayDim() > 0 || d.getType() != CLASS)
482                 throw new SyntaxError(lex);
483
484             if (lex.get() != ')')
485                 throw new SyntaxError(lex);
486
487             Stmnt b = parseBlock(tbl2);
488             catchList = ASTList.append(catchList, new Pair(d, b));
489         }
490
491         Stmnt finallyBlock = null;
492         if (lex.lookAhead() == FINALLY) {
493             lex.get(); // FINALLY
494
finallyBlock = parseBlock(tbl);
495         }
496
497         return Stmnt.make(TRY, block, catchList, finallyBlock);
498     }
499
500     /* return.statement : RETURN [ expression ] ";"
501      */

502     private Stmnt parseReturn(SymbolTable tbl) throws CompileError {
503         int t = lex.get(); // RETURN
504
Stmnt s = new Stmnt(t);
505         if (lex.lookAhead() != ';')
506             s.setLeft(parseExpression(tbl));
507
508         if (lex.get() != ';')
509             throw new CompileError("; is missing", lex);
510
511         return s;
512     }
513
514     /* throw.statement : THROW expression ";"
515      */

516     private Stmnt parseThrow(SymbolTable tbl) throws CompileError {
517         int t = lex.get(); // THROW
518
ASTree expr = parseExpression(tbl);
519         if (lex.get() != ';')
520             throw new CompileError("; is missing", lex);
521
522         return new Stmnt(t, expr);
523     }
524
525     /* break.statement : BREAK [ Identifier ] ";"
526      */

527     private Stmnt parseBreak(SymbolTable tbl)
528         throws CompileError
529     {
530         return parseContinue(tbl);
531     }
532
533     /* continue.statement : CONTINUE [ Identifier ] ";"
534      */

535     private Stmnt parseContinue(SymbolTable tbl)
536         throws CompileError
537     {
538         int t = lex.get(); // CONTINUE
539
Stmnt s = new Stmnt(t);
540         int t2 = lex.get();
541         if (t2 == Identifier) {
542             s.setLeft(new Symbol(lex.getString()));
543             t2 = lex.get();
544         }
545
546         if (t2 != ';')
547             throw new CompileError("; is missing", lex);
548
549         return s;
550     }
551
552     /* declaration.or.expression
553      * : [ FINAL ] built-in-type array.dimension declarators
554      * | [ FINAL ] class.type array.dimension declarators
555      * | expression ';'
556      * | expr.list ';' if exprList is true
557      *
558      * Note: FINAL is currently ignored. This must be fixed
559      * in future.
560      */

561     private Stmnt parseDeclarationOrExpression(SymbolTable tbl,
562                                                boolean exprList)
563         throws CompileError
564     {
565         int t = lex.lookAhead();
566         while (t == FINAL) {
567             lex.get();
568             t = lex.lookAhead();
569         }
570
571         if (isBuiltinType(t)) {
572             t = lex.get();
573             int dim = parseArrayDimension();
574             return parseDeclarators(tbl, new Declarator(t, dim));
575         }
576         else if (t == Identifier) {
577             int i = nextIsClassType(0);
578             if (i >= 0)
579                 if (lex.lookAhead(i) == Identifier) {
580                     ASTList name = parseClassType(tbl);
581                     int dim = parseArrayDimension();
582                     return parseDeclarators(tbl, new Declarator(name, dim));
583                 }
584         }
585
586         Stmnt expr;
587         if (exprList)
588             expr = parseExprList(tbl);
589         else
590             expr = new Stmnt(EXPR, parseExpression(tbl));
591
592         if (lex.get() != ';')
593             throw new CompileError("; is missing", lex);
594
595         return expr;
596     }
597
598     /* expr.list : ( expression ',')* expression
599      */

600     private Stmnt parseExprList(SymbolTable tbl) throws CompileError {
601         Stmnt expr = null;
602         for (;;) {
603             Stmnt e = new Stmnt(EXPR, parseExpression(tbl));
604             expr = (Stmnt)ASTList.concat(expr, new Stmnt(BLOCK, e));
605             if (lex.lookAhead() == ',')
606                 lex.get();
607             else
608                 return expr;
609         }
610     }
611
612     /* declarators : declarator [ ',' declarator ]* ';'
613      */

614     private Stmnt parseDeclarators(SymbolTable tbl, Declarator d)
615         throws CompileError
616     {
617         Stmnt decl = null;
618         for (;;) {
619             decl = (Stmnt)ASTList.concat(decl,
620                                 new Stmnt(DECL, parseDeclarator(tbl, d)));
621             int t = lex.get();
622             if (t == ';')
623                 return decl;
624             else if (t != ',')
625                 throw new CompileError("; is missing", lex);
626         }
627     }
628
629     /* declarator : Identifier array.dimension [ '=' initializer ]
630      */

631     private Declarator parseDeclarator(SymbolTable tbl, Declarator d)
632         throws CompileError
633     {
634         if (lex.get() != Identifier || d.getType() == VOID)
635             throw new SyntaxError(lex);
636
637         String JavaDoc name = lex.getString();
638         Symbol symbol = new Symbol(name);
639         int dim = parseArrayDimension();
640         ASTree init = null;
641         if (lex.lookAhead() == '=') {
642             lex.get();
643             init = parseInitializer(tbl);
644         }
645
646         Declarator decl = d.make(symbol, dim, init);
647         tbl.append(name, decl);
648         return decl;
649     }
650
651     /* initializer : expression | array.initializer
652      */

653     private ASTree parseInitializer(SymbolTable tbl) throws CompileError {
654         if (lex.lookAhead() == '{')
655             return parseArrayInitializer(tbl);
656         else
657             return parseExpression(tbl);
658     }
659
660     /* array.initializer :
661      * '{' (( array.initializer | expression ) ',')* '}'
662      */

663     private ASTree parseArrayInitializer(SymbolTable tbl)
664         throws CompileError
665     {
666         lex.get(); // '{'
667
throw new CompileError("array initializer is not supported", lex);
668     }
669
670     /* par.expression : '(' expression ')'
671      */

672     private ASTree parseParExpression(SymbolTable tbl) throws CompileError {
673         if (lex.get() != '(')
674             throw new SyntaxError(lex);
675
676         ASTree expr = parseExpression(tbl);
677         if (lex.get() != ')')
678             throw new SyntaxError(lex);
679
680         return expr;
681     }
682
683     /* expression : conditional.expr
684      * | conditional.expr assign.op expression (right-to-left)
685      */

686     public ASTree parseExpression(SymbolTable tbl) throws CompileError {
687         ASTree left = parseConditionalExpr(tbl);
688         if (!isAssignOp(lex.lookAhead()))
689             return left;
690
691         int t = lex.get();
692         ASTree right = parseExpression(tbl);
693         return AssignExpr.makeAssign(t, left, right);
694     }
695
696     private static boolean isAssignOp(int t) {
697         return t == '=' || t == MOD_E || t == AND_E
698                 || t == MUL_E || t == PLUS_E || t == MINUS_E || t == DIV_E
699                 || t == EXOR_E || t == OR_E || t == LSHIFT_E
700                 || t == RSHIFT_E || t == ARSHIFT_E;
701     }
702
703     /* conditional.expr (right-to-left)
704      * : logical.or.expr [ '?' expression ':' conditional.expr ]
705      */

706     private ASTree parseConditionalExpr(SymbolTable tbl) throws CompileError {
707         ASTree cond = parseBinaryExpr(tbl);
708         if (lex.lookAhead() == '?') {
709             lex.get();
710             ASTree thenExpr = parseExpression(tbl);
711             if (lex.get() != ':')
712                 throw new CompileError(": is missing", lex);
713
714             ASTree elseExpr = parseExpression(tbl);
715             return new CondExpr(cond, thenExpr, elseExpr);
716         }
717         else
718             return cond;
719     }
720
721     /* logical.or.expr 10 (operator precedence)
722      * : logical.and.expr
723      * | logical.or.expr OROR logical.and.expr left-to-right
724      *
725      * logical.and.expr 9
726      * : inclusive.or.expr
727      * | logical.and.expr ANDAND inclusive.or.expr
728      *
729      * inclusive.or.expr 8
730      * : exclusive.or.expr
731      * | inclusive.or.expr "|" exclusive.or.expr
732      *
733      * exclusive.or.expr 7
734      * : and.expr
735      * | exclusive.or.expr "^" and.expr
736      *
737      * and.expr 6
738      * : equality.expr
739      * | and.expr "&" equality.expr
740      *
741      * equality.expr 5
742      * : relational.expr
743      * | equality.expr (EQ | NEQ) relational.expr
744      *
745      * relational.expr 4
746      * : shift.expr
747      * | relational.expr (LE | GE | "<" | ">") shift.expr
748      * | relational.expr INSTANCEOF class.type ("[" "]")*
749      *
750      * shift.expr 3
751      * : additive.expr
752      * | shift.expr (LSHIFT | RSHIFT | ARSHIFT) additive.expr
753      *
754      * additive.expr 2
755      * : multiply.expr
756      * | additive.expr ("+" | "-") multiply.expr
757      *
758      * multiply.expr 1
759      * : unary.expr
760      * | multiply.expr ("*" | "/" | "%") unary.expr
761      */

762     private ASTree parseBinaryExpr(SymbolTable tbl) throws CompileError {
763         ASTree expr = parseUnaryExpr(tbl);
764         for (;;) {
765             int t = lex.lookAhead();
766             int p = getOpPrecedence(t);
767             if (p == 0)
768                 return expr;
769             else
770                 expr = binaryExpr2(tbl, expr, p);
771         }
772     }
773
774     private ASTree parseInstanceOf(SymbolTable tbl, ASTree expr)
775         throws CompileError
776     {
777         int t = lex.lookAhead();
778         if (isBuiltinType(t)) {
779             lex.get(); // primitive type
780
int dim = parseArrayDimension();
781             return new InstanceOfExpr(t, dim, expr);
782         }
783         else {
784             ASTList name = parseClassType(tbl);
785             int dim = parseArrayDimension();
786             return new InstanceOfExpr(name, dim, expr);
787         }
788     }
789
790     private ASTree binaryExpr2(SymbolTable tbl, ASTree expr, int prec)
791         throws CompileError
792     {
793         int t = lex.get();
794         if (t == INSTANCEOF)
795             return parseInstanceOf(tbl, expr);
796
797         ASTree expr2 = parseUnaryExpr(tbl);
798         for (;;) {
799             int t2 = lex.lookAhead();
800             int p2 = getOpPrecedence(t2);
801             if (p2 != 0 && prec > p2)
802                 expr2 = binaryExpr2(tbl, expr2, p2);
803             else
804                 return BinExpr.makeBin(t, expr, expr2);
805         }
806     }
807
808     // !"#$%&'( )*+,-./0 12345678 9:;<=>?
809
private static final int[] binaryOpPrecedence
810         = { 0, 0, 0, 0, 1, 6, 0, 0,
811              0, 1, 2, 0, 2, 0, 1, 0,
812              0, 0, 0, 0, 0, 0, 0, 0,
813              0, 0, 0, 4, 0, 4, 0 };
814
815     private int getOpPrecedence(int c) {
816         if ('!' <= c && c <= '?')
817             return binaryOpPrecedence[c - '!'];
818         else if (c == '^')
819             return 7;
820         else if (c == '|')
821             return 8;
822         else if (c == ANDAND)
823             return 9;
824         else if (c == OROR)
825             return 10;
826         else if (c == EQ || c == NEQ)
827             return 5;
828         else if (c == LE || c == GE || c == INSTANCEOF)
829             return 4;
830         else if (c == LSHIFT || c == RSHIFT || c == ARSHIFT)
831             return 3;
832         else
833             return 0; // not a binary operator
834
}
835
836     /* unary.expr : "++"|"--" unary.expr
837                   | "+"|"-" unary.expr
838                   | "!"|"~" unary.expr
839                   | cast.expr
840                   | postfix.expr
841
842        unary.expr.not.plus.minus is a unary expression starting without
843        "+", "-", "++", or "--".
844      */

845     private ASTree parseUnaryExpr(SymbolTable tbl) throws CompileError {
846         int t;
847         switch (lex.lookAhead()) {
848         case '+' :
849         case '-' :
850         case PLUSPLUS :
851         case MINUSMINUS :
852         case '!' :
853         case '~' :
854             t = lex.get();
855             return Expr.make(t, parseUnaryExpr(tbl));
856         case '(' :
857             return parseCast(tbl);
858         default :
859             return parsePostfix(tbl);
860         }
861     }
862
863     /* cast.expr : "(" builtin.type ("[" "]")* ")" unary.expr
864                  | "(" class.type ("[" "]")* ")" unary.expr2
865
866        unary.expr2 is a unary.expr begining with "(", NULL, StringL,
867        Identifier, THIS, SUPER, or NEW.
868
869        Either "(int.class)" or "(String[].class)" is a not cast expression.
870      */

871     private ASTree parseCast(SymbolTable tbl) throws CompileError {
872         int t = lex.lookAhead(1);
873         if (isBuiltinType(t) && nextIsBuiltinCast()) {
874             lex.get(); // '('
875
lex.get(); // primitive type
876
int dim = parseArrayDimension();
877             if (lex.get() != ')')
878                 throw new CompileError(") is missing", lex);
879
880             return new CastExpr(t, dim, parseUnaryExpr(tbl));
881         }
882         else if (t == Identifier && nextIsClassCast()) {
883             lex.get(); // '('
884
ASTList name = parseClassType(tbl);
885             int dim = parseArrayDimension();
886             if (lex.get() != ')')
887                 throw new CompileError(") is missing", lex);
888
889             return new CastExpr(name, dim, parseUnaryExpr(tbl));
890         }
891         else
892             return parsePostfix(tbl);
893     }
894
895     private boolean nextIsBuiltinCast() {
896         int t;
897         int i = 2;
898         while ((t = lex.lookAhead(i++)) == '[')
899             if (lex.lookAhead(i++) != ']')
900                 return false;
901
902         return lex.lookAhead(i - 1) == ')';
903     }
904
905     private boolean nextIsClassCast() {
906         int i = nextIsClassType(1);
907         if (i < 0)
908             return false;
909
910         int t = lex.lookAhead(i);
911         if (t != ')')
912             return false;
913
914         t = lex.lookAhead(i + 1);
915         return t == '(' || t == NULL || t == StringL
916                || t == Identifier || t == THIS || t == SUPER || t == NEW
917                || t == TRUE || t == FALSE || t == LongConstant
918                || t == IntConstant || t == CharConstant
919                || t == DoubleConstant || t == FloatConstant;
920     }
921
922     private int nextIsClassType(int i) {
923         int t;
924         while (lex.lookAhead(++i) == '.')
925             if (lex.lookAhead(++i) != Identifier)
926                 return -1;
927
928         while ((t = lex.lookAhead(i++)) == '[')
929             if (lex.lookAhead(i++) != ']')
930                 return -1;
931
932         return i - 1;
933     }
934
935     /* array.dimension : [ "[" "]" ]*
936      */

937     private int parseArrayDimension() throws CompileError {
938         int arrayDim = 0;
939         while (lex.lookAhead() == '[') {
940             ++arrayDim;
941             lex.get();
942             if (lex.get() != ']')
943                 throw new CompileError("] is missing", lex);
944         }
945
946         return arrayDim;
947     }
948
949     /* class.type : Identifier ( "." Identifier )*
950      */

951     private ASTList parseClassType(SymbolTable tbl) throws CompileError {
952         ASTList list = null;
953         for (;;) {
954             if (lex.get() != Identifier)
955                 throw new SyntaxError(lex);
956
957             list = ASTList.append(list, new Symbol(lex.getString()));
958             if (lex.lookAhead() == '.')
959                 lex.get();
960             else
961                 break;
962         }
963
964         return list;
965     }
966
967     /* postfix.expr : number.literal
968      * | primary.expr
969      * | method.expr
970      * | postfix.expr "++" | "--"
971      * | postfix.expr "[" array.size "]"
972      * | postfix.expr "." Identifier
973      * | postfix.expr ( "[" "]" )* "." CLASS
974      * | postfix.expr "#" Identifier
975      *
976      * "#" is not an operator of regular Java. It separates
977      * a class name and a member name in an expression for static member
978      * access. For example,
979      * java.lang.Integer.toString(3) in regular Java
980      * must be written like this:
981      * java.lang.Integer#toString(3) for this compiler.
982      */

983     private ASTree parsePostfix(SymbolTable tbl) throws CompileError {
984         int token = lex.lookAhead();
985         switch (token) {
986         case LongConstant :
987         case IntConstant :
988         case CharConstant :
989             lex.get();
990             return new IntConst(lex.getLong(), token);
991         case DoubleConstant :
992         case FloatConstant :
993             lex.get();
994             return new DoubleConst(lex.getDouble(), token);
995         default :
996             break;
997         }
998
999         String JavaDoc str;
1000        ASTree index;
1001        ASTree expr = parsePrimaryExpr(tbl);
1002        int t;
1003        while (true) {
1004            switch (lex.lookAhead()) {
1005            case '(' :
1006                expr = parseMethodCall(tbl, expr);
1007                break;
1008            case '[' :
1009                if (lex.lookAhead(1) == ']') {
1010                    int dim = parseArrayDimension();
1011                    if (lex.get() != '.' || lex.get() != CLASS)
1012                        throw new SyntaxError(lex);
1013
1014                    expr = parseDotClass(expr, dim);
1015                }
1016                else {
1017                    index = parseArrayIndex(tbl);
1018                    if (index == null)
1019                        throw new SyntaxError(lex);
1020
1021                    expr = Expr.make(ARRAY, expr, index);
1022                }
1023                break;
1024            case PLUSPLUS :
1025            case MINUSMINUS :
1026                t = lex.get();
1027                expr = Expr.make(t, null, expr);
1028                break;
1029            case '.' :
1030                lex.get();
1031                t = lex.get();
1032                if (t == CLASS) {
1033                    expr = parseDotClass(expr, 0);
1034                }
1035                else if (t == Identifier) {
1036                    str = lex.getString();
1037                    expr = Expr.make('.', expr, new Member(str));
1038                }
1039                else
1040                    throw new CompileError("missing member name", lex);
1041                break;
1042            case '#' :
1043                lex.get();
1044                t = lex.get();
1045                if (t != Identifier)
1046                    throw new CompileError("missing static member name", lex);
1047
1048                str = lex.getString();
1049                expr = Expr.make(MEMBER, new Symbol(toClassName(expr)),
1050                                 new Member(str));
1051                break;
1052            default :
1053                return expr;
1054            }
1055        }
1056    }
1057
1058    /* Parse a .class expression on a class type. For example,
1059     * String.class => ('.' "String" "class")
1060     * String[].class => ('.' "[LString;" "class")
1061     */

1062    private ASTree parseDotClass(ASTree className, int dim)
1063        throws CompileError
1064    {
1065        String JavaDoc cname = toClassName(className);
1066        if (dim > 0) {
1067            StringBuffer JavaDoc sbuf = new StringBuffer JavaDoc();
1068            while (dim-- > 0)
1069                sbuf.append('[');
1070
1071            sbuf.append('L').append(cname.replace('.', '/')).append(';');
1072            cname = sbuf.toString();
1073        }
1074
1075        return Expr.make('.', new Symbol(cname), new Member("class"));
1076    }
1077
1078    /* Parses a .class expression on a built-in type. For example,
1079     * int.class => ('#' "java.lang.Integer" "TYPE")
1080     * int[].class => ('.' "[I", "class")
1081     */

1082    private ASTree parseDotClass(int builtinType, int dim)
1083        throws CompileError
1084    {
1085        if (dim > 0) {
1086            String JavaDoc cname = CodeGen.toJvmTypeName(builtinType, dim);
1087            return Expr.make('.', new Symbol(cname), new Member("class"));
1088        }
1089        else {
1090            String JavaDoc cname;
1091            switch(builtinType) {
1092            case BOOLEAN :
1093                cname = "java.lang.Boolean";
1094                break;
1095            case BYTE :
1096                cname = "java.lang.Byte";
1097                break;
1098            case CHAR :
1099                cname = "java.lang.Character";
1100                break;
1101            case SHORT :
1102                cname = "java.lang.Short";
1103                break;
1104            case INT :
1105                cname = "java.lang.Integer";
1106                break;
1107            case LONG :
1108                cname = "java.lang.Long";
1109                break;
1110            case FLOAT :
1111                cname = "java.lang.Float";
1112                break;
1113            case DOUBLE :
1114                cname = "java.lang.Double";
1115                break;
1116            case VOID :
1117                cname = "java.lang.Void";
1118                break;
1119            default :
1120                throw new CompileError("invalid builtin type: "
1121                                       + builtinType);
1122            }
1123
1124            return Expr.make(MEMBER, new Symbol(cname), new Member("TYPE"));
1125        }
1126    }
1127
1128    /* method.call : method.expr "(" argument.list ")"
1129     * method.expr : THIS | SUPER | Identifier
1130     * | postfix.expr "." Identifier
1131     * | postfix.expr "#" Identifier
1132     */

1133    private ASTree parseMethodCall(SymbolTable tbl, ASTree expr)
1134        throws CompileError
1135    {
1136        if (expr instanceof Keyword) {
1137            int token = ((Keyword)expr).get();
1138            if (token != THIS && token != SUPER)
1139                throw new SyntaxError(lex);
1140        }
1141        else if (expr instanceof Symbol) // Identifier
1142
;
1143        else if (expr instanceof Expr) {
1144            int op = ((Expr)expr).getOperator();
1145            if (op != '.' && op != MEMBER)
1146                throw new SyntaxError(lex);
1147        }
1148
1149        return CallExpr.makeCall(expr, parseArgumentList(tbl));
1150    }
1151
1152    private String JavaDoc toClassName(ASTree name)
1153        throws CompileError
1154    {
1155        StringBuffer JavaDoc sbuf = new StringBuffer JavaDoc();
1156        toClassName(name, sbuf);
1157        return sbuf.toString();
1158    }
1159
1160    private void toClassName(ASTree name, StringBuffer JavaDoc sbuf)
1161        throws CompileError
1162    {
1163        if (name instanceof Symbol) {
1164            sbuf.append(((Symbol)name).get());
1165            return;
1166        }
1167        else if (name instanceof Expr) {
1168            Expr expr = (Expr)name;
1169            if (expr.getOperator() == '.') {
1170                toClassName(expr.oprand1(), sbuf);
1171                sbuf.append('.');
1172                toClassName(expr.oprand2(), sbuf);
1173                return;
1174            }
1175        }
1176
1177        throw new CompileError("bad static member access", lex);
1178    }
1179
1180    /* primary.expr : THIS | SUPER | TRUE | FALSE | NULL
1181     * | StringL
1182     * | Identifier
1183     * | NEW new.expr
1184     * | "(" expression ")"
1185     * | builtin.type ( "[" "]" )* "." CLASS
1186     *
1187     * Identifier represents either a local variable name, a member name,
1188     * or a class name.
1189     */

1190    private ASTree parsePrimaryExpr(SymbolTable tbl) throws CompileError {
1191        int t;
1192        String JavaDoc name;
1193        Declarator decl;
1194        ASTree expr;
1195
1196        switch (t = lex.get()) {
1197        case THIS :
1198        case SUPER :
1199        case TRUE :
1200        case FALSE :
1201        case NULL :
1202            return new Keyword(t);
1203        case Identifier :
1204            name = lex.getString();
1205            decl = tbl.lookup(name);
1206            if (decl == null)
1207                return new Member(name); // this or static member
1208
else
1209                return new Variable(name, decl); // local variable
1210
case StringL :
1211            return new StringL(lex.getString());
1212        case NEW :
1213            return parseNew(tbl);
1214        case '(' :
1215            expr = parseExpression(tbl);
1216            if (lex.get() == ')')
1217                return expr;
1218            else
1219                throw new CompileError(") is missing", lex);
1220        default :
1221            if (isBuiltinType(t) || t == VOID) {
1222                int dim = parseArrayDimension();
1223                if (lex.get() == '.' && lex.get() == CLASS)
1224                    return parseDotClass(t, dim);
1225            }
1226
1227            throw new SyntaxError(lex);
1228        }
1229    }
1230
1231    /* new.expr : class.type "(" argument.list ")"
1232     * | class.type array.size [ array.initializer ]
1233     * | primitive.type array.size [ array.initializer ]
1234     */

1235    private NewExpr parseNew(SymbolTable tbl) throws CompileError {
1236        ASTree init = null;
1237        int t = lex.lookAhead();
1238        if (isBuiltinType(t)) {
1239            lex.get();
1240            ASTList size = parseArraySize(tbl);
1241            if (lex.lookAhead() == '{')
1242                init = parseArrayInitializer(tbl);
1243
1244            return new NewExpr(t, size, init);
1245        }
1246        else if (t == Identifier) {
1247            ASTList name = parseClassType(tbl);
1248            t = lex.lookAhead();
1249            if (t == '(') {
1250                ASTList args = parseArgumentList(tbl);
1251                return new NewExpr(name, args);
1252            }
1253            else if (t == '[') {
1254                ASTList size = parseArraySize(tbl);
1255                if (lex.lookAhead() == '{')
1256                    init = parseArrayInitializer(tbl);
1257
1258                return NewExpr.makeObjectArray(name, size, init);
1259            }
1260        }
1261
1262        throw new SyntaxError(lex);
1263    }
1264
1265    /* array.size : [ array.index ]*
1266     */

1267    private ASTList parseArraySize(SymbolTable tbl) throws CompileError {
1268        ASTList list = null;
1269        while (lex.lookAhead() == '[')
1270            list = ASTList.append(list, parseArrayIndex(tbl));
1271
1272        return list;
1273    }
1274
1275    /* array.index : "[" [ expression ] "]"
1276     */

1277    private ASTree parseArrayIndex(SymbolTable tbl) throws CompileError {
1278        lex.get(); // '['
1279
if (lex.lookAhead() == ']') {
1280            lex.get();
1281            return null;
1282        }
1283        else {
1284            ASTree index = parseExpression(tbl);
1285            if (lex.get() != ']')
1286                throw new CompileError("] is missing", lex);
1287
1288            return index;
1289        }
1290    }
1291
1292    /* argument.list : "(" [ expression [ "," expression ]* ] ")"
1293     */

1294    private ASTList parseArgumentList(SymbolTable tbl) throws CompileError {
1295        if (lex.get() != '(')
1296            throw new CompileError("( is missing", lex);
1297
1298        ASTList list = null;
1299        if (lex.lookAhead() != ')')
1300            for (;;) {
1301                list = ASTList.append(list, parseExpression(tbl));
1302                if (lex.lookAhead() == ',')
1303                    lex.get();
1304                else
1305                    break;
1306            }
1307
1308        if (lex.get() != ')')
1309            throw new CompileError(") is missing", lex);
1310
1311        return list;
1312    }
1313}
1314
1315
Popular Tags