21 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, |
21 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, |
22 * CA 95054 USA or visit www.sun.com if you need additional information or |
22 * CA 95054 USA or visit www.sun.com if you need additional information or |
23 * have any questions. |
23 * have any questions. |
24 */ |
24 */ |
25 |
25 |
|
26 |
26 package com.sun.tools.javac.parser; |
27 package com.sun.tools.javac.parser; |
27 |
28 |
28 import java.util.*; |
29 import com.sun.tools.javac.tree.JCTree.JCCompilationUnit; |
|
30 import com.sun.tools.javac.tree.JCTree.JCExpression; |
|
31 import com.sun.tools.javac.tree.JCTree.JCStatement; |
29 |
32 |
30 import com.sun.tools.javac.tree.*; |
33 /** |
31 import com.sun.tools.javac.code.*; |
34 * Reads syntactic units from source code. |
32 import com.sun.tools.javac.util.*; |
35 * Parsers are normally created from a ParserFactory. |
33 import com.sun.tools.javac.util.List; |
|
34 import static com.sun.tools.javac.util.ListBuffer.lb; |
|
35 |
|
36 import com.sun.tools.javac.tree.JCTree.*; |
|
37 |
|
38 import static com.sun.tools.javac.parser.Token.*; |
|
39 |
|
40 /** The parser maps a token sequence into an abstract syntax |
|
41 * tree. It operates by recursive descent, with code derived |
|
42 * systematically from an LL(1) grammar. For efficiency reasons, an |
|
43 * operator precedence scheme is used for parsing binary operation |
|
44 * expressions. |
|
45 * |
36 * |
46 * <p><b>This is NOT part of any API supported by Sun Microsystems. If |
37 * <p><b>This is NOT part of any API supported by Sun Microsystems. |
47 * you write code that depends on this, you do so at your own risk. |
38 * If you write code that depends on this, you do so at your own risk. |
48 * This code and its internal interfaces are subject to change or |
39 * This code and its internal interfaces are subject to change or |
49 * deletion without notice.</b> |
40 * deletion without notice.</b> |
50 */ |
41 */ |
51 public class Parser { |
42 public interface Parser { |
52 |
43 /** |
53 /** A factory for creating parsers. */ |
44 * Parse a compilation unit. |
54 public static class Factory { |
45 * @return a compilation unit |
55 /** The context key for the parser factory. */ |
|
56 protected static final Context.Key<Parser.Factory> parserFactoryKey = |
|
57 new Context.Key<Parser.Factory>(); |
|
58 |
|
59 /** Get the Factory instance for this context. */ |
|
60 public static Factory instance(Context context) { |
|
61 Factory instance = context.get(parserFactoryKey); |
|
62 if (instance == null) |
|
63 instance = new Factory(context); |
|
64 return instance; |
|
65 } |
|
66 |
|
67 final TreeMaker F; |
|
68 final Log log; |
|
69 final Keywords keywords; |
|
70 final Source source; |
|
71 final Name.Table names; |
|
72 final Options options; |
|
73 |
|
74 /** Create a new parser factory. */ |
|
75 protected Factory(Context context) { |
|
76 context.put(parserFactoryKey, this); |
|
77 this.F = TreeMaker.instance(context); |
|
78 this.log = Log.instance(context); |
|
79 this.names = Name.Table.instance(context); |
|
80 this.keywords = Keywords.instance(context); |
|
81 this.source = Source.instance(context); |
|
82 this.options = Options.instance(context); |
|
83 } |
|
84 |
|
85 /** |
|
86 * Create a new Parser. |
|
87 * @param S Lexer for getting tokens while parsing |
|
88 * @param keepDocComments true if javadoc comments should be kept |
|
89 * @param genEndPos true if end positions should be generated |
|
90 */ |
|
91 public Parser newParser(Lexer S, boolean keepDocComments, boolean genEndPos) { |
|
92 if (!genEndPos) |
|
93 return new Parser(this, S, keepDocComments); |
|
94 else |
|
95 return new EndPosParser(this, S, keepDocComments); |
|
96 } |
|
97 } |
|
98 |
|
99 /** The number of precedence levels of infix operators. |
|
100 */ |
46 */ |
101 private static final int infixPrecedenceLevels = 10; |
47 JCCompilationUnit parseCompilationUnit(); |
102 |
|
103 /** The scanner used for lexical analysis. |
|
104 */ |
|
105 private Lexer S; |
|
106 |
|
107 /** The factory to be used for abstract syntax tree construction. |
|
108 */ |
|
109 protected TreeMaker F; |
|
110 |
|
111 /** The log to be used for error diagnostics. |
|
112 */ |
|
113 private Log log; |
|
114 |
|
115 /** The keyword table. */ |
|
116 private Keywords keywords; |
|
117 |
|
118 /** The Source language setting. */ |
|
119 private Source source; |
|
120 |
|
121 /** The name table. */ |
|
122 private Name.Table names; |
|
123 |
|
124 /** Construct a parser from a given scanner, tree factory and log. |
|
125 */ |
|
126 protected Parser(Factory fac, |
|
127 Lexer S, |
|
128 boolean keepDocComments) { |
|
129 this.S = S; |
|
130 S.nextToken(); // prime the pump |
|
131 this.F = fac.F; |
|
132 this.log = fac.log; |
|
133 this.names = fac.names; |
|
134 this.keywords = fac.keywords; |
|
135 this.source = fac.source; |
|
136 Options options = fac.options; |
|
137 this.allowGenerics = source.allowGenerics(); |
|
138 this.allowVarargs = source.allowVarargs(); |
|
139 this.allowAsserts = source.allowAsserts(); |
|
140 this.allowEnums = source.allowEnums(); |
|
141 this.allowForeach = source.allowForeach(); |
|
142 this.allowStaticImport = source.allowStaticImport(); |
|
143 this.allowAnnotations = source.allowAnnotations(); |
|
144 this.keepDocComments = keepDocComments; |
|
145 if (keepDocComments) docComments = new HashMap<JCTree,String>(); |
|
146 this.errorTree = F.Erroneous(); |
|
147 } |
|
148 |
|
149 /** Switch: Should generics be recognized? |
|
150 */ |
|
151 boolean allowGenerics; |
|
152 |
|
153 /** Switch: Should varargs be recognized? |
|
154 */ |
|
155 boolean allowVarargs; |
|
156 |
|
157 /** Switch: should we recognize assert statements, or just give a warning? |
|
158 */ |
|
159 boolean allowAsserts; |
|
160 |
|
161 /** Switch: should we recognize enums, or just give a warning? |
|
162 */ |
|
163 boolean allowEnums; |
|
164 |
|
165 /** Switch: should we recognize foreach? |
|
166 */ |
|
167 boolean allowForeach; |
|
168 |
|
169 /** Switch: should we recognize foreach? |
|
170 */ |
|
171 boolean allowStaticImport; |
|
172 |
|
173 /** Switch: should we recognize annotations? |
|
174 */ |
|
175 boolean allowAnnotations; |
|
176 |
|
177 /** Switch: should we keep docComments? |
|
178 */ |
|
179 boolean keepDocComments; |
|
180 |
|
181 /** When terms are parsed, the mode determines which is expected: |
|
182 * mode = EXPR : an expression |
|
183 * mode = TYPE : a type |
|
184 * mode = NOPARAMS : no parameters allowed for type |
|
185 * mode = TYPEARG : type argument |
|
186 */ |
|
187 static final int EXPR = 1; |
|
188 static final int TYPE = 2; |
|
189 static final int NOPARAMS = 4; |
|
190 static final int TYPEARG = 8; |
|
191 |
|
192 /** The current mode. |
|
193 */ |
|
194 private int mode = 0; |
|
195 |
|
196 /** The mode of the term that was parsed last. |
|
197 */ |
|
198 private int lastmode = 0; |
|
199 |
|
200 /* ---------- error recovery -------------- */ |
|
201 |
|
202 private JCErroneous errorTree; |
|
203 |
|
204 /** Skip forward until a suitable stop token is found. |
|
205 */ |
|
206 private void skip(boolean stopAtImport, boolean stopAtMemberDecl, boolean stopAtIdentifier, boolean stopAtStatement) { |
|
207 while (true) { |
|
208 switch (S.token()) { |
|
209 case SEMI: |
|
210 S.nextToken(); |
|
211 return; |
|
212 case PUBLIC: |
|
213 case FINAL: |
|
214 case ABSTRACT: |
|
215 case MONKEYS_AT: |
|
216 case EOF: |
|
217 case CLASS: |
|
218 case INTERFACE: |
|
219 case ENUM: |
|
220 return; |
|
221 case IMPORT: |
|
222 if (stopAtImport) |
|
223 return; |
|
224 break; |
|
225 case LBRACE: |
|
226 case RBRACE: |
|
227 case PRIVATE: |
|
228 case PROTECTED: |
|
229 case STATIC: |
|
230 case TRANSIENT: |
|
231 case NATIVE: |
|
232 case VOLATILE: |
|
233 case SYNCHRONIZED: |
|
234 case STRICTFP: |
|
235 case LT: |
|
236 case BYTE: |
|
237 case SHORT: |
|
238 case CHAR: |
|
239 case INT: |
|
240 case LONG: |
|
241 case FLOAT: |
|
242 case DOUBLE: |
|
243 case BOOLEAN: |
|
244 case VOID: |
|
245 if (stopAtMemberDecl) |
|
246 return; |
|
247 break; |
|
248 case IDENTIFIER: |
|
249 if (stopAtIdentifier) |
|
250 return; |
|
251 break; |
|
252 case CASE: |
|
253 case DEFAULT: |
|
254 case IF: |
|
255 case FOR: |
|
256 case WHILE: |
|
257 case DO: |
|
258 case TRY: |
|
259 case SWITCH: |
|
260 case RETURN: |
|
261 case THROW: |
|
262 case BREAK: |
|
263 case CONTINUE: |
|
264 case ELSE: |
|
265 case FINALLY: |
|
266 case CATCH: |
|
267 if (stopAtStatement) |
|
268 return; |
|
269 break; |
|
270 } |
|
271 S.nextToken(); |
|
272 } |
|
273 } |
|
274 |
|
275 private JCErroneous syntaxError(int pos, String key, Token... args) { |
|
276 return syntaxError(pos, null, key, args); |
|
277 } |
|
278 |
|
279 private JCErroneous syntaxError(int pos, List<JCTree> errs, String key, Token... args) { |
|
280 setErrorEndPos(pos); |
|
281 reportSyntaxError(pos, key, (Object[])args); |
|
282 return toP(F.at(pos).Erroneous(errs)); |
|
283 } |
|
284 |
|
285 private int errorPos = Position.NOPOS; |
|
286 /** |
|
287 * Report a syntax error at given position using the given |
|
288 * argument unless one was already reported at the same position. |
|
289 */ |
|
290 private void reportSyntaxError(int pos, String key, Object... args) { |
|
291 if (pos > S.errPos() || pos == Position.NOPOS) { |
|
292 if (S.token() == EOF) |
|
293 log.error(pos, "premature.eof"); |
|
294 else |
|
295 log.error(pos, key, args); |
|
296 } |
|
297 S.errPos(pos); |
|
298 if (S.pos() == errorPos) |
|
299 S.nextToken(); // guarantee progress |
|
300 errorPos = S.pos(); |
|
301 } |
|
302 |
|
303 |
|
304 /** Generate a syntax error at current position unless one was already |
|
305 * reported at the same position. |
|
306 */ |
|
307 private JCErroneous syntaxError(String key) { |
|
308 return syntaxError(S.pos(), key); |
|
309 } |
|
310 |
|
311 /** Generate a syntax error at current position unless one was |
|
312 * already reported at the same position. |
|
313 */ |
|
314 private JCErroneous syntaxError(String key, Token arg) { |
|
315 return syntaxError(S.pos(), key, arg); |
|
316 } |
|
317 |
|
318 /** If next input token matches given token, skip it, otherwise report |
|
319 * an error. |
|
320 */ |
|
321 public void accept(Token token) { |
|
322 if (S.token() == token) { |
|
323 S.nextToken(); |
|
324 } else { |
|
325 setErrorEndPos(S.pos()); |
|
326 reportSyntaxError(S.prevEndPos(), "expected", token); |
|
327 } |
|
328 } |
|
329 |
|
330 /** Report an illegal start of expression/type error at given position. |
|
331 */ |
|
332 JCExpression illegal(int pos) { |
|
333 setErrorEndPos(S.pos()); |
|
334 if ((mode & EXPR) != 0) |
|
335 return syntaxError(pos, "illegal.start.of.expr"); |
|
336 else |
|
337 return syntaxError(pos, "illegal.start.of.type"); |
|
338 |
|
339 } |
|
340 |
|
341 /** Report an illegal start of expression/type error at current position. |
|
342 */ |
|
343 JCExpression illegal() { |
|
344 return illegal(S.pos()); |
|
345 } |
|
346 |
|
347 /** Diagnose a modifier flag from the set, if any. */ |
|
348 void checkNoMods(long mods) { |
|
349 if (mods != 0) { |
|
350 long lowestMod = mods & -mods; |
|
351 log.error(S.pos(), "mod.not.allowed.here", |
|
352 Flags.asFlagSet(lowestMod)); |
|
353 } |
|
354 } |
|
355 |
|
356 /* ---------- doc comments --------- */ |
|
357 |
|
358 /** A hashtable to store all documentation comments |
|
359 * indexed by the tree nodes they refer to. |
|
360 * defined only if option flag keepDocComment is set. |
|
361 */ |
|
362 Map<JCTree, String> docComments; |
|
363 |
|
364 /** Make an entry into docComments hashtable, |
|
365 * provided flag keepDocComments is set and given doc comment is non-null. |
|
366 * @param tree The tree to be used as index in the hashtable |
|
367 * @param dc The doc comment to associate with the tree, or null. |
|
368 */ |
|
369 void attach(JCTree tree, String dc) { |
|
370 if (keepDocComments && dc != null) { |
|
371 // System.out.println("doc comment = ");System.out.println(dc);//DEBUG |
|
372 docComments.put(tree, dc); |
|
373 } |
|
374 } |
|
375 |
|
376 /* -------- source positions ------- */ |
|
377 |
|
378 private int errorEndPos = -1; |
|
379 |
|
380 private void setErrorEndPos(int errPos) { |
|
381 if (errPos > errorEndPos) |
|
382 errorEndPos = errPos; |
|
383 } |
|
384 |
|
385 protected int getErrorEndPos() { |
|
386 return errorEndPos; |
|
387 } |
|
388 |
48 |
389 /** |
49 /** |
390 * Store ending position for a tree. |
50 * Parse an expression. |
391 * @param tree The tree. |
51 * @return an expression |
392 * @param endpos The ending position to associate with the tree. |
|
393 */ |
52 */ |
394 protected void storeEnd(JCTree tree, int endpos) {} |
53 JCExpression parseExpression(); |
395 |
54 |
396 /** |
55 /** |
397 * Store ending position for a tree. The ending position should |
56 * Parse a statement. |
398 * be the ending position of the current token. |
57 * @return an expression |
399 * @param t The tree. |
|
400 */ |
58 */ |
401 protected <T extends JCTree> T to(T t) { return t; } |
59 JCStatement parseStatement(); |
402 |
60 |
403 /** |
61 /** |
404 * Store ending position for a tree. The ending position should |
62 * Parse a type. |
405 * be greater of the ending position of the previous token and errorEndPos. |
63 * @return an expression for a type |
406 * @param t The tree. |
|
407 */ |
64 */ |
408 protected <T extends JCTree> T toP(T t) { return t; } |
65 JCExpression parseType(); |
409 |
|
410 /** Get the start position for a tree node. The start position is |
|
411 * defined to be the position of the first character of the first |
|
412 * token of the node's source text. |
|
413 * @param tree The tree node |
|
414 */ |
|
415 public int getStartPos(JCTree tree) { |
|
416 return TreeInfo.getStartPos(tree); |
|
417 } |
|
418 |
|
419 /** |
|
420 * Get the end position for a tree node. The end position is |
|
421 * defined to be the position of the last character of the last |
|
422 * token of the node's source text. Returns Position.NOPOS if end |
|
423 * positions are not generated or the position is otherwise not |
|
424 * found. |
|
425 * @param tree The tree node |
|
426 */ |
|
427 public int getEndPos(JCTree tree) { |
|
428 return Position.NOPOS; |
|
429 } |
|
430 |
|
431 |
|
432 |
|
433 /* ---------- parsing -------------- */ |
|
434 |
|
435 /** |
|
436 * Ident = IDENTIFIER |
|
437 */ |
|
438 Name ident() { |
|
439 if (S.token() == IDENTIFIER) { |
|
440 Name name = S.name(); |
|
441 S.nextToken(); |
|
442 return name; |
|
443 } else if (S.token() == ASSERT) { |
|
444 if (allowAsserts) { |
|
445 log.error(S.pos(), "assert.as.identifier"); |
|
446 S.nextToken(); |
|
447 return names.error; |
|
448 } else { |
|
449 log.warning(S.pos(), "assert.as.identifier"); |
|
450 Name name = S.name(); |
|
451 S.nextToken(); |
|
452 return name; |
|
453 } |
|
454 } else if (S.token() == ENUM) { |
|
455 if (allowEnums) { |
|
456 log.error(S.pos(), "enum.as.identifier"); |
|
457 S.nextToken(); |
|
458 return names.error; |
|
459 } else { |
|
460 log.warning(S.pos(), "enum.as.identifier"); |
|
461 Name name = S.name(); |
|
462 S.nextToken(); |
|
463 return name; |
|
464 } |
|
465 } else { |
|
466 accept(IDENTIFIER); |
|
467 return names.error; |
|
468 } |
|
469 } |
66 } |
470 |
|
471 /** |
|
472 * Qualident = Ident { DOT Ident } |
|
473 */ |
|
474 public JCExpression qualident() { |
|
475 JCExpression t = toP(F.at(S.pos()).Ident(ident())); |
|
476 while (S.token() == DOT) { |
|
477 int pos = S.pos(); |
|
478 S.nextToken(); |
|
479 t = toP(F.at(pos).Select(t, ident())); |
|
480 } |
|
481 return t; |
|
482 } |
|
483 |
|
484 /** |
|
485 * Literal = |
|
486 * INTLITERAL |
|
487 * | LONGLITERAL |
|
488 * | FLOATLITERAL |
|
489 * | DOUBLELITERAL |
|
490 * | CHARLITERAL |
|
491 * | STRINGLITERAL |
|
492 * | TRUE |
|
493 * | FALSE |
|
494 * | NULL |
|
495 */ |
|
496 JCExpression literal(Name prefix) { |
|
497 int pos = S.pos(); |
|
498 JCExpression t = errorTree; |
|
499 switch (S.token()) { |
|
500 case INTLITERAL: |
|
501 try { |
|
502 t = F.at(pos).Literal( |
|
503 TypeTags.INT, |
|
504 Convert.string2int(strval(prefix), S.radix())); |
|
505 } catch (NumberFormatException ex) { |
|
506 log.error(S.pos(), "int.number.too.large", strval(prefix)); |
|
507 } |
|
508 break; |
|
509 case LONGLITERAL: |
|
510 try { |
|
511 t = F.at(pos).Literal( |
|
512 TypeTags.LONG, |
|
513 new Long(Convert.string2long(strval(prefix), S.radix()))); |
|
514 } catch (NumberFormatException ex) { |
|
515 log.error(S.pos(), "int.number.too.large", strval(prefix)); |
|
516 } |
|
517 break; |
|
518 case FLOATLITERAL: { |
|
519 String proper = (S.radix() == 16 ? ("0x"+ S.stringVal()) : S.stringVal()); |
|
520 Float n; |
|
521 try { |
|
522 n = Float.valueOf(proper); |
|
523 } catch (NumberFormatException ex) { |
|
524 // error already repoted in scanner |
|
525 n = Float.NaN; |
|
526 } |
|
527 if (n.floatValue() == 0.0f && !isZero(proper)) |
|
528 log.error(S.pos(), "fp.number.too.small"); |
|
529 else if (n.floatValue() == Float.POSITIVE_INFINITY) |
|
530 log.error(S.pos(), "fp.number.too.large"); |
|
531 else |
|
532 t = F.at(pos).Literal(TypeTags.FLOAT, n); |
|
533 break; |
|
534 } |
|
535 case DOUBLELITERAL: { |
|
536 String proper = (S.radix() == 16 ? ("0x"+ S.stringVal()) : S.stringVal()); |
|
537 Double n; |
|
538 try { |
|
539 n = Double.valueOf(proper); |
|
540 } catch (NumberFormatException ex) { |
|
541 // error already reported in scanner |
|
542 n = Double.NaN; |
|
543 } |
|
544 if (n.doubleValue() == 0.0d && !isZero(proper)) |
|
545 log.error(S.pos(), "fp.number.too.small"); |
|
546 else if (n.doubleValue() == Double.POSITIVE_INFINITY) |
|
547 log.error(S.pos(), "fp.number.too.large"); |
|
548 else |
|
549 t = F.at(pos).Literal(TypeTags.DOUBLE, n); |
|
550 break; |
|
551 } |
|
552 case CHARLITERAL: |
|
553 t = F.at(pos).Literal( |
|
554 TypeTags.CHAR, |
|
555 S.stringVal().charAt(0) + 0); |
|
556 break; |
|
557 case STRINGLITERAL: |
|
558 t = F.at(pos).Literal( |
|
559 TypeTags.CLASS, |
|
560 S.stringVal()); |
|
561 break; |
|
562 case TRUE: case FALSE: |
|
563 t = F.at(pos).Literal( |
|
564 TypeTags.BOOLEAN, |
|
565 (S.token() == TRUE ? 1 : 0)); |
|
566 break; |
|
567 case NULL: |
|
568 t = F.at(pos).Literal( |
|
569 TypeTags.BOT, |
|
570 null); |
|
571 break; |
|
572 default: |
|
573 assert false; |
|
574 } |
|
575 if (t == errorTree) |
|
576 t = F.at(pos).Erroneous(); |
|
577 storeEnd(t, S.endPos()); |
|
578 S.nextToken(); |
|
579 return t; |
|
580 } |
|
581 //where |
|
582 boolean isZero(String s) { |
|
583 char[] cs = s.toCharArray(); |
|
584 int base = ((Character.toLowerCase(s.charAt(1)) == 'x') ? 16 : 10); |
|
585 int i = ((base==16) ? 2 : 0); |
|
586 while (i < cs.length && (cs[i] == '0' || cs[i] == '.')) i++; |
|
587 return !(i < cs.length && (Character.digit(cs[i], base) > 0)); |
|
588 } |
|
589 |
|
590 String strval(Name prefix) { |
|
591 String s = S.stringVal(); |
|
592 return (prefix.len == 0) ? s : prefix + s; |
|
593 } |
|
594 |
|
595 /** terms can be either expressions or types. |
|
596 */ |
|
597 public JCExpression expression() { |
|
598 return term(EXPR); |
|
599 } |
|
600 |
|
601 public JCExpression type() { |
|
602 return term(TYPE); |
|
603 } |
|
604 |
|
605 JCExpression term(int newmode) { |
|
606 int prevmode = mode; |
|
607 mode = newmode; |
|
608 JCExpression t = term(); |
|
609 lastmode = mode; |
|
610 mode = prevmode; |
|
611 return t; |
|
612 } |
|
613 |
|
614 /** |
|
615 * Expression = Expression1 [ExpressionRest] |
|
616 * ExpressionRest = [AssignmentOperator Expression1] |
|
617 * AssignmentOperator = "=" | "+=" | "-=" | "*=" | "/=" | |
|
618 * "&=" | "|=" | "^=" | |
|
619 * "%=" | "<<=" | ">>=" | ">>>=" |
|
620 * Type = Type1 |
|
621 * TypeNoParams = TypeNoParams1 |
|
622 * StatementExpression = Expression |
|
623 * ConstantExpression = Expression |
|
624 */ |
|
625 JCExpression term() { |
|
626 JCExpression t = term1(); |
|
627 if ((mode & EXPR) != 0 && |
|
628 S.token() == EQ || PLUSEQ.compareTo(S.token()) <= 0 && S.token().compareTo(GTGTGTEQ) <= 0) |
|
629 return termRest(t); |
|
630 else |
|
631 return t; |
|
632 } |
|
633 |
|
634 JCExpression termRest(JCExpression t) { |
|
635 switch (S.token()) { |
|
636 case EQ: { |
|
637 int pos = S.pos(); |
|
638 S.nextToken(); |
|
639 mode = EXPR; |
|
640 JCExpression t1 = term(); |
|
641 return toP(F.at(pos).Assign(t, t1)); |
|
642 } |
|
643 case PLUSEQ: |
|
644 case SUBEQ: |
|
645 case STAREQ: |
|
646 case SLASHEQ: |
|
647 case PERCENTEQ: |
|
648 case AMPEQ: |
|
649 case BAREQ: |
|
650 case CARETEQ: |
|
651 case LTLTEQ: |
|
652 case GTGTEQ: |
|
653 case GTGTGTEQ: |
|
654 int pos = S.pos(); |
|
655 Token token = S.token(); |
|
656 S.nextToken(); |
|
657 mode = EXPR; |
|
658 JCExpression t1 = term(); |
|
659 return F.at(pos).Assignop(optag(token), t, t1); |
|
660 default: |
|
661 return t; |
|
662 } |
|
663 } |
|
664 |
|
665 /** Expression1 = Expression2 [Expression1Rest] |
|
666 * Type1 = Type2 |
|
667 * TypeNoParams1 = TypeNoParams2 |
|
668 */ |
|
669 JCExpression term1() { |
|
670 JCExpression t = term2(); |
|
671 if ((mode & EXPR) != 0 && S.token() == QUES) { |
|
672 mode = EXPR; |
|
673 return term1Rest(t); |
|
674 } else { |
|
675 return t; |
|
676 } |
|
677 } |
|
678 |
|
679 /** Expression1Rest = ["?" Expression ":" Expression1] |
|
680 */ |
|
681 JCExpression term1Rest(JCExpression t) { |
|
682 if (S.token() == QUES) { |
|
683 int pos = S.pos(); |
|
684 S.nextToken(); |
|
685 JCExpression t1 = term(); |
|
686 accept(COLON); |
|
687 JCExpression t2 = term1(); |
|
688 return F.at(pos).Conditional(t, t1, t2); |
|
689 } else { |
|
690 return t; |
|
691 } |
|
692 } |
|
693 |
|
694 /** Expression2 = Expression3 [Expression2Rest] |
|
695 * Type2 = Type3 |
|
696 * TypeNoParams2 = TypeNoParams3 |
|
697 */ |
|
698 JCExpression term2() { |
|
699 JCExpression t = term3(); |
|
700 if ((mode & EXPR) != 0 && prec(S.token()) >= TreeInfo.orPrec) { |
|
701 mode = EXPR; |
|
702 return term2Rest(t, TreeInfo.orPrec); |
|
703 } else { |
|
704 return t; |
|
705 } |
|
706 } |
|
707 |
|
708 /* Expression2Rest = {infixop Expression3} |
|
709 * | Expression3 instanceof Type |
|
710 * infixop = "||" |
|
711 * | "&&" |
|
712 * | "|" |
|
713 * | "^" |
|
714 * | "&" |
|
715 * | "==" | "!=" |
|
716 * | "<" | ">" | "<=" | ">=" |
|
717 * | "<<" | ">>" | ">>>" |
|
718 * | "+" | "-" |
|
719 * | "*" | "/" | "%" |
|
720 */ |
|
721 JCExpression term2Rest(JCExpression t, int minprec) { |
|
722 List<JCExpression[]> savedOd = odStackSupply.elems; |
|
723 JCExpression[] odStack = newOdStack(); |
|
724 List<Token[]> savedOp = opStackSupply.elems; |
|
725 Token[] opStack = newOpStack(); |
|
726 // optimization, was odStack = new Tree[...]; opStack = new Tree[...]; |
|
727 int top = 0; |
|
728 odStack[0] = t; |
|
729 int startPos = S.pos(); |
|
730 Token topOp = ERROR; |
|
731 while (prec(S.token()) >= minprec) { |
|
732 opStack[top] = topOp; |
|
733 top++; |
|
734 topOp = S.token(); |
|
735 int pos = S.pos(); |
|
736 S.nextToken(); |
|
737 odStack[top] = topOp == INSTANCEOF ? type() : term3(); |
|
738 while (top > 0 && prec(topOp) >= prec(S.token())) { |
|
739 odStack[top-1] = makeOp(pos, topOp, odStack[top-1], |
|
740 odStack[top]); |
|
741 top--; |
|
742 topOp = opStack[top]; |
|
743 } |
|
744 } |
|
745 assert top == 0; |
|
746 t = odStack[0]; |
|
747 |
|
748 if (t.getTag() == JCTree.PLUS) { |
|
749 StringBuffer buf = foldStrings(t); |
|
750 if (buf != null) { |
|
751 t = toP(F.at(startPos).Literal(TypeTags.CLASS, buf.toString())); |
|
752 } |
|
753 } |
|
754 |
|
755 odStackSupply.elems = savedOd; // optimization |
|
756 opStackSupply.elems = savedOp; // optimization |
|
757 return t; |
|
758 } |
|
759 //where |
|
760 /** Construct a binary or type test node. |
|
761 */ |
|
762 private JCExpression makeOp(int pos, |
|
763 Token topOp, |
|
764 JCExpression od1, |
|
765 JCExpression od2) |
|
766 { |
|
767 if (topOp == INSTANCEOF) { |
|
768 return F.at(pos).TypeTest(od1, od2); |
|
769 } else { |
|
770 return F.at(pos).Binary(optag(topOp), od1, od2); |
|
771 } |
|
772 } |
|
773 /** If tree is a concatenation of string literals, replace it |
|
774 * by a single literal representing the concatenated string. |
|
775 */ |
|
776 protected StringBuffer foldStrings(JCTree tree) { |
|
777 List<String> buf = List.nil(); |
|
778 while (true) { |
|
779 if (tree.getTag() == JCTree.LITERAL) { |
|
780 JCLiteral lit = (JCLiteral) tree; |
|
781 if (lit.typetag == TypeTags.CLASS) { |
|
782 StringBuffer sbuf = |
|
783 new StringBuffer((String)lit.value); |
|
784 while (buf.nonEmpty()) { |
|
785 sbuf.append(buf.head); |
|
786 buf = buf.tail; |
|
787 } |
|
788 return sbuf; |
|
789 } |
|
790 } else if (tree.getTag() == JCTree.PLUS) { |
|
791 JCBinary op = (JCBinary)tree; |
|
792 if (op.rhs.getTag() == JCTree.LITERAL) { |
|
793 JCLiteral lit = (JCLiteral) op.rhs; |
|
794 if (lit.typetag == TypeTags.CLASS) { |
|
795 buf = buf.prepend((String) lit.value); |
|
796 tree = op.lhs; |
|
797 continue; |
|
798 } |
|
799 } |
|
800 } |
|
801 return null; |
|
802 } |
|
803 } |
|
804 |
|
805 /** optimization: To save allocating a new operand/operator stack |
|
806 * for every binary operation, we use supplys. |
|
807 */ |
|
808 ListBuffer<JCExpression[]> odStackSupply = new ListBuffer<JCExpression[]>(); |
|
809 ListBuffer<Token[]> opStackSupply = new ListBuffer<Token[]>(); |
|
810 |
|
811 private JCExpression[] newOdStack() { |
|
812 if (odStackSupply.elems == odStackSupply.last) |
|
813 odStackSupply.append(new JCExpression[infixPrecedenceLevels + 1]); |
|
814 JCExpression[] odStack = odStackSupply.elems.head; |
|
815 odStackSupply.elems = odStackSupply.elems.tail; |
|
816 return odStack; |
|
817 } |
|
818 |
|
819 private Token[] newOpStack() { |
|
820 if (opStackSupply.elems == opStackSupply.last) |
|
821 opStackSupply.append(new Token[infixPrecedenceLevels + 1]); |
|
822 Token[] opStack = opStackSupply.elems.head; |
|
823 opStackSupply.elems = opStackSupply.elems.tail; |
|
824 return opStack; |
|
825 } |
|
826 |
|
827 /** Expression3 = PrefixOp Expression3 |
|
828 * | "(" Expr | TypeNoParams ")" Expression3 |
|
829 * | Primary {Selector} {PostfixOp} |
|
830 * Primary = "(" Expression ")" |
|
831 * | Literal |
|
832 * | [TypeArguments] THIS [Arguments] |
|
833 * | [TypeArguments] SUPER SuperSuffix |
|
834 * | NEW [TypeArguments] Creator |
|
835 * | Ident { "." Ident } |
|
836 * [ "[" ( "]" BracketsOpt "." CLASS | Expression "]" ) |
|
837 * | Arguments |
|
838 * | "." ( CLASS | THIS | [TypeArguments] SUPER Arguments | NEW [TypeArguments] InnerCreator ) |
|
839 * ] |
|
840 * | BasicType BracketsOpt "." CLASS |
|
841 * PrefixOp = "++" | "--" | "!" | "~" | "+" | "-" |
|
842 * PostfixOp = "++" | "--" |
|
843 * Type3 = Ident { "." Ident } [TypeArguments] {TypeSelector} BracketsOpt |
|
844 * | BasicType |
|
845 * TypeNoParams3 = Ident { "." Ident } BracketsOpt |
|
846 * Selector = "." [TypeArguments] Ident [Arguments] |
|
847 * | "." THIS |
|
848 * | "." [TypeArguments] SUPER SuperSuffix |
|
849 * | "." NEW [TypeArguments] InnerCreator |
|
850 * | "[" Expression "]" |
|
851 * TypeSelector = "." Ident [TypeArguments] |
|
852 * SuperSuffix = Arguments | "." Ident [Arguments] |
|
853 */ |
|
854 protected JCExpression term3() { |
|
855 int pos = S.pos(); |
|
856 JCExpression t; |
|
857 List<JCExpression> typeArgs = typeArgumentsOpt(EXPR); |
|
858 switch (S.token()) { |
|
859 case QUES: |
|
860 if ((mode & TYPE) != 0 && (mode & (TYPEARG|NOPARAMS)) == TYPEARG) { |
|
861 mode = TYPE; |
|
862 return typeArgument(); |
|
863 } else |
|
864 return illegal(); |
|
865 case PLUSPLUS: case SUBSUB: case BANG: case TILDE: case PLUS: case SUB: |
|
866 if (typeArgs == null && (mode & EXPR) != 0) { |
|
867 Token token = S.token(); |
|
868 S.nextToken(); |
|
869 mode = EXPR; |
|
870 if (token == SUB && |
|
871 (S.token() == INTLITERAL || S.token() == LONGLITERAL) && |
|
872 S.radix() == 10) { |
|
873 mode = EXPR; |
|
874 t = literal(names.hyphen); |
|
875 } else { |
|
876 t = term3(); |
|
877 return F.at(pos).Unary(unoptag(token), t); |
|
878 } |
|
879 } else return illegal(); |
|
880 break; |
|
881 case LPAREN: |
|
882 if (typeArgs == null && (mode & EXPR) != 0) { |
|
883 S.nextToken(); |
|
884 mode = EXPR | TYPE | NOPARAMS; |
|
885 t = term3(); |
|
886 if ((mode & TYPE) != 0 && S.token() == LT) { |
|
887 // Could be a cast to a parameterized type |
|
888 int op = JCTree.LT; |
|
889 int pos1 = S.pos(); |
|
890 S.nextToken(); |
|
891 mode &= (EXPR | TYPE); |
|
892 mode |= TYPEARG; |
|
893 JCExpression t1 = term3(); |
|
894 if ((mode & TYPE) != 0 && |
|
895 (S.token() == COMMA || S.token() == GT)) { |
|
896 mode = TYPE; |
|
897 ListBuffer<JCExpression> args = new ListBuffer<JCExpression>(); |
|
898 args.append(t1); |
|
899 while (S.token() == COMMA) { |
|
900 S.nextToken(); |
|
901 args.append(typeArgument()); |
|
902 } |
|
903 accept(GT); |
|
904 t = F.at(pos1).TypeApply(t, args.toList()); |
|
905 checkGenerics(); |
|
906 t = bracketsOpt(toP(t)); |
|
907 } else if ((mode & EXPR) != 0) { |
|
908 mode = EXPR; |
|
909 t = F.at(pos1).Binary(op, t, term2Rest(t1, TreeInfo.shiftPrec)); |
|
910 t = termRest(term1Rest(term2Rest(t, TreeInfo.orPrec))); |
|
911 } else { |
|
912 accept(GT); |
|
913 } |
|
914 } else { |
|
915 t = termRest(term1Rest(term2Rest(t, TreeInfo.orPrec))); |
|
916 } |
|
917 accept(RPAREN); |
|
918 lastmode = mode; |
|
919 mode = EXPR; |
|
920 if ((lastmode & EXPR) == 0) { |
|
921 JCExpression t1 = term3(); |
|
922 return F.at(pos).TypeCast(t, t1); |
|
923 } else if ((lastmode & TYPE) != 0) { |
|
924 switch (S.token()) { |
|
925 /*case PLUSPLUS: case SUBSUB: */ |
|
926 case BANG: case TILDE: |
|
927 case LPAREN: case THIS: case SUPER: |
|
928 case INTLITERAL: case LONGLITERAL: case FLOATLITERAL: |
|
929 case DOUBLELITERAL: case CHARLITERAL: case STRINGLITERAL: |
|
930 case TRUE: case FALSE: case NULL: |
|
931 case NEW: case IDENTIFIER: case ASSERT: case ENUM: |
|
932 case BYTE: case SHORT: case CHAR: case INT: |
|
933 case LONG: case FLOAT: case DOUBLE: case BOOLEAN: case VOID: |
|
934 JCExpression t1 = term3(); |
|
935 return F.at(pos).TypeCast(t, t1); |
|
936 } |
|
937 } |
|
938 } else return illegal(); |
|
939 t = toP(F.at(pos).Parens(t)); |
|
940 break; |
|
941 case THIS: |
|
942 if ((mode & EXPR) != 0) { |
|
943 mode = EXPR; |
|
944 t = to(F.at(pos).Ident(names._this)); |
|
945 S.nextToken(); |
|
946 if (typeArgs == null) |
|
947 t = argumentsOpt(null, t); |
|
948 else |
|
949 t = arguments(typeArgs, t); |
|
950 typeArgs = null; |
|
951 } else return illegal(); |
|
952 break; |
|
953 case SUPER: |
|
954 if ((mode & EXPR) != 0) { |
|
955 mode = EXPR; |
|
956 t = to(superSuffix(typeArgs, F.at(pos).Ident(names._super))); |
|
957 typeArgs = null; |
|
958 } else return illegal(); |
|
959 break; |
|
960 case INTLITERAL: case LONGLITERAL: case FLOATLITERAL: case DOUBLELITERAL: |
|
961 case CHARLITERAL: case STRINGLITERAL: |
|
962 case TRUE: case FALSE: case NULL: |
|
963 if (typeArgs == null && (mode & EXPR) != 0) { |
|
964 mode = EXPR; |
|
965 t = literal(names.empty); |
|
966 } else return illegal(); |
|
967 break; |
|
968 case NEW: |
|
969 if (typeArgs != null) return illegal(); |
|
970 if ((mode & EXPR) != 0) { |
|
971 mode = EXPR; |
|
972 S.nextToken(); |
|
973 if (S.token() == LT) typeArgs = typeArguments(); |
|
974 t = creator(pos, typeArgs); |
|
975 typeArgs = null; |
|
976 } else return illegal(); |
|
977 break; |
|
978 case IDENTIFIER: case ASSERT: case ENUM: |
|
979 if (typeArgs != null) return illegal(); |
|
980 t = toP(F.at(S.pos()).Ident(ident())); |
|
981 loop: while (true) { |
|
982 pos = S.pos(); |
|
983 switch (S.token()) { |
|
984 case LBRACKET: |
|
985 S.nextToken(); |
|
986 if (S.token() == RBRACKET) { |
|
987 S.nextToken(); |
|
988 t = bracketsOpt(t); |
|
989 t = toP(F.at(pos).TypeArray(t)); |
|
990 t = bracketsSuffix(t); |
|
991 } else { |
|
992 if ((mode & EXPR) != 0) { |
|
993 mode = EXPR; |
|
994 JCExpression t1 = term(); |
|
995 t = to(F.at(pos).Indexed(t, t1)); |
|
996 } |
|
997 accept(RBRACKET); |
|
998 } |
|
999 break loop; |
|
1000 case LPAREN: |
|
1001 if ((mode & EXPR) != 0) { |
|
1002 mode = EXPR; |
|
1003 t = arguments(typeArgs, t); |
|
1004 typeArgs = null; |
|
1005 } |
|
1006 break loop; |
|
1007 case DOT: |
|
1008 S.nextToken(); |
|
1009 int oldmode = mode; |
|
1010 mode &= ~NOPARAMS; |
|
1011 typeArgs = typeArgumentsOpt(EXPR); |
|
1012 mode = oldmode; |
|
1013 if ((mode & EXPR) != 0) { |
|
1014 switch (S.token()) { |
|
1015 case CLASS: |
|
1016 if (typeArgs != null) return illegal(); |
|
1017 mode = EXPR; |
|
1018 t = to(F.at(pos).Select(t, names._class)); |
|
1019 S.nextToken(); |
|
1020 break loop; |
|
1021 case THIS: |
|
1022 if (typeArgs != null) return illegal(); |
|
1023 mode = EXPR; |
|
1024 t = to(F.at(pos).Select(t, names._this)); |
|
1025 S.nextToken(); |
|
1026 break loop; |
|
1027 case SUPER: |
|
1028 mode = EXPR; |
|
1029 t = to(F.at(pos).Select(t, names._super)); |
|
1030 t = superSuffix(typeArgs, t); |
|
1031 typeArgs = null; |
|
1032 break loop; |
|
1033 case NEW: |
|
1034 if (typeArgs != null) return illegal(); |
|
1035 mode = EXPR; |
|
1036 int pos1 = S.pos(); |
|
1037 S.nextToken(); |
|
1038 if (S.token() == LT) typeArgs = typeArguments(); |
|
1039 t = innerCreator(pos1, typeArgs, t); |
|
1040 typeArgs = null; |
|
1041 break loop; |
|
1042 } |
|
1043 } |
|
1044 // typeArgs saved for next loop iteration. |
|
1045 t = toP(F.at(pos).Select(t, ident())); |
|
1046 break; |
|
1047 default: |
|
1048 break loop; |
|
1049 } |
|
1050 } |
|
1051 if (typeArgs != null) illegal(); |
|
1052 t = typeArgumentsOpt(t); |
|
1053 break; |
|
1054 case BYTE: case SHORT: case CHAR: case INT: case LONG: case FLOAT: |
|
1055 case DOUBLE: case BOOLEAN: |
|
1056 if (typeArgs != null) illegal(); |
|
1057 t = bracketsSuffix(bracketsOpt(basicType())); |
|
1058 break; |
|
1059 case VOID: |
|
1060 if (typeArgs != null) illegal(); |
|
1061 if ((mode & EXPR) != 0) { |
|
1062 S.nextToken(); |
|
1063 if (S.token() == DOT) { |
|
1064 JCPrimitiveTypeTree ti = toP(F.at(pos).TypeIdent(TypeTags.VOID)); |
|
1065 t = bracketsSuffix(ti); |
|
1066 } else { |
|
1067 return illegal(pos); |
|
1068 } |
|
1069 } else { |
|
1070 return illegal(); |
|
1071 } |
|
1072 break; |
|
1073 default: |
|
1074 return illegal(); |
|
1075 } |
|
1076 if (typeArgs != null) illegal(); |
|
1077 while (true) { |
|
1078 int pos1 = S.pos(); |
|
1079 if (S.token() == LBRACKET) { |
|
1080 S.nextToken(); |
|
1081 if ((mode & TYPE) != 0) { |
|
1082 int oldmode = mode; |
|
1083 mode = TYPE; |
|
1084 if (S.token() == RBRACKET) { |
|
1085 S.nextToken(); |
|
1086 t = bracketsOpt(t); |
|
1087 t = toP(F.at(pos1).TypeArray(t)); |
|
1088 return t; |
|
1089 } |
|
1090 mode = oldmode; |
|
1091 } |
|
1092 if ((mode & EXPR) != 0) { |
|
1093 mode = EXPR; |
|
1094 JCExpression t1 = term(); |
|
1095 t = to(F.at(pos1).Indexed(t, t1)); |
|
1096 } |
|
1097 accept(RBRACKET); |
|
1098 } else if (S.token() == DOT) { |
|
1099 S.nextToken(); |
|
1100 typeArgs = typeArgumentsOpt(EXPR); |
|
1101 if (S.token() == SUPER && (mode & EXPR) != 0) { |
|
1102 mode = EXPR; |
|
1103 t = to(F.at(pos1).Select(t, names._super)); |
|
1104 S.nextToken(); |
|
1105 t = arguments(typeArgs, t); |
|
1106 typeArgs = null; |
|
1107 } else if (S.token() == NEW && (mode & EXPR) != 0) { |
|
1108 if (typeArgs != null) return illegal(); |
|
1109 mode = EXPR; |
|
1110 int pos2 = S.pos(); |
|
1111 S.nextToken(); |
|
1112 if (S.token() == LT) typeArgs = typeArguments(); |
|
1113 t = innerCreator(pos2, typeArgs, t); |
|
1114 typeArgs = null; |
|
1115 } else { |
|
1116 t = toP(F.at(pos1).Select(t, ident())); |
|
1117 t = argumentsOpt(typeArgs, typeArgumentsOpt(t)); |
|
1118 typeArgs = null; |
|
1119 } |
|
1120 } else { |
|
1121 break; |
|
1122 } |
|
1123 } |
|
1124 while ((S.token() == PLUSPLUS || S.token() == SUBSUB) && (mode & EXPR) != 0) { |
|
1125 mode = EXPR; |
|
1126 t = to(F.at(S.pos()).Unary( |
|
1127 S.token() == PLUSPLUS ? JCTree.POSTINC : JCTree.POSTDEC, t)); |
|
1128 S.nextToken(); |
|
1129 } |
|
1130 return toP(t); |
|
1131 } |
|
1132 |
|
1133 /** SuperSuffix = Arguments | "." [TypeArguments] Ident [Arguments] |
|
1134 */ |
|
1135 JCExpression superSuffix(List<JCExpression> typeArgs, JCExpression t) { |
|
1136 S.nextToken(); |
|
1137 if (S.token() == LPAREN || typeArgs != null) { |
|
1138 t = arguments(typeArgs, t); |
|
1139 } else { |
|
1140 int pos = S.pos(); |
|
1141 accept(DOT); |
|
1142 typeArgs = (S.token() == LT) ? typeArguments() : null; |
|
1143 t = toP(F.at(pos).Select(t, ident())); |
|
1144 t = argumentsOpt(typeArgs, t); |
|
1145 } |
|
1146 return t; |
|
1147 } |
|
1148 |
|
1149 /** BasicType = BYTE | SHORT | CHAR | INT | LONG | FLOAT | DOUBLE | BOOLEAN |
|
1150 */ |
|
1151 JCPrimitiveTypeTree basicType() { |
|
1152 JCPrimitiveTypeTree t = to(F.at(S.pos()).TypeIdent(typetag(S.token()))); |
|
1153 S.nextToken(); |
|
1154 return t; |
|
1155 } |
|
1156 |
|
1157 /** ArgumentsOpt = [ Arguments ] |
|
1158 */ |
|
1159 JCExpression argumentsOpt(List<JCExpression> typeArgs, JCExpression t) { |
|
1160 if ((mode & EXPR) != 0 && S.token() == LPAREN || typeArgs != null) { |
|
1161 mode = EXPR; |
|
1162 return arguments(typeArgs, t); |
|
1163 } else { |
|
1164 return t; |
|
1165 } |
|
1166 } |
|
1167 |
|
1168 /** Arguments = "(" [Expression { COMMA Expression }] ")" |
|
1169 */ |
|
1170 List<JCExpression> arguments() { |
|
1171 ListBuffer<JCExpression> args = lb(); |
|
1172 if (S.token() == LPAREN) { |
|
1173 S.nextToken(); |
|
1174 if (S.token() != RPAREN) { |
|
1175 args.append(expression()); |
|
1176 while (S.token() == COMMA) { |
|
1177 S.nextToken(); |
|
1178 args.append(expression()); |
|
1179 } |
|
1180 } |
|
1181 accept(RPAREN); |
|
1182 } else { |
|
1183 syntaxError(S.pos(), "expected", LPAREN); |
|
1184 } |
|
1185 return args.toList(); |
|
1186 } |
|
1187 |
|
1188 JCMethodInvocation arguments(List<JCExpression> typeArgs, JCExpression t) { |
|
1189 int pos = S.pos(); |
|
1190 List<JCExpression> args = arguments(); |
|
1191 return toP(F.at(pos).Apply(typeArgs, t, args)); |
|
1192 } |
|
1193 |
|
1194 /** TypeArgumentsOpt = [ TypeArguments ] |
|
1195 */ |
|
1196 JCExpression typeArgumentsOpt(JCExpression t) { |
|
1197 if (S.token() == LT && |
|
1198 (mode & TYPE) != 0 && |
|
1199 (mode & NOPARAMS) == 0) { |
|
1200 mode = TYPE; |
|
1201 checkGenerics(); |
|
1202 return typeArguments(t); |
|
1203 } else { |
|
1204 return t; |
|
1205 } |
|
1206 } |
|
1207 List<JCExpression> typeArgumentsOpt() { |
|
1208 return typeArgumentsOpt(TYPE); |
|
1209 } |
|
1210 |
|
1211 List<JCExpression> typeArgumentsOpt(int useMode) { |
|
1212 if (S.token() == LT) { |
|
1213 checkGenerics(); |
|
1214 if ((mode & useMode) == 0 || |
|
1215 (mode & NOPARAMS) != 0) { |
|
1216 illegal(); |
|
1217 } |
|
1218 mode = useMode; |
|
1219 return typeArguments(); |
|
1220 } |
|
1221 return null; |
|
1222 } |
|
1223 |
|
1224 /** TypeArguments = "<" TypeArgument {"," TypeArgument} ">" |
|
1225 */ |
|
1226 List<JCExpression> typeArguments() { |
|
1227 ListBuffer<JCExpression> args = lb(); |
|
1228 if (S.token() == LT) { |
|
1229 S.nextToken(); |
|
1230 args.append(((mode & EXPR) == 0) ? typeArgument() : type()); |
|
1231 while (S.token() == COMMA) { |
|
1232 S.nextToken(); |
|
1233 args.append(((mode & EXPR) == 0) ? typeArgument() : type()); |
|
1234 } |
|
1235 switch (S.token()) { |
|
1236 case GTGTGTEQ: |
|
1237 S.token(GTGTEQ); |
|
1238 break; |
|
1239 case GTGTEQ: |
|
1240 S.token(GTEQ); |
|
1241 break; |
|
1242 case GTEQ: |
|
1243 S.token(EQ); |
|
1244 break; |
|
1245 case GTGTGT: |
|
1246 S.token(GTGT); |
|
1247 break; |
|
1248 case GTGT: |
|
1249 S.token(GT); |
|
1250 break; |
|
1251 default: |
|
1252 accept(GT); |
|
1253 break; |
|
1254 } |
|
1255 } else { |
|
1256 syntaxError(S.pos(), "expected", LT); |
|
1257 } |
|
1258 return args.toList(); |
|
1259 } |
|
1260 |
|
1261 /** TypeArgument = Type |
|
1262 * | "?" |
|
1263 * | "?" EXTENDS Type {"&" Type} |
|
1264 * | "?" SUPER Type |
|
1265 */ |
|
1266 JCExpression typeArgument() { |
|
1267 if (S.token() != QUES) return type(); |
|
1268 int pos = S.pos(); |
|
1269 S.nextToken(); |
|
1270 if (S.token() == EXTENDS) { |
|
1271 TypeBoundKind t = to(F.at(S.pos()).TypeBoundKind(BoundKind.EXTENDS)); |
|
1272 S.nextToken(); |
|
1273 return F.at(pos).Wildcard(t, type()); |
|
1274 } else if (S.token() == SUPER) { |
|
1275 TypeBoundKind t = to(F.at(S.pos()).TypeBoundKind(BoundKind.SUPER)); |
|
1276 S.nextToken(); |
|
1277 return F.at(pos).Wildcard(t, type()); |
|
1278 } else if (S.token() == IDENTIFIER) { |
|
1279 //error recovery |
|
1280 reportSyntaxError(S.prevEndPos(), "expected3", |
|
1281 GT, EXTENDS, SUPER); |
|
1282 TypeBoundKind t = F.at(Position.NOPOS).TypeBoundKind(BoundKind.UNBOUND); |
|
1283 JCExpression wc = toP(F.at(pos).Wildcard(t, null)); |
|
1284 JCIdent id = toP(F.at(S.pos()).Ident(ident())); |
|
1285 return F.at(pos).Erroneous(List.<JCTree>of(wc, id)); |
|
1286 } else { |
|
1287 TypeBoundKind t = F.at(Position.NOPOS).TypeBoundKind(BoundKind.UNBOUND); |
|
1288 return toP(F.at(pos).Wildcard(t, null)); |
|
1289 } |
|
1290 } |
|
1291 |
|
1292 JCTypeApply typeArguments(JCExpression t) { |
|
1293 int pos = S.pos(); |
|
1294 List<JCExpression> args = typeArguments(); |
|
1295 return toP(F.at(pos).TypeApply(t, args)); |
|
1296 } |
|
1297 |
|
1298 /** BracketsOpt = {"[" "]"} |
|
1299 */ |
|
1300 private JCExpression bracketsOpt(JCExpression t) { |
|
1301 if (S.token() == LBRACKET) { |
|
1302 int pos = S.pos(); |
|
1303 S.nextToken(); |
|
1304 t = bracketsOptCont(t, pos); |
|
1305 F.at(pos); |
|
1306 } |
|
1307 return t; |
|
1308 } |
|
1309 |
|
1310 private JCArrayTypeTree bracketsOptCont(JCExpression t, int pos) { |
|
1311 accept(RBRACKET); |
|
1312 t = bracketsOpt(t); |
|
1313 return toP(F.at(pos).TypeArray(t)); |
|
1314 } |
|
1315 |
|
1316 /** BracketsSuffixExpr = "." CLASS |
|
1317 * BracketsSuffixType = |
|
1318 */ |
|
1319 JCExpression bracketsSuffix(JCExpression t) { |
|
1320 if ((mode & EXPR) != 0 && S.token() == DOT) { |
|
1321 mode = EXPR; |
|
1322 int pos = S.pos(); |
|
1323 S.nextToken(); |
|
1324 accept(CLASS); |
|
1325 if (S.pos() == errorEndPos) { |
|
1326 // error recovery |
|
1327 Name name = null; |
|
1328 if (S.token() == IDENTIFIER) { |
|
1329 name = S.name(); |
|
1330 S.nextToken(); |
|
1331 } else { |
|
1332 name = names.error; |
|
1333 } |
|
1334 t = F.at(pos).Erroneous(List.<JCTree>of(toP(F.at(pos).Select(t, name)))); |
|
1335 } else { |
|
1336 t = toP(F.at(pos).Select(t, names._class)); |
|
1337 } |
|
1338 } else if ((mode & TYPE) != 0) { |
|
1339 mode = TYPE; |
|
1340 } else { |
|
1341 syntaxError(S.pos(), "dot.class.expected"); |
|
1342 } |
|
1343 return t; |
|
1344 } |
|
1345 |
|
1346 /** Creator = Qualident [TypeArguments] ( ArrayCreatorRest | ClassCreatorRest ) |
|
1347 */ |
|
1348 JCExpression creator(int newpos, List<JCExpression> typeArgs) { |
|
1349 switch (S.token()) { |
|
1350 case BYTE: case SHORT: case CHAR: case INT: case LONG: case FLOAT: |
|
1351 case DOUBLE: case BOOLEAN: |
|
1352 if (typeArgs == null) |
|
1353 return arrayCreatorRest(newpos, basicType()); |
|
1354 break; |
|
1355 default: |
|
1356 } |
|
1357 JCExpression t = qualident(); |
|
1358 int oldmode = mode; |
|
1359 mode = TYPE; |
|
1360 if (S.token() == LT) { |
|
1361 checkGenerics(); |
|
1362 t = typeArguments(t); |
|
1363 } |
|
1364 while (S.token() == DOT) { |
|
1365 int pos = S.pos(); |
|
1366 S.nextToken(); |
|
1367 t = toP(F.at(pos).Select(t, ident())); |
|
1368 if (S.token() == LT) { |
|
1369 checkGenerics(); |
|
1370 t = typeArguments(t); |
|
1371 } |
|
1372 } |
|
1373 mode = oldmode; |
|
1374 if (S.token() == LBRACKET) { |
|
1375 JCExpression e = arrayCreatorRest(newpos, t); |
|
1376 if (typeArgs != null) { |
|
1377 int pos = newpos; |
|
1378 if (!typeArgs.isEmpty() && typeArgs.head.pos != Position.NOPOS) { |
|
1379 // note: this should always happen but we should |
|
1380 // not rely on this as the parser is continuously |
|
1381 // modified to improve error recovery. |
|
1382 pos = typeArgs.head.pos; |
|
1383 } |
|
1384 setErrorEndPos(S.prevEndPos()); |
|
1385 reportSyntaxError(pos, "cannot.create.array.with.type.arguments"); |
|
1386 return toP(F.at(newpos).Erroneous(typeArgs.prepend(e))); |
|
1387 } |
|
1388 return e; |
|
1389 } else if (S.token() == LPAREN) { |
|
1390 return classCreatorRest(newpos, null, typeArgs, t); |
|
1391 } else { |
|
1392 reportSyntaxError(S.pos(), "expected2", |
|
1393 LPAREN, LBRACKET); |
|
1394 t = toP(F.at(newpos).NewClass(null, typeArgs, t, List.<JCExpression>nil(), null)); |
|
1395 return toP(F.at(newpos).Erroneous(List.<JCTree>of(t))); |
|
1396 } |
|
1397 } |
|
1398 |
|
1399 /** InnerCreator = Ident [TypeArguments] ClassCreatorRest |
|
1400 */ |
|
1401 JCExpression innerCreator(int newpos, List<JCExpression> typeArgs, JCExpression encl) { |
|
1402 JCExpression t = toP(F.at(S.pos()).Ident(ident())); |
|
1403 if (S.token() == LT) { |
|
1404 checkGenerics(); |
|
1405 t = typeArguments(t); |
|
1406 } |
|
1407 return classCreatorRest(newpos, encl, typeArgs, t); |
|
1408 } |
|
1409 |
|
1410 /** ArrayCreatorRest = "[" ( "]" BracketsOpt ArrayInitializer |
|
1411 * | Expression "]" {"[" Expression "]"} BracketsOpt ) |
|
1412 */ |
|
1413 JCExpression arrayCreatorRest(int newpos, JCExpression elemtype) { |
|
1414 accept(LBRACKET); |
|
1415 if (S.token() == RBRACKET) { |
|
1416 accept(RBRACKET); |
|
1417 elemtype = bracketsOpt(elemtype); |
|
1418 if (S.token() == LBRACE) { |
|
1419 return arrayInitializer(newpos, elemtype); |
|
1420 } else { |
|
1421 return syntaxError(S.pos(), "array.dimension.missing"); |
|
1422 } |
|
1423 } else { |
|
1424 ListBuffer<JCExpression> dims = new ListBuffer<JCExpression>(); |
|
1425 dims.append(expression()); |
|
1426 accept(RBRACKET); |
|
1427 while (S.token() == LBRACKET) { |
|
1428 int pos = S.pos(); |
|
1429 S.nextToken(); |
|
1430 if (S.token() == RBRACKET) { |
|
1431 elemtype = bracketsOptCont(elemtype, pos); |
|
1432 } else { |
|
1433 dims.append(expression()); |
|
1434 accept(RBRACKET); |
|
1435 } |
|
1436 } |
|
1437 return toP(F.at(newpos).NewArray(elemtype, dims.toList(), null)); |
|
1438 } |
|
1439 } |
|
1440 |
|
1441 /** ClassCreatorRest = Arguments [ClassBody] |
|
1442 */ |
|
1443 JCExpression classCreatorRest(int newpos, |
|
1444 JCExpression encl, |
|
1445 List<JCExpression> typeArgs, |
|
1446 JCExpression t) |
|
1447 { |
|
1448 List<JCExpression> args = arguments(); |
|
1449 JCClassDecl body = null; |
|
1450 if (S.token() == LBRACE) { |
|
1451 int pos = S.pos(); |
|
1452 List<JCTree> defs = classOrInterfaceBody(names.empty, false); |
|
1453 JCModifiers mods = F.at(Position.NOPOS).Modifiers(0); |
|
1454 body = toP(F.at(pos).AnonymousClassDef(mods, defs)); |
|
1455 } |
|
1456 return toP(F.at(newpos).NewClass(encl, typeArgs, t, args, body)); |
|
1457 } |
|
1458 |
|
1459 /** ArrayInitializer = "{" [VariableInitializer {"," VariableInitializer}] [","] "}" |
|
1460 */ |
|
1461 JCExpression arrayInitializer(int newpos, JCExpression t) { |
|
1462 accept(LBRACE); |
|
1463 ListBuffer<JCExpression> elems = new ListBuffer<JCExpression>(); |
|
1464 if (S.token() == COMMA) { |
|
1465 S.nextToken(); |
|
1466 } else if (S.token() != RBRACE) { |
|
1467 elems.append(variableInitializer()); |
|
1468 while (S.token() == COMMA) { |
|
1469 S.nextToken(); |
|
1470 if (S.token() == RBRACE) break; |
|
1471 elems.append(variableInitializer()); |
|
1472 } |
|
1473 } |
|
1474 accept(RBRACE); |
|
1475 return toP(F.at(newpos).NewArray(t, List.<JCExpression>nil(), elems.toList())); |
|
1476 } |
|
1477 |
|
1478 /** VariableInitializer = ArrayInitializer | Expression |
|
1479 */ |
|
1480 public JCExpression variableInitializer() { |
|
1481 return S.token() == LBRACE ? arrayInitializer(S.pos(), null) : expression(); |
|
1482 } |
|
1483 |
|
1484 /** ParExpression = "(" Expression ")" |
|
1485 */ |
|
1486 JCExpression parExpression() { |
|
1487 accept(LPAREN); |
|
1488 JCExpression t = expression(); |
|
1489 accept(RPAREN); |
|
1490 return t; |
|
1491 } |
|
1492 |
|
1493 /** Block = "{" BlockStatements "}" |
|
1494 */ |
|
1495 JCBlock block(int pos, long flags) { |
|
1496 accept(LBRACE); |
|
1497 List<JCStatement> stats = blockStatements(); |
|
1498 JCBlock t = F.at(pos).Block(flags, stats); |
|
1499 while (S.token() == CASE || S.token() == DEFAULT) { |
|
1500 syntaxError("orphaned", S.token()); |
|
1501 switchBlockStatementGroups(); |
|
1502 } |
|
1503 // the Block node has a field "endpos" for first char of last token, which is |
|
1504 // usually but not necessarily the last char of the last token. |
|
1505 t.endpos = S.pos(); |
|
1506 accept(RBRACE); |
|
1507 return toP(t); |
|
1508 } |
|
1509 |
|
1510 public JCBlock block() { |
|
1511 return block(S.pos(), 0); |
|
1512 } |
|
1513 |
|
1514 /** BlockStatements = { BlockStatement } |
|
1515 * BlockStatement = LocalVariableDeclarationStatement |
|
1516 * | ClassOrInterfaceOrEnumDeclaration |
|
1517 * | [Ident ":"] Statement |
|
1518 * LocalVariableDeclarationStatement |
|
1519 * = { FINAL | '@' Annotation } Type VariableDeclarators ";" |
|
1520 */ |
|
1521 @SuppressWarnings("fallthrough") |
|
1522 List<JCStatement> blockStatements() { |
|
1523 //todo: skip to anchor on error(?) |
|
1524 int lastErrPos = -1; |
|
1525 ListBuffer<JCStatement> stats = new ListBuffer<JCStatement>(); |
|
1526 while (true) { |
|
1527 int pos = S.pos(); |
|
1528 switch (S.token()) { |
|
1529 case RBRACE: case CASE: case DEFAULT: case EOF: |
|
1530 return stats.toList(); |
|
1531 case LBRACE: case IF: case FOR: case WHILE: case DO: case TRY: |
|
1532 case SWITCH: case SYNCHRONIZED: case RETURN: case THROW: case BREAK: |
|
1533 case CONTINUE: case SEMI: case ELSE: case FINALLY: case CATCH: |
|
1534 stats.append(statement()); |
|
1535 break; |
|
1536 case MONKEYS_AT: |
|
1537 case FINAL: { |
|
1538 String dc = S.docComment(); |
|
1539 JCModifiers mods = modifiersOpt(); |
|
1540 if (S.token() == INTERFACE || |
|
1541 S.token() == CLASS || |
|
1542 allowEnums && S.token() == ENUM) { |
|
1543 stats.append(classOrInterfaceOrEnumDeclaration(mods, dc)); |
|
1544 } else { |
|
1545 JCExpression t = type(); |
|
1546 stats.appendList(variableDeclarators(mods, t, |
|
1547 new ListBuffer<JCStatement>())); |
|
1548 // A "LocalVariableDeclarationStatement" subsumes the terminating semicolon |
|
1549 storeEnd(stats.elems.last(), S.endPos()); |
|
1550 accept(SEMI); |
|
1551 } |
|
1552 break; |
|
1553 } |
|
1554 case ABSTRACT: case STRICTFP: { |
|
1555 String dc = S.docComment(); |
|
1556 JCModifiers mods = modifiersOpt(); |
|
1557 stats.append(classOrInterfaceOrEnumDeclaration(mods, dc)); |
|
1558 break; |
|
1559 } |
|
1560 case INTERFACE: |
|
1561 case CLASS: |
|
1562 stats.append(classOrInterfaceOrEnumDeclaration(modifiersOpt(), |
|
1563 S.docComment())); |
|
1564 break; |
|
1565 case ENUM: |
|
1566 case ASSERT: |
|
1567 if (allowEnums && S.token() == ENUM) { |
|
1568 log.error(S.pos(), "local.enum"); |
|
1569 stats. |
|
1570 append(classOrInterfaceOrEnumDeclaration(modifiersOpt(), |
|
1571 S.docComment())); |
|
1572 break; |
|
1573 } else if (allowAsserts && S.token() == ASSERT) { |
|
1574 stats.append(statement()); |
|
1575 break; |
|
1576 } |
|
1577 /* fall through to default */ |
|
1578 default: |
|
1579 Name name = S.name(); |
|
1580 JCExpression t = term(EXPR | TYPE); |
|
1581 if (S.token() == COLON && t.getTag() == JCTree.IDENT) { |
|
1582 S.nextToken(); |
|
1583 JCStatement stat = statement(); |
|
1584 stats.append(F.at(pos).Labelled(name, stat)); |
|
1585 } else if ((lastmode & TYPE) != 0 && |
|
1586 (S.token() == IDENTIFIER || |
|
1587 S.token() == ASSERT || |
|
1588 S.token() == ENUM)) { |
|
1589 pos = S.pos(); |
|
1590 JCModifiers mods = F.at(Position.NOPOS).Modifiers(0); |
|
1591 F.at(pos); |
|
1592 stats.appendList(variableDeclarators(mods, t, |
|
1593 new ListBuffer<JCStatement>())); |
|
1594 // A "LocalVariableDeclarationStatement" subsumes the terminating semicolon |
|
1595 storeEnd(stats.elems.last(), S.endPos()); |
|
1596 accept(SEMI); |
|
1597 } else { |
|
1598 // This Exec is an "ExpressionStatement"; it subsumes the terminating semicolon |
|
1599 stats.append(to(F.at(pos).Exec(checkExprStat(t)))); |
|
1600 accept(SEMI); |
|
1601 } |
|
1602 } |
|
1603 |
|
1604 // error recovery |
|
1605 if (S.pos() == lastErrPos) |
|
1606 return stats.toList(); |
|
1607 if (S.pos() <= errorEndPos) { |
|
1608 skip(false, true, true, true); |
|
1609 lastErrPos = S.pos(); |
|
1610 } |
|
1611 |
|
1612 // ensure no dangling /** @deprecated */ active |
|
1613 S.resetDeprecatedFlag(); |
|
1614 } |
|
1615 } |
|
1616 |
|
1617 /** Statement = |
|
1618 * Block |
|
1619 * | IF ParExpression Statement [ELSE Statement] |
|
1620 * | FOR "(" ForInitOpt ";" [Expression] ";" ForUpdateOpt ")" Statement |
|
1621 * | FOR "(" FormalParameter : Expression ")" Statement |
|
1622 * | WHILE ParExpression Statement |
|
1623 * | DO Statement WHILE ParExpression ";" |
|
1624 * | TRY Block ( Catches | [Catches] FinallyPart ) |
|
1625 * | SWITCH ParExpression "{" SwitchBlockStatementGroups "}" |
|
1626 * | SYNCHRONIZED ParExpression Block |
|
1627 * | RETURN [Expression] ";" |
|
1628 * | THROW Expression ";" |
|
1629 * | BREAK [Ident] ";" |
|
1630 * | CONTINUE [Ident] ";" |
|
1631 * | ASSERT Expression [ ":" Expression ] ";" |
|
1632 * | ";" |
|
1633 * | ExpressionStatement |
|
1634 * | Ident ":" Statement |
|
1635 */ |
|
1636 @SuppressWarnings("fallthrough") |
|
1637 public JCStatement statement() { |
|
1638 int pos = S.pos(); |
|
1639 switch (S.token()) { |
|
1640 case LBRACE: |
|
1641 return block(); |
|
1642 case IF: { |
|
1643 S.nextToken(); |
|
1644 JCExpression cond = parExpression(); |
|
1645 JCStatement thenpart = statement(); |
|
1646 JCStatement elsepart = null; |
|
1647 if (S.token() == ELSE) { |
|
1648 S.nextToken(); |
|
1649 elsepart = statement(); |
|
1650 } |
|
1651 return F.at(pos).If(cond, thenpart, elsepart); |
|
1652 } |
|
1653 case FOR: { |
|
1654 S.nextToken(); |
|
1655 accept(LPAREN); |
|
1656 List<JCStatement> inits = S.token() == SEMI ? List.<JCStatement>nil() : forInit(); |
|
1657 if (inits.length() == 1 && |
|
1658 inits.head.getTag() == JCTree.VARDEF && |
|
1659 ((JCVariableDecl) inits.head).init == null && |
|
1660 S.token() == COLON) { |
|
1661 checkForeach(); |
|
1662 JCVariableDecl var = (JCVariableDecl)inits.head; |
|
1663 accept(COLON); |
|
1664 JCExpression expr = expression(); |
|
1665 accept(RPAREN); |
|
1666 JCStatement body = statement(); |
|
1667 return F.at(pos).ForeachLoop(var, expr, body); |
|
1668 } else { |
|
1669 accept(SEMI); |
|
1670 JCExpression cond = S.token() == SEMI ? null : expression(); |
|
1671 accept(SEMI); |
|
1672 List<JCExpressionStatement> steps = S.token() == RPAREN ? List.<JCExpressionStatement>nil() : forUpdate(); |
|
1673 accept(RPAREN); |
|
1674 JCStatement body = statement(); |
|
1675 return F.at(pos).ForLoop(inits, cond, steps, body); |
|
1676 } |
|
1677 } |
|
1678 case WHILE: { |
|
1679 S.nextToken(); |
|
1680 JCExpression cond = parExpression(); |
|
1681 JCStatement body = statement(); |
|
1682 return F.at(pos).WhileLoop(cond, body); |
|
1683 } |
|
1684 case DO: { |
|
1685 S.nextToken(); |
|
1686 JCStatement body = statement(); |
|
1687 accept(WHILE); |
|
1688 JCExpression cond = parExpression(); |
|
1689 JCDoWhileLoop t = to(F.at(pos).DoLoop(body, cond)); |
|
1690 accept(SEMI); |
|
1691 return t; |
|
1692 } |
|
1693 case TRY: { |
|
1694 S.nextToken(); |
|
1695 JCBlock body = block(); |
|
1696 ListBuffer<JCCatch> catchers = new ListBuffer<JCCatch>(); |
|
1697 JCBlock finalizer = null; |
|
1698 if (S.token() == CATCH || S.token() == FINALLY) { |
|
1699 while (S.token() == CATCH) catchers.append(catchClause()); |
|
1700 if (S.token() == FINALLY) { |
|
1701 S.nextToken(); |
|
1702 finalizer = block(); |
|
1703 } |
|
1704 } else { |
|
1705 log.error(pos, "try.without.catch.or.finally"); |
|
1706 } |
|
1707 return F.at(pos).Try(body, catchers.toList(), finalizer); |
|
1708 } |
|
1709 case SWITCH: { |
|
1710 S.nextToken(); |
|
1711 JCExpression selector = parExpression(); |
|
1712 accept(LBRACE); |
|
1713 List<JCCase> cases = switchBlockStatementGroups(); |
|
1714 JCSwitch t = to(F.at(pos).Switch(selector, cases)); |
|
1715 accept(RBRACE); |
|
1716 return t; |
|
1717 } |
|
1718 case SYNCHRONIZED: { |
|
1719 S.nextToken(); |
|
1720 JCExpression lock = parExpression(); |
|
1721 JCBlock body = block(); |
|
1722 return F.at(pos).Synchronized(lock, body); |
|
1723 } |
|
1724 case RETURN: { |
|
1725 S.nextToken(); |
|
1726 JCExpression result = S.token() == SEMI ? null : expression(); |
|
1727 JCReturn t = to(F.at(pos).Return(result)); |
|
1728 accept(SEMI); |
|
1729 return t; |
|
1730 } |
|
1731 case THROW: { |
|
1732 S.nextToken(); |
|
1733 JCExpression exc = expression(); |
|
1734 JCThrow t = to(F.at(pos).Throw(exc)); |
|
1735 accept(SEMI); |
|
1736 return t; |
|
1737 } |
|
1738 case BREAK: { |
|
1739 S.nextToken(); |
|
1740 Name label = (S.token() == IDENTIFIER || S.token() == ASSERT || S.token() == ENUM) ? ident() : null; |
|
1741 JCBreak t = to(F.at(pos).Break(label)); |
|
1742 accept(SEMI); |
|
1743 return t; |
|
1744 } |
|
1745 case CONTINUE: { |
|
1746 S.nextToken(); |
|
1747 Name label = (S.token() == IDENTIFIER || S.token() == ASSERT || S.token() == ENUM) ? ident() : null; |
|
1748 JCContinue t = to(F.at(pos).Continue(label)); |
|
1749 accept(SEMI); |
|
1750 return t; |
|
1751 } |
|
1752 case SEMI: |
|
1753 S.nextToken(); |
|
1754 return toP(F.at(pos).Skip()); |
|
1755 case ELSE: |
|
1756 return toP(F.Exec(syntaxError("else.without.if"))); |
|
1757 case FINALLY: |
|
1758 return toP(F.Exec(syntaxError("finally.without.try"))); |
|
1759 case CATCH: |
|
1760 return toP(F.Exec(syntaxError("catch.without.try"))); |
|
1761 case ASSERT: { |
|
1762 if (allowAsserts && S.token() == ASSERT) { |
|
1763 S.nextToken(); |
|
1764 JCExpression assertion = expression(); |
|
1765 JCExpression message = null; |
|
1766 if (S.token() == COLON) { |
|
1767 S.nextToken(); |
|
1768 message = expression(); |
|
1769 } |
|
1770 JCAssert t = to(F.at(pos).Assert(assertion, message)); |
|
1771 accept(SEMI); |
|
1772 return t; |
|
1773 } |
|
1774 /* else fall through to default case */ |
|
1775 } |
|
1776 case ENUM: |
|
1777 default: |
|
1778 Name name = S.name(); |
|
1779 JCExpression expr = expression(); |
|
1780 if (S.token() == COLON && expr.getTag() == JCTree.IDENT) { |
|
1781 S.nextToken(); |
|
1782 JCStatement stat = statement(); |
|
1783 return F.at(pos).Labelled(name, stat); |
|
1784 } else { |
|
1785 // This Exec is an "ExpressionStatement"; it subsumes the terminating semicolon |
|
1786 JCExpressionStatement stat = to(F.at(pos).Exec(checkExprStat(expr))); |
|
1787 accept(SEMI); |
|
1788 return stat; |
|
1789 } |
|
1790 } |
|
1791 } |
|
1792 |
|
1793 /** CatchClause = CATCH "(" FormalParameter ")" Block |
|
1794 */ |
|
1795 JCCatch catchClause() { |
|
1796 int pos = S.pos(); |
|
1797 accept(CATCH); |
|
1798 accept(LPAREN); |
|
1799 JCVariableDecl formal = |
|
1800 variableDeclaratorId(optFinal(Flags.PARAMETER), |
|
1801 qualident()); |
|
1802 accept(RPAREN); |
|
1803 JCBlock body = block(); |
|
1804 return F.at(pos).Catch(formal, body); |
|
1805 } |
|
1806 |
|
1807 /** SwitchBlockStatementGroups = { SwitchBlockStatementGroup } |
|
1808 * SwitchBlockStatementGroup = SwitchLabel BlockStatements |
|
1809 * SwitchLabel = CASE ConstantExpression ":" | DEFAULT ":" |
|
1810 */ |
|
1811 List<JCCase> switchBlockStatementGroups() { |
|
1812 ListBuffer<JCCase> cases = new ListBuffer<JCCase>(); |
|
1813 while (true) { |
|
1814 int pos = S.pos(); |
|
1815 switch (S.token()) { |
|
1816 case CASE: { |
|
1817 S.nextToken(); |
|
1818 JCExpression pat = expression(); |
|
1819 accept(COLON); |
|
1820 List<JCStatement> stats = blockStatements(); |
|
1821 JCCase c = F.at(pos).Case(pat, stats); |
|
1822 if (stats.isEmpty()) |
|
1823 storeEnd(c, S.prevEndPos()); |
|
1824 cases.append(c); |
|
1825 break; |
|
1826 } |
|
1827 case DEFAULT: { |
|
1828 S.nextToken(); |
|
1829 accept(COLON); |
|
1830 List<JCStatement> stats = blockStatements(); |
|
1831 JCCase c = F.at(pos).Case(null, stats); |
|
1832 if (stats.isEmpty()) |
|
1833 storeEnd(c, S.prevEndPos()); |
|
1834 cases.append(c); |
|
1835 break; |
|
1836 } |
|
1837 case RBRACE: case EOF: |
|
1838 return cases.toList(); |
|
1839 default: |
|
1840 S.nextToken(); // to ensure progress |
|
1841 syntaxError(pos, "expected3", |
|
1842 CASE, DEFAULT, RBRACE); |
|
1843 } |
|
1844 } |
|
1845 } |
|
1846 |
|
1847 /** MoreStatementExpressions = { COMMA StatementExpression } |
|
1848 */ |
|
1849 <T extends ListBuffer<? super JCExpressionStatement>> T moreStatementExpressions(int pos, |
|
1850 JCExpression first, |
|
1851 T stats) { |
|
1852 // This Exec is a "StatementExpression"; it subsumes no terminating token |
|
1853 stats.append(toP(F.at(pos).Exec(checkExprStat(first)))); |
|
1854 while (S.token() == COMMA) { |
|
1855 S.nextToken(); |
|
1856 pos = S.pos(); |
|
1857 JCExpression t = expression(); |
|
1858 // This Exec is a "StatementExpression"; it subsumes no terminating token |
|
1859 stats.append(toP(F.at(pos).Exec(checkExprStat(t)))); |
|
1860 } |
|
1861 return stats; |
|
1862 } |
|
1863 |
|
1864 /** ForInit = StatementExpression MoreStatementExpressions |
|
1865 * | { FINAL | '@' Annotation } Type VariableDeclarators |
|
1866 */ |
|
1867 List<JCStatement> forInit() { |
|
1868 ListBuffer<JCStatement> stats = lb(); |
|
1869 int pos = S.pos(); |
|
1870 if (S.token() == FINAL || S.token() == MONKEYS_AT) { |
|
1871 return variableDeclarators(optFinal(0), type(), stats).toList(); |
|
1872 } else { |
|
1873 JCExpression t = term(EXPR | TYPE); |
|
1874 if ((lastmode & TYPE) != 0 && |
|
1875 (S.token() == IDENTIFIER || S.token() == ASSERT || S.token() == ENUM)) |
|
1876 return variableDeclarators(modifiersOpt(), t, stats).toList(); |
|
1877 else |
|
1878 return moreStatementExpressions(pos, t, stats).toList(); |
|
1879 } |
|
1880 } |
|
1881 |
|
1882 /** ForUpdate = StatementExpression MoreStatementExpressions |
|
1883 */ |
|
1884 List<JCExpressionStatement> forUpdate() { |
|
1885 return moreStatementExpressions(S.pos(), |
|
1886 expression(), |
|
1887 new ListBuffer<JCExpressionStatement>()).toList(); |
|
1888 } |
|
1889 |
|
1890 /** AnnotationsOpt = { '@' Annotation } |
|
1891 */ |
|
1892 List<JCAnnotation> annotationsOpt() { |
|
1893 if (S.token() != MONKEYS_AT) return List.nil(); // optimization |
|
1894 ListBuffer<JCAnnotation> buf = new ListBuffer<JCAnnotation>(); |
|
1895 while (S.token() == MONKEYS_AT) { |
|
1896 int pos = S.pos(); |
|
1897 S.nextToken(); |
|
1898 buf.append(annotation(pos)); |
|
1899 } |
|
1900 return buf.toList(); |
|
1901 } |
|
1902 |
|
1903 /** ModifiersOpt = { Modifier } |
|
1904 * Modifier = PUBLIC | PROTECTED | PRIVATE | STATIC | ABSTRACT | FINAL |
|
1905 * | NATIVE | SYNCHRONIZED | TRANSIENT | VOLATILE | "@" |
|
1906 * | "@" Annotation |
|
1907 */ |
|
1908 JCModifiers modifiersOpt() { |
|
1909 return modifiersOpt(null); |
|
1910 } |
|
1911 JCModifiers modifiersOpt(JCModifiers partial) { |
|
1912 long flags = (partial == null) ? 0 : partial.flags; |
|
1913 if (S.deprecatedFlag()) { |
|
1914 flags |= Flags.DEPRECATED; |
|
1915 S.resetDeprecatedFlag(); |
|
1916 } |
|
1917 ListBuffer<JCAnnotation> annotations = new ListBuffer<JCAnnotation>(); |
|
1918 if (partial != null) annotations.appendList(partial.annotations); |
|
1919 int pos = S.pos(); |
|
1920 int lastPos = Position.NOPOS; |
|
1921 loop: |
|
1922 while (true) { |
|
1923 long flag; |
|
1924 switch (S.token()) { |
|
1925 case PRIVATE : flag = Flags.PRIVATE; break; |
|
1926 case PROTECTED : flag = Flags.PROTECTED; break; |
|
1927 case PUBLIC : flag = Flags.PUBLIC; break; |
|
1928 case STATIC : flag = Flags.STATIC; break; |
|
1929 case TRANSIENT : flag = Flags.TRANSIENT; break; |
|
1930 case FINAL : flag = Flags.FINAL; break; |
|
1931 case ABSTRACT : flag = Flags.ABSTRACT; break; |
|
1932 case NATIVE : flag = Flags.NATIVE; break; |
|
1933 case VOLATILE : flag = Flags.VOLATILE; break; |
|
1934 case SYNCHRONIZED: flag = Flags.SYNCHRONIZED; break; |
|
1935 case STRICTFP : flag = Flags.STRICTFP; break; |
|
1936 case MONKEYS_AT : flag = Flags.ANNOTATION; break; |
|
1937 default: break loop; |
|
1938 } |
|
1939 if ((flags & flag) != 0) log.error(S.pos(), "repeated.modifier"); |
|
1940 lastPos = S.pos(); |
|
1941 S.nextToken(); |
|
1942 if (flag == Flags.ANNOTATION) { |
|
1943 checkAnnotations(); |
|
1944 if (S.token() != INTERFACE) { |
|
1945 JCAnnotation ann = annotation(lastPos); |
|
1946 // if first modifier is an annotation, set pos to annotation's. |
|
1947 if (flags == 0 && annotations.isEmpty()) |
|
1948 pos = ann.pos; |
|
1949 annotations.append(ann); |
|
1950 lastPos = ann.pos; |
|
1951 flag = 0; |
|
1952 } |
|
1953 } |
|
1954 flags |= flag; |
|
1955 } |
|
1956 switch (S.token()) { |
|
1957 case ENUM: flags |= Flags.ENUM; break; |
|
1958 case INTERFACE: flags |= Flags.INTERFACE; break; |
|
1959 default: break; |
|
1960 } |
|
1961 |
|
1962 /* A modifiers tree with no modifier tokens or annotations |
|
1963 * has no text position. */ |
|
1964 if (flags == 0 && annotations.isEmpty()) |
|
1965 pos = Position.NOPOS; |
|
1966 |
|
1967 JCModifiers mods = F.at(pos).Modifiers(flags, annotations.toList()); |
|
1968 if (pos != Position.NOPOS) |
|
1969 storeEnd(mods, S.prevEndPos()); |
|
1970 return mods; |
|
1971 } |
|
1972 |
|
1973 /** Annotation = "@" Qualident [ "(" AnnotationFieldValues ")" ] |
|
1974 * @param pos position of "@" token |
|
1975 */ |
|
1976 JCAnnotation annotation(int pos) { |
|
1977 // accept(AT); // AT consumed by caller |
|
1978 checkAnnotations(); |
|
1979 JCTree ident = qualident(); |
|
1980 List<JCExpression> fieldValues = annotationFieldValuesOpt(); |
|
1981 JCAnnotation ann = F.at(pos).Annotation(ident, fieldValues); |
|
1982 storeEnd(ann, S.prevEndPos()); |
|
1983 return ann; |
|
1984 } |
|
1985 |
|
1986 List<JCExpression> annotationFieldValuesOpt() { |
|
1987 return (S.token() == LPAREN) ? annotationFieldValues() : List.<JCExpression>nil(); |
|
1988 } |
|
1989 |
|
1990 /** AnnotationFieldValues = "(" [ AnnotationFieldValue { "," AnnotationFieldValue } ] ")" */ |
|
1991 List<JCExpression> annotationFieldValues() { |
|
1992 accept(LPAREN); |
|
1993 ListBuffer<JCExpression> buf = new ListBuffer<JCExpression>(); |
|
1994 if (S.token() != RPAREN) { |
|
1995 buf.append(annotationFieldValue()); |
|
1996 while (S.token() == COMMA) { |
|
1997 S.nextToken(); |
|
1998 buf.append(annotationFieldValue()); |
|
1999 } |
|
2000 } |
|
2001 accept(RPAREN); |
|
2002 return buf.toList(); |
|
2003 } |
|
2004 |
|
2005 /** AnnotationFieldValue = AnnotationValue |
|
2006 * | Identifier "=" AnnotationValue |
|
2007 */ |
|
2008 JCExpression annotationFieldValue() { |
|
2009 if (S.token() == IDENTIFIER) { |
|
2010 mode = EXPR; |
|
2011 JCExpression t1 = term1(); |
|
2012 if (t1.getTag() == JCTree.IDENT && S.token() == EQ) { |
|
2013 int pos = S.pos(); |
|
2014 accept(EQ); |
|
2015 return toP(F.at(pos).Assign(t1, annotationValue())); |
|
2016 } else { |
|
2017 return t1; |
|
2018 } |
|
2019 } |
|
2020 return annotationValue(); |
|
2021 } |
|
2022 |
|
2023 /* AnnotationValue = ConditionalExpression |
|
2024 * | Annotation |
|
2025 * | "{" [ AnnotationValue { "," AnnotationValue } ] "}" |
|
2026 */ |
|
2027 JCExpression annotationValue() { |
|
2028 int pos; |
|
2029 switch (S.token()) { |
|
2030 case MONKEYS_AT: |
|
2031 pos = S.pos(); |
|
2032 S.nextToken(); |
|
2033 return annotation(pos); |
|
2034 case LBRACE: |
|
2035 pos = S.pos(); |
|
2036 accept(LBRACE); |
|
2037 ListBuffer<JCExpression> buf = new ListBuffer<JCExpression>(); |
|
2038 if (S.token() != RBRACE) { |
|
2039 buf.append(annotationValue()); |
|
2040 while (S.token() == COMMA) { |
|
2041 S.nextToken(); |
|
2042 if (S.token() == RPAREN) break; |
|
2043 buf.append(annotationValue()); |
|
2044 } |
|
2045 } |
|
2046 accept(RBRACE); |
|
2047 return toP(F.at(pos).NewArray(null, List.<JCExpression>nil(), buf.toList())); |
|
2048 default: |
|
2049 mode = EXPR; |
|
2050 return term1(); |
|
2051 } |
|
2052 } |
|
2053 |
|
2054 /** VariableDeclarators = VariableDeclarator { "," VariableDeclarator } |
|
2055 */ |
|
2056 public <T extends ListBuffer<? super JCVariableDecl>> T variableDeclarators(JCModifiers mods, |
|
2057 JCExpression type, |
|
2058 T vdefs) |
|
2059 { |
|
2060 return variableDeclaratorsRest(S.pos(), mods, type, ident(), false, null, vdefs); |
|
2061 } |
|
2062 |
|
2063 /** VariableDeclaratorsRest = VariableDeclaratorRest { "," VariableDeclarator } |
|
2064 * ConstantDeclaratorsRest = ConstantDeclaratorRest { "," ConstantDeclarator } |
|
2065 * |
|
2066 * @param reqInit Is an initializer always required? |
|
2067 * @param dc The documentation comment for the variable declarations, or null. |
|
2068 */ |
|
2069 <T extends ListBuffer<? super JCVariableDecl>> T variableDeclaratorsRest(int pos, |
|
2070 JCModifiers mods, |
|
2071 JCExpression type, |
|
2072 Name name, |
|
2073 boolean reqInit, |
|
2074 String dc, |
|
2075 T vdefs) |
|
2076 { |
|
2077 vdefs.append(variableDeclaratorRest(pos, mods, type, name, reqInit, dc)); |
|
2078 while (S.token() == COMMA) { |
|
2079 // All but last of multiple declarators subsume a comma |
|
2080 storeEnd((JCTree)vdefs.elems.last(), S.endPos()); |
|
2081 S.nextToken(); |
|
2082 vdefs.append(variableDeclarator(mods, type, reqInit, dc)); |
|
2083 } |
|
2084 return vdefs; |
|
2085 } |
|
2086 |
|
2087 /** VariableDeclarator = Ident VariableDeclaratorRest |
|
2088 * ConstantDeclarator = Ident ConstantDeclaratorRest |
|
2089 */ |
|
2090 JCVariableDecl variableDeclarator(JCModifiers mods, JCExpression type, boolean reqInit, String dc) { |
|
2091 return variableDeclaratorRest(S.pos(), mods, type, ident(), reqInit, dc); |
|
2092 } |
|
2093 |
|
2094 /** VariableDeclaratorRest = BracketsOpt ["=" VariableInitializer] |
|
2095 * ConstantDeclaratorRest = BracketsOpt "=" VariableInitializer |
|
2096 * |
|
2097 * @param reqInit Is an initializer always required? |
|
2098 * @param dc The documentation comment for the variable declarations, or null. |
|
2099 */ |
|
2100 JCVariableDecl variableDeclaratorRest(int pos, JCModifiers mods, JCExpression type, Name name, |
|
2101 boolean reqInit, String dc) { |
|
2102 type = bracketsOpt(type); |
|
2103 JCExpression init = null; |
|
2104 if (S.token() == EQ) { |
|
2105 S.nextToken(); |
|
2106 init = variableInitializer(); |
|
2107 } |
|
2108 else if (reqInit) syntaxError(S.pos(), "expected", EQ); |
|
2109 JCVariableDecl result = |
|
2110 toP(F.at(pos).VarDef(mods, name, type, init)); |
|
2111 attach(result, dc); |
|
2112 return result; |
|
2113 } |
|
2114 |
|
2115 /** VariableDeclaratorId = Ident BracketsOpt |
|
2116 */ |
|
2117 JCVariableDecl variableDeclaratorId(JCModifiers mods, JCExpression type) { |
|
2118 int pos = S.pos(); |
|
2119 Name name = ident(); |
|
2120 if ((mods.flags & Flags.VARARGS) == 0) |
|
2121 type = bracketsOpt(type); |
|
2122 return toP(F.at(pos).VarDef(mods, name, type, null)); |
|
2123 } |
|
2124 |
|
2125 /** CompilationUnit = [ { "@" Annotation } PACKAGE Qualident ";"] {ImportDeclaration} {TypeDeclaration} |
|
2126 */ |
|
2127 public JCTree.JCCompilationUnit compilationUnit() { |
|
2128 int pos = S.pos(); |
|
2129 JCExpression pid = null; |
|
2130 String dc = S.docComment(); |
|
2131 JCModifiers mods = null; |
|
2132 List<JCAnnotation> packageAnnotations = List.nil(); |
|
2133 if (S.token() == MONKEYS_AT) |
|
2134 mods = modifiersOpt(); |
|
2135 |
|
2136 if (S.token() == PACKAGE) { |
|
2137 if (mods != null) { |
|
2138 checkNoMods(mods.flags); |
|
2139 packageAnnotations = mods.annotations; |
|
2140 mods = null; |
|
2141 } |
|
2142 S.nextToken(); |
|
2143 pid = qualident(); |
|
2144 accept(SEMI); |
|
2145 } |
|
2146 ListBuffer<JCTree> defs = new ListBuffer<JCTree>(); |
|
2147 boolean checkForImports = true; |
|
2148 while (S.token() != EOF) { |
|
2149 if (S.pos() <= errorEndPos) { |
|
2150 // error recovery |
|
2151 skip(checkForImports, false, false, false); |
|
2152 if (S.token() == EOF) |
|
2153 break; |
|
2154 } |
|
2155 if (checkForImports && mods == null && S.token() == IMPORT) { |
|
2156 defs.append(importDeclaration()); |
|
2157 } else { |
|
2158 JCTree def = typeDeclaration(mods); |
|
2159 if (def instanceof JCExpressionStatement) |
|
2160 def = ((JCExpressionStatement)def).expr; |
|
2161 defs.append(def); |
|
2162 if (def instanceof JCClassDecl) |
|
2163 checkForImports = false; |
|
2164 mods = null; |
|
2165 } |
|
2166 } |
|
2167 JCTree.JCCompilationUnit toplevel = F.at(pos).TopLevel(packageAnnotations, pid, defs.toList()); |
|
2168 attach(toplevel, dc); |
|
2169 if (defs.elems.isEmpty()) |
|
2170 storeEnd(toplevel, S.prevEndPos()); |
|
2171 if (keepDocComments) toplevel.docComments = docComments; |
|
2172 return toplevel; |
|
2173 } |
|
2174 |
|
2175 /** ImportDeclaration = IMPORT [ STATIC ] Ident { "." Ident } [ "." "*" ] ";" |
|
2176 */ |
|
2177 JCTree importDeclaration() { |
|
2178 int pos = S.pos(); |
|
2179 S.nextToken(); |
|
2180 boolean importStatic = false; |
|
2181 if (S.token() == STATIC) { |
|
2182 checkStaticImports(); |
|
2183 importStatic = true; |
|
2184 S.nextToken(); |
|
2185 } |
|
2186 JCExpression pid = toP(F.at(S.pos()).Ident(ident())); |
|
2187 do { |
|
2188 int pos1 = S.pos(); |
|
2189 accept(DOT); |
|
2190 if (S.token() == STAR) { |
|
2191 pid = to(F.at(pos1).Select(pid, names.asterisk)); |
|
2192 S.nextToken(); |
|
2193 break; |
|
2194 } else { |
|
2195 pid = toP(F.at(pos1).Select(pid, ident())); |
|
2196 } |
|
2197 } while (S.token() == DOT); |
|
2198 accept(SEMI); |
|
2199 return toP(F.at(pos).Import(pid, importStatic)); |
|
2200 } |
|
2201 |
|
2202 /** TypeDeclaration = ClassOrInterfaceOrEnumDeclaration |
|
2203 * | ";" |
|
2204 */ |
|
2205 JCTree typeDeclaration(JCModifiers mods) { |
|
2206 int pos = S.pos(); |
|
2207 if (mods == null && S.token() == SEMI) { |
|
2208 S.nextToken(); |
|
2209 return toP(F.at(pos).Skip()); |
|
2210 } else { |
|
2211 String dc = S.docComment(); |
|
2212 return classOrInterfaceOrEnumDeclaration(modifiersOpt(mods), dc); |
|
2213 } |
|
2214 } |
|
2215 |
|
2216 /** ClassOrInterfaceOrEnumDeclaration = ModifiersOpt |
|
2217 * (ClassDeclaration | InterfaceDeclaration | EnumDeclaration) |
|
2218 * @param mods Any modifiers starting the class or interface declaration |
|
2219 * @param dc The documentation comment for the class, or null. |
|
2220 */ |
|
2221 JCStatement classOrInterfaceOrEnumDeclaration(JCModifiers mods, String dc) { |
|
2222 if (S.token() == CLASS) { |
|
2223 return classDeclaration(mods, dc); |
|
2224 } else if (S.token() == INTERFACE) { |
|
2225 return interfaceDeclaration(mods, dc); |
|
2226 } else if (allowEnums) { |
|
2227 if (S.token() == ENUM) { |
|
2228 return enumDeclaration(mods, dc); |
|
2229 } else { |
|
2230 int pos = S.pos(); |
|
2231 List<JCTree> errs; |
|
2232 if (S.token() == IDENTIFIER) { |
|
2233 errs = List.<JCTree>of(mods, toP(F.at(pos).Ident(ident()))); |
|
2234 setErrorEndPos(S.pos()); |
|
2235 } else { |
|
2236 errs = List.<JCTree>of(mods); |
|
2237 } |
|
2238 return toP(F.Exec(syntaxError(pos, errs, "expected3", |
|
2239 CLASS, INTERFACE, ENUM))); |
|
2240 } |
|
2241 } else { |
|
2242 if (S.token() == ENUM) { |
|
2243 log.error(S.pos(), "enums.not.supported.in.source", source.name); |
|
2244 allowEnums = true; |
|
2245 return enumDeclaration(mods, dc); |
|
2246 } |
|
2247 int pos = S.pos(); |
|
2248 List<JCTree> errs; |
|
2249 if (S.token() == IDENTIFIER) { |
|
2250 errs = List.<JCTree>of(mods, toP(F.at(pos).Ident(ident()))); |
|
2251 setErrorEndPos(S.pos()); |
|
2252 } else { |
|
2253 errs = List.<JCTree>of(mods); |
|
2254 } |
|
2255 return toP(F.Exec(syntaxError(pos, errs, "expected2", |
|
2256 CLASS, INTERFACE))); |
|
2257 } |
|
2258 } |
|
2259 |
|
2260 /** ClassDeclaration = CLASS Ident TypeParametersOpt [EXTENDS Type] |
|
2261 * [IMPLEMENTS TypeList] ClassBody |
|
2262 * @param mods The modifiers starting the class declaration |
|
2263 * @param dc The documentation comment for the class, or null. |
|
2264 */ |
|
2265 JCClassDecl classDeclaration(JCModifiers mods, String dc) { |
|
2266 int pos = S.pos(); |
|
2267 accept(CLASS); |
|
2268 Name name = ident(); |
|
2269 |
|
2270 List<JCTypeParameter> typarams = typeParametersOpt(); |
|
2271 |
|
2272 JCTree extending = null; |
|
2273 if (S.token() == EXTENDS) { |
|
2274 S.nextToken(); |
|
2275 extending = type(); |
|
2276 } |
|
2277 List<JCExpression> implementing = List.nil(); |
|
2278 if (S.token() == IMPLEMENTS) { |
|
2279 S.nextToken(); |
|
2280 implementing = typeList(); |
|
2281 } |
|
2282 List<JCTree> defs = classOrInterfaceBody(name, false); |
|
2283 JCClassDecl result = toP(F.at(pos).ClassDef( |
|
2284 mods, name, typarams, extending, implementing, defs)); |
|
2285 attach(result, dc); |
|
2286 return result; |
|
2287 } |
|
2288 |
|
2289 /** InterfaceDeclaration = INTERFACE Ident TypeParametersOpt |
|
2290 * [EXTENDS TypeList] InterfaceBody |
|
2291 * @param mods The modifiers starting the interface declaration |
|
2292 * @param dc The documentation comment for the interface, or null. |
|
2293 */ |
|
2294 JCClassDecl interfaceDeclaration(JCModifiers mods, String dc) { |
|
2295 int pos = S.pos(); |
|
2296 accept(INTERFACE); |
|
2297 Name name = ident(); |
|
2298 |
|
2299 List<JCTypeParameter> typarams = typeParametersOpt(); |
|
2300 |
|
2301 List<JCExpression> extending = List.nil(); |
|
2302 if (S.token() == EXTENDS) { |
|
2303 S.nextToken(); |
|
2304 extending = typeList(); |
|
2305 } |
|
2306 List<JCTree> defs = classOrInterfaceBody(name, true); |
|
2307 JCClassDecl result = toP(F.at(pos).ClassDef( |
|
2308 mods, name, typarams, null, extending, defs)); |
|
2309 attach(result, dc); |
|
2310 return result; |
|
2311 } |
|
2312 |
|
2313 /** EnumDeclaration = ENUM Ident [IMPLEMENTS TypeList] EnumBody |
|
2314 * @param mods The modifiers starting the enum declaration |
|
2315 * @param dc The documentation comment for the enum, or null. |
|
2316 */ |
|
2317 JCClassDecl enumDeclaration(JCModifiers mods, String dc) { |
|
2318 int pos = S.pos(); |
|
2319 accept(ENUM); |
|
2320 Name name = ident(); |
|
2321 |
|
2322 List<JCExpression> implementing = List.nil(); |
|
2323 if (S.token() == IMPLEMENTS) { |
|
2324 S.nextToken(); |
|
2325 implementing = typeList(); |
|
2326 } |
|
2327 |
|
2328 List<JCTree> defs = enumBody(name); |
|
2329 JCModifiers newMods = |
|
2330 F.at(mods.pos).Modifiers(mods.flags|Flags.ENUM, mods.annotations); |
|
2331 JCClassDecl result = toP(F.at(pos). |
|
2332 ClassDef(newMods, name, List.<JCTypeParameter>nil(), |
|
2333 null, implementing, defs)); |
|
2334 attach(result, dc); |
|
2335 return result; |
|
2336 } |
|
2337 |
|
2338 /** EnumBody = "{" { EnumeratorDeclarationList } [","] |
|
2339 * [ ";" {ClassBodyDeclaration} ] "}" |
|
2340 */ |
|
2341 List<JCTree> enumBody(Name enumName) { |
|
2342 accept(LBRACE); |
|
2343 ListBuffer<JCTree> defs = new ListBuffer<JCTree>(); |
|
2344 if (S.token() == COMMA) { |
|
2345 S.nextToken(); |
|
2346 } else if (S.token() != RBRACE && S.token() != SEMI) { |
|
2347 defs.append(enumeratorDeclaration(enumName)); |
|
2348 while (S.token() == COMMA) { |
|
2349 S.nextToken(); |
|
2350 if (S.token() == RBRACE || S.token() == SEMI) break; |
|
2351 defs.append(enumeratorDeclaration(enumName)); |
|
2352 } |
|
2353 if (S.token() != SEMI && S.token() != RBRACE) { |
|
2354 defs.append(syntaxError(S.pos(), "expected3", |
|
2355 COMMA, RBRACE, SEMI)); |
|
2356 S.nextToken(); |
|
2357 } |
|
2358 } |
|
2359 if (S.token() == SEMI) { |
|
2360 S.nextToken(); |
|
2361 while (S.token() != RBRACE && S.token() != EOF) { |
|
2362 defs.appendList(classOrInterfaceBodyDeclaration(enumName, |
|
2363 false)); |
|
2364 if (S.pos() <= errorEndPos) { |
|
2365 // error recovery |
|
2366 skip(false, true, true, false); |
|
2367 } |
|
2368 } |
|
2369 } |
|
2370 accept(RBRACE); |
|
2371 return defs.toList(); |
|
2372 } |
|
2373 |
|
2374 /** EnumeratorDeclaration = AnnotationsOpt [TypeArguments] IDENTIFIER [ Arguments ] [ "{" ClassBody "}" ] |
|
2375 */ |
|
2376 JCTree enumeratorDeclaration(Name enumName) { |
|
2377 String dc = S.docComment(); |
|
2378 int flags = Flags.PUBLIC|Flags.STATIC|Flags.FINAL|Flags.ENUM; |
|
2379 if (S.deprecatedFlag()) { |
|
2380 flags |= Flags.DEPRECATED; |
|
2381 S.resetDeprecatedFlag(); |
|
2382 } |
|
2383 int pos = S.pos(); |
|
2384 List<JCAnnotation> annotations = annotationsOpt(); |
|
2385 JCModifiers mods = F.at(annotations.isEmpty() ? Position.NOPOS : pos).Modifiers(flags, annotations); |
|
2386 List<JCExpression> typeArgs = typeArgumentsOpt(); |
|
2387 int identPos = S.pos(); |
|
2388 Name name = ident(); |
|
2389 int createPos = S.pos(); |
|
2390 List<JCExpression> args = (S.token() == LPAREN) |
|
2391 ? arguments() : List.<JCExpression>nil(); |
|
2392 JCClassDecl body = null; |
|
2393 if (S.token() == LBRACE) { |
|
2394 JCModifiers mods1 = F.at(Position.NOPOS).Modifiers(Flags.ENUM | Flags.STATIC); |
|
2395 List<JCTree> defs = classOrInterfaceBody(names.empty, false); |
|
2396 body = toP(F.at(identPos).AnonymousClassDef(mods1, defs)); |
|
2397 } |
|
2398 if (args.isEmpty() && body == null) |
|
2399 createPos = Position.NOPOS; |
|
2400 JCIdent ident = F.at(Position.NOPOS).Ident(enumName); |
|
2401 JCNewClass create = F.at(createPos).NewClass(null, typeArgs, ident, args, body); |
|
2402 if (createPos != Position.NOPOS) |
|
2403 storeEnd(create, S.prevEndPos()); |
|
2404 ident = F.at(Position.NOPOS).Ident(enumName); |
|
2405 JCTree result = toP(F.at(pos).VarDef(mods, name, ident, create)); |
|
2406 attach(result, dc); |
|
2407 return result; |
|
2408 } |
|
2409 |
|
2410 /** TypeList = Type {"," Type} |
|
2411 */ |
|
2412 List<JCExpression> typeList() { |
|
2413 ListBuffer<JCExpression> ts = new ListBuffer<JCExpression>(); |
|
2414 ts.append(type()); |
|
2415 while (S.token() == COMMA) { |
|
2416 S.nextToken(); |
|
2417 ts.append(type()); |
|
2418 } |
|
2419 return ts.toList(); |
|
2420 } |
|
2421 |
|
2422 /** ClassBody = "{" {ClassBodyDeclaration} "}" |
|
2423 * InterfaceBody = "{" {InterfaceBodyDeclaration} "}" |
|
2424 */ |
|
2425 List<JCTree> classOrInterfaceBody(Name className, boolean isInterface) { |
|
2426 accept(LBRACE); |
|
2427 if (S.pos() <= errorEndPos) { |
|
2428 // error recovery |
|
2429 skip(false, true, false, false); |
|
2430 if (S.token() == LBRACE) |
|
2431 S.nextToken(); |
|
2432 } |
|
2433 ListBuffer<JCTree> defs = new ListBuffer<JCTree>(); |
|
2434 while (S.token() != RBRACE && S.token() != EOF) { |
|
2435 defs.appendList(classOrInterfaceBodyDeclaration(className, isInterface)); |
|
2436 if (S.pos() <= errorEndPos) { |
|
2437 // error recovery |
|
2438 skip(false, true, true, false); |
|
2439 } |
|
2440 } |
|
2441 accept(RBRACE); |
|
2442 return defs.toList(); |
|
2443 } |
|
2444 |
|
2445 /** ClassBodyDeclaration = |
|
2446 * ";" |
|
2447 * | [STATIC] Block |
|
2448 * | ModifiersOpt |
|
2449 * ( Type Ident |
|
2450 * ( VariableDeclaratorsRest ";" | MethodDeclaratorRest ) |
|
2451 * | VOID Ident MethodDeclaratorRest |
|
2452 * | TypeParameters (Type | VOID) Ident MethodDeclaratorRest |
|
2453 * | Ident ConstructorDeclaratorRest |
|
2454 * | TypeParameters Ident ConstructorDeclaratorRest |
|
2455 * | ClassOrInterfaceOrEnumDeclaration |
|
2456 * ) |
|
2457 * InterfaceBodyDeclaration = |
|
2458 * ";" |
|
2459 * | ModifiersOpt Type Ident |
|
2460 * ( ConstantDeclaratorsRest | InterfaceMethodDeclaratorRest ";" ) |
|
2461 */ |
|
2462 List<JCTree> classOrInterfaceBodyDeclaration(Name className, boolean isInterface) { |
|
2463 if (S.token() == SEMI) { |
|
2464 S.nextToken(); |
|
2465 return List.<JCTree>of(F.at(Position.NOPOS).Block(0, List.<JCStatement>nil())); |
|
2466 } else { |
|
2467 String dc = S.docComment(); |
|
2468 int pos = S.pos(); |
|
2469 JCModifiers mods = modifiersOpt(); |
|
2470 if (S.token() == CLASS || |
|
2471 S.token() == INTERFACE || |
|
2472 allowEnums && S.token() == ENUM) { |
|
2473 return List.<JCTree>of(classOrInterfaceOrEnumDeclaration(mods, dc)); |
|
2474 } else if (S.token() == LBRACE && !isInterface && |
|
2475 (mods.flags & Flags.StandardFlags & ~Flags.STATIC) == 0 && |
|
2476 mods.annotations.isEmpty()) { |
|
2477 return List.<JCTree>of(block(pos, mods.flags)); |
|
2478 } else { |
|
2479 pos = S.pos(); |
|
2480 List<JCTypeParameter> typarams = typeParametersOpt(); |
|
2481 // Hack alert: if there are type arguments but no Modifiers, the start |
|
2482 // position will be lost unless we set the Modifiers position. There |
|
2483 // should be an AST node for type parameters (BugId 5005090). |
|
2484 if (typarams.length() > 0 && mods.pos == Position.NOPOS) { |
|
2485 mods.pos = pos; |
|
2486 } |
|
2487 Token token = S.token(); |
|
2488 Name name = S.name(); |
|
2489 pos = S.pos(); |
|
2490 JCExpression type; |
|
2491 boolean isVoid = S.token() == VOID; |
|
2492 if (isVoid) { |
|
2493 type = to(F.at(pos).TypeIdent(TypeTags.VOID)); |
|
2494 S.nextToken(); |
|
2495 } else { |
|
2496 type = type(); |
|
2497 } |
|
2498 if (S.token() == LPAREN && !isInterface && type.getTag() == JCTree.IDENT) { |
|
2499 if (isInterface || name != className) |
|
2500 log.error(pos, "invalid.meth.decl.ret.type.req"); |
|
2501 return List.of(methodDeclaratorRest( |
|
2502 pos, mods, null, names.init, typarams, |
|
2503 isInterface, true, dc)); |
|
2504 } else { |
|
2505 pos = S.pos(); |
|
2506 name = ident(); |
|
2507 if (S.token() == LPAREN) { |
|
2508 return List.of(methodDeclaratorRest( |
|
2509 pos, mods, type, name, typarams, |
|
2510 isInterface, isVoid, dc)); |
|
2511 } else if (!isVoid && typarams.isEmpty()) { |
|
2512 List<JCTree> defs = |
|
2513 variableDeclaratorsRest(pos, mods, type, name, isInterface, dc, |
|
2514 new ListBuffer<JCTree>()).toList(); |
|
2515 storeEnd(defs.last(), S.endPos()); |
|
2516 accept(SEMI); |
|
2517 return defs; |
|
2518 } else { |
|
2519 pos = S.pos(); |
|
2520 List<JCTree> err = isVoid |
|
2521 ? List.<JCTree>of(toP(F.at(pos).MethodDef(mods, name, type, typarams, |
|
2522 List.<JCVariableDecl>nil(), List.<JCExpression>nil(), null, null))) |
|
2523 : null; |
|
2524 return List.<JCTree>of(syntaxError(S.pos(), err, "expected", LPAREN)); |
|
2525 } |
|
2526 } |
|
2527 } |
|
2528 } |
|
2529 } |
|
2530 |
|
2531 /** MethodDeclaratorRest = |
|
2532 * FormalParameters BracketsOpt [Throws TypeList] ( MethodBody | [DEFAULT AnnotationValue] ";") |
|
2533 * VoidMethodDeclaratorRest = |
|
2534 * FormalParameters [Throws TypeList] ( MethodBody | ";") |
|
2535 * InterfaceMethodDeclaratorRest = |
|
2536 * FormalParameters BracketsOpt [THROWS TypeList] ";" |
|
2537 * VoidInterfaceMethodDeclaratorRest = |
|
2538 * FormalParameters [THROWS TypeList] ";" |
|
2539 * ConstructorDeclaratorRest = |
|
2540 * "(" FormalParameterListOpt ")" [THROWS TypeList] MethodBody |
|
2541 */ |
|
2542 JCTree methodDeclaratorRest(int pos, |
|
2543 JCModifiers mods, |
|
2544 JCExpression type, |
|
2545 Name name, |
|
2546 List<JCTypeParameter> typarams, |
|
2547 boolean isInterface, boolean isVoid, |
|
2548 String dc) { |
|
2549 List<JCVariableDecl> params = formalParameters(); |
|
2550 if (!isVoid) type = bracketsOpt(type); |
|
2551 List<JCExpression> thrown = List.nil(); |
|
2552 if (S.token() == THROWS) { |
|
2553 S.nextToken(); |
|
2554 thrown = qualidentList(); |
|
2555 } |
|
2556 JCBlock body = null; |
|
2557 JCExpression defaultValue; |
|
2558 if (S.token() == LBRACE) { |
|
2559 body = block(); |
|
2560 defaultValue = null; |
|
2561 } else { |
|
2562 if (S.token() == DEFAULT) { |
|
2563 accept(DEFAULT); |
|
2564 defaultValue = annotationValue(); |
|
2565 } else { |
|
2566 defaultValue = null; |
|
2567 } |
|
2568 accept(SEMI); |
|
2569 if (S.pos() <= errorEndPos) { |
|
2570 // error recovery |
|
2571 skip(false, true, false, false); |
|
2572 if (S.token() == LBRACE) { |
|
2573 body = block(); |
|
2574 } |
|
2575 } |
|
2576 } |
|
2577 JCMethodDecl result = |
|
2578 toP(F.at(pos).MethodDef(mods, name, type, typarams, |
|
2579 params, thrown, |
|
2580 body, defaultValue)); |
|
2581 attach(result, dc); |
|
2582 return result; |
|
2583 } |
|
2584 |
|
2585 /** QualidentList = Qualident {"," Qualident} |
|
2586 */ |
|
2587 List<JCExpression> qualidentList() { |
|
2588 ListBuffer<JCExpression> ts = new ListBuffer<JCExpression>(); |
|
2589 ts.append(qualident()); |
|
2590 while (S.token() == COMMA) { |
|
2591 S.nextToken(); |
|
2592 ts.append(qualident()); |
|
2593 } |
|
2594 return ts.toList(); |
|
2595 } |
|
2596 |
|
2597 /** TypeParametersOpt = ["<" TypeParameter {"," TypeParameter} ">"] |
|
2598 */ |
|
2599 List<JCTypeParameter> typeParametersOpt() { |
|
2600 if (S.token() == LT) { |
|
2601 checkGenerics(); |
|
2602 ListBuffer<JCTypeParameter> typarams = new ListBuffer<JCTypeParameter>(); |
|
2603 S.nextToken(); |
|
2604 typarams.append(typeParameter()); |
|
2605 while (S.token() == COMMA) { |
|
2606 S.nextToken(); |
|
2607 typarams.append(typeParameter()); |
|
2608 } |
|
2609 accept(GT); |
|
2610 return typarams.toList(); |
|
2611 } else { |
|
2612 return List.nil(); |
|
2613 } |
|
2614 } |
|
2615 |
|
2616 /** TypeParameter = TypeVariable [TypeParameterBound] |
|
2617 * TypeParameterBound = EXTENDS Type {"&" Type} |
|
2618 * TypeVariable = Ident |
|
2619 */ |
|
2620 JCTypeParameter typeParameter() { |
|
2621 int pos = S.pos(); |
|
2622 Name name = ident(); |
|
2623 ListBuffer<JCExpression> bounds = new ListBuffer<JCExpression>(); |
|
2624 if (S.token() == EXTENDS) { |
|
2625 S.nextToken(); |
|
2626 bounds.append(type()); |
|
2627 while (S.token() == AMP) { |
|
2628 S.nextToken(); |
|
2629 bounds.append(type()); |
|
2630 } |
|
2631 } |
|
2632 return toP(F.at(pos).TypeParameter(name, bounds.toList())); |
|
2633 } |
|
2634 |
|
2635 /** FormalParameters = "(" [ FormalParameterList ] ")" |
|
2636 * FormalParameterList = [ FormalParameterListNovarargs , ] LastFormalParameter |
|
2637 * FormalParameterListNovarargs = [ FormalParameterListNovarargs , ] FormalParameter |
|
2638 */ |
|
2639 List<JCVariableDecl> formalParameters() { |
|
2640 ListBuffer<JCVariableDecl> params = new ListBuffer<JCVariableDecl>(); |
|
2641 JCVariableDecl lastParam = null; |
|
2642 accept(LPAREN); |
|
2643 if (S.token() != RPAREN) { |
|
2644 params.append(lastParam = formalParameter()); |
|
2645 while ((lastParam.mods.flags & Flags.VARARGS) == 0 && S.token() == COMMA) { |
|
2646 S.nextToken(); |
|
2647 params.append(lastParam = formalParameter()); |
|
2648 } |
|
2649 } |
|
2650 accept(RPAREN); |
|
2651 return params.toList(); |
|
2652 } |
|
2653 |
|
2654 JCModifiers optFinal(long flags) { |
|
2655 JCModifiers mods = modifiersOpt(); |
|
2656 checkNoMods(mods.flags & ~(Flags.FINAL | Flags.DEPRECATED)); |
|
2657 mods.flags |= flags; |
|
2658 return mods; |
|
2659 } |
|
2660 |
|
2661 /** FormalParameter = { FINAL | '@' Annotation } Type VariableDeclaratorId |
|
2662 * LastFormalParameter = { FINAL | '@' Annotation } Type '...' Ident | FormalParameter |
|
2663 */ |
|
2664 JCVariableDecl formalParameter() { |
|
2665 JCModifiers mods = optFinal(Flags.PARAMETER); |
|
2666 JCExpression type = type(); |
|
2667 if (S.token() == ELLIPSIS) { |
|
2668 checkVarargs(); |
|
2669 mods.flags |= Flags.VARARGS; |
|
2670 type = to(F.at(S.pos()).TypeArray(type)); |
|
2671 S.nextToken(); |
|
2672 } |
|
2673 return variableDeclaratorId(mods, type); |
|
2674 } |
|
2675 |
|
2676 /* ---------- auxiliary methods -------------- */ |
|
2677 |
|
2678 /** Check that given tree is a legal expression statement. |
|
2679 */ |
|
2680 protected JCExpression checkExprStat(JCExpression t) { |
|
2681 switch(t.getTag()) { |
|
2682 case JCTree.PREINC: case JCTree.PREDEC: |
|
2683 case JCTree.POSTINC: case JCTree.POSTDEC: |
|
2684 case JCTree.ASSIGN: |
|
2685 case JCTree.BITOR_ASG: case JCTree.BITXOR_ASG: case JCTree.BITAND_ASG: |
|
2686 case JCTree.SL_ASG: case JCTree.SR_ASG: case JCTree.USR_ASG: |
|
2687 case JCTree.PLUS_ASG: case JCTree.MINUS_ASG: |
|
2688 case JCTree.MUL_ASG: case JCTree.DIV_ASG: case JCTree.MOD_ASG: |
|
2689 case JCTree.APPLY: case JCTree.NEWCLASS: |
|
2690 case JCTree.ERRONEOUS: |
|
2691 return t; |
|
2692 default: |
|
2693 log.error(t.pos, "not.stmt"); |
|
2694 return F.at(t.pos).Erroneous(List.<JCTree>of(t)); |
|
2695 } |
|
2696 } |
|
2697 |
|
2698 /** Return precedence of operator represented by token, |
|
2699 * -1 if token is not a binary operator. @see TreeInfo.opPrec |
|
2700 */ |
|
2701 static int prec(Token token) { |
|
2702 int oc = optag(token); |
|
2703 return (oc >= 0) ? TreeInfo.opPrec(oc) : -1; |
|
2704 } |
|
2705 |
|
2706 /** Return operation tag of binary operator represented by token, |
|
2707 * -1 if token is not a binary operator. |
|
2708 */ |
|
2709 static int optag(Token token) { |
|
2710 switch (token) { |
|
2711 case BARBAR: |
|
2712 return JCTree.OR; |
|
2713 case AMPAMP: |
|
2714 return JCTree.AND; |
|
2715 case BAR: |
|
2716 return JCTree.BITOR; |
|
2717 case BAREQ: |
|
2718 return JCTree.BITOR_ASG; |
|
2719 case CARET: |
|
2720 return JCTree.BITXOR; |
|
2721 case CARETEQ: |
|
2722 return JCTree.BITXOR_ASG; |
|
2723 case AMP: |
|
2724 return JCTree.BITAND; |
|
2725 case AMPEQ: |
|
2726 return JCTree.BITAND_ASG; |
|
2727 case EQEQ: |
|
2728 return JCTree.EQ; |
|
2729 case BANGEQ: |
|
2730 return JCTree.NE; |
|
2731 case LT: |
|
2732 return JCTree.LT; |
|
2733 case GT: |
|
2734 return JCTree.GT; |
|
2735 case LTEQ: |
|
2736 return JCTree.LE; |
|
2737 case GTEQ: |
|
2738 return JCTree.GE; |
|
2739 case LTLT: |
|
2740 return JCTree.SL; |
|
2741 case LTLTEQ: |
|
2742 return JCTree.SL_ASG; |
|
2743 case GTGT: |
|
2744 return JCTree.SR; |
|
2745 case GTGTEQ: |
|
2746 return JCTree.SR_ASG; |
|
2747 case GTGTGT: |
|
2748 return JCTree.USR; |
|
2749 case GTGTGTEQ: |
|
2750 return JCTree.USR_ASG; |
|
2751 case PLUS: |
|
2752 return JCTree.PLUS; |
|
2753 case PLUSEQ: |
|
2754 return JCTree.PLUS_ASG; |
|
2755 case SUB: |
|
2756 return JCTree.MINUS; |
|
2757 case SUBEQ: |
|
2758 return JCTree.MINUS_ASG; |
|
2759 case STAR: |
|
2760 return JCTree.MUL; |
|
2761 case STAREQ: |
|
2762 return JCTree.MUL_ASG; |
|
2763 case SLASH: |
|
2764 return JCTree.DIV; |
|
2765 case SLASHEQ: |
|
2766 return JCTree.DIV_ASG; |
|
2767 case PERCENT: |
|
2768 return JCTree.MOD; |
|
2769 case PERCENTEQ: |
|
2770 return JCTree.MOD_ASG; |
|
2771 case INSTANCEOF: |
|
2772 return JCTree.TYPETEST; |
|
2773 default: |
|
2774 return -1; |
|
2775 } |
|
2776 } |
|
2777 |
|
2778 /** Return operation tag of unary operator represented by token, |
|
2779 * -1 if token is not a binary operator. |
|
2780 */ |
|
2781 static int unoptag(Token token) { |
|
2782 switch (token) { |
|
2783 case PLUS: |
|
2784 return JCTree.POS; |
|
2785 case SUB: |
|
2786 return JCTree.NEG; |
|
2787 case BANG: |
|
2788 return JCTree.NOT; |
|
2789 case TILDE: |
|
2790 return JCTree.COMPL; |
|
2791 case PLUSPLUS: |
|
2792 return JCTree.PREINC; |
|
2793 case SUBSUB: |
|
2794 return JCTree.PREDEC; |
|
2795 default: |
|
2796 return -1; |
|
2797 } |
|
2798 } |
|
2799 |
|
2800 /** Return type tag of basic type represented by token, |
|
2801 * -1 if token is not a basic type identifier. |
|
2802 */ |
|
2803 static int typetag(Token token) { |
|
2804 switch (token) { |
|
2805 case BYTE: |
|
2806 return TypeTags.BYTE; |
|
2807 case CHAR: |
|
2808 return TypeTags.CHAR; |
|
2809 case SHORT: |
|
2810 return TypeTags.SHORT; |
|
2811 case INT: |
|
2812 return TypeTags.INT; |
|
2813 case LONG: |
|
2814 return TypeTags.LONG; |
|
2815 case FLOAT: |
|
2816 return TypeTags.FLOAT; |
|
2817 case DOUBLE: |
|
2818 return TypeTags.DOUBLE; |
|
2819 case BOOLEAN: |
|
2820 return TypeTags.BOOLEAN; |
|
2821 default: |
|
2822 return -1; |
|
2823 } |
|
2824 } |
|
2825 |
|
2826 void checkGenerics() { |
|
2827 if (!allowGenerics) { |
|
2828 log.error(S.pos(), "generics.not.supported.in.source", source.name); |
|
2829 allowGenerics = true; |
|
2830 } |
|
2831 } |
|
2832 void checkVarargs() { |
|
2833 if (!allowVarargs) { |
|
2834 log.error(S.pos(), "varargs.not.supported.in.source", source.name); |
|
2835 allowVarargs = true; |
|
2836 } |
|
2837 } |
|
2838 void checkForeach() { |
|
2839 if (!allowForeach) { |
|
2840 log.error(S.pos(), "foreach.not.supported.in.source", source.name); |
|
2841 allowForeach = true; |
|
2842 } |
|
2843 } |
|
2844 void checkStaticImports() { |
|
2845 if (!allowStaticImport) { |
|
2846 log.error(S.pos(), "static.import.not.supported.in.source", source.name); |
|
2847 allowStaticImport = true; |
|
2848 } |
|
2849 } |
|
2850 void checkAnnotations() { |
|
2851 if (!allowAnnotations) { |
|
2852 log.error(S.pos(), "annotations.not.supported.in.source", source.name); |
|
2853 allowAnnotations = true; |
|
2854 } |
|
2855 } |
|
2856 } |
|