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