/Users/lyon/j4p/src/javassist/compiler/Parser.java

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