Tue, 09 Sep 2008 10:40:50 -0700
6724118: change JavaCompiler to not use Scanner directly
6736119: refactor Parser and Parser.Factory
Reviewed-by: mcimadamore
1.1 --- a/src/share/classes/com/sun/tools/javac/api/JavacTaskImpl.java Tue Sep 09 10:28:21 2008 -0700 1.2 +++ b/src/share/classes/com/sun/tools/javac/api/JavacTaskImpl.java Tue Sep 09 10:40:50 2008 -0700 1.3 @@ -27,6 +27,7 @@ 1.4 1.5 import java.io.File; 1.6 import java.io.IOException; 1.7 +import java.nio.CharBuffer; 1.8 import java.util.*; 1.9 import java.util.concurrent.atomic.AtomicBoolean; 1.10 1.11 @@ -45,7 +46,7 @@ 1.12 import com.sun.tools.javac.main.*; 1.13 import com.sun.tools.javac.model.*; 1.14 import com.sun.tools.javac.parser.Parser; 1.15 -import com.sun.tools.javac.parser.Scanner; 1.16 +import com.sun.tools.javac.parser.ParserFactory; 1.17 import com.sun.tools.javac.tree.*; 1.18 import com.sun.tools.javac.tree.JCTree.*; 1.19 import com.sun.tools.javac.util.*; 1.20 @@ -93,6 +94,9 @@ 1.21 args.getClass(); 1.22 context.getClass(); 1.23 fileObjects.getClass(); 1.24 + 1.25 + // force the use of the scanner that captures Javadoc comments 1.26 + com.sun.tools.javac.parser.DocCommentScanner.Factory.preRegister(context); 1.27 } 1.28 1.29 JavacTaskImpl(JavacTool tool, 1.30 @@ -166,8 +170,6 @@ 1.31 if (!filenames.isEmpty()) 1.32 throw new IllegalArgumentException("Malformed arguments " + filenames.toString(" ")); 1.33 compiler = JavaCompiler.instance(context); 1.34 - // force the use of the scanner that captures Javadoc comments 1.35 - com.sun.tools.javac.parser.DocCommentScanner.Factory.preRegister(context); 1.36 compiler.keepComments = true; 1.37 compiler.genEndPos = true; 1.38 // NOTE: this value will be updated after annotation processing 1.39 @@ -519,14 +521,12 @@ 1.40 throw new IllegalArgumentException(); 1.41 compiler = JavaCompiler.instance(context); 1.42 JavaFileObject prev = compiler.log.useSource(null); 1.43 - Scanner.Factory scannerFactory = Scanner.Factory.instance(context); 1.44 - Parser.Factory parserFactory = Parser.Factory.instance(context); 1.45 + ParserFactory parserFactory = ParserFactory.instance(context); 1.46 Attr attr = Attr.instance(context); 1.47 try { 1.48 - Scanner scanner = scannerFactory.newScanner((expr+"\u0000").toCharArray(), 1.49 - expr.length()); 1.50 - Parser parser = parserFactory.newParser(scanner, false, false); 1.51 - JCTree tree = parser.type(); 1.52 + CharBuffer buf = CharBuffer.wrap((expr+"\u0000").toCharArray(), 0, expr.length()); 1.53 + Parser parser = parserFactory.newParser(buf, false, false, false); 1.54 + JCTree tree = parser.parseType(); 1.55 return attr.attribType(tree, (Symbol.TypeSymbol)scope); 1.56 } finally { 1.57 compiler.log.useSource(prev);
2.1 --- a/src/share/classes/com/sun/tools/javac/main/JavaCompiler.java Tue Sep 09 10:28:21 2008 -0700 2.2 +++ b/src/share/classes/com/sun/tools/javac/main/JavaCompiler.java Tue Sep 09 10:40:50 2008 -0700 2.3 @@ -276,7 +276,7 @@ 2.4 2.5 /** Factory for parsers. 2.6 */ 2.7 - protected Parser.Factory parserFactory; 2.8 + protected ParserFactory parserFactory; 2.9 2.10 /** Optional listener for progress events 2.11 */ 2.12 @@ -320,7 +320,7 @@ 2.13 todo = Todo.instance(context); 2.14 2.15 fileManager = context.get(JavaFileManager.class); 2.16 - parserFactory = Parser.Factory.instance(context); 2.17 + parserFactory = ParserFactory.instance(context); 2.18 2.19 try { 2.20 // catch completion problems with predefineds 2.21 @@ -510,10 +510,6 @@ 2.22 return parseErrors; 2.23 } 2.24 2.25 - protected Scanner.Factory getScannerFactory() { 2.26 - return Scanner.Factory.instance(context); 2.27 - } 2.28 - 2.29 /** Try to open input stream with given name. 2.30 * Report an error if this fails. 2.31 * @param filename The file name of the input stream to be opened. 2.32 @@ -545,13 +541,9 @@ 2.33 taskListener.started(e); 2.34 } 2.35 int initialErrorCount = log.nerrors; 2.36 - Scanner scanner = getScannerFactory().newScanner(content); 2.37 - Parser parser = parserFactory.newParser(scanner, keepComments(), genEndPos); 2.38 - tree = parser.compilationUnit(); 2.39 + Parser parser = parserFactory.newParser(content, keepComments(), genEndPos, lineDebugInfo); 2.40 + tree = parser.parseCompilationUnit(); 2.41 parseErrors |= (log.nerrors > initialErrorCount); 2.42 - if (lineDebugInfo) { 2.43 - tree.lineMap = scanner.getLineMap(); 2.44 - } 2.45 if (verbose) { 2.46 printVerbose("parsing.done", Long.toString(elapsed(msec))); 2.47 }
3.1 --- a/src/share/classes/com/sun/tools/javac/parser/EndPosParser.java Tue Sep 09 10:28:21 2008 -0700 3.2 +++ b/src/share/classes/com/sun/tools/javac/parser/EndPosParser.java Tue Sep 09 10:40:50 2008 -0700 3.3 @@ -41,10 +41,10 @@ 3.4 * This code and its internal interfaces are subject to change or 3.5 * deletion without notice.</b></p> 3.6 */ 3.7 -public class EndPosParser extends Parser { 3.8 +public class EndPosParser extends JavacParser { 3.9 3.10 - public EndPosParser(Factory fac, Lexer S, boolean keepDocComments) { 3.11 - super(fac, S, keepDocComments); 3.12 + public EndPosParser(ParserFactory fac, Lexer S, boolean keepDocComments, boolean keepLineMap) { 3.13 + super(fac, S, keepDocComments, keepLineMap); 3.14 this.S = S; 3.15 endPositions = new HashMap<JCTree,Integer>(); 3.16 } 3.17 @@ -79,8 +79,8 @@ 3.18 } 3.19 3.20 @Override 3.21 - public JCCompilationUnit compilationUnit() { 3.22 - JCCompilationUnit t = super.compilationUnit(); 3.23 + public JCCompilationUnit parseCompilationUnit() { 3.24 + JCCompilationUnit t = super.parseCompilationUnit(); 3.25 t.endPositions = endPositions; 3.26 return t; 3.27 }
4.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 4.2 +++ b/src/share/classes/com/sun/tools/javac/parser/JavacParser.java Tue Sep 09 10:40:50 2008 -0700 4.3 @@ -0,0 +1,2819 @@ 4.4 +/* 4.5 + * Copyright 1999-2008 Sun Microsystems, Inc. All Rights Reserved. 4.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4.7 + * 4.8 + * This code is free software; you can redistribute it and/or modify it 4.9 + * under the terms of the GNU General Public License version 2 only, as 4.10 + * published by the Free Software Foundation. Sun designates this 4.11 + * particular file as subject to the "Classpath" exception as provided 4.12 + * by Sun in the LICENSE file that accompanied this code. 4.13 + * 4.14 + * This code is distributed in the hope that it will be useful, but WITHOUT 4.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 4.16 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 4.17 + * version 2 for more details (a copy is included in the LICENSE file that 4.18 + * accompanied this code). 4.19 + * 4.20 + * You should have received a copy of the GNU General Public License version 4.21 + * 2 along with this work; if not, write to the Free Software Foundation, 4.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 4.23 + * 4.24 + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, 4.25 + * CA 95054 USA or visit www.sun.com if you need additional information or 4.26 + * have any questions. 4.27 + */ 4.28 + 4.29 +package com.sun.tools.javac.parser; 4.30 + 4.31 +import java.util.*; 4.32 + 4.33 +import com.sun.tools.javac.tree.*; 4.34 +import com.sun.tools.javac.code.*; 4.35 +import com.sun.tools.javac.util.*; 4.36 +import com.sun.tools.javac.util.List; 4.37 +import static com.sun.tools.javac.util.ListBuffer.lb; 4.38 + 4.39 +import com.sun.tools.javac.tree.JCTree.*; 4.40 + 4.41 +import static com.sun.tools.javac.parser.Token.*; 4.42 + 4.43 +/** The parser maps a token sequence into an abstract syntax 4.44 + * tree. It operates by recursive descent, with code derived 4.45 + * systematically from an LL(1) grammar. For efficiency reasons, an 4.46 + * operator precedence scheme is used for parsing binary operation 4.47 + * expressions. 4.48 + * 4.49 + * <p><b>This is NOT part of any API supported by Sun Microsystems. If 4.50 + * you write code that depends on this, you do so at your own risk. 4.51 + * This code and its internal interfaces are subject to change or 4.52 + * deletion without notice.</b> 4.53 + */ 4.54 +public class JavacParser implements Parser { 4.55 + 4.56 + /** The number of precedence levels of infix operators. 4.57 + */ 4.58 + private static final int infixPrecedenceLevels = 10; 4.59 + 4.60 + /** The scanner used for lexical analysis. 4.61 + */ 4.62 + private Lexer S; 4.63 + 4.64 + /** The factory to be used for abstract syntax tree construction. 4.65 + */ 4.66 + protected TreeMaker F; 4.67 + 4.68 + /** The log to be used for error diagnostics. 4.69 + */ 4.70 + private Log log; 4.71 + 4.72 + /** The keyword table. */ 4.73 + private Keywords keywords; 4.74 + 4.75 + /** The Source language setting. */ 4.76 + private Source source; 4.77 + 4.78 + /** The name table. */ 4.79 + private Name.Table names; 4.80 + 4.81 + /** Construct a parser from a given scanner, tree factory and log. 4.82 + */ 4.83 + protected JavacParser(ParserFactory fac, 4.84 + Lexer S, 4.85 + boolean keepDocComments, 4.86 + boolean keepLineMap) { 4.87 + this.S = S; 4.88 + S.nextToken(); // prime the pump 4.89 + this.F = fac.F; 4.90 + this.log = fac.log; 4.91 + this.names = fac.names; 4.92 + this.keywords = fac.keywords; 4.93 + this.source = fac.source; 4.94 + this.allowGenerics = source.allowGenerics(); 4.95 + this.allowVarargs = source.allowVarargs(); 4.96 + this.allowAsserts = source.allowAsserts(); 4.97 + this.allowEnums = source.allowEnums(); 4.98 + this.allowForeach = source.allowForeach(); 4.99 + this.allowStaticImport = source.allowStaticImport(); 4.100 + this.allowAnnotations = source.allowAnnotations(); 4.101 + this.keepDocComments = keepDocComments; 4.102 + if (keepDocComments) 4.103 + docComments = new HashMap<JCTree,String>(); 4.104 + this.keepLineMap = keepLineMap; 4.105 + this.errorTree = F.Erroneous(); 4.106 + } 4.107 + 4.108 + /** Switch: Should generics be recognized? 4.109 + */ 4.110 + boolean allowGenerics; 4.111 + 4.112 + /** Switch: Should varargs be recognized? 4.113 + */ 4.114 + boolean allowVarargs; 4.115 + 4.116 + /** Switch: should we recognize assert statements, or just give a warning? 4.117 + */ 4.118 + boolean allowAsserts; 4.119 + 4.120 + /** Switch: should we recognize enums, or just give a warning? 4.121 + */ 4.122 + boolean allowEnums; 4.123 + 4.124 + /** Switch: should we recognize foreach? 4.125 + */ 4.126 + boolean allowForeach; 4.127 + 4.128 + /** Switch: should we recognize foreach? 4.129 + */ 4.130 + boolean allowStaticImport; 4.131 + 4.132 + /** Switch: should we recognize annotations? 4.133 + */ 4.134 + boolean allowAnnotations; 4.135 + 4.136 + /** Switch: should we keep docComments? 4.137 + */ 4.138 + boolean keepDocComments; 4.139 + 4.140 + /** Switch: should we keep line table? 4.141 + */ 4.142 + boolean keepLineMap; 4.143 + 4.144 + /** When terms are parsed, the mode determines which is expected: 4.145 + * mode = EXPR : an expression 4.146 + * mode = TYPE : a type 4.147 + * mode = NOPARAMS : no parameters allowed for type 4.148 + * mode = TYPEARG : type argument 4.149 + */ 4.150 + static final int EXPR = 1; 4.151 + static final int TYPE = 2; 4.152 + static final int NOPARAMS = 4; 4.153 + static final int TYPEARG = 8; 4.154 + 4.155 + /** The current mode. 4.156 + */ 4.157 + private int mode = 0; 4.158 + 4.159 + /** The mode of the term that was parsed last. 4.160 + */ 4.161 + private int lastmode = 0; 4.162 + 4.163 +/* ---------- error recovery -------------- */ 4.164 + 4.165 + private JCErroneous errorTree; 4.166 + 4.167 + /** Skip forward until a suitable stop token is found. 4.168 + */ 4.169 + private void skip(boolean stopAtImport, boolean stopAtMemberDecl, boolean stopAtIdentifier, boolean stopAtStatement) { 4.170 + while (true) { 4.171 + switch (S.token()) { 4.172 + case SEMI: 4.173 + S.nextToken(); 4.174 + return; 4.175 + case PUBLIC: 4.176 + case FINAL: 4.177 + case ABSTRACT: 4.178 + case MONKEYS_AT: 4.179 + case EOF: 4.180 + case CLASS: 4.181 + case INTERFACE: 4.182 + case ENUM: 4.183 + return; 4.184 + case IMPORT: 4.185 + if (stopAtImport) 4.186 + return; 4.187 + break; 4.188 + case LBRACE: 4.189 + case RBRACE: 4.190 + case PRIVATE: 4.191 + case PROTECTED: 4.192 + case STATIC: 4.193 + case TRANSIENT: 4.194 + case NATIVE: 4.195 + case VOLATILE: 4.196 + case SYNCHRONIZED: 4.197 + case STRICTFP: 4.198 + case LT: 4.199 + case BYTE: 4.200 + case SHORT: 4.201 + case CHAR: 4.202 + case INT: 4.203 + case LONG: 4.204 + case FLOAT: 4.205 + case DOUBLE: 4.206 + case BOOLEAN: 4.207 + case VOID: 4.208 + if (stopAtMemberDecl) 4.209 + return; 4.210 + break; 4.211 + case IDENTIFIER: 4.212 + if (stopAtIdentifier) 4.213 + return; 4.214 + break; 4.215 + case CASE: 4.216 + case DEFAULT: 4.217 + case IF: 4.218 + case FOR: 4.219 + case WHILE: 4.220 + case DO: 4.221 + case TRY: 4.222 + case SWITCH: 4.223 + case RETURN: 4.224 + case THROW: 4.225 + case BREAK: 4.226 + case CONTINUE: 4.227 + case ELSE: 4.228 + case FINALLY: 4.229 + case CATCH: 4.230 + if (stopAtStatement) 4.231 + return; 4.232 + break; 4.233 + } 4.234 + S.nextToken(); 4.235 + } 4.236 + } 4.237 + 4.238 + private JCErroneous syntaxError(int pos, String key, Token... args) { 4.239 + return syntaxError(pos, null, key, args); 4.240 + } 4.241 + 4.242 + private JCErroneous syntaxError(int pos, List<JCTree> errs, String key, Token... args) { 4.243 + setErrorEndPos(pos); 4.244 + reportSyntaxError(pos, key, (Object[])args); 4.245 + return toP(F.at(pos).Erroneous(errs)); 4.246 + } 4.247 + 4.248 + private int errorPos = Position.NOPOS; 4.249 + /** 4.250 + * Report a syntax error at given position using the given 4.251 + * argument unless one was already reported at the same position. 4.252 + */ 4.253 + private void reportSyntaxError(int pos, String key, Object... args) { 4.254 + if (pos > S.errPos() || pos == Position.NOPOS) { 4.255 + if (S.token() == EOF) 4.256 + log.error(pos, "premature.eof"); 4.257 + else 4.258 + log.error(pos, key, args); 4.259 + } 4.260 + S.errPos(pos); 4.261 + if (S.pos() == errorPos) 4.262 + S.nextToken(); // guarantee progress 4.263 + errorPos = S.pos(); 4.264 + } 4.265 + 4.266 + 4.267 + /** Generate a syntax error at current position unless one was already 4.268 + * reported at the same position. 4.269 + */ 4.270 + private JCErroneous syntaxError(String key) { 4.271 + return syntaxError(S.pos(), key); 4.272 + } 4.273 + 4.274 + /** Generate a syntax error at current position unless one was 4.275 + * already reported at the same position. 4.276 + */ 4.277 + private JCErroneous syntaxError(String key, Token arg) { 4.278 + return syntaxError(S.pos(), key, arg); 4.279 + } 4.280 + 4.281 + /** If next input token matches given token, skip it, otherwise report 4.282 + * an error. 4.283 + */ 4.284 + public void accept(Token token) { 4.285 + if (S.token() == token) { 4.286 + S.nextToken(); 4.287 + } else { 4.288 + setErrorEndPos(S.pos()); 4.289 + reportSyntaxError(S.prevEndPos(), "expected", token); 4.290 + } 4.291 + } 4.292 + 4.293 + /** Report an illegal start of expression/type error at given position. 4.294 + */ 4.295 + JCExpression illegal(int pos) { 4.296 + setErrorEndPos(S.pos()); 4.297 + if ((mode & EXPR) != 0) 4.298 + return syntaxError(pos, "illegal.start.of.expr"); 4.299 + else 4.300 + return syntaxError(pos, "illegal.start.of.type"); 4.301 + 4.302 + } 4.303 + 4.304 + /** Report an illegal start of expression/type error at current position. 4.305 + */ 4.306 + JCExpression illegal() { 4.307 + return illegal(S.pos()); 4.308 + } 4.309 + 4.310 + /** Diagnose a modifier flag from the set, if any. */ 4.311 + void checkNoMods(long mods) { 4.312 + if (mods != 0) { 4.313 + long lowestMod = mods & -mods; 4.314 + log.error(S.pos(), "mod.not.allowed.here", 4.315 + Flags.asFlagSet(lowestMod)); 4.316 + } 4.317 + } 4.318 + 4.319 +/* ---------- doc comments --------- */ 4.320 + 4.321 + /** A hashtable to store all documentation comments 4.322 + * indexed by the tree nodes they refer to. 4.323 + * defined only if option flag keepDocComment is set. 4.324 + */ 4.325 + Map<JCTree, String> docComments; 4.326 + 4.327 + /** Make an entry into docComments hashtable, 4.328 + * provided flag keepDocComments is set and given doc comment is non-null. 4.329 + * @param tree The tree to be used as index in the hashtable 4.330 + * @param dc The doc comment to associate with the tree, or null. 4.331 + */ 4.332 + void attach(JCTree tree, String dc) { 4.333 + if (keepDocComments && dc != null) { 4.334 +// System.out.println("doc comment = ");System.out.println(dc);//DEBUG 4.335 + docComments.put(tree, dc); 4.336 + } 4.337 + } 4.338 + 4.339 +/* -------- source positions ------- */ 4.340 + 4.341 + private int errorEndPos = -1; 4.342 + 4.343 + private void setErrorEndPos(int errPos) { 4.344 + if (errPos > errorEndPos) 4.345 + errorEndPos = errPos; 4.346 + } 4.347 + 4.348 + protected int getErrorEndPos() { 4.349 + return errorEndPos; 4.350 + } 4.351 + 4.352 + /** 4.353 + * Store ending position for a tree. 4.354 + * @param tree The tree. 4.355 + * @param endpos The ending position to associate with the tree. 4.356 + */ 4.357 + protected void storeEnd(JCTree tree, int endpos) {} 4.358 + 4.359 + /** 4.360 + * Store ending position for a tree. The ending position should 4.361 + * be the ending position of the current token. 4.362 + * @param t The tree. 4.363 + */ 4.364 + protected <T extends JCTree> T to(T t) { return t; } 4.365 + 4.366 + /** 4.367 + * Store ending position for a tree. The ending position should 4.368 + * be greater of the ending position of the previous token and errorEndPos. 4.369 + * @param t The tree. 4.370 + */ 4.371 + protected <T extends JCTree> T toP(T t) { return t; } 4.372 + 4.373 + /** Get the start position for a tree node. The start position is 4.374 + * defined to be the position of the first character of the first 4.375 + * token of the node's source text. 4.376 + * @param tree The tree node 4.377 + */ 4.378 + public int getStartPos(JCTree tree) { 4.379 + return TreeInfo.getStartPos(tree); 4.380 + } 4.381 + 4.382 + /** 4.383 + * Get the end position for a tree node. The end position is 4.384 + * defined to be the position of the last character of the last 4.385 + * token of the node's source text. Returns Position.NOPOS if end 4.386 + * positions are not generated or the position is otherwise not 4.387 + * found. 4.388 + * @param tree The tree node 4.389 + */ 4.390 + public int getEndPos(JCTree tree) { 4.391 + return Position.NOPOS; 4.392 + } 4.393 + 4.394 + 4.395 + 4.396 +/* ---------- parsing -------------- */ 4.397 + 4.398 + /** 4.399 + * Ident = IDENTIFIER 4.400 + */ 4.401 + Name ident() { 4.402 + if (S.token() == IDENTIFIER) { 4.403 + Name name = S.name(); 4.404 + S.nextToken(); 4.405 + return name; 4.406 + } else if (S.token() == ASSERT) { 4.407 + if (allowAsserts) { 4.408 + log.error(S.pos(), "assert.as.identifier"); 4.409 + S.nextToken(); 4.410 + return names.error; 4.411 + } else { 4.412 + log.warning(S.pos(), "assert.as.identifier"); 4.413 + Name name = S.name(); 4.414 + S.nextToken(); 4.415 + return name; 4.416 + } 4.417 + } else if (S.token() == ENUM) { 4.418 + if (allowEnums) { 4.419 + log.error(S.pos(), "enum.as.identifier"); 4.420 + S.nextToken(); 4.421 + return names.error; 4.422 + } else { 4.423 + log.warning(S.pos(), "enum.as.identifier"); 4.424 + Name name = S.name(); 4.425 + S.nextToken(); 4.426 + return name; 4.427 + } 4.428 + } else { 4.429 + accept(IDENTIFIER); 4.430 + return names.error; 4.431 + } 4.432 +} 4.433 + 4.434 + /** 4.435 + * Qualident = Ident { DOT Ident } 4.436 + */ 4.437 + public JCExpression qualident() { 4.438 + JCExpression t = toP(F.at(S.pos()).Ident(ident())); 4.439 + while (S.token() == DOT) { 4.440 + int pos = S.pos(); 4.441 + S.nextToken(); 4.442 + t = toP(F.at(pos).Select(t, ident())); 4.443 + } 4.444 + return t; 4.445 + } 4.446 + 4.447 + /** 4.448 + * Literal = 4.449 + * INTLITERAL 4.450 + * | LONGLITERAL 4.451 + * | FLOATLITERAL 4.452 + * | DOUBLELITERAL 4.453 + * | CHARLITERAL 4.454 + * | STRINGLITERAL 4.455 + * | TRUE 4.456 + * | FALSE 4.457 + * | NULL 4.458 + */ 4.459 + JCExpression literal(Name prefix) { 4.460 + int pos = S.pos(); 4.461 + JCExpression t = errorTree; 4.462 + switch (S.token()) { 4.463 + case INTLITERAL: 4.464 + try { 4.465 + t = F.at(pos).Literal( 4.466 + TypeTags.INT, 4.467 + Convert.string2int(strval(prefix), S.radix())); 4.468 + } catch (NumberFormatException ex) { 4.469 + log.error(S.pos(), "int.number.too.large", strval(prefix)); 4.470 + } 4.471 + break; 4.472 + case LONGLITERAL: 4.473 + try { 4.474 + t = F.at(pos).Literal( 4.475 + TypeTags.LONG, 4.476 + new Long(Convert.string2long(strval(prefix), S.radix()))); 4.477 + } catch (NumberFormatException ex) { 4.478 + log.error(S.pos(), "int.number.too.large", strval(prefix)); 4.479 + } 4.480 + break; 4.481 + case FLOATLITERAL: { 4.482 + String proper = (S.radix() == 16 ? ("0x"+ S.stringVal()) : S.stringVal()); 4.483 + Float n; 4.484 + try { 4.485 + n = Float.valueOf(proper); 4.486 + } catch (NumberFormatException ex) { 4.487 + // error already repoted in scanner 4.488 + n = Float.NaN; 4.489 + } 4.490 + if (n.floatValue() == 0.0f && !isZero(proper)) 4.491 + log.error(S.pos(), "fp.number.too.small"); 4.492 + else if (n.floatValue() == Float.POSITIVE_INFINITY) 4.493 + log.error(S.pos(), "fp.number.too.large"); 4.494 + else 4.495 + t = F.at(pos).Literal(TypeTags.FLOAT, n); 4.496 + break; 4.497 + } 4.498 + case DOUBLELITERAL: { 4.499 + String proper = (S.radix() == 16 ? ("0x"+ S.stringVal()) : S.stringVal()); 4.500 + Double n; 4.501 + try { 4.502 + n = Double.valueOf(proper); 4.503 + } catch (NumberFormatException ex) { 4.504 + // error already reported in scanner 4.505 + n = Double.NaN; 4.506 + } 4.507 + if (n.doubleValue() == 0.0d && !isZero(proper)) 4.508 + log.error(S.pos(), "fp.number.too.small"); 4.509 + else if (n.doubleValue() == Double.POSITIVE_INFINITY) 4.510 + log.error(S.pos(), "fp.number.too.large"); 4.511 + else 4.512 + t = F.at(pos).Literal(TypeTags.DOUBLE, n); 4.513 + break; 4.514 + } 4.515 + case CHARLITERAL: 4.516 + t = F.at(pos).Literal( 4.517 + TypeTags.CHAR, 4.518 + S.stringVal().charAt(0) + 0); 4.519 + break; 4.520 + case STRINGLITERAL: 4.521 + t = F.at(pos).Literal( 4.522 + TypeTags.CLASS, 4.523 + S.stringVal()); 4.524 + break; 4.525 + case TRUE: case FALSE: 4.526 + t = F.at(pos).Literal( 4.527 + TypeTags.BOOLEAN, 4.528 + (S.token() == TRUE ? 1 : 0)); 4.529 + break; 4.530 + case NULL: 4.531 + t = F.at(pos).Literal( 4.532 + TypeTags.BOT, 4.533 + null); 4.534 + break; 4.535 + default: 4.536 + assert false; 4.537 + } 4.538 + if (t == errorTree) 4.539 + t = F.at(pos).Erroneous(); 4.540 + storeEnd(t, S.endPos()); 4.541 + S.nextToken(); 4.542 + return t; 4.543 + } 4.544 +//where 4.545 + boolean isZero(String s) { 4.546 + char[] cs = s.toCharArray(); 4.547 + int base = ((Character.toLowerCase(s.charAt(1)) == 'x') ? 16 : 10); 4.548 + int i = ((base==16) ? 2 : 0); 4.549 + while (i < cs.length && (cs[i] == '0' || cs[i] == '.')) i++; 4.550 + return !(i < cs.length && (Character.digit(cs[i], base) > 0)); 4.551 + } 4.552 + 4.553 + String strval(Name prefix) { 4.554 + String s = S.stringVal(); 4.555 + return (prefix.len == 0) ? s : prefix + s; 4.556 + } 4.557 + 4.558 + /** terms can be either expressions or types. 4.559 + */ 4.560 + public JCExpression parseExpression() { 4.561 + return term(EXPR); 4.562 + } 4.563 + 4.564 + public JCExpression parseType() { 4.565 + return term(TYPE); 4.566 + } 4.567 + 4.568 + JCExpression term(int newmode) { 4.569 + int prevmode = mode; 4.570 + mode = newmode; 4.571 + JCExpression t = term(); 4.572 + lastmode = mode; 4.573 + mode = prevmode; 4.574 + return t; 4.575 + } 4.576 + 4.577 + /** 4.578 + * Expression = Expression1 [ExpressionRest] 4.579 + * ExpressionRest = [AssignmentOperator Expression1] 4.580 + * AssignmentOperator = "=" | "+=" | "-=" | "*=" | "/=" | 4.581 + * "&=" | "|=" | "^=" | 4.582 + * "%=" | "<<=" | ">>=" | ">>>=" 4.583 + * Type = Type1 4.584 + * TypeNoParams = TypeNoParams1 4.585 + * StatementExpression = Expression 4.586 + * ConstantExpression = Expression 4.587 + */ 4.588 + JCExpression term() { 4.589 + JCExpression t = term1(); 4.590 + if ((mode & EXPR) != 0 && 4.591 + S.token() == EQ || PLUSEQ.compareTo(S.token()) <= 0 && S.token().compareTo(GTGTGTEQ) <= 0) 4.592 + return termRest(t); 4.593 + else 4.594 + return t; 4.595 + } 4.596 + 4.597 + JCExpression termRest(JCExpression t) { 4.598 + switch (S.token()) { 4.599 + case EQ: { 4.600 + int pos = S.pos(); 4.601 + S.nextToken(); 4.602 + mode = EXPR; 4.603 + JCExpression t1 = term(); 4.604 + return toP(F.at(pos).Assign(t, t1)); 4.605 + } 4.606 + case PLUSEQ: 4.607 + case SUBEQ: 4.608 + case STAREQ: 4.609 + case SLASHEQ: 4.610 + case PERCENTEQ: 4.611 + case AMPEQ: 4.612 + case BAREQ: 4.613 + case CARETEQ: 4.614 + case LTLTEQ: 4.615 + case GTGTEQ: 4.616 + case GTGTGTEQ: 4.617 + int pos = S.pos(); 4.618 + Token token = S.token(); 4.619 + S.nextToken(); 4.620 + mode = EXPR; 4.621 + JCExpression t1 = term(); 4.622 + return F.at(pos).Assignop(optag(token), t, t1); 4.623 + default: 4.624 + return t; 4.625 + } 4.626 + } 4.627 + 4.628 + /** Expression1 = Expression2 [Expression1Rest] 4.629 + * Type1 = Type2 4.630 + * TypeNoParams1 = TypeNoParams2 4.631 + */ 4.632 + JCExpression term1() { 4.633 + JCExpression t = term2(); 4.634 + if ((mode & EXPR) != 0 && S.token() == QUES) { 4.635 + mode = EXPR; 4.636 + return term1Rest(t); 4.637 + } else { 4.638 + return t; 4.639 + } 4.640 + } 4.641 + 4.642 + /** Expression1Rest = ["?" Expression ":" Expression1] 4.643 + */ 4.644 + JCExpression term1Rest(JCExpression t) { 4.645 + if (S.token() == QUES) { 4.646 + int pos = S.pos(); 4.647 + S.nextToken(); 4.648 + JCExpression t1 = term(); 4.649 + accept(COLON); 4.650 + JCExpression t2 = term1(); 4.651 + return F.at(pos).Conditional(t, t1, t2); 4.652 + } else { 4.653 + return t; 4.654 + } 4.655 + } 4.656 + 4.657 + /** Expression2 = Expression3 [Expression2Rest] 4.658 + * Type2 = Type3 4.659 + * TypeNoParams2 = TypeNoParams3 4.660 + */ 4.661 + JCExpression term2() { 4.662 + JCExpression t = term3(); 4.663 + if ((mode & EXPR) != 0 && prec(S.token()) >= TreeInfo.orPrec) { 4.664 + mode = EXPR; 4.665 + return term2Rest(t, TreeInfo.orPrec); 4.666 + } else { 4.667 + return t; 4.668 + } 4.669 + } 4.670 + 4.671 + /* Expression2Rest = {infixop Expression3} 4.672 + * | Expression3 instanceof Type 4.673 + * infixop = "||" 4.674 + * | "&&" 4.675 + * | "|" 4.676 + * | "^" 4.677 + * | "&" 4.678 + * | "==" | "!=" 4.679 + * | "<" | ">" | "<=" | ">=" 4.680 + * | "<<" | ">>" | ">>>" 4.681 + * | "+" | "-" 4.682 + * | "*" | "/" | "%" 4.683 + */ 4.684 + JCExpression term2Rest(JCExpression t, int minprec) { 4.685 + List<JCExpression[]> savedOd = odStackSupply.elems; 4.686 + JCExpression[] odStack = newOdStack(); 4.687 + List<Token[]> savedOp = opStackSupply.elems; 4.688 + Token[] opStack = newOpStack(); 4.689 + // optimization, was odStack = new Tree[...]; opStack = new Tree[...]; 4.690 + int top = 0; 4.691 + odStack[0] = t; 4.692 + int startPos = S.pos(); 4.693 + Token topOp = ERROR; 4.694 + while (prec(S.token()) >= minprec) { 4.695 + opStack[top] = topOp; 4.696 + top++; 4.697 + topOp = S.token(); 4.698 + int pos = S.pos(); 4.699 + S.nextToken(); 4.700 + odStack[top] = topOp == INSTANCEOF ? parseType() : term3(); 4.701 + while (top > 0 && prec(topOp) >= prec(S.token())) { 4.702 + odStack[top-1] = makeOp(pos, topOp, odStack[top-1], 4.703 + odStack[top]); 4.704 + top--; 4.705 + topOp = opStack[top]; 4.706 + } 4.707 + } 4.708 + assert top == 0; 4.709 + t = odStack[0]; 4.710 + 4.711 + if (t.getTag() == JCTree.PLUS) { 4.712 + StringBuffer buf = foldStrings(t); 4.713 + if (buf != null) { 4.714 + t = toP(F.at(startPos).Literal(TypeTags.CLASS, buf.toString())); 4.715 + } 4.716 + } 4.717 + 4.718 + odStackSupply.elems = savedOd; // optimization 4.719 + opStackSupply.elems = savedOp; // optimization 4.720 + return t; 4.721 + } 4.722 +//where 4.723 + /** Construct a binary or type test node. 4.724 + */ 4.725 + private JCExpression makeOp(int pos, 4.726 + Token topOp, 4.727 + JCExpression od1, 4.728 + JCExpression od2) 4.729 + { 4.730 + if (topOp == INSTANCEOF) { 4.731 + return F.at(pos).TypeTest(od1, od2); 4.732 + } else { 4.733 + return F.at(pos).Binary(optag(topOp), od1, od2); 4.734 + } 4.735 + } 4.736 + /** If tree is a concatenation of string literals, replace it 4.737 + * by a single literal representing the concatenated string. 4.738 + */ 4.739 + protected StringBuffer foldStrings(JCTree tree) { 4.740 + List<String> buf = List.nil(); 4.741 + while (true) { 4.742 + if (tree.getTag() == JCTree.LITERAL) { 4.743 + JCLiteral lit = (JCLiteral) tree; 4.744 + if (lit.typetag == TypeTags.CLASS) { 4.745 + StringBuffer sbuf = 4.746 + new StringBuffer((String)lit.value); 4.747 + while (buf.nonEmpty()) { 4.748 + sbuf.append(buf.head); 4.749 + buf = buf.tail; 4.750 + } 4.751 + return sbuf; 4.752 + } 4.753 + } else if (tree.getTag() == JCTree.PLUS) { 4.754 + JCBinary op = (JCBinary)tree; 4.755 + if (op.rhs.getTag() == JCTree.LITERAL) { 4.756 + JCLiteral lit = (JCLiteral) op.rhs; 4.757 + if (lit.typetag == TypeTags.CLASS) { 4.758 + buf = buf.prepend((String) lit.value); 4.759 + tree = op.lhs; 4.760 + continue; 4.761 + } 4.762 + } 4.763 + } 4.764 + return null; 4.765 + } 4.766 + } 4.767 + 4.768 + /** optimization: To save allocating a new operand/operator stack 4.769 + * for every binary operation, we use supplys. 4.770 + */ 4.771 + ListBuffer<JCExpression[]> odStackSupply = new ListBuffer<JCExpression[]>(); 4.772 + ListBuffer<Token[]> opStackSupply = new ListBuffer<Token[]>(); 4.773 + 4.774 + private JCExpression[] newOdStack() { 4.775 + if (odStackSupply.elems == odStackSupply.last) 4.776 + odStackSupply.append(new JCExpression[infixPrecedenceLevels + 1]); 4.777 + JCExpression[] odStack = odStackSupply.elems.head; 4.778 + odStackSupply.elems = odStackSupply.elems.tail; 4.779 + return odStack; 4.780 + } 4.781 + 4.782 + private Token[] newOpStack() { 4.783 + if (opStackSupply.elems == opStackSupply.last) 4.784 + opStackSupply.append(new Token[infixPrecedenceLevels + 1]); 4.785 + Token[] opStack = opStackSupply.elems.head; 4.786 + opStackSupply.elems = opStackSupply.elems.tail; 4.787 + return opStack; 4.788 + } 4.789 + 4.790 + /** Expression3 = PrefixOp Expression3 4.791 + * | "(" Expr | TypeNoParams ")" Expression3 4.792 + * | Primary {Selector} {PostfixOp} 4.793 + * Primary = "(" Expression ")" 4.794 + * | Literal 4.795 + * | [TypeArguments] THIS [Arguments] 4.796 + * | [TypeArguments] SUPER SuperSuffix 4.797 + * | NEW [TypeArguments] Creator 4.798 + * | Ident { "." Ident } 4.799 + * [ "[" ( "]" BracketsOpt "." CLASS | Expression "]" ) 4.800 + * | Arguments 4.801 + * | "." ( CLASS | THIS | [TypeArguments] SUPER Arguments | NEW [TypeArguments] InnerCreator ) 4.802 + * ] 4.803 + * | BasicType BracketsOpt "." CLASS 4.804 + * PrefixOp = "++" | "--" | "!" | "~" | "+" | "-" 4.805 + * PostfixOp = "++" | "--" 4.806 + * Type3 = Ident { "." Ident } [TypeArguments] {TypeSelector} BracketsOpt 4.807 + * | BasicType 4.808 + * TypeNoParams3 = Ident { "." Ident } BracketsOpt 4.809 + * Selector = "." [TypeArguments] Ident [Arguments] 4.810 + * | "." THIS 4.811 + * | "." [TypeArguments] SUPER SuperSuffix 4.812 + * | "." NEW [TypeArguments] InnerCreator 4.813 + * | "[" Expression "]" 4.814 + * TypeSelector = "." Ident [TypeArguments] 4.815 + * SuperSuffix = Arguments | "." Ident [Arguments] 4.816 + */ 4.817 + protected JCExpression term3() { 4.818 + int pos = S.pos(); 4.819 + JCExpression t; 4.820 + List<JCExpression> typeArgs = typeArgumentsOpt(EXPR); 4.821 + switch (S.token()) { 4.822 + case QUES: 4.823 + if ((mode & TYPE) != 0 && (mode & (TYPEARG|NOPARAMS)) == TYPEARG) { 4.824 + mode = TYPE; 4.825 + return typeArgument(); 4.826 + } else 4.827 + return illegal(); 4.828 + case PLUSPLUS: case SUBSUB: case BANG: case TILDE: case PLUS: case SUB: 4.829 + if (typeArgs == null && (mode & EXPR) != 0) { 4.830 + Token token = S.token(); 4.831 + S.nextToken(); 4.832 + mode = EXPR; 4.833 + if (token == SUB && 4.834 + (S.token() == INTLITERAL || S.token() == LONGLITERAL) && 4.835 + S.radix() == 10) { 4.836 + mode = EXPR; 4.837 + t = literal(names.hyphen); 4.838 + } else { 4.839 + t = term3(); 4.840 + return F.at(pos).Unary(unoptag(token), t); 4.841 + } 4.842 + } else return illegal(); 4.843 + break; 4.844 + case LPAREN: 4.845 + if (typeArgs == null && (mode & EXPR) != 0) { 4.846 + S.nextToken(); 4.847 + mode = EXPR | TYPE | NOPARAMS; 4.848 + t = term3(); 4.849 + if ((mode & TYPE) != 0 && S.token() == LT) { 4.850 + // Could be a cast to a parameterized type 4.851 + int op = JCTree.LT; 4.852 + int pos1 = S.pos(); 4.853 + S.nextToken(); 4.854 + mode &= (EXPR | TYPE); 4.855 + mode |= TYPEARG; 4.856 + JCExpression t1 = term3(); 4.857 + if ((mode & TYPE) != 0 && 4.858 + (S.token() == COMMA || S.token() == GT)) { 4.859 + mode = TYPE; 4.860 + ListBuffer<JCExpression> args = new ListBuffer<JCExpression>(); 4.861 + args.append(t1); 4.862 + while (S.token() == COMMA) { 4.863 + S.nextToken(); 4.864 + args.append(typeArgument()); 4.865 + } 4.866 + accept(GT); 4.867 + t = F.at(pos1).TypeApply(t, args.toList()); 4.868 + checkGenerics(); 4.869 + t = bracketsOpt(toP(t)); 4.870 + } else if ((mode & EXPR) != 0) { 4.871 + mode = EXPR; 4.872 + t = F.at(pos1).Binary(op, t, term2Rest(t1, TreeInfo.shiftPrec)); 4.873 + t = termRest(term1Rest(term2Rest(t, TreeInfo.orPrec))); 4.874 + } else { 4.875 + accept(GT); 4.876 + } 4.877 + } else { 4.878 + t = termRest(term1Rest(term2Rest(t, TreeInfo.orPrec))); 4.879 + } 4.880 + accept(RPAREN); 4.881 + lastmode = mode; 4.882 + mode = EXPR; 4.883 + if ((lastmode & EXPR) == 0) { 4.884 + JCExpression t1 = term3(); 4.885 + return F.at(pos).TypeCast(t, t1); 4.886 + } else if ((lastmode & TYPE) != 0) { 4.887 + switch (S.token()) { 4.888 + /*case PLUSPLUS: case SUBSUB: */ 4.889 + case BANG: case TILDE: 4.890 + case LPAREN: case THIS: case SUPER: 4.891 + case INTLITERAL: case LONGLITERAL: case FLOATLITERAL: 4.892 + case DOUBLELITERAL: case CHARLITERAL: case STRINGLITERAL: 4.893 + case TRUE: case FALSE: case NULL: 4.894 + case NEW: case IDENTIFIER: case ASSERT: case ENUM: 4.895 + case BYTE: case SHORT: case CHAR: case INT: 4.896 + case LONG: case FLOAT: case DOUBLE: case BOOLEAN: case VOID: 4.897 + JCExpression t1 = term3(); 4.898 + return F.at(pos).TypeCast(t, t1); 4.899 + } 4.900 + } 4.901 + } else return illegal(); 4.902 + t = toP(F.at(pos).Parens(t)); 4.903 + break; 4.904 + case THIS: 4.905 + if ((mode & EXPR) != 0) { 4.906 + mode = EXPR; 4.907 + t = to(F.at(pos).Ident(names._this)); 4.908 + S.nextToken(); 4.909 + if (typeArgs == null) 4.910 + t = argumentsOpt(null, t); 4.911 + else 4.912 + t = arguments(typeArgs, t); 4.913 + typeArgs = null; 4.914 + } else return illegal(); 4.915 + break; 4.916 + case SUPER: 4.917 + if ((mode & EXPR) != 0) { 4.918 + mode = EXPR; 4.919 + t = to(superSuffix(typeArgs, F.at(pos).Ident(names._super))); 4.920 + typeArgs = null; 4.921 + } else return illegal(); 4.922 + break; 4.923 + case INTLITERAL: case LONGLITERAL: case FLOATLITERAL: case DOUBLELITERAL: 4.924 + case CHARLITERAL: case STRINGLITERAL: 4.925 + case TRUE: case FALSE: case NULL: 4.926 + if (typeArgs == null && (mode & EXPR) != 0) { 4.927 + mode = EXPR; 4.928 + t = literal(names.empty); 4.929 + } else return illegal(); 4.930 + break; 4.931 + case NEW: 4.932 + if (typeArgs != null) return illegal(); 4.933 + if ((mode & EXPR) != 0) { 4.934 + mode = EXPR; 4.935 + S.nextToken(); 4.936 + if (S.token() == LT) typeArgs = typeArguments(); 4.937 + t = creator(pos, typeArgs); 4.938 + typeArgs = null; 4.939 + } else return illegal(); 4.940 + break; 4.941 + case IDENTIFIER: case ASSERT: case ENUM: 4.942 + if (typeArgs != null) return illegal(); 4.943 + t = toP(F.at(S.pos()).Ident(ident())); 4.944 + loop: while (true) { 4.945 + pos = S.pos(); 4.946 + switch (S.token()) { 4.947 + case LBRACKET: 4.948 + S.nextToken(); 4.949 + if (S.token() == RBRACKET) { 4.950 + S.nextToken(); 4.951 + t = bracketsOpt(t); 4.952 + t = toP(F.at(pos).TypeArray(t)); 4.953 + t = bracketsSuffix(t); 4.954 + } else { 4.955 + if ((mode & EXPR) != 0) { 4.956 + mode = EXPR; 4.957 + JCExpression t1 = term(); 4.958 + t = to(F.at(pos).Indexed(t, t1)); 4.959 + } 4.960 + accept(RBRACKET); 4.961 + } 4.962 + break loop; 4.963 + case LPAREN: 4.964 + if ((mode & EXPR) != 0) { 4.965 + mode = EXPR; 4.966 + t = arguments(typeArgs, t); 4.967 + typeArgs = null; 4.968 + } 4.969 + break loop; 4.970 + case DOT: 4.971 + S.nextToken(); 4.972 + int oldmode = mode; 4.973 + mode &= ~NOPARAMS; 4.974 + typeArgs = typeArgumentsOpt(EXPR); 4.975 + mode = oldmode; 4.976 + if ((mode & EXPR) != 0) { 4.977 + switch (S.token()) { 4.978 + case CLASS: 4.979 + if (typeArgs != null) return illegal(); 4.980 + mode = EXPR; 4.981 + t = to(F.at(pos).Select(t, names._class)); 4.982 + S.nextToken(); 4.983 + break loop; 4.984 + case THIS: 4.985 + if (typeArgs != null) return illegal(); 4.986 + mode = EXPR; 4.987 + t = to(F.at(pos).Select(t, names._this)); 4.988 + S.nextToken(); 4.989 + break loop; 4.990 + case SUPER: 4.991 + mode = EXPR; 4.992 + t = to(F.at(pos).Select(t, names._super)); 4.993 + t = superSuffix(typeArgs, t); 4.994 + typeArgs = null; 4.995 + break loop; 4.996 + case NEW: 4.997 + if (typeArgs != null) return illegal(); 4.998 + mode = EXPR; 4.999 + int pos1 = S.pos(); 4.1000 + S.nextToken(); 4.1001 + if (S.token() == LT) typeArgs = typeArguments(); 4.1002 + t = innerCreator(pos1, typeArgs, t); 4.1003 + typeArgs = null; 4.1004 + break loop; 4.1005 + } 4.1006 + } 4.1007 + // typeArgs saved for next loop iteration. 4.1008 + t = toP(F.at(pos).Select(t, ident())); 4.1009 + break; 4.1010 + default: 4.1011 + break loop; 4.1012 + } 4.1013 + } 4.1014 + if (typeArgs != null) illegal(); 4.1015 + t = typeArgumentsOpt(t); 4.1016 + break; 4.1017 + case BYTE: case SHORT: case CHAR: case INT: case LONG: case FLOAT: 4.1018 + case DOUBLE: case BOOLEAN: 4.1019 + if (typeArgs != null) illegal(); 4.1020 + t = bracketsSuffix(bracketsOpt(basicType())); 4.1021 + break; 4.1022 + case VOID: 4.1023 + if (typeArgs != null) illegal(); 4.1024 + if ((mode & EXPR) != 0) { 4.1025 + S.nextToken(); 4.1026 + if (S.token() == DOT) { 4.1027 + JCPrimitiveTypeTree ti = toP(F.at(pos).TypeIdent(TypeTags.VOID)); 4.1028 + t = bracketsSuffix(ti); 4.1029 + } else { 4.1030 + return illegal(pos); 4.1031 + } 4.1032 + } else { 4.1033 + return illegal(); 4.1034 + } 4.1035 + break; 4.1036 + default: 4.1037 + return illegal(); 4.1038 + } 4.1039 + if (typeArgs != null) illegal(); 4.1040 + while (true) { 4.1041 + int pos1 = S.pos(); 4.1042 + if (S.token() == LBRACKET) { 4.1043 + S.nextToken(); 4.1044 + if ((mode & TYPE) != 0) { 4.1045 + int oldmode = mode; 4.1046 + mode = TYPE; 4.1047 + if (S.token() == RBRACKET) { 4.1048 + S.nextToken(); 4.1049 + t = bracketsOpt(t); 4.1050 + t = toP(F.at(pos1).TypeArray(t)); 4.1051 + return t; 4.1052 + } 4.1053 + mode = oldmode; 4.1054 + } 4.1055 + if ((mode & EXPR) != 0) { 4.1056 + mode = EXPR; 4.1057 + JCExpression t1 = term(); 4.1058 + t = to(F.at(pos1).Indexed(t, t1)); 4.1059 + } 4.1060 + accept(RBRACKET); 4.1061 + } else if (S.token() == DOT) { 4.1062 + S.nextToken(); 4.1063 + typeArgs = typeArgumentsOpt(EXPR); 4.1064 + if (S.token() == SUPER && (mode & EXPR) != 0) { 4.1065 + mode = EXPR; 4.1066 + t = to(F.at(pos1).Select(t, names._super)); 4.1067 + S.nextToken(); 4.1068 + t = arguments(typeArgs, t); 4.1069 + typeArgs = null; 4.1070 + } else if (S.token() == NEW && (mode & EXPR) != 0) { 4.1071 + if (typeArgs != null) return illegal(); 4.1072 + mode = EXPR; 4.1073 + int pos2 = S.pos(); 4.1074 + S.nextToken(); 4.1075 + if (S.token() == LT) typeArgs = typeArguments(); 4.1076 + t = innerCreator(pos2, typeArgs, t); 4.1077 + typeArgs = null; 4.1078 + } else { 4.1079 + t = toP(F.at(pos1).Select(t, ident())); 4.1080 + t = argumentsOpt(typeArgs, typeArgumentsOpt(t)); 4.1081 + typeArgs = null; 4.1082 + } 4.1083 + } else { 4.1084 + break; 4.1085 + } 4.1086 + } 4.1087 + while ((S.token() == PLUSPLUS || S.token() == SUBSUB) && (mode & EXPR) != 0) { 4.1088 + mode = EXPR; 4.1089 + t = to(F.at(S.pos()).Unary( 4.1090 + S.token() == PLUSPLUS ? JCTree.POSTINC : JCTree.POSTDEC, t)); 4.1091 + S.nextToken(); 4.1092 + } 4.1093 + return toP(t); 4.1094 + } 4.1095 + 4.1096 + /** SuperSuffix = Arguments | "." [TypeArguments] Ident [Arguments] 4.1097 + */ 4.1098 + JCExpression superSuffix(List<JCExpression> typeArgs, JCExpression t) { 4.1099 + S.nextToken(); 4.1100 + if (S.token() == LPAREN || typeArgs != null) { 4.1101 + t = arguments(typeArgs, t); 4.1102 + } else { 4.1103 + int pos = S.pos(); 4.1104 + accept(DOT); 4.1105 + typeArgs = (S.token() == LT) ? typeArguments() : null; 4.1106 + t = toP(F.at(pos).Select(t, ident())); 4.1107 + t = argumentsOpt(typeArgs, t); 4.1108 + } 4.1109 + return t; 4.1110 + } 4.1111 + 4.1112 + /** BasicType = BYTE | SHORT | CHAR | INT | LONG | FLOAT | DOUBLE | BOOLEAN 4.1113 + */ 4.1114 + JCPrimitiveTypeTree basicType() { 4.1115 + JCPrimitiveTypeTree t = to(F.at(S.pos()).TypeIdent(typetag(S.token()))); 4.1116 + S.nextToken(); 4.1117 + return t; 4.1118 + } 4.1119 + 4.1120 + /** ArgumentsOpt = [ Arguments ] 4.1121 + */ 4.1122 + JCExpression argumentsOpt(List<JCExpression> typeArgs, JCExpression t) { 4.1123 + if ((mode & EXPR) != 0 && S.token() == LPAREN || typeArgs != null) { 4.1124 + mode = EXPR; 4.1125 + return arguments(typeArgs, t); 4.1126 + } else { 4.1127 + return t; 4.1128 + } 4.1129 + } 4.1130 + 4.1131 + /** Arguments = "(" [Expression { COMMA Expression }] ")" 4.1132 + */ 4.1133 + List<JCExpression> arguments() { 4.1134 + ListBuffer<JCExpression> args = lb(); 4.1135 + if (S.token() == LPAREN) { 4.1136 + S.nextToken(); 4.1137 + if (S.token() != RPAREN) { 4.1138 + args.append(parseExpression()); 4.1139 + while (S.token() == COMMA) { 4.1140 + S.nextToken(); 4.1141 + args.append(parseExpression()); 4.1142 + } 4.1143 + } 4.1144 + accept(RPAREN); 4.1145 + } else { 4.1146 + syntaxError(S.pos(), "expected", LPAREN); 4.1147 + } 4.1148 + return args.toList(); 4.1149 + } 4.1150 + 4.1151 + JCMethodInvocation arguments(List<JCExpression> typeArgs, JCExpression t) { 4.1152 + int pos = S.pos(); 4.1153 + List<JCExpression> args = arguments(); 4.1154 + return toP(F.at(pos).Apply(typeArgs, t, args)); 4.1155 + } 4.1156 + 4.1157 + /** TypeArgumentsOpt = [ TypeArguments ] 4.1158 + */ 4.1159 + JCExpression typeArgumentsOpt(JCExpression t) { 4.1160 + if (S.token() == LT && 4.1161 + (mode & TYPE) != 0 && 4.1162 + (mode & NOPARAMS) == 0) { 4.1163 + mode = TYPE; 4.1164 + checkGenerics(); 4.1165 + return typeArguments(t); 4.1166 + } else { 4.1167 + return t; 4.1168 + } 4.1169 + } 4.1170 + List<JCExpression> typeArgumentsOpt() { 4.1171 + return typeArgumentsOpt(TYPE); 4.1172 + } 4.1173 + 4.1174 + List<JCExpression> typeArgumentsOpt(int useMode) { 4.1175 + if (S.token() == LT) { 4.1176 + checkGenerics(); 4.1177 + if ((mode & useMode) == 0 || 4.1178 + (mode & NOPARAMS) != 0) { 4.1179 + illegal(); 4.1180 + } 4.1181 + mode = useMode; 4.1182 + return typeArguments(); 4.1183 + } 4.1184 + return null; 4.1185 + } 4.1186 + 4.1187 + /** TypeArguments = "<" TypeArgument {"," TypeArgument} ">" 4.1188 + */ 4.1189 + List<JCExpression> typeArguments() { 4.1190 + ListBuffer<JCExpression> args = lb(); 4.1191 + if (S.token() == LT) { 4.1192 + S.nextToken(); 4.1193 + args.append(((mode & EXPR) == 0) ? typeArgument() : parseType()); 4.1194 + while (S.token() == COMMA) { 4.1195 + S.nextToken(); 4.1196 + args.append(((mode & EXPR) == 0) ? typeArgument() : parseType()); 4.1197 + } 4.1198 + switch (S.token()) { 4.1199 + case GTGTGTEQ: 4.1200 + S.token(GTGTEQ); 4.1201 + break; 4.1202 + case GTGTEQ: 4.1203 + S.token(GTEQ); 4.1204 + break; 4.1205 + case GTEQ: 4.1206 + S.token(EQ); 4.1207 + break; 4.1208 + case GTGTGT: 4.1209 + S.token(GTGT); 4.1210 + break; 4.1211 + case GTGT: 4.1212 + S.token(GT); 4.1213 + break; 4.1214 + default: 4.1215 + accept(GT); 4.1216 + break; 4.1217 + } 4.1218 + } else { 4.1219 + syntaxError(S.pos(), "expected", LT); 4.1220 + } 4.1221 + return args.toList(); 4.1222 + } 4.1223 + 4.1224 + /** TypeArgument = Type 4.1225 + * | "?" 4.1226 + * | "?" EXTENDS Type {"&" Type} 4.1227 + * | "?" SUPER Type 4.1228 + */ 4.1229 + JCExpression typeArgument() { 4.1230 + if (S.token() != QUES) return parseType(); 4.1231 + int pos = S.pos(); 4.1232 + S.nextToken(); 4.1233 + if (S.token() == EXTENDS) { 4.1234 + TypeBoundKind t = to(F.at(S.pos()).TypeBoundKind(BoundKind.EXTENDS)); 4.1235 + S.nextToken(); 4.1236 + return F.at(pos).Wildcard(t, parseType()); 4.1237 + } else if (S.token() == SUPER) { 4.1238 + TypeBoundKind t = to(F.at(S.pos()).TypeBoundKind(BoundKind.SUPER)); 4.1239 + S.nextToken(); 4.1240 + return F.at(pos).Wildcard(t, parseType()); 4.1241 + } else if (S.token() == IDENTIFIER) { 4.1242 + //error recovery 4.1243 + reportSyntaxError(S.prevEndPos(), "expected3", 4.1244 + GT, EXTENDS, SUPER); 4.1245 + TypeBoundKind t = F.at(Position.NOPOS).TypeBoundKind(BoundKind.UNBOUND); 4.1246 + JCExpression wc = toP(F.at(pos).Wildcard(t, null)); 4.1247 + JCIdent id = toP(F.at(S.pos()).Ident(ident())); 4.1248 + return F.at(pos).Erroneous(List.<JCTree>of(wc, id)); 4.1249 + } else { 4.1250 + TypeBoundKind t = F.at(Position.NOPOS).TypeBoundKind(BoundKind.UNBOUND); 4.1251 + return toP(F.at(pos).Wildcard(t, null)); 4.1252 + } 4.1253 + } 4.1254 + 4.1255 + JCTypeApply typeArguments(JCExpression t) { 4.1256 + int pos = S.pos(); 4.1257 + List<JCExpression> args = typeArguments(); 4.1258 + return toP(F.at(pos).TypeApply(t, args)); 4.1259 + } 4.1260 + 4.1261 + /** BracketsOpt = {"[" "]"} 4.1262 + */ 4.1263 + private JCExpression bracketsOpt(JCExpression t) { 4.1264 + if (S.token() == LBRACKET) { 4.1265 + int pos = S.pos(); 4.1266 + S.nextToken(); 4.1267 + t = bracketsOptCont(t, pos); 4.1268 + F.at(pos); 4.1269 + } 4.1270 + return t; 4.1271 + } 4.1272 + 4.1273 + private JCArrayTypeTree bracketsOptCont(JCExpression t, int pos) { 4.1274 + accept(RBRACKET); 4.1275 + t = bracketsOpt(t); 4.1276 + return toP(F.at(pos).TypeArray(t)); 4.1277 + } 4.1278 + 4.1279 + /** BracketsSuffixExpr = "." CLASS 4.1280 + * BracketsSuffixType = 4.1281 + */ 4.1282 + JCExpression bracketsSuffix(JCExpression t) { 4.1283 + if ((mode & EXPR) != 0 && S.token() == DOT) { 4.1284 + mode = EXPR; 4.1285 + int pos = S.pos(); 4.1286 + S.nextToken(); 4.1287 + accept(CLASS); 4.1288 + if (S.pos() == errorEndPos) { 4.1289 + // error recovery 4.1290 + Name name = null; 4.1291 + if (S.token() == IDENTIFIER) { 4.1292 + name = S.name(); 4.1293 + S.nextToken(); 4.1294 + } else { 4.1295 + name = names.error; 4.1296 + } 4.1297 + t = F.at(pos).Erroneous(List.<JCTree>of(toP(F.at(pos).Select(t, name)))); 4.1298 + } else { 4.1299 + t = toP(F.at(pos).Select(t, names._class)); 4.1300 + } 4.1301 + } else if ((mode & TYPE) != 0) { 4.1302 + mode = TYPE; 4.1303 + } else { 4.1304 + syntaxError(S.pos(), "dot.class.expected"); 4.1305 + } 4.1306 + return t; 4.1307 + } 4.1308 + 4.1309 + /** Creator = Qualident [TypeArguments] ( ArrayCreatorRest | ClassCreatorRest ) 4.1310 + */ 4.1311 + JCExpression creator(int newpos, List<JCExpression> typeArgs) { 4.1312 + switch (S.token()) { 4.1313 + case BYTE: case SHORT: case CHAR: case INT: case LONG: case FLOAT: 4.1314 + case DOUBLE: case BOOLEAN: 4.1315 + if (typeArgs == null) 4.1316 + return arrayCreatorRest(newpos, basicType()); 4.1317 + break; 4.1318 + default: 4.1319 + } 4.1320 + JCExpression t = qualident(); 4.1321 + int oldmode = mode; 4.1322 + mode = TYPE; 4.1323 + if (S.token() == LT) { 4.1324 + checkGenerics(); 4.1325 + t = typeArguments(t); 4.1326 + } 4.1327 + while (S.token() == DOT) { 4.1328 + int pos = S.pos(); 4.1329 + S.nextToken(); 4.1330 + t = toP(F.at(pos).Select(t, ident())); 4.1331 + if (S.token() == LT) { 4.1332 + checkGenerics(); 4.1333 + t = typeArguments(t); 4.1334 + } 4.1335 + } 4.1336 + mode = oldmode; 4.1337 + if (S.token() == LBRACKET) { 4.1338 + JCExpression e = arrayCreatorRest(newpos, t); 4.1339 + if (typeArgs != null) { 4.1340 + int pos = newpos; 4.1341 + if (!typeArgs.isEmpty() && typeArgs.head.pos != Position.NOPOS) { 4.1342 + // note: this should always happen but we should 4.1343 + // not rely on this as the parser is continuously 4.1344 + // modified to improve error recovery. 4.1345 + pos = typeArgs.head.pos; 4.1346 + } 4.1347 + setErrorEndPos(S.prevEndPos()); 4.1348 + reportSyntaxError(pos, "cannot.create.array.with.type.arguments"); 4.1349 + return toP(F.at(newpos).Erroneous(typeArgs.prepend(e))); 4.1350 + } 4.1351 + return e; 4.1352 + } else if (S.token() == LPAREN) { 4.1353 + return classCreatorRest(newpos, null, typeArgs, t); 4.1354 + } else { 4.1355 + reportSyntaxError(S.pos(), "expected2", 4.1356 + LPAREN, LBRACKET); 4.1357 + t = toP(F.at(newpos).NewClass(null, typeArgs, t, List.<JCExpression>nil(), null)); 4.1358 + return toP(F.at(newpos).Erroneous(List.<JCTree>of(t))); 4.1359 + } 4.1360 + } 4.1361 + 4.1362 + /** InnerCreator = Ident [TypeArguments] ClassCreatorRest 4.1363 + */ 4.1364 + JCExpression innerCreator(int newpos, List<JCExpression> typeArgs, JCExpression encl) { 4.1365 + JCExpression t = toP(F.at(S.pos()).Ident(ident())); 4.1366 + if (S.token() == LT) { 4.1367 + checkGenerics(); 4.1368 + t = typeArguments(t); 4.1369 + } 4.1370 + return classCreatorRest(newpos, encl, typeArgs, t); 4.1371 + } 4.1372 + 4.1373 + /** ArrayCreatorRest = "[" ( "]" BracketsOpt ArrayInitializer 4.1374 + * | Expression "]" {"[" Expression "]"} BracketsOpt ) 4.1375 + */ 4.1376 + JCExpression arrayCreatorRest(int newpos, JCExpression elemtype) { 4.1377 + accept(LBRACKET); 4.1378 + if (S.token() == RBRACKET) { 4.1379 + accept(RBRACKET); 4.1380 + elemtype = bracketsOpt(elemtype); 4.1381 + if (S.token() == LBRACE) { 4.1382 + return arrayInitializer(newpos, elemtype); 4.1383 + } else { 4.1384 + return syntaxError(S.pos(), "array.dimension.missing"); 4.1385 + } 4.1386 + } else { 4.1387 + ListBuffer<JCExpression> dims = new ListBuffer<JCExpression>(); 4.1388 + dims.append(parseExpression()); 4.1389 + accept(RBRACKET); 4.1390 + while (S.token() == LBRACKET) { 4.1391 + int pos = S.pos(); 4.1392 + S.nextToken(); 4.1393 + if (S.token() == RBRACKET) { 4.1394 + elemtype = bracketsOptCont(elemtype, pos); 4.1395 + } else { 4.1396 + dims.append(parseExpression()); 4.1397 + accept(RBRACKET); 4.1398 + } 4.1399 + } 4.1400 + return toP(F.at(newpos).NewArray(elemtype, dims.toList(), null)); 4.1401 + } 4.1402 + } 4.1403 + 4.1404 + /** ClassCreatorRest = Arguments [ClassBody] 4.1405 + */ 4.1406 + JCExpression classCreatorRest(int newpos, 4.1407 + JCExpression encl, 4.1408 + List<JCExpression> typeArgs, 4.1409 + JCExpression t) 4.1410 + { 4.1411 + List<JCExpression> args = arguments(); 4.1412 + JCClassDecl body = null; 4.1413 + if (S.token() == LBRACE) { 4.1414 + int pos = S.pos(); 4.1415 + List<JCTree> defs = classOrInterfaceBody(names.empty, false); 4.1416 + JCModifiers mods = F.at(Position.NOPOS).Modifiers(0); 4.1417 + body = toP(F.at(pos).AnonymousClassDef(mods, defs)); 4.1418 + } 4.1419 + return toP(F.at(newpos).NewClass(encl, typeArgs, t, args, body)); 4.1420 + } 4.1421 + 4.1422 + /** ArrayInitializer = "{" [VariableInitializer {"," VariableInitializer}] [","] "}" 4.1423 + */ 4.1424 + JCExpression arrayInitializer(int newpos, JCExpression t) { 4.1425 + accept(LBRACE); 4.1426 + ListBuffer<JCExpression> elems = new ListBuffer<JCExpression>(); 4.1427 + if (S.token() == COMMA) { 4.1428 + S.nextToken(); 4.1429 + } else if (S.token() != RBRACE) { 4.1430 + elems.append(variableInitializer()); 4.1431 + while (S.token() == COMMA) { 4.1432 + S.nextToken(); 4.1433 + if (S.token() == RBRACE) break; 4.1434 + elems.append(variableInitializer()); 4.1435 + } 4.1436 + } 4.1437 + accept(RBRACE); 4.1438 + return toP(F.at(newpos).NewArray(t, List.<JCExpression>nil(), elems.toList())); 4.1439 + } 4.1440 + 4.1441 + /** VariableInitializer = ArrayInitializer | Expression 4.1442 + */ 4.1443 + public JCExpression variableInitializer() { 4.1444 + return S.token() == LBRACE ? arrayInitializer(S.pos(), null) : parseExpression(); 4.1445 + } 4.1446 + 4.1447 + /** ParExpression = "(" Expression ")" 4.1448 + */ 4.1449 + JCExpression parExpression() { 4.1450 + accept(LPAREN); 4.1451 + JCExpression t = parseExpression(); 4.1452 + accept(RPAREN); 4.1453 + return t; 4.1454 + } 4.1455 + 4.1456 + /** Block = "{" BlockStatements "}" 4.1457 + */ 4.1458 + JCBlock block(int pos, long flags) { 4.1459 + accept(LBRACE); 4.1460 + List<JCStatement> stats = blockStatements(); 4.1461 + JCBlock t = F.at(pos).Block(flags, stats); 4.1462 + while (S.token() == CASE || S.token() == DEFAULT) { 4.1463 + syntaxError("orphaned", S.token()); 4.1464 + switchBlockStatementGroups(); 4.1465 + } 4.1466 + // the Block node has a field "endpos" for first char of last token, which is 4.1467 + // usually but not necessarily the last char of the last token. 4.1468 + t.endpos = S.pos(); 4.1469 + accept(RBRACE); 4.1470 + return toP(t); 4.1471 + } 4.1472 + 4.1473 + public JCBlock block() { 4.1474 + return block(S.pos(), 0); 4.1475 + } 4.1476 + 4.1477 + /** BlockStatements = { BlockStatement } 4.1478 + * BlockStatement = LocalVariableDeclarationStatement 4.1479 + * | ClassOrInterfaceOrEnumDeclaration 4.1480 + * | [Ident ":"] Statement 4.1481 + * LocalVariableDeclarationStatement 4.1482 + * = { FINAL | '@' Annotation } Type VariableDeclarators ";" 4.1483 + */ 4.1484 + @SuppressWarnings("fallthrough") 4.1485 + List<JCStatement> blockStatements() { 4.1486 +//todo: skip to anchor on error(?) 4.1487 + int lastErrPos = -1; 4.1488 + ListBuffer<JCStatement> stats = new ListBuffer<JCStatement>(); 4.1489 + while (true) { 4.1490 + int pos = S.pos(); 4.1491 + switch (S.token()) { 4.1492 + case RBRACE: case CASE: case DEFAULT: case EOF: 4.1493 + return stats.toList(); 4.1494 + case LBRACE: case IF: case FOR: case WHILE: case DO: case TRY: 4.1495 + case SWITCH: case SYNCHRONIZED: case RETURN: case THROW: case BREAK: 4.1496 + case CONTINUE: case SEMI: case ELSE: case FINALLY: case CATCH: 4.1497 + stats.append(parseStatement()); 4.1498 + break; 4.1499 + case MONKEYS_AT: 4.1500 + case FINAL: { 4.1501 + String dc = S.docComment(); 4.1502 + JCModifiers mods = modifiersOpt(); 4.1503 + if (S.token() == INTERFACE || 4.1504 + S.token() == CLASS || 4.1505 + allowEnums && S.token() == ENUM) { 4.1506 + stats.append(classOrInterfaceOrEnumDeclaration(mods, dc)); 4.1507 + } else { 4.1508 + JCExpression t = parseType(); 4.1509 + stats.appendList(variableDeclarators(mods, t, 4.1510 + new ListBuffer<JCStatement>())); 4.1511 + // A "LocalVariableDeclarationStatement" subsumes the terminating semicolon 4.1512 + storeEnd(stats.elems.last(), S.endPos()); 4.1513 + accept(SEMI); 4.1514 + } 4.1515 + break; 4.1516 + } 4.1517 + case ABSTRACT: case STRICTFP: { 4.1518 + String dc = S.docComment(); 4.1519 + JCModifiers mods = modifiersOpt(); 4.1520 + stats.append(classOrInterfaceOrEnumDeclaration(mods, dc)); 4.1521 + break; 4.1522 + } 4.1523 + case INTERFACE: 4.1524 + case CLASS: 4.1525 + stats.append(classOrInterfaceOrEnumDeclaration(modifiersOpt(), 4.1526 + S.docComment())); 4.1527 + break; 4.1528 + case ENUM: 4.1529 + case ASSERT: 4.1530 + if (allowEnums && S.token() == ENUM) { 4.1531 + log.error(S.pos(), "local.enum"); 4.1532 + stats. 4.1533 + append(classOrInterfaceOrEnumDeclaration(modifiersOpt(), 4.1534 + S.docComment())); 4.1535 + break; 4.1536 + } else if (allowAsserts && S.token() == ASSERT) { 4.1537 + stats.append(parseStatement()); 4.1538 + break; 4.1539 + } 4.1540 + /* fall through to default */ 4.1541 + default: 4.1542 + Name name = S.name(); 4.1543 + JCExpression t = term(EXPR | TYPE); 4.1544 + if (S.token() == COLON && t.getTag() == JCTree.IDENT) { 4.1545 + S.nextToken(); 4.1546 + JCStatement stat = parseStatement(); 4.1547 + stats.append(F.at(pos).Labelled(name, stat)); 4.1548 + } else if ((lastmode & TYPE) != 0 && 4.1549 + (S.token() == IDENTIFIER || 4.1550 + S.token() == ASSERT || 4.1551 + S.token() == ENUM)) { 4.1552 + pos = S.pos(); 4.1553 + JCModifiers mods = F.at(Position.NOPOS).Modifiers(0); 4.1554 + F.at(pos); 4.1555 + stats.appendList(variableDeclarators(mods, t, 4.1556 + new ListBuffer<JCStatement>())); 4.1557 + // A "LocalVariableDeclarationStatement" subsumes the terminating semicolon 4.1558 + storeEnd(stats.elems.last(), S.endPos()); 4.1559 + accept(SEMI); 4.1560 + } else { 4.1561 + // This Exec is an "ExpressionStatement"; it subsumes the terminating semicolon 4.1562 + stats.append(to(F.at(pos).Exec(checkExprStat(t)))); 4.1563 + accept(SEMI); 4.1564 + } 4.1565 + } 4.1566 + 4.1567 + // error recovery 4.1568 + if (S.pos() == lastErrPos) 4.1569 + return stats.toList(); 4.1570 + if (S.pos() <= errorEndPos) { 4.1571 + skip(false, true, true, true); 4.1572 + lastErrPos = S.pos(); 4.1573 + } 4.1574 + 4.1575 + // ensure no dangling /** @deprecated */ active 4.1576 + S.resetDeprecatedFlag(); 4.1577 + } 4.1578 + } 4.1579 + 4.1580 + /** Statement = 4.1581 + * Block 4.1582 + * | IF ParExpression Statement [ELSE Statement] 4.1583 + * | FOR "(" ForInitOpt ";" [Expression] ";" ForUpdateOpt ")" Statement 4.1584 + * | FOR "(" FormalParameter : Expression ")" Statement 4.1585 + * | WHILE ParExpression Statement 4.1586 + * | DO Statement WHILE ParExpression ";" 4.1587 + * | TRY Block ( Catches | [Catches] FinallyPart ) 4.1588 + * | SWITCH ParExpression "{" SwitchBlockStatementGroups "}" 4.1589 + * | SYNCHRONIZED ParExpression Block 4.1590 + * | RETURN [Expression] ";" 4.1591 + * | THROW Expression ";" 4.1592 + * | BREAK [Ident] ";" 4.1593 + * | CONTINUE [Ident] ";" 4.1594 + * | ASSERT Expression [ ":" Expression ] ";" 4.1595 + * | ";" 4.1596 + * | ExpressionStatement 4.1597 + * | Ident ":" Statement 4.1598 + */ 4.1599 + @SuppressWarnings("fallthrough") 4.1600 + public JCStatement parseStatement() { 4.1601 + int pos = S.pos(); 4.1602 + switch (S.token()) { 4.1603 + case LBRACE: 4.1604 + return block(); 4.1605 + case IF: { 4.1606 + S.nextToken(); 4.1607 + JCExpression cond = parExpression(); 4.1608 + JCStatement thenpart = parseStatement(); 4.1609 + JCStatement elsepart = null; 4.1610 + if (S.token() == ELSE) { 4.1611 + S.nextToken(); 4.1612 + elsepart = parseStatement(); 4.1613 + } 4.1614 + return F.at(pos).If(cond, thenpart, elsepart); 4.1615 + } 4.1616 + case FOR: { 4.1617 + S.nextToken(); 4.1618 + accept(LPAREN); 4.1619 + List<JCStatement> inits = S.token() == SEMI ? List.<JCStatement>nil() : forInit(); 4.1620 + if (inits.length() == 1 && 4.1621 + inits.head.getTag() == JCTree.VARDEF && 4.1622 + ((JCVariableDecl) inits.head).init == null && 4.1623 + S.token() == COLON) { 4.1624 + checkForeach(); 4.1625 + JCVariableDecl var = (JCVariableDecl)inits.head; 4.1626 + accept(COLON); 4.1627 + JCExpression expr = parseExpression(); 4.1628 + accept(RPAREN); 4.1629 + JCStatement body = parseStatement(); 4.1630 + return F.at(pos).ForeachLoop(var, expr, body); 4.1631 + } else { 4.1632 + accept(SEMI); 4.1633 + JCExpression cond = S.token() == SEMI ? null : parseExpression(); 4.1634 + accept(SEMI); 4.1635 + List<JCExpressionStatement> steps = S.token() == RPAREN ? List.<JCExpressionStatement>nil() : forUpdate(); 4.1636 + accept(RPAREN); 4.1637 + JCStatement body = parseStatement(); 4.1638 + return F.at(pos).ForLoop(inits, cond, steps, body); 4.1639 + } 4.1640 + } 4.1641 + case WHILE: { 4.1642 + S.nextToken(); 4.1643 + JCExpression cond = parExpression(); 4.1644 + JCStatement body = parseStatement(); 4.1645 + return F.at(pos).WhileLoop(cond, body); 4.1646 + } 4.1647 + case DO: { 4.1648 + S.nextToken(); 4.1649 + JCStatement body = parseStatement(); 4.1650 + accept(WHILE); 4.1651 + JCExpression cond = parExpression(); 4.1652 + JCDoWhileLoop t = to(F.at(pos).DoLoop(body, cond)); 4.1653 + accept(SEMI); 4.1654 + return t; 4.1655 + } 4.1656 + case TRY: { 4.1657 + S.nextToken(); 4.1658 + JCBlock body = block(); 4.1659 + ListBuffer<JCCatch> catchers = new ListBuffer<JCCatch>(); 4.1660 + JCBlock finalizer = null; 4.1661 + if (S.token() == CATCH || S.token() == FINALLY) { 4.1662 + while (S.token() == CATCH) catchers.append(catchClause()); 4.1663 + if (S.token() == FINALLY) { 4.1664 + S.nextToken(); 4.1665 + finalizer = block(); 4.1666 + } 4.1667 + } else { 4.1668 + log.error(pos, "try.without.catch.or.finally"); 4.1669 + } 4.1670 + return F.at(pos).Try(body, catchers.toList(), finalizer); 4.1671 + } 4.1672 + case SWITCH: { 4.1673 + S.nextToken(); 4.1674 + JCExpression selector = parExpression(); 4.1675 + accept(LBRACE); 4.1676 + List<JCCase> cases = switchBlockStatementGroups(); 4.1677 + JCSwitch t = to(F.at(pos).Switch(selector, cases)); 4.1678 + accept(RBRACE); 4.1679 + return t; 4.1680 + } 4.1681 + case SYNCHRONIZED: { 4.1682 + S.nextToken(); 4.1683 + JCExpression lock = parExpression(); 4.1684 + JCBlock body = block(); 4.1685 + return F.at(pos).Synchronized(lock, body); 4.1686 + } 4.1687 + case RETURN: { 4.1688 + S.nextToken(); 4.1689 + JCExpression result = S.token() == SEMI ? null : parseExpression(); 4.1690 + JCReturn t = to(F.at(pos).Return(result)); 4.1691 + accept(SEMI); 4.1692 + return t; 4.1693 + } 4.1694 + case THROW: { 4.1695 + S.nextToken(); 4.1696 + JCExpression exc = parseExpression(); 4.1697 + JCThrow t = to(F.at(pos).Throw(exc)); 4.1698 + accept(SEMI); 4.1699 + return t; 4.1700 + } 4.1701 + case BREAK: { 4.1702 + S.nextToken(); 4.1703 + Name label = (S.token() == IDENTIFIER || S.token() == ASSERT || S.token() == ENUM) ? ident() : null; 4.1704 + JCBreak t = to(F.at(pos).Break(label)); 4.1705 + accept(SEMI); 4.1706 + return t; 4.1707 + } 4.1708 + case CONTINUE: { 4.1709 + S.nextToken(); 4.1710 + Name label = (S.token() == IDENTIFIER || S.token() == ASSERT || S.token() == ENUM) ? ident() : null; 4.1711 + JCContinue t = to(F.at(pos).Continue(label)); 4.1712 + accept(SEMI); 4.1713 + return t; 4.1714 + } 4.1715 + case SEMI: 4.1716 + S.nextToken(); 4.1717 + return toP(F.at(pos).Skip()); 4.1718 + case ELSE: 4.1719 + return toP(F.Exec(syntaxError("else.without.if"))); 4.1720 + case FINALLY: 4.1721 + return toP(F.Exec(syntaxError("finally.without.try"))); 4.1722 + case CATCH: 4.1723 + return toP(F.Exec(syntaxError("catch.without.try"))); 4.1724 + case ASSERT: { 4.1725 + if (allowAsserts && S.token() == ASSERT) { 4.1726 + S.nextToken(); 4.1727 + JCExpression assertion = parseExpression(); 4.1728 + JCExpression message = null; 4.1729 + if (S.token() == COLON) { 4.1730 + S.nextToken(); 4.1731 + message = parseExpression(); 4.1732 + } 4.1733 + JCAssert t = to(F.at(pos).Assert(assertion, message)); 4.1734 + accept(SEMI); 4.1735 + return t; 4.1736 + } 4.1737 + /* else fall through to default case */ 4.1738 + } 4.1739 + case ENUM: 4.1740 + default: 4.1741 + Name name = S.name(); 4.1742 + JCExpression expr = parseExpression(); 4.1743 + if (S.token() == COLON && expr.getTag() == JCTree.IDENT) { 4.1744 + S.nextToken(); 4.1745 + JCStatement stat = parseStatement(); 4.1746 + return F.at(pos).Labelled(name, stat); 4.1747 + } else { 4.1748 + // This Exec is an "ExpressionStatement"; it subsumes the terminating semicolon 4.1749 + JCExpressionStatement stat = to(F.at(pos).Exec(checkExprStat(expr))); 4.1750 + accept(SEMI); 4.1751 + return stat; 4.1752 + } 4.1753 + } 4.1754 + } 4.1755 + 4.1756 + /** CatchClause = CATCH "(" FormalParameter ")" Block 4.1757 + */ 4.1758 + JCCatch catchClause() { 4.1759 + int pos = S.pos(); 4.1760 + accept(CATCH); 4.1761 + accept(LPAREN); 4.1762 + JCVariableDecl formal = 4.1763 + variableDeclaratorId(optFinal(Flags.PARAMETER), 4.1764 + qualident()); 4.1765 + accept(RPAREN); 4.1766 + JCBlock body = block(); 4.1767 + return F.at(pos).Catch(formal, body); 4.1768 + } 4.1769 + 4.1770 + /** SwitchBlockStatementGroups = { SwitchBlockStatementGroup } 4.1771 + * SwitchBlockStatementGroup = SwitchLabel BlockStatements 4.1772 + * SwitchLabel = CASE ConstantExpression ":" | DEFAULT ":" 4.1773 + */ 4.1774 + List<JCCase> switchBlockStatementGroups() { 4.1775 + ListBuffer<JCCase> cases = new ListBuffer<JCCase>(); 4.1776 + while (true) { 4.1777 + int pos = S.pos(); 4.1778 + switch (S.token()) { 4.1779 + case CASE: { 4.1780 + S.nextToken(); 4.1781 + JCExpression pat = parseExpression(); 4.1782 + accept(COLON); 4.1783 + List<JCStatement> stats = blockStatements(); 4.1784 + JCCase c = F.at(pos).Case(pat, stats); 4.1785 + if (stats.isEmpty()) 4.1786 + storeEnd(c, S.prevEndPos()); 4.1787 + cases.append(c); 4.1788 + break; 4.1789 + } 4.1790 + case DEFAULT: { 4.1791 + S.nextToken(); 4.1792 + accept(COLON); 4.1793 + List<JCStatement> stats = blockStatements(); 4.1794 + JCCase c = F.at(pos).Case(null, stats); 4.1795 + if (stats.isEmpty()) 4.1796 + storeEnd(c, S.prevEndPos()); 4.1797 + cases.append(c); 4.1798 + break; 4.1799 + } 4.1800 + case RBRACE: case EOF: 4.1801 + return cases.toList(); 4.1802 + default: 4.1803 + S.nextToken(); // to ensure progress 4.1804 + syntaxError(pos, "expected3", 4.1805 + CASE, DEFAULT, RBRACE); 4.1806 + } 4.1807 + } 4.1808 + } 4.1809 + 4.1810 + /** MoreStatementExpressions = { COMMA StatementExpression } 4.1811 + */ 4.1812 + <T extends ListBuffer<? super JCExpressionStatement>> T moreStatementExpressions(int pos, 4.1813 + JCExpression first, 4.1814 + T stats) { 4.1815 + // This Exec is a "StatementExpression"; it subsumes no terminating token 4.1816 + stats.append(toP(F.at(pos).Exec(checkExprStat(first)))); 4.1817 + while (S.token() == COMMA) { 4.1818 + S.nextToken(); 4.1819 + pos = S.pos(); 4.1820 + JCExpression t = parseExpression(); 4.1821 + // This Exec is a "StatementExpression"; it subsumes no terminating token 4.1822 + stats.append(toP(F.at(pos).Exec(checkExprStat(t)))); 4.1823 + } 4.1824 + return stats; 4.1825 + } 4.1826 + 4.1827 + /** ForInit = StatementExpression MoreStatementExpressions 4.1828 + * | { FINAL | '@' Annotation } Type VariableDeclarators 4.1829 + */ 4.1830 + List<JCStatement> forInit() { 4.1831 + ListBuffer<JCStatement> stats = lb(); 4.1832 + int pos = S.pos(); 4.1833 + if (S.token() == FINAL || S.token() == MONKEYS_AT) { 4.1834 + return variableDeclarators(optFinal(0), parseType(), stats).toList(); 4.1835 + } else { 4.1836 + JCExpression t = term(EXPR | TYPE); 4.1837 + if ((lastmode & TYPE) != 0 && 4.1838 + (S.token() == IDENTIFIER || S.token() == ASSERT || S.token() == ENUM)) 4.1839 + return variableDeclarators(modifiersOpt(), t, stats).toList(); 4.1840 + else 4.1841 + return moreStatementExpressions(pos, t, stats).toList(); 4.1842 + } 4.1843 + } 4.1844 + 4.1845 + /** ForUpdate = StatementExpression MoreStatementExpressions 4.1846 + */ 4.1847 + List<JCExpressionStatement> forUpdate() { 4.1848 + return moreStatementExpressions(S.pos(), 4.1849 + parseExpression(), 4.1850 + new ListBuffer<JCExpressionStatement>()).toList(); 4.1851 + } 4.1852 + 4.1853 + /** AnnotationsOpt = { '@' Annotation } 4.1854 + */ 4.1855 + List<JCAnnotation> annotationsOpt() { 4.1856 + if (S.token() != MONKEYS_AT) return List.nil(); // optimization 4.1857 + ListBuffer<JCAnnotation> buf = new ListBuffer<JCAnnotation>(); 4.1858 + while (S.token() == MONKEYS_AT) { 4.1859 + int pos = S.pos(); 4.1860 + S.nextToken(); 4.1861 + buf.append(annotation(pos)); 4.1862 + } 4.1863 + return buf.toList(); 4.1864 + } 4.1865 + 4.1866 + /** ModifiersOpt = { Modifier } 4.1867 + * Modifier = PUBLIC | PROTECTED | PRIVATE | STATIC | ABSTRACT | FINAL 4.1868 + * | NATIVE | SYNCHRONIZED | TRANSIENT | VOLATILE | "@" 4.1869 + * | "@" Annotation 4.1870 + */ 4.1871 + JCModifiers modifiersOpt() { 4.1872 + return modifiersOpt(null); 4.1873 + } 4.1874 + JCModifiers modifiersOpt(JCModifiers partial) { 4.1875 + long flags = (partial == null) ? 0 : partial.flags; 4.1876 + if (S.deprecatedFlag()) { 4.1877 + flags |= Flags.DEPRECATED; 4.1878 + S.resetDeprecatedFlag(); 4.1879 + } 4.1880 + ListBuffer<JCAnnotation> annotations = new ListBuffer<JCAnnotation>(); 4.1881 + if (partial != null) annotations.appendList(partial.annotations); 4.1882 + int pos = S.pos(); 4.1883 + int lastPos = Position.NOPOS; 4.1884 + loop: 4.1885 + while (true) { 4.1886 + long flag; 4.1887 + switch (S.token()) { 4.1888 + case PRIVATE : flag = Flags.PRIVATE; break; 4.1889 + case PROTECTED : flag = Flags.PROTECTED; break; 4.1890 + case PUBLIC : flag = Flags.PUBLIC; break; 4.1891 + case STATIC : flag = Flags.STATIC; break; 4.1892 + case TRANSIENT : flag = Flags.TRANSIENT; break; 4.1893 + case FINAL : flag = Flags.FINAL; break; 4.1894 + case ABSTRACT : flag = Flags.ABSTRACT; break; 4.1895 + case NATIVE : flag = Flags.NATIVE; break; 4.1896 + case VOLATILE : flag = Flags.VOLATILE; break; 4.1897 + case SYNCHRONIZED: flag = Flags.SYNCHRONIZED; break; 4.1898 + case STRICTFP : flag = Flags.STRICTFP; break; 4.1899 + case MONKEYS_AT : flag = Flags.ANNOTATION; break; 4.1900 + default: break loop; 4.1901 + } 4.1902 + if ((flags & flag) != 0) log.error(S.pos(), "repeated.modifier"); 4.1903 + lastPos = S.pos(); 4.1904 + S.nextToken(); 4.1905 + if (flag == Flags.ANNOTATION) { 4.1906 + checkAnnotations(); 4.1907 + if (S.token() != INTERFACE) { 4.1908 + JCAnnotation ann = annotation(lastPos); 4.1909 + // if first modifier is an annotation, set pos to annotation's. 4.1910 + if (flags == 0 && annotations.isEmpty()) 4.1911 + pos = ann.pos; 4.1912 + annotations.append(ann); 4.1913 + lastPos = ann.pos; 4.1914 + flag = 0; 4.1915 + } 4.1916 + } 4.1917 + flags |= flag; 4.1918 + } 4.1919 + switch (S.token()) { 4.1920 + case ENUM: flags |= Flags.ENUM; break; 4.1921 + case INTERFACE: flags |= Flags.INTERFACE; break; 4.1922 + default: break; 4.1923 + } 4.1924 + 4.1925 + /* A modifiers tree with no modifier tokens or annotations 4.1926 + * has no text position. */ 4.1927 + if (flags == 0 && annotations.isEmpty()) 4.1928 + pos = Position.NOPOS; 4.1929 + 4.1930 + JCModifiers mods = F.at(pos).Modifiers(flags, annotations.toList()); 4.1931 + if (pos != Position.NOPOS) 4.1932 + storeEnd(mods, S.prevEndPos()); 4.1933 + return mods; 4.1934 + } 4.1935 + 4.1936 + /** Annotation = "@" Qualident [ "(" AnnotationFieldValues ")" ] 4.1937 + * @param pos position of "@" token 4.1938 + */ 4.1939 + JCAnnotation annotation(int pos) { 4.1940 + // accept(AT); // AT consumed by caller 4.1941 + checkAnnotations(); 4.1942 + JCTree ident = qualident(); 4.1943 + List<JCExpression> fieldValues = annotationFieldValuesOpt(); 4.1944 + JCAnnotation ann = F.at(pos).Annotation(ident, fieldValues); 4.1945 + storeEnd(ann, S.prevEndPos()); 4.1946 + return ann; 4.1947 + } 4.1948 + 4.1949 + List<JCExpression> annotationFieldValuesOpt() { 4.1950 + return (S.token() == LPAREN) ? annotationFieldValues() : List.<JCExpression>nil(); 4.1951 + } 4.1952 + 4.1953 + /** AnnotationFieldValues = "(" [ AnnotationFieldValue { "," AnnotationFieldValue } ] ")" */ 4.1954 + List<JCExpression> annotationFieldValues() { 4.1955 + accept(LPAREN); 4.1956 + ListBuffer<JCExpression> buf = new ListBuffer<JCExpression>(); 4.1957 + if (S.token() != RPAREN) { 4.1958 + buf.append(annotationFieldValue()); 4.1959 + while (S.token() == COMMA) { 4.1960 + S.nextToken(); 4.1961 + buf.append(annotationFieldValue()); 4.1962 + } 4.1963 + } 4.1964 + accept(RPAREN); 4.1965 + return buf.toList(); 4.1966 + } 4.1967 + 4.1968 + /** AnnotationFieldValue = AnnotationValue 4.1969 + * | Identifier "=" AnnotationValue 4.1970 + */ 4.1971 + JCExpression annotationFieldValue() { 4.1972 + if (S.token() == IDENTIFIER) { 4.1973 + mode = EXPR; 4.1974 + JCExpression t1 = term1(); 4.1975 + if (t1.getTag() == JCTree.IDENT && S.token() == EQ) { 4.1976 + int pos = S.pos(); 4.1977 + accept(EQ); 4.1978 + return toP(F.at(pos).Assign(t1, annotationValue())); 4.1979 + } else { 4.1980 + return t1; 4.1981 + } 4.1982 + } 4.1983 + return annotationValue(); 4.1984 + } 4.1985 + 4.1986 + /* AnnotationValue = ConditionalExpression 4.1987 + * | Annotation 4.1988 + * | "{" [ AnnotationValue { "," AnnotationValue } ] "}" 4.1989 + */ 4.1990 + JCExpression annotationValue() { 4.1991 + int pos; 4.1992 + switch (S.token()) { 4.1993 + case MONKEYS_AT: 4.1994 + pos = S.pos(); 4.1995 + S.nextToken(); 4.1996 + return annotation(pos); 4.1997 + case LBRACE: 4.1998 + pos = S.pos(); 4.1999 + accept(LBRACE); 4.2000 + ListBuffer<JCExpression> buf = new ListBuffer<JCExpression>(); 4.2001 + if (S.token() != RBRACE) { 4.2002 + buf.append(annotationValue()); 4.2003 + while (S.token() == COMMA) { 4.2004 + S.nextToken(); 4.2005 + if (S.token() == RPAREN) break; 4.2006 + buf.append(annotationValue()); 4.2007 + } 4.2008 + } 4.2009 + accept(RBRACE); 4.2010 + return toP(F.at(pos).NewArray(null, List.<JCExpression>nil(), buf.toList())); 4.2011 + default: 4.2012 + mode = EXPR; 4.2013 + return term1(); 4.2014 + } 4.2015 + } 4.2016 + 4.2017 + /** VariableDeclarators = VariableDeclarator { "," VariableDeclarator } 4.2018 + */ 4.2019 + public <T extends ListBuffer<? super JCVariableDecl>> T variableDeclarators(JCModifiers mods, 4.2020 + JCExpression type, 4.2021 + T vdefs) 4.2022 + { 4.2023 + return variableDeclaratorsRest(S.pos(), mods, type, ident(), false, null, vdefs); 4.2024 + } 4.2025 + 4.2026 + /** VariableDeclaratorsRest = VariableDeclaratorRest { "," VariableDeclarator } 4.2027 + * ConstantDeclaratorsRest = ConstantDeclaratorRest { "," ConstantDeclarator } 4.2028 + * 4.2029 + * @param reqInit Is an initializer always required? 4.2030 + * @param dc The documentation comment for the variable declarations, or null. 4.2031 + */ 4.2032 + <T extends ListBuffer<? super JCVariableDecl>> T variableDeclaratorsRest(int pos, 4.2033 + JCModifiers mods, 4.2034 + JCExpression type, 4.2035 + Name name, 4.2036 + boolean reqInit, 4.2037 + String dc, 4.2038 + T vdefs) 4.2039 + { 4.2040 + vdefs.append(variableDeclaratorRest(pos, mods, type, name, reqInit, dc)); 4.2041 + while (S.token() == COMMA) { 4.2042 + // All but last of multiple declarators subsume a comma 4.2043 + storeEnd((JCTree)vdefs.elems.last(), S.endPos()); 4.2044 + S.nextToken(); 4.2045 + vdefs.append(variableDeclarator(mods, type, reqInit, dc)); 4.2046 + } 4.2047 + return vdefs; 4.2048 + } 4.2049 + 4.2050 + /** VariableDeclarator = Ident VariableDeclaratorRest 4.2051 + * ConstantDeclarator = Ident ConstantDeclaratorRest 4.2052 + */ 4.2053 + JCVariableDecl variableDeclarator(JCModifiers mods, JCExpression type, boolean reqInit, String dc) { 4.2054 + return variableDeclaratorRest(S.pos(), mods, type, ident(), reqInit, dc); 4.2055 + } 4.2056 + 4.2057 + /** VariableDeclaratorRest = BracketsOpt ["=" VariableInitializer] 4.2058 + * ConstantDeclaratorRest = BracketsOpt "=" VariableInitializer 4.2059 + * 4.2060 + * @param reqInit Is an initializer always required? 4.2061 + * @param dc The documentation comment for the variable declarations, or null. 4.2062 + */ 4.2063 + JCVariableDecl variableDeclaratorRest(int pos, JCModifiers mods, JCExpression type, Name name, 4.2064 + boolean reqInit, String dc) { 4.2065 + type = bracketsOpt(type); 4.2066 + JCExpression init = null; 4.2067 + if (S.token() == EQ) { 4.2068 + S.nextToken(); 4.2069 + init = variableInitializer(); 4.2070 + } 4.2071 + else if (reqInit) syntaxError(S.pos(), "expected", EQ); 4.2072 + JCVariableDecl result = 4.2073 + toP(F.at(pos).VarDef(mods, name, type, init)); 4.2074 + attach(result, dc); 4.2075 + return result; 4.2076 + } 4.2077 + 4.2078 + /** VariableDeclaratorId = Ident BracketsOpt 4.2079 + */ 4.2080 + JCVariableDecl variableDeclaratorId(JCModifiers mods, JCExpression type) { 4.2081 + int pos = S.pos(); 4.2082 + Name name = ident(); 4.2083 + if ((mods.flags & Flags.VARARGS) == 0) 4.2084 + type = bracketsOpt(type); 4.2085 + return toP(F.at(pos).VarDef(mods, name, type, null)); 4.2086 + } 4.2087 + 4.2088 + /** CompilationUnit = [ { "@" Annotation } PACKAGE Qualident ";"] {ImportDeclaration} {TypeDeclaration} 4.2089 + */ 4.2090 + public JCTree.JCCompilationUnit parseCompilationUnit() { 4.2091 + int pos = S.pos(); 4.2092 + JCExpression pid = null; 4.2093 + String dc = S.docComment(); 4.2094 + JCModifiers mods = null; 4.2095 + List<JCAnnotation> packageAnnotations = List.nil(); 4.2096 + if (S.token() == MONKEYS_AT) 4.2097 + mods = modifiersOpt(); 4.2098 + 4.2099 + if (S.token() == PACKAGE) { 4.2100 + if (mods != null) { 4.2101 + checkNoMods(mods.flags); 4.2102 + packageAnnotations = mods.annotations; 4.2103 + mods = null; 4.2104 + } 4.2105 + S.nextToken(); 4.2106 + pid = qualident(); 4.2107 + accept(SEMI); 4.2108 + } 4.2109 + ListBuffer<JCTree> defs = new ListBuffer<JCTree>(); 4.2110 + boolean checkForImports = true; 4.2111 + while (S.token() != EOF) { 4.2112 + if (S.pos() <= errorEndPos) { 4.2113 + // error recovery 4.2114 + skip(checkForImports, false, false, false); 4.2115 + if (S.token() == EOF) 4.2116 + break; 4.2117 + } 4.2118 + if (checkForImports && mods == null && S.token() == IMPORT) { 4.2119 + defs.append(importDeclaration()); 4.2120 + } else { 4.2121 + JCTree def = typeDeclaration(mods); 4.2122 + if (def instanceof JCExpressionStatement) 4.2123 + def = ((JCExpressionStatement)def).expr; 4.2124 + defs.append(def); 4.2125 + if (def instanceof JCClassDecl) 4.2126 + checkForImports = false; 4.2127 + mods = null; 4.2128 + } 4.2129 + } 4.2130 + JCTree.JCCompilationUnit toplevel = F.at(pos).TopLevel(packageAnnotations, pid, defs.toList()); 4.2131 + attach(toplevel, dc); 4.2132 + if (defs.elems.isEmpty()) 4.2133 + storeEnd(toplevel, S.prevEndPos()); 4.2134 + if (keepDocComments) 4.2135 + toplevel.docComments = docComments; 4.2136 + if (keepLineMap) 4.2137 + toplevel.lineMap = S.getLineMap(); 4.2138 + return toplevel; 4.2139 + } 4.2140 + 4.2141 + /** ImportDeclaration = IMPORT [ STATIC ] Ident { "." Ident } [ "." "*" ] ";" 4.2142 + */ 4.2143 + JCTree importDeclaration() { 4.2144 + int pos = S.pos(); 4.2145 + S.nextToken(); 4.2146 + boolean importStatic = false; 4.2147 + if (S.token() == STATIC) { 4.2148 + checkStaticImports(); 4.2149 + importStatic = true; 4.2150 + S.nextToken(); 4.2151 + } 4.2152 + JCExpression pid = toP(F.at(S.pos()).Ident(ident())); 4.2153 + do { 4.2154 + int pos1 = S.pos(); 4.2155 + accept(DOT); 4.2156 + if (S.token() == STAR) { 4.2157 + pid = to(F.at(pos1).Select(pid, names.asterisk)); 4.2158 + S.nextToken(); 4.2159 + break; 4.2160 + } else { 4.2161 + pid = toP(F.at(pos1).Select(pid, ident())); 4.2162 + } 4.2163 + } while (S.token() == DOT); 4.2164 + accept(SEMI); 4.2165 + return toP(F.at(pos).Import(pid, importStatic)); 4.2166 + } 4.2167 + 4.2168 + /** TypeDeclaration = ClassOrInterfaceOrEnumDeclaration 4.2169 + * | ";" 4.2170 + */ 4.2171 + JCTree typeDeclaration(JCModifiers mods) { 4.2172 + int pos = S.pos(); 4.2173 + if (mods == null && S.token() == SEMI) { 4.2174 + S.nextToken(); 4.2175 + return toP(F.at(pos).Skip()); 4.2176 + } else { 4.2177 + String dc = S.docComment(); 4.2178 + return classOrInterfaceOrEnumDeclaration(modifiersOpt(mods), dc); 4.2179 + } 4.2180 + } 4.2181 + 4.2182 + /** ClassOrInterfaceOrEnumDeclaration = ModifiersOpt 4.2183 + * (ClassDeclaration | InterfaceDeclaration | EnumDeclaration) 4.2184 + * @param mods Any modifiers starting the class or interface declaration 4.2185 + * @param dc The documentation comment for the class, or null. 4.2186 + */ 4.2187 + JCStatement classOrInterfaceOrEnumDeclaration(JCModifiers mods, String dc) { 4.2188 + if (S.token() == CLASS) { 4.2189 + return classDeclaration(mods, dc); 4.2190 + } else if (S.token() == INTERFACE) { 4.2191 + return interfaceDeclaration(mods, dc); 4.2192 + } else if (allowEnums) { 4.2193 + if (S.token() == ENUM) { 4.2194 + return enumDeclaration(mods, dc); 4.2195 + } else { 4.2196 + int pos = S.pos(); 4.2197 + List<JCTree> errs; 4.2198 + if (S.token() == IDENTIFIER) { 4.2199 + errs = List.<JCTree>of(mods, toP(F.at(pos).Ident(ident()))); 4.2200 + setErrorEndPos(S.pos()); 4.2201 + } else { 4.2202 + errs = List.<JCTree>of(mods); 4.2203 + } 4.2204 + return toP(F.Exec(syntaxError(pos, errs, "expected3", 4.2205 + CLASS, INTERFACE, ENUM))); 4.2206 + } 4.2207 + } else { 4.2208 + if (S.token() == ENUM) { 4.2209 + log.error(S.pos(), "enums.not.supported.in.source", source.name); 4.2210 + allowEnums = true; 4.2211 + return enumDeclaration(mods, dc); 4.2212 + } 4.2213 + int pos = S.pos(); 4.2214 + List<JCTree> errs; 4.2215 + if (S.token() == IDENTIFIER) { 4.2216 + errs = List.<JCTree>of(mods, toP(F.at(pos).Ident(ident()))); 4.2217 + setErrorEndPos(S.pos()); 4.2218 + } else { 4.2219 + errs = List.<JCTree>of(mods); 4.2220 + } 4.2221 + return toP(F.Exec(syntaxError(pos, errs, "expected2", 4.2222 + CLASS, INTERFACE))); 4.2223 + } 4.2224 + } 4.2225 + 4.2226 + /** ClassDeclaration = CLASS Ident TypeParametersOpt [EXTENDS Type] 4.2227 + * [IMPLEMENTS TypeList] ClassBody 4.2228 + * @param mods The modifiers starting the class declaration 4.2229 + * @param dc The documentation comment for the class, or null. 4.2230 + */ 4.2231 + JCClassDecl classDeclaration(JCModifiers mods, String dc) { 4.2232 + int pos = S.pos(); 4.2233 + accept(CLASS); 4.2234 + Name name = ident(); 4.2235 + 4.2236 + List<JCTypeParameter> typarams = typeParametersOpt(); 4.2237 + 4.2238 + JCTree extending = null; 4.2239 + if (S.token() == EXTENDS) { 4.2240 + S.nextToken(); 4.2241 + extending = parseType(); 4.2242 + } 4.2243 + List<JCExpression> implementing = List.nil(); 4.2244 + if (S.token() == IMPLEMENTS) { 4.2245 + S.nextToken(); 4.2246 + implementing = typeList(); 4.2247 + } 4.2248 + List<JCTree> defs = classOrInterfaceBody(name, false); 4.2249 + JCClassDecl result = toP(F.at(pos).ClassDef( 4.2250 + mods, name, typarams, extending, implementing, defs)); 4.2251 + attach(result, dc); 4.2252 + return result; 4.2253 + } 4.2254 + 4.2255 + /** InterfaceDeclaration = INTERFACE Ident TypeParametersOpt 4.2256 + * [EXTENDS TypeList] InterfaceBody 4.2257 + * @param mods The modifiers starting the interface declaration 4.2258 + * @param dc The documentation comment for the interface, or null. 4.2259 + */ 4.2260 + JCClassDecl interfaceDeclaration(JCModifiers mods, String dc) { 4.2261 + int pos = S.pos(); 4.2262 + accept(INTERFACE); 4.2263 + Name name = ident(); 4.2264 + 4.2265 + List<JCTypeParameter> typarams = typeParametersOpt(); 4.2266 + 4.2267 + List<JCExpression> extending = List.nil(); 4.2268 + if (S.token() == EXTENDS) { 4.2269 + S.nextToken(); 4.2270 + extending = typeList(); 4.2271 + } 4.2272 + List<JCTree> defs = classOrInterfaceBody(name, true); 4.2273 + JCClassDecl result = toP(F.at(pos).ClassDef( 4.2274 + mods, name, typarams, null, extending, defs)); 4.2275 + attach(result, dc); 4.2276 + return result; 4.2277 + } 4.2278 + 4.2279 + /** EnumDeclaration = ENUM Ident [IMPLEMENTS TypeList] EnumBody 4.2280 + * @param mods The modifiers starting the enum declaration 4.2281 + * @param dc The documentation comment for the enum, or null. 4.2282 + */ 4.2283 + JCClassDecl enumDeclaration(JCModifiers mods, String dc) { 4.2284 + int pos = S.pos(); 4.2285 + accept(ENUM); 4.2286 + Name name = ident(); 4.2287 + 4.2288 + List<JCExpression> implementing = List.nil(); 4.2289 + if (S.token() == IMPLEMENTS) { 4.2290 + S.nextToken(); 4.2291 + implementing = typeList(); 4.2292 + } 4.2293 + 4.2294 + List<JCTree> defs = enumBody(name); 4.2295 + JCModifiers newMods = 4.2296 + F.at(mods.pos).Modifiers(mods.flags|Flags.ENUM, mods.annotations); 4.2297 + JCClassDecl result = toP(F.at(pos). 4.2298 + ClassDef(newMods, name, List.<JCTypeParameter>nil(), 4.2299 + null, implementing, defs)); 4.2300 + attach(result, dc); 4.2301 + return result; 4.2302 + } 4.2303 + 4.2304 + /** EnumBody = "{" { EnumeratorDeclarationList } [","] 4.2305 + * [ ";" {ClassBodyDeclaration} ] "}" 4.2306 + */ 4.2307 + List<JCTree> enumBody(Name enumName) { 4.2308 + accept(LBRACE); 4.2309 + ListBuffer<JCTree> defs = new ListBuffer<JCTree>(); 4.2310 + if (S.token() == COMMA) { 4.2311 + S.nextToken(); 4.2312 + } else if (S.token() != RBRACE && S.token() != SEMI) { 4.2313 + defs.append(enumeratorDeclaration(enumName)); 4.2314 + while (S.token() == COMMA) { 4.2315 + S.nextToken(); 4.2316 + if (S.token() == RBRACE || S.token() == SEMI) break; 4.2317 + defs.append(enumeratorDeclaration(enumName)); 4.2318 + } 4.2319 + if (S.token() != SEMI && S.token() != RBRACE) { 4.2320 + defs.append(syntaxError(S.pos(), "expected3", 4.2321 + COMMA, RBRACE, SEMI)); 4.2322 + S.nextToken(); 4.2323 + } 4.2324 + } 4.2325 + if (S.token() == SEMI) { 4.2326 + S.nextToken(); 4.2327 + while (S.token() != RBRACE && S.token() != EOF) { 4.2328 + defs.appendList(classOrInterfaceBodyDeclaration(enumName, 4.2329 + false)); 4.2330 + if (S.pos() <= errorEndPos) { 4.2331 + // error recovery 4.2332 + skip(false, true, true, false); 4.2333 + } 4.2334 + } 4.2335 + } 4.2336 + accept(RBRACE); 4.2337 + return defs.toList(); 4.2338 + } 4.2339 + 4.2340 + /** EnumeratorDeclaration = AnnotationsOpt [TypeArguments] IDENTIFIER [ Arguments ] [ "{" ClassBody "}" ] 4.2341 + */ 4.2342 + JCTree enumeratorDeclaration(Name enumName) { 4.2343 + String dc = S.docComment(); 4.2344 + int flags = Flags.PUBLIC|Flags.STATIC|Flags.FINAL|Flags.ENUM; 4.2345 + if (S.deprecatedFlag()) { 4.2346 + flags |= Flags.DEPRECATED; 4.2347 + S.resetDeprecatedFlag(); 4.2348 + } 4.2349 + int pos = S.pos(); 4.2350 + List<JCAnnotation> annotations = annotationsOpt(); 4.2351 + JCModifiers mods = F.at(annotations.isEmpty() ? Position.NOPOS : pos).Modifiers(flags, annotations); 4.2352 + List<JCExpression> typeArgs = typeArgumentsOpt(); 4.2353 + int identPos = S.pos(); 4.2354 + Name name = ident(); 4.2355 + int createPos = S.pos(); 4.2356 + List<JCExpression> args = (S.token() == LPAREN) 4.2357 + ? arguments() : List.<JCExpression>nil(); 4.2358 + JCClassDecl body = null; 4.2359 + if (S.token() == LBRACE) { 4.2360 + JCModifiers mods1 = F.at(Position.NOPOS).Modifiers(Flags.ENUM | Flags.STATIC); 4.2361 + List<JCTree> defs = classOrInterfaceBody(names.empty, false); 4.2362 + body = toP(F.at(identPos).AnonymousClassDef(mods1, defs)); 4.2363 + } 4.2364 + if (args.isEmpty() && body == null) 4.2365 + createPos = Position.NOPOS; 4.2366 + JCIdent ident = F.at(Position.NOPOS).Ident(enumName); 4.2367 + JCNewClass create = F.at(createPos).NewClass(null, typeArgs, ident, args, body); 4.2368 + if (createPos != Position.NOPOS) 4.2369 + storeEnd(create, S.prevEndPos()); 4.2370 + ident = F.at(Position.NOPOS).Ident(enumName); 4.2371 + JCTree result = toP(F.at(pos).VarDef(mods, name, ident, create)); 4.2372 + attach(result, dc); 4.2373 + return result; 4.2374 + } 4.2375 + 4.2376 + /** TypeList = Type {"," Type} 4.2377 + */ 4.2378 + List<JCExpression> typeList() { 4.2379 + ListBuffer<JCExpression> ts = new ListBuffer<JCExpression>(); 4.2380 + ts.append(parseType()); 4.2381 + while (S.token() == COMMA) { 4.2382 + S.nextToken(); 4.2383 + ts.append(parseType()); 4.2384 + } 4.2385 + return ts.toList(); 4.2386 + } 4.2387 + 4.2388 + /** ClassBody = "{" {ClassBodyDeclaration} "}" 4.2389 + * InterfaceBody = "{" {InterfaceBodyDeclaration} "}" 4.2390 + */ 4.2391 + List<JCTree> classOrInterfaceBody(Name className, boolean isInterface) { 4.2392 + accept(LBRACE); 4.2393 + if (S.pos() <= errorEndPos) { 4.2394 + // error recovery 4.2395 + skip(false, true, false, false); 4.2396 + if (S.token() == LBRACE) 4.2397 + S.nextToken(); 4.2398 + } 4.2399 + ListBuffer<JCTree> defs = new ListBuffer<JCTree>(); 4.2400 + while (S.token() != RBRACE && S.token() != EOF) { 4.2401 + defs.appendList(classOrInterfaceBodyDeclaration(className, isInterface)); 4.2402 + if (S.pos() <= errorEndPos) { 4.2403 + // error recovery 4.2404 + skip(false, true, true, false); 4.2405 + } 4.2406 + } 4.2407 + accept(RBRACE); 4.2408 + return defs.toList(); 4.2409 + } 4.2410 + 4.2411 + /** ClassBodyDeclaration = 4.2412 + * ";" 4.2413 + * | [STATIC] Block 4.2414 + * | ModifiersOpt 4.2415 + * ( Type Ident 4.2416 + * ( VariableDeclaratorsRest ";" | MethodDeclaratorRest ) 4.2417 + * | VOID Ident MethodDeclaratorRest 4.2418 + * | TypeParameters (Type | VOID) Ident MethodDeclaratorRest 4.2419 + * | Ident ConstructorDeclaratorRest 4.2420 + * | TypeParameters Ident ConstructorDeclaratorRest 4.2421 + * | ClassOrInterfaceOrEnumDeclaration 4.2422 + * ) 4.2423 + * InterfaceBodyDeclaration = 4.2424 + * ";" 4.2425 + * | ModifiersOpt Type Ident 4.2426 + * ( ConstantDeclaratorsRest | InterfaceMethodDeclaratorRest ";" ) 4.2427 + */ 4.2428 + List<JCTree> classOrInterfaceBodyDeclaration(Name className, boolean isInterface) { 4.2429 + if (S.token() == SEMI) { 4.2430 + S.nextToken(); 4.2431 + return List.<JCTree>of(F.at(Position.NOPOS).Block(0, List.<JCStatement>nil())); 4.2432 + } else { 4.2433 + String dc = S.docComment(); 4.2434 + int pos = S.pos(); 4.2435 + JCModifiers mods = modifiersOpt(); 4.2436 + if (S.token() == CLASS || 4.2437 + S.token() == INTERFACE || 4.2438 + allowEnums && S.token() == ENUM) { 4.2439 + return List.<JCTree>of(classOrInterfaceOrEnumDeclaration(mods, dc)); 4.2440 + } else if (S.token() == LBRACE && !isInterface && 4.2441 + (mods.flags & Flags.StandardFlags & ~Flags.STATIC) == 0 && 4.2442 + mods.annotations.isEmpty()) { 4.2443 + return List.<JCTree>of(block(pos, mods.flags)); 4.2444 + } else { 4.2445 + pos = S.pos(); 4.2446 + List<JCTypeParameter> typarams = typeParametersOpt(); 4.2447 + // Hack alert: if there are type arguments but no Modifiers, the start 4.2448 + // position will be lost unless we set the Modifiers position. There 4.2449 + // should be an AST node for type parameters (BugId 5005090). 4.2450 + if (typarams.length() > 0 && mods.pos == Position.NOPOS) { 4.2451 + mods.pos = pos; 4.2452 + } 4.2453 + Token token = S.token(); 4.2454 + Name name = S.name(); 4.2455 + pos = S.pos(); 4.2456 + JCExpression type; 4.2457 + boolean isVoid = S.token() == VOID; 4.2458 + if (isVoid) { 4.2459 + type = to(F.at(pos).TypeIdent(TypeTags.VOID)); 4.2460 + S.nextToken(); 4.2461 + } else { 4.2462 + type = parseType(); 4.2463 + } 4.2464 + if (S.token() == LPAREN && !isInterface && type.getTag() == JCTree.IDENT) { 4.2465 + if (isInterface || name != className) 4.2466 + log.error(pos, "invalid.meth.decl.ret.type.req"); 4.2467 + return List.of(methodDeclaratorRest( 4.2468 + pos, mods, null, names.init, typarams, 4.2469 + isInterface, true, dc)); 4.2470 + } else { 4.2471 + pos = S.pos(); 4.2472 + name = ident(); 4.2473 + if (S.token() == LPAREN) { 4.2474 + return List.of(methodDeclaratorRest( 4.2475 + pos, mods, type, name, typarams, 4.2476 + isInterface, isVoid, dc)); 4.2477 + } else if (!isVoid && typarams.isEmpty()) { 4.2478 + List<JCTree> defs = 4.2479 + variableDeclaratorsRest(pos, mods, type, name, isInterface, dc, 4.2480 + new ListBuffer<JCTree>()).toList(); 4.2481 + storeEnd(defs.last(), S.endPos()); 4.2482 + accept(SEMI); 4.2483 + return defs; 4.2484 + } else { 4.2485 + pos = S.pos(); 4.2486 + List<JCTree> err = isVoid 4.2487 + ? List.<JCTree>of(toP(F.at(pos).MethodDef(mods, name, type, typarams, 4.2488 + List.<JCVariableDecl>nil(), List.<JCExpression>nil(), null, null))) 4.2489 + : null; 4.2490 + return List.<JCTree>of(syntaxError(S.pos(), err, "expected", LPAREN)); 4.2491 + } 4.2492 + } 4.2493 + } 4.2494 + } 4.2495 + } 4.2496 + 4.2497 + /** MethodDeclaratorRest = 4.2498 + * FormalParameters BracketsOpt [Throws TypeList] ( MethodBody | [DEFAULT AnnotationValue] ";") 4.2499 + * VoidMethodDeclaratorRest = 4.2500 + * FormalParameters [Throws TypeList] ( MethodBody | ";") 4.2501 + * InterfaceMethodDeclaratorRest = 4.2502 + * FormalParameters BracketsOpt [THROWS TypeList] ";" 4.2503 + * VoidInterfaceMethodDeclaratorRest = 4.2504 + * FormalParameters [THROWS TypeList] ";" 4.2505 + * ConstructorDeclaratorRest = 4.2506 + * "(" FormalParameterListOpt ")" [THROWS TypeList] MethodBody 4.2507 + */ 4.2508 + JCTree methodDeclaratorRest(int pos, 4.2509 + JCModifiers mods, 4.2510 + JCExpression type, 4.2511 + Name name, 4.2512 + List<JCTypeParameter> typarams, 4.2513 + boolean isInterface, boolean isVoid, 4.2514 + String dc) { 4.2515 + List<JCVariableDecl> params = formalParameters(); 4.2516 + if (!isVoid) type = bracketsOpt(type); 4.2517 + List<JCExpression> thrown = List.nil(); 4.2518 + if (S.token() == THROWS) { 4.2519 + S.nextToken(); 4.2520 + thrown = qualidentList(); 4.2521 + } 4.2522 + JCBlock body = null; 4.2523 + JCExpression defaultValue; 4.2524 + if (S.token() == LBRACE) { 4.2525 + body = block(); 4.2526 + defaultValue = null; 4.2527 + } else { 4.2528 + if (S.token() == DEFAULT) { 4.2529 + accept(DEFAULT); 4.2530 + defaultValue = annotationValue(); 4.2531 + } else { 4.2532 + defaultValue = null; 4.2533 + } 4.2534 + accept(SEMI); 4.2535 + if (S.pos() <= errorEndPos) { 4.2536 + // error recovery 4.2537 + skip(false, true, false, false); 4.2538 + if (S.token() == LBRACE) { 4.2539 + body = block(); 4.2540 + } 4.2541 + } 4.2542 + } 4.2543 + JCMethodDecl result = 4.2544 + toP(F.at(pos).MethodDef(mods, name, type, typarams, 4.2545 + params, thrown, 4.2546 + body, defaultValue)); 4.2547 + attach(result, dc); 4.2548 + return result; 4.2549 + } 4.2550 + 4.2551 + /** QualidentList = Qualident {"," Qualident} 4.2552 + */ 4.2553 + List<JCExpression> qualidentList() { 4.2554 + ListBuffer<JCExpression> ts = new ListBuffer<JCExpression>(); 4.2555 + ts.append(qualident()); 4.2556 + while (S.token() == COMMA) { 4.2557 + S.nextToken(); 4.2558 + ts.append(qualident()); 4.2559 + } 4.2560 + return ts.toList(); 4.2561 + } 4.2562 + 4.2563 + /** TypeParametersOpt = ["<" TypeParameter {"," TypeParameter} ">"] 4.2564 + */ 4.2565 + List<JCTypeParameter> typeParametersOpt() { 4.2566 + if (S.token() == LT) { 4.2567 + checkGenerics(); 4.2568 + ListBuffer<JCTypeParameter> typarams = new ListBuffer<JCTypeParameter>(); 4.2569 + S.nextToken(); 4.2570 + typarams.append(typeParameter()); 4.2571 + while (S.token() == COMMA) { 4.2572 + S.nextToken(); 4.2573 + typarams.append(typeParameter()); 4.2574 + } 4.2575 + accept(GT); 4.2576 + return typarams.toList(); 4.2577 + } else { 4.2578 + return List.nil(); 4.2579 + } 4.2580 + } 4.2581 + 4.2582 + /** TypeParameter = TypeVariable [TypeParameterBound] 4.2583 + * TypeParameterBound = EXTENDS Type {"&" Type} 4.2584 + * TypeVariable = Ident 4.2585 + */ 4.2586 + JCTypeParameter typeParameter() { 4.2587 + int pos = S.pos(); 4.2588 + Name name = ident(); 4.2589 + ListBuffer<JCExpression> bounds = new ListBuffer<JCExpression>(); 4.2590 + if (S.token() == EXTENDS) { 4.2591 + S.nextToken(); 4.2592 + bounds.append(parseType()); 4.2593 + while (S.token() == AMP) { 4.2594 + S.nextToken(); 4.2595 + bounds.append(parseType()); 4.2596 + } 4.2597 + } 4.2598 + return toP(F.at(pos).TypeParameter(name, bounds.toList())); 4.2599 + } 4.2600 + 4.2601 + /** FormalParameters = "(" [ FormalParameterList ] ")" 4.2602 + * FormalParameterList = [ FormalParameterListNovarargs , ] LastFormalParameter 4.2603 + * FormalParameterListNovarargs = [ FormalParameterListNovarargs , ] FormalParameter 4.2604 + */ 4.2605 + List<JCVariableDecl> formalParameters() { 4.2606 + ListBuffer<JCVariableDecl> params = new ListBuffer<JCVariableDecl>(); 4.2607 + JCVariableDecl lastParam = null; 4.2608 + accept(LPAREN); 4.2609 + if (S.token() != RPAREN) { 4.2610 + params.append(lastParam = formalParameter()); 4.2611 + while ((lastParam.mods.flags & Flags.VARARGS) == 0 && S.token() == COMMA) { 4.2612 + S.nextToken(); 4.2613 + params.append(lastParam = formalParameter()); 4.2614 + } 4.2615 + } 4.2616 + accept(RPAREN); 4.2617 + return params.toList(); 4.2618 + } 4.2619 + 4.2620 + JCModifiers optFinal(long flags) { 4.2621 + JCModifiers mods = modifiersOpt(); 4.2622 + checkNoMods(mods.flags & ~(Flags.FINAL | Flags.DEPRECATED)); 4.2623 + mods.flags |= flags; 4.2624 + return mods; 4.2625 + } 4.2626 + 4.2627 + /** FormalParameter = { FINAL | '@' Annotation } Type VariableDeclaratorId 4.2628 + * LastFormalParameter = { FINAL | '@' Annotation } Type '...' Ident | FormalParameter 4.2629 + */ 4.2630 + JCVariableDecl formalParameter() { 4.2631 + JCModifiers mods = optFinal(Flags.PARAMETER); 4.2632 + JCExpression type = parseType(); 4.2633 + if (S.token() == ELLIPSIS) { 4.2634 + checkVarargs(); 4.2635 + mods.flags |= Flags.VARARGS; 4.2636 + type = to(F.at(S.pos()).TypeArray(type)); 4.2637 + S.nextToken(); 4.2638 + } 4.2639 + return variableDeclaratorId(mods, type); 4.2640 + } 4.2641 + 4.2642 +/* ---------- auxiliary methods -------------- */ 4.2643 + 4.2644 + /** Check that given tree is a legal expression statement. 4.2645 + */ 4.2646 + protected JCExpression checkExprStat(JCExpression t) { 4.2647 + switch(t.getTag()) { 4.2648 + case JCTree.PREINC: case JCTree.PREDEC: 4.2649 + case JCTree.POSTINC: case JCTree.POSTDEC: 4.2650 + case JCTree.ASSIGN: 4.2651 + case JCTree.BITOR_ASG: case JCTree.BITXOR_ASG: case JCTree.BITAND_ASG: 4.2652 + case JCTree.SL_ASG: case JCTree.SR_ASG: case JCTree.USR_ASG: 4.2653 + case JCTree.PLUS_ASG: case JCTree.MINUS_ASG: 4.2654 + case JCTree.MUL_ASG: case JCTree.DIV_ASG: case JCTree.MOD_ASG: 4.2655 + case JCTree.APPLY: case JCTree.NEWCLASS: 4.2656 + case JCTree.ERRONEOUS: 4.2657 + return t; 4.2658 + default: 4.2659 + log.error(t.pos, "not.stmt"); 4.2660 + return F.at(t.pos).Erroneous(List.<JCTree>of(t)); 4.2661 + } 4.2662 + } 4.2663 + 4.2664 + /** Return precedence of operator represented by token, 4.2665 + * -1 if token is not a binary operator. @see TreeInfo.opPrec 4.2666 + */ 4.2667 + static int prec(Token token) { 4.2668 + int oc = optag(token); 4.2669 + return (oc >= 0) ? TreeInfo.opPrec(oc) : -1; 4.2670 + } 4.2671 + 4.2672 + /** Return operation tag of binary operator represented by token, 4.2673 + * -1 if token is not a binary operator. 4.2674 + */ 4.2675 + static int optag(Token token) { 4.2676 + switch (token) { 4.2677 + case BARBAR: 4.2678 + return JCTree.OR; 4.2679 + case AMPAMP: 4.2680 + return JCTree.AND; 4.2681 + case BAR: 4.2682 + return JCTree.BITOR; 4.2683 + case BAREQ: 4.2684 + return JCTree.BITOR_ASG; 4.2685 + case CARET: 4.2686 + return JCTree.BITXOR; 4.2687 + case CARETEQ: 4.2688 + return JCTree.BITXOR_ASG; 4.2689 + case AMP: 4.2690 + return JCTree.BITAND; 4.2691 + case AMPEQ: 4.2692 + return JCTree.BITAND_ASG; 4.2693 + case EQEQ: 4.2694 + return JCTree.EQ; 4.2695 + case BANGEQ: 4.2696 + return JCTree.NE; 4.2697 + case LT: 4.2698 + return JCTree.LT; 4.2699 + case GT: 4.2700 + return JCTree.GT; 4.2701 + case LTEQ: 4.2702 + return JCTree.LE; 4.2703 + case GTEQ: 4.2704 + return JCTree.GE; 4.2705 + case LTLT: 4.2706 + return JCTree.SL; 4.2707 + case LTLTEQ: 4.2708 + return JCTree.SL_ASG; 4.2709 + case GTGT: 4.2710 + return JCTree.SR; 4.2711 + case GTGTEQ: 4.2712 + return JCTree.SR_ASG; 4.2713 + case GTGTGT: 4.2714 + return JCTree.USR; 4.2715 + case GTGTGTEQ: 4.2716 + return JCTree.USR_ASG; 4.2717 + case PLUS: 4.2718 + return JCTree.PLUS; 4.2719 + case PLUSEQ: 4.2720 + return JCTree.PLUS_ASG; 4.2721 + case SUB: 4.2722 + return JCTree.MINUS; 4.2723 + case SUBEQ: 4.2724 + return JCTree.MINUS_ASG; 4.2725 + case STAR: 4.2726 + return JCTree.MUL; 4.2727 + case STAREQ: 4.2728 + return JCTree.MUL_ASG; 4.2729 + case SLASH: 4.2730 + return JCTree.DIV; 4.2731 + case SLASHEQ: 4.2732 + return JCTree.DIV_ASG; 4.2733 + case PERCENT: 4.2734 + return JCTree.MOD; 4.2735 + case PERCENTEQ: 4.2736 + return JCTree.MOD_ASG; 4.2737 + case INSTANCEOF: 4.2738 + return JCTree.TYPETEST; 4.2739 + default: 4.2740 + return -1; 4.2741 + } 4.2742 + } 4.2743 + 4.2744 + /** Return operation tag of unary operator represented by token, 4.2745 + * -1 if token is not a binary operator. 4.2746 + */ 4.2747 + static int unoptag(Token token) { 4.2748 + switch (token) { 4.2749 + case PLUS: 4.2750 + return JCTree.POS; 4.2751 + case SUB: 4.2752 + return JCTree.NEG; 4.2753 + case BANG: 4.2754 + return JCTree.NOT; 4.2755 + case TILDE: 4.2756 + return JCTree.COMPL; 4.2757 + case PLUSPLUS: 4.2758 + return JCTree.PREINC; 4.2759 + case SUBSUB: 4.2760 + return JCTree.PREDEC; 4.2761 + default: 4.2762 + return -1; 4.2763 + } 4.2764 + } 4.2765 + 4.2766 + /** Return type tag of basic type represented by token, 4.2767 + * -1 if token is not a basic type identifier. 4.2768 + */ 4.2769 + static int typetag(Token token) { 4.2770 + switch (token) { 4.2771 + case BYTE: 4.2772 + return TypeTags.BYTE; 4.2773 + case CHAR: 4.2774 + return TypeTags.CHAR; 4.2775 + case SHORT: 4.2776 + return TypeTags.SHORT; 4.2777 + case INT: 4.2778 + return TypeTags.INT; 4.2779 + case LONG: 4.2780 + return TypeTags.LONG; 4.2781 + case FLOAT: 4.2782 + return TypeTags.FLOAT; 4.2783 + case DOUBLE: 4.2784 + return TypeTags.DOUBLE; 4.2785 + case BOOLEAN: 4.2786 + return TypeTags.BOOLEAN; 4.2787 + default: 4.2788 + return -1; 4.2789 + } 4.2790 + } 4.2791 + 4.2792 + void checkGenerics() { 4.2793 + if (!allowGenerics) { 4.2794 + log.error(S.pos(), "generics.not.supported.in.source", source.name); 4.2795 + allowGenerics = true; 4.2796 + } 4.2797 + } 4.2798 + void checkVarargs() { 4.2799 + if (!allowVarargs) { 4.2800 + log.error(S.pos(), "varargs.not.supported.in.source", source.name); 4.2801 + allowVarargs = true; 4.2802 + } 4.2803 + } 4.2804 + void checkForeach() { 4.2805 + if (!allowForeach) { 4.2806 + log.error(S.pos(), "foreach.not.supported.in.source", source.name); 4.2807 + allowForeach = true; 4.2808 + } 4.2809 + } 4.2810 + void checkStaticImports() { 4.2811 + if (!allowStaticImport) { 4.2812 + log.error(S.pos(), "static.import.not.supported.in.source", source.name); 4.2813 + allowStaticImport = true; 4.2814 + } 4.2815 + } 4.2816 + void checkAnnotations() { 4.2817 + if (!allowAnnotations) { 4.2818 + log.error(S.pos(), "annotations.not.supported.in.source", source.name); 4.2819 + allowAnnotations = true; 4.2820 + } 4.2821 + } 4.2822 +}
5.1 --- a/src/share/classes/com/sun/tools/javac/parser/Parser.java Tue Sep 09 10:28:21 2008 -0700 5.2 +++ b/src/share/classes/com/sun/tools/javac/parser/Parser.java Tue Sep 09 10:40:50 2008 -0700 5.3 @@ -23,2834 +23,44 @@ 5.4 * have any questions. 5.5 */ 5.6 5.7 + 5.8 package com.sun.tools.javac.parser; 5.9 5.10 -import java.util.*; 5.11 +import com.sun.tools.javac.tree.JCTree.JCCompilationUnit; 5.12 +import com.sun.tools.javac.tree.JCTree.JCExpression; 5.13 +import com.sun.tools.javac.tree.JCTree.JCStatement; 5.14 5.15 -import com.sun.tools.javac.tree.*; 5.16 -import com.sun.tools.javac.code.*; 5.17 -import com.sun.tools.javac.util.*; 5.18 -import com.sun.tools.javac.util.List; 5.19 -import static com.sun.tools.javac.util.ListBuffer.lb; 5.20 - 5.21 -import com.sun.tools.javac.tree.JCTree.*; 5.22 - 5.23 -import static com.sun.tools.javac.parser.Token.*; 5.24 - 5.25 -/** The parser maps a token sequence into an abstract syntax 5.26 - * tree. It operates by recursive descent, with code derived 5.27 - * systematically from an LL(1) grammar. For efficiency reasons, an 5.28 - * operator precedence scheme is used for parsing binary operation 5.29 - * expressions. 5.30 +/** 5.31 + * Reads syntactic units from source code. 5.32 + * Parsers are normally created from a ParserFactory. 5.33 * 5.34 - * <p><b>This is NOT part of any API supported by Sun Microsystems. If 5.35 - * you write code that depends on this, you do so at your own risk. 5.36 - * This code and its internal interfaces are subject to change or 5.37 - * deletion without notice.</b> 5.38 + * <p><b>This is NOT part of any API supported by Sun Microsystems. 5.39 + * If you write code that depends on this, you do so at your own risk. 5.40 + * This code and its internal interfaces are subject to change or 5.41 + * deletion without notice.</b> 5.42 */ 5.43 -public class Parser { 5.44 - 5.45 - /** A factory for creating parsers. */ 5.46 - public static class Factory { 5.47 - /** The context key for the parser factory. */ 5.48 - protected static final Context.Key<Parser.Factory> parserFactoryKey = 5.49 - new Context.Key<Parser.Factory>(); 5.50 - 5.51 - /** Get the Factory instance for this context. */ 5.52 - public static Factory instance(Context context) { 5.53 - Factory instance = context.get(parserFactoryKey); 5.54 - if (instance == null) 5.55 - instance = new Factory(context); 5.56 - return instance; 5.57 - } 5.58 - 5.59 - final TreeMaker F; 5.60 - final Log log; 5.61 - final Keywords keywords; 5.62 - final Source source; 5.63 - final Name.Table names; 5.64 - final Options options; 5.65 - 5.66 - /** Create a new parser factory. */ 5.67 - protected Factory(Context context) { 5.68 - context.put(parserFactoryKey, this); 5.69 - this.F = TreeMaker.instance(context); 5.70 - this.log = Log.instance(context); 5.71 - this.names = Name.Table.instance(context); 5.72 - this.keywords = Keywords.instance(context); 5.73 - this.source = Source.instance(context); 5.74 - this.options = Options.instance(context); 5.75 - } 5.76 - 5.77 - /** 5.78 - * Create a new Parser. 5.79 - * @param S Lexer for getting tokens while parsing 5.80 - * @param keepDocComments true if javadoc comments should be kept 5.81 - * @param genEndPos true if end positions should be generated 5.82 - */ 5.83 - public Parser newParser(Lexer S, boolean keepDocComments, boolean genEndPos) { 5.84 - if (!genEndPos) 5.85 - return new Parser(this, S, keepDocComments); 5.86 - else 5.87 - return new EndPosParser(this, S, keepDocComments); 5.88 - } 5.89 - } 5.90 - 5.91 - /** The number of precedence levels of infix operators. 5.92 +public interface Parser { 5.93 + /** 5.94 + * Parse a compilation unit. 5.95 + * @return a compilation unit 5.96 */ 5.97 - private static final int infixPrecedenceLevels = 10; 5.98 - 5.99 - /** The scanner used for lexical analysis. 5.100 - */ 5.101 - private Lexer S; 5.102 - 5.103 - /** The factory to be used for abstract syntax tree construction. 5.104 - */ 5.105 - protected TreeMaker F; 5.106 - 5.107 - /** The log to be used for error diagnostics. 5.108 - */ 5.109 - private Log log; 5.110 - 5.111 - /** The keyword table. */ 5.112 - private Keywords keywords; 5.113 - 5.114 - /** The Source language setting. */ 5.115 - private Source source; 5.116 - 5.117 - /** The name table. */ 5.118 - private Name.Table names; 5.119 - 5.120 - /** Construct a parser from a given scanner, tree factory and log. 5.121 - */ 5.122 - protected Parser(Factory fac, 5.123 - Lexer S, 5.124 - boolean keepDocComments) { 5.125 - this.S = S; 5.126 - S.nextToken(); // prime the pump 5.127 - this.F = fac.F; 5.128 - this.log = fac.log; 5.129 - this.names = fac.names; 5.130 - this.keywords = fac.keywords; 5.131 - this.source = fac.source; 5.132 - Options options = fac.options; 5.133 - this.allowGenerics = source.allowGenerics(); 5.134 - this.allowVarargs = source.allowVarargs(); 5.135 - this.allowAsserts = source.allowAsserts(); 5.136 - this.allowEnums = source.allowEnums(); 5.137 - this.allowForeach = source.allowForeach(); 5.138 - this.allowStaticImport = source.allowStaticImport(); 5.139 - this.allowAnnotations = source.allowAnnotations(); 5.140 - this.keepDocComments = keepDocComments; 5.141 - if (keepDocComments) docComments = new HashMap<JCTree,String>(); 5.142 - this.errorTree = F.Erroneous(); 5.143 - } 5.144 - 5.145 - /** Switch: Should generics be recognized? 5.146 - */ 5.147 - boolean allowGenerics; 5.148 - 5.149 - /** Switch: Should varargs be recognized? 5.150 - */ 5.151 - boolean allowVarargs; 5.152 - 5.153 - /** Switch: should we recognize assert statements, or just give a warning? 5.154 - */ 5.155 - boolean allowAsserts; 5.156 - 5.157 - /** Switch: should we recognize enums, or just give a warning? 5.158 - */ 5.159 - boolean allowEnums; 5.160 - 5.161 - /** Switch: should we recognize foreach? 5.162 - */ 5.163 - boolean allowForeach; 5.164 - 5.165 - /** Switch: should we recognize foreach? 5.166 - */ 5.167 - boolean allowStaticImport; 5.168 - 5.169 - /** Switch: should we recognize annotations? 5.170 - */ 5.171 - boolean allowAnnotations; 5.172 - 5.173 - /** Switch: should we keep docComments? 5.174 - */ 5.175 - boolean keepDocComments; 5.176 - 5.177 - /** When terms are parsed, the mode determines which is expected: 5.178 - * mode = EXPR : an expression 5.179 - * mode = TYPE : a type 5.180 - * mode = NOPARAMS : no parameters allowed for type 5.181 - * mode = TYPEARG : type argument 5.182 - */ 5.183 - static final int EXPR = 1; 5.184 - static final int TYPE = 2; 5.185 - static final int NOPARAMS = 4; 5.186 - static final int TYPEARG = 8; 5.187 - 5.188 - /** The current mode. 5.189 - */ 5.190 - private int mode = 0; 5.191 - 5.192 - /** The mode of the term that was parsed last. 5.193 - */ 5.194 - private int lastmode = 0; 5.195 - 5.196 -/* ---------- error recovery -------------- */ 5.197 - 5.198 - private JCErroneous errorTree; 5.199 - 5.200 - /** Skip forward until a suitable stop token is found. 5.201 - */ 5.202 - private void skip(boolean stopAtImport, boolean stopAtMemberDecl, boolean stopAtIdentifier, boolean stopAtStatement) { 5.203 - while (true) { 5.204 - switch (S.token()) { 5.205 - case SEMI: 5.206 - S.nextToken(); 5.207 - return; 5.208 - case PUBLIC: 5.209 - case FINAL: 5.210 - case ABSTRACT: 5.211 - case MONKEYS_AT: 5.212 - case EOF: 5.213 - case CLASS: 5.214 - case INTERFACE: 5.215 - case ENUM: 5.216 - return; 5.217 - case IMPORT: 5.218 - if (stopAtImport) 5.219 - return; 5.220 - break; 5.221 - case LBRACE: 5.222 - case RBRACE: 5.223 - case PRIVATE: 5.224 - case PROTECTED: 5.225 - case STATIC: 5.226 - case TRANSIENT: 5.227 - case NATIVE: 5.228 - case VOLATILE: 5.229 - case SYNCHRONIZED: 5.230 - case STRICTFP: 5.231 - case LT: 5.232 - case BYTE: 5.233 - case SHORT: 5.234 - case CHAR: 5.235 - case INT: 5.236 - case LONG: 5.237 - case FLOAT: 5.238 - case DOUBLE: 5.239 - case BOOLEAN: 5.240 - case VOID: 5.241 - if (stopAtMemberDecl) 5.242 - return; 5.243 - break; 5.244 - case IDENTIFIER: 5.245 - if (stopAtIdentifier) 5.246 - return; 5.247 - break; 5.248 - case CASE: 5.249 - case DEFAULT: 5.250 - case IF: 5.251 - case FOR: 5.252 - case WHILE: 5.253 - case DO: 5.254 - case TRY: 5.255 - case SWITCH: 5.256 - case RETURN: 5.257 - case THROW: 5.258 - case BREAK: 5.259 - case CONTINUE: 5.260 - case ELSE: 5.261 - case FINALLY: 5.262 - case CATCH: 5.263 - if (stopAtStatement) 5.264 - return; 5.265 - break; 5.266 - } 5.267 - S.nextToken(); 5.268 - } 5.269 - } 5.270 - 5.271 - private JCErroneous syntaxError(int pos, String key, Token... args) { 5.272 - return syntaxError(pos, null, key, args); 5.273 - } 5.274 - 5.275 - private JCErroneous syntaxError(int pos, List<JCTree> errs, String key, Token... args) { 5.276 - setErrorEndPos(pos); 5.277 - reportSyntaxError(pos, key, (Object[])args); 5.278 - return toP(F.at(pos).Erroneous(errs)); 5.279 - } 5.280 - 5.281 - private int errorPos = Position.NOPOS; 5.282 - /** 5.283 - * Report a syntax error at given position using the given 5.284 - * argument unless one was already reported at the same position. 5.285 - */ 5.286 - private void reportSyntaxError(int pos, String key, Object... args) { 5.287 - if (pos > S.errPos() || pos == Position.NOPOS) { 5.288 - if (S.token() == EOF) 5.289 - log.error(pos, "premature.eof"); 5.290 - else 5.291 - log.error(pos, key, args); 5.292 - } 5.293 - S.errPos(pos); 5.294 - if (S.pos() == errorPos) 5.295 - S.nextToken(); // guarantee progress 5.296 - errorPos = S.pos(); 5.297 - } 5.298 - 5.299 - 5.300 - /** Generate a syntax error at current position unless one was already 5.301 - * reported at the same position. 5.302 - */ 5.303 - private JCErroneous syntaxError(String key) { 5.304 - return syntaxError(S.pos(), key); 5.305 - } 5.306 - 5.307 - /** Generate a syntax error at current position unless one was 5.308 - * already reported at the same position. 5.309 - */ 5.310 - private JCErroneous syntaxError(String key, Token arg) { 5.311 - return syntaxError(S.pos(), key, arg); 5.312 - } 5.313 - 5.314 - /** If next input token matches given token, skip it, otherwise report 5.315 - * an error. 5.316 - */ 5.317 - public void accept(Token token) { 5.318 - if (S.token() == token) { 5.319 - S.nextToken(); 5.320 - } else { 5.321 - setErrorEndPos(S.pos()); 5.322 - reportSyntaxError(S.prevEndPos(), "expected", token); 5.323 - } 5.324 - } 5.325 - 5.326 - /** Report an illegal start of expression/type error at given position. 5.327 - */ 5.328 - JCExpression illegal(int pos) { 5.329 - setErrorEndPos(S.pos()); 5.330 - if ((mode & EXPR) != 0) 5.331 - return syntaxError(pos, "illegal.start.of.expr"); 5.332 - else 5.333 - return syntaxError(pos, "illegal.start.of.type"); 5.334 - 5.335 - } 5.336 - 5.337 - /** Report an illegal start of expression/type error at current position. 5.338 - */ 5.339 - JCExpression illegal() { 5.340 - return illegal(S.pos()); 5.341 - } 5.342 - 5.343 - /** Diagnose a modifier flag from the set, if any. */ 5.344 - void checkNoMods(long mods) { 5.345 - if (mods != 0) { 5.346 - long lowestMod = mods & -mods; 5.347 - log.error(S.pos(), "mod.not.allowed.here", 5.348 - Flags.asFlagSet(lowestMod)); 5.349 - } 5.350 - } 5.351 - 5.352 -/* ---------- doc comments --------- */ 5.353 - 5.354 - /** A hashtable to store all documentation comments 5.355 - * indexed by the tree nodes they refer to. 5.356 - * defined only if option flag keepDocComment is set. 5.357 - */ 5.358 - Map<JCTree, String> docComments; 5.359 - 5.360 - /** Make an entry into docComments hashtable, 5.361 - * provided flag keepDocComments is set and given doc comment is non-null. 5.362 - * @param tree The tree to be used as index in the hashtable 5.363 - * @param dc The doc comment to associate with the tree, or null. 5.364 - */ 5.365 - void attach(JCTree tree, String dc) { 5.366 - if (keepDocComments && dc != null) { 5.367 -// System.out.println("doc comment = ");System.out.println(dc);//DEBUG 5.368 - docComments.put(tree, dc); 5.369 - } 5.370 - } 5.371 - 5.372 -/* -------- source positions ------- */ 5.373 - 5.374 - private int errorEndPos = -1; 5.375 - 5.376 - private void setErrorEndPos(int errPos) { 5.377 - if (errPos > errorEndPos) 5.378 - errorEndPos = errPos; 5.379 - } 5.380 - 5.381 - protected int getErrorEndPos() { 5.382 - return errorEndPos; 5.383 - } 5.384 + JCCompilationUnit parseCompilationUnit(); 5.385 5.386 /** 5.387 - * Store ending position for a tree. 5.388 - * @param tree The tree. 5.389 - * @param endpos The ending position to associate with the tree. 5.390 + * Parse an expression. 5.391 + * @return an expression 5.392 */ 5.393 - protected void storeEnd(JCTree tree, int endpos) {} 5.394 + JCExpression parseExpression(); 5.395 5.396 /** 5.397 - * Store ending position for a tree. The ending position should 5.398 - * be the ending position of the current token. 5.399 - * @param t The tree. 5.400 + * Parse a statement. 5.401 + * @return an expression 5.402 */ 5.403 - protected <T extends JCTree> T to(T t) { return t; } 5.404 + JCStatement parseStatement(); 5.405 5.406 /** 5.407 - * Store ending position for a tree. The ending position should 5.408 - * be greater of the ending position of the previous token and errorEndPos. 5.409 - * @param t The tree. 5.410 + * Parse a type. 5.411 + * @return an expression for a type 5.412 */ 5.413 - protected <T extends JCTree> T toP(T t) { return t; } 5.414 - 5.415 - /** Get the start position for a tree node. The start position is 5.416 - * defined to be the position of the first character of the first 5.417 - * token of the node's source text. 5.418 - * @param tree The tree node 5.419 - */ 5.420 - public int getStartPos(JCTree tree) { 5.421 - return TreeInfo.getStartPos(tree); 5.422 - } 5.423 - 5.424 - /** 5.425 - * Get the end position for a tree node. The end position is 5.426 - * defined to be the position of the last character of the last 5.427 - * token of the node's source text. Returns Position.NOPOS if end 5.428 - * positions are not generated or the position is otherwise not 5.429 - * found. 5.430 - * @param tree The tree node 5.431 - */ 5.432 - public int getEndPos(JCTree tree) { 5.433 - return Position.NOPOS; 5.434 - } 5.435 - 5.436 - 5.437 - 5.438 -/* ---------- parsing -------------- */ 5.439 - 5.440 - /** 5.441 - * Ident = IDENTIFIER 5.442 - */ 5.443 - Name ident() { 5.444 - if (S.token() == IDENTIFIER) { 5.445 - Name name = S.name(); 5.446 - S.nextToken(); 5.447 - return name; 5.448 - } else if (S.token() == ASSERT) { 5.449 - if (allowAsserts) { 5.450 - log.error(S.pos(), "assert.as.identifier"); 5.451 - S.nextToken(); 5.452 - return names.error; 5.453 - } else { 5.454 - log.warning(S.pos(), "assert.as.identifier"); 5.455 - Name name = S.name(); 5.456 - S.nextToken(); 5.457 - return name; 5.458 - } 5.459 - } else if (S.token() == ENUM) { 5.460 - if (allowEnums) { 5.461 - log.error(S.pos(), "enum.as.identifier"); 5.462 - S.nextToken(); 5.463 - return names.error; 5.464 - } else { 5.465 - log.warning(S.pos(), "enum.as.identifier"); 5.466 - Name name = S.name(); 5.467 - S.nextToken(); 5.468 - return name; 5.469 - } 5.470 - } else { 5.471 - accept(IDENTIFIER); 5.472 - return names.error; 5.473 - } 5.474 + JCExpression parseType(); 5.475 } 5.476 - 5.477 - /** 5.478 - * Qualident = Ident { DOT Ident } 5.479 - */ 5.480 - public JCExpression qualident() { 5.481 - JCExpression t = toP(F.at(S.pos()).Ident(ident())); 5.482 - while (S.token() == DOT) { 5.483 - int pos = S.pos(); 5.484 - S.nextToken(); 5.485 - t = toP(F.at(pos).Select(t, ident())); 5.486 - } 5.487 - return t; 5.488 - } 5.489 - 5.490 - /** 5.491 - * Literal = 5.492 - * INTLITERAL 5.493 - * | LONGLITERAL 5.494 - * | FLOATLITERAL 5.495 - * | DOUBLELITERAL 5.496 - * | CHARLITERAL 5.497 - * | STRINGLITERAL 5.498 - * | TRUE 5.499 - * | FALSE 5.500 - * | NULL 5.501 - */ 5.502 - JCExpression literal(Name prefix) { 5.503 - int pos = S.pos(); 5.504 - JCExpression t = errorTree; 5.505 - switch (S.token()) { 5.506 - case INTLITERAL: 5.507 - try { 5.508 - t = F.at(pos).Literal( 5.509 - TypeTags.INT, 5.510 - Convert.string2int(strval(prefix), S.radix())); 5.511 - } catch (NumberFormatException ex) { 5.512 - log.error(S.pos(), "int.number.too.large", strval(prefix)); 5.513 - } 5.514 - break; 5.515 - case LONGLITERAL: 5.516 - try { 5.517 - t = F.at(pos).Literal( 5.518 - TypeTags.LONG, 5.519 - new Long(Convert.string2long(strval(prefix), S.radix()))); 5.520 - } catch (NumberFormatException ex) { 5.521 - log.error(S.pos(), "int.number.too.large", strval(prefix)); 5.522 - } 5.523 - break; 5.524 - case FLOATLITERAL: { 5.525 - String proper = (S.radix() == 16 ? ("0x"+ S.stringVal()) : S.stringVal()); 5.526 - Float n; 5.527 - try { 5.528 - n = Float.valueOf(proper); 5.529 - } catch (NumberFormatException ex) { 5.530 - // error already repoted in scanner 5.531 - n = Float.NaN; 5.532 - } 5.533 - if (n.floatValue() == 0.0f && !isZero(proper)) 5.534 - log.error(S.pos(), "fp.number.too.small"); 5.535 - else if (n.floatValue() == Float.POSITIVE_INFINITY) 5.536 - log.error(S.pos(), "fp.number.too.large"); 5.537 - else 5.538 - t = F.at(pos).Literal(TypeTags.FLOAT, n); 5.539 - break; 5.540 - } 5.541 - case DOUBLELITERAL: { 5.542 - String proper = (S.radix() == 16 ? ("0x"+ S.stringVal()) : S.stringVal()); 5.543 - Double n; 5.544 - try { 5.545 - n = Double.valueOf(proper); 5.546 - } catch (NumberFormatException ex) { 5.547 - // error already reported in scanner 5.548 - n = Double.NaN; 5.549 - } 5.550 - if (n.doubleValue() == 0.0d && !isZero(proper)) 5.551 - log.error(S.pos(), "fp.number.too.small"); 5.552 - else if (n.doubleValue() == Double.POSITIVE_INFINITY) 5.553 - log.error(S.pos(), "fp.number.too.large"); 5.554 - else 5.555 - t = F.at(pos).Literal(TypeTags.DOUBLE, n); 5.556 - break; 5.557 - } 5.558 - case CHARLITERAL: 5.559 - t = F.at(pos).Literal( 5.560 - TypeTags.CHAR, 5.561 - S.stringVal().charAt(0) + 0); 5.562 - break; 5.563 - case STRINGLITERAL: 5.564 - t = F.at(pos).Literal( 5.565 - TypeTags.CLASS, 5.566 - S.stringVal()); 5.567 - break; 5.568 - case TRUE: case FALSE: 5.569 - t = F.at(pos).Literal( 5.570 - TypeTags.BOOLEAN, 5.571 - (S.token() == TRUE ? 1 : 0)); 5.572 - break; 5.573 - case NULL: 5.574 - t = F.at(pos).Literal( 5.575 - TypeTags.BOT, 5.576 - null); 5.577 - break; 5.578 - default: 5.579 - assert false; 5.580 - } 5.581 - if (t == errorTree) 5.582 - t = F.at(pos).Erroneous(); 5.583 - storeEnd(t, S.endPos()); 5.584 - S.nextToken(); 5.585 - return t; 5.586 - } 5.587 -//where 5.588 - boolean isZero(String s) { 5.589 - char[] cs = s.toCharArray(); 5.590 - int base = ((Character.toLowerCase(s.charAt(1)) == 'x') ? 16 : 10); 5.591 - int i = ((base==16) ? 2 : 0); 5.592 - while (i < cs.length && (cs[i] == '0' || cs[i] == '.')) i++; 5.593 - return !(i < cs.length && (Character.digit(cs[i], base) > 0)); 5.594 - } 5.595 - 5.596 - String strval(Name prefix) { 5.597 - String s = S.stringVal(); 5.598 - return (prefix.len == 0) ? s : prefix + s; 5.599 - } 5.600 - 5.601 - /** terms can be either expressions or types. 5.602 - */ 5.603 - public JCExpression expression() { 5.604 - return term(EXPR); 5.605 - } 5.606 - 5.607 - public JCExpression type() { 5.608 - return term(TYPE); 5.609 - } 5.610 - 5.611 - JCExpression term(int newmode) { 5.612 - int prevmode = mode; 5.613 - mode = newmode; 5.614 - JCExpression t = term(); 5.615 - lastmode = mode; 5.616 - mode = prevmode; 5.617 - return t; 5.618 - } 5.619 - 5.620 - /** 5.621 - * Expression = Expression1 [ExpressionRest] 5.622 - * ExpressionRest = [AssignmentOperator Expression1] 5.623 - * AssignmentOperator = "=" | "+=" | "-=" | "*=" | "/=" | 5.624 - * "&=" | "|=" | "^=" | 5.625 - * "%=" | "<<=" | ">>=" | ">>>=" 5.626 - * Type = Type1 5.627 - * TypeNoParams = TypeNoParams1 5.628 - * StatementExpression = Expression 5.629 - * ConstantExpression = Expression 5.630 - */ 5.631 - JCExpression term() { 5.632 - JCExpression t = term1(); 5.633 - if ((mode & EXPR) != 0 && 5.634 - S.token() == EQ || PLUSEQ.compareTo(S.token()) <= 0 && S.token().compareTo(GTGTGTEQ) <= 0) 5.635 - return termRest(t); 5.636 - else 5.637 - return t; 5.638 - } 5.639 - 5.640 - JCExpression termRest(JCExpression t) { 5.641 - switch (S.token()) { 5.642 - case EQ: { 5.643 - int pos = S.pos(); 5.644 - S.nextToken(); 5.645 - mode = EXPR; 5.646 - JCExpression t1 = term(); 5.647 - return toP(F.at(pos).Assign(t, t1)); 5.648 - } 5.649 - case PLUSEQ: 5.650 - case SUBEQ: 5.651 - case STAREQ: 5.652 - case SLASHEQ: 5.653 - case PERCENTEQ: 5.654 - case AMPEQ: 5.655 - case BAREQ: 5.656 - case CARETEQ: 5.657 - case LTLTEQ: 5.658 - case GTGTEQ: 5.659 - case GTGTGTEQ: 5.660 - int pos = S.pos(); 5.661 - Token token = S.token(); 5.662 - S.nextToken(); 5.663 - mode = EXPR; 5.664 - JCExpression t1 = term(); 5.665 - return F.at(pos).Assignop(optag(token), t, t1); 5.666 - default: 5.667 - return t; 5.668 - } 5.669 - } 5.670 - 5.671 - /** Expression1 = Expression2 [Expression1Rest] 5.672 - * Type1 = Type2 5.673 - * TypeNoParams1 = TypeNoParams2 5.674 - */ 5.675 - JCExpression term1() { 5.676 - JCExpression t = term2(); 5.677 - if ((mode & EXPR) != 0 && S.token() == QUES) { 5.678 - mode = EXPR; 5.679 - return term1Rest(t); 5.680 - } else { 5.681 - return t; 5.682 - } 5.683 - } 5.684 - 5.685 - /** Expression1Rest = ["?" Expression ":" Expression1] 5.686 - */ 5.687 - JCExpression term1Rest(JCExpression t) { 5.688 - if (S.token() == QUES) { 5.689 - int pos = S.pos(); 5.690 - S.nextToken(); 5.691 - JCExpression t1 = term(); 5.692 - accept(COLON); 5.693 - JCExpression t2 = term1(); 5.694 - return F.at(pos).Conditional(t, t1, t2); 5.695 - } else { 5.696 - return t; 5.697 - } 5.698 - } 5.699 - 5.700 - /** Expression2 = Expression3 [Expression2Rest] 5.701 - * Type2 = Type3 5.702 - * TypeNoParams2 = TypeNoParams3 5.703 - */ 5.704 - JCExpression term2() { 5.705 - JCExpression t = term3(); 5.706 - if ((mode & EXPR) != 0 && prec(S.token()) >= TreeInfo.orPrec) { 5.707 - mode = EXPR; 5.708 - return term2Rest(t, TreeInfo.orPrec); 5.709 - } else { 5.710 - return t; 5.711 - } 5.712 - } 5.713 - 5.714 - /* Expression2Rest = {infixop Expression3} 5.715 - * | Expression3 instanceof Type 5.716 - * infixop = "||" 5.717 - * | "&&" 5.718 - * | "|" 5.719 - * | "^" 5.720 - * | "&" 5.721 - * | "==" | "!=" 5.722 - * | "<" | ">" | "<=" | ">=" 5.723 - * | "<<" | ">>" | ">>>" 5.724 - * | "+" | "-" 5.725 - * | "*" | "/" | "%" 5.726 - */ 5.727 - JCExpression term2Rest(JCExpression t, int minprec) { 5.728 - List<JCExpression[]> savedOd = odStackSupply.elems; 5.729 - JCExpression[] odStack = newOdStack(); 5.730 - List<Token[]> savedOp = opStackSupply.elems; 5.731 - Token[] opStack = newOpStack(); 5.732 - // optimization, was odStack = new Tree[...]; opStack = new Tree[...]; 5.733 - int top = 0; 5.734 - odStack[0] = t; 5.735 - int startPos = S.pos(); 5.736 - Token topOp = ERROR; 5.737 - while (prec(S.token()) >= minprec) { 5.738 - opStack[top] = topOp; 5.739 - top++; 5.740 - topOp = S.token(); 5.741 - int pos = S.pos(); 5.742 - S.nextToken(); 5.743 - odStack[top] = topOp == INSTANCEOF ? type() : term3(); 5.744 - while (top > 0 && prec(topOp) >= prec(S.token())) { 5.745 - odStack[top-1] = makeOp(pos, topOp, odStack[top-1], 5.746 - odStack[top]); 5.747 - top--; 5.748 - topOp = opStack[top]; 5.749 - } 5.750 - } 5.751 - assert top == 0; 5.752 - t = odStack[0]; 5.753 - 5.754 - if (t.getTag() == JCTree.PLUS) { 5.755 - StringBuffer buf = foldStrings(t); 5.756 - if (buf != null) { 5.757 - t = toP(F.at(startPos).Literal(TypeTags.CLASS, buf.toString())); 5.758 - } 5.759 - } 5.760 - 5.761 - odStackSupply.elems = savedOd; // optimization 5.762 - opStackSupply.elems = savedOp; // optimization 5.763 - return t; 5.764 - } 5.765 -//where 5.766 - /** Construct a binary or type test node. 5.767 - */ 5.768 - private JCExpression makeOp(int pos, 5.769 - Token topOp, 5.770 - JCExpression od1, 5.771 - JCExpression od2) 5.772 - { 5.773 - if (topOp == INSTANCEOF) { 5.774 - return F.at(pos).TypeTest(od1, od2); 5.775 - } else { 5.776 - return F.at(pos).Binary(optag(topOp), od1, od2); 5.777 - } 5.778 - } 5.779 - /** If tree is a concatenation of string literals, replace it 5.780 - * by a single literal representing the concatenated string. 5.781 - */ 5.782 - protected StringBuffer foldStrings(JCTree tree) { 5.783 - List<String> buf = List.nil(); 5.784 - while (true) { 5.785 - if (tree.getTag() == JCTree.LITERAL) { 5.786 - JCLiteral lit = (JCLiteral) tree; 5.787 - if (lit.typetag == TypeTags.CLASS) { 5.788 - StringBuffer sbuf = 5.789 - new StringBuffer((String)lit.value); 5.790 - while (buf.nonEmpty()) { 5.791 - sbuf.append(buf.head); 5.792 - buf = buf.tail; 5.793 - } 5.794 - return sbuf; 5.795 - } 5.796 - } else if (tree.getTag() == JCTree.PLUS) { 5.797 - JCBinary op = (JCBinary)tree; 5.798 - if (op.rhs.getTag() == JCTree.LITERAL) { 5.799 - JCLiteral lit = (JCLiteral) op.rhs; 5.800 - if (lit.typetag == TypeTags.CLASS) { 5.801 - buf = buf.prepend((String) lit.value); 5.802 - tree = op.lhs; 5.803 - continue; 5.804 - } 5.805 - } 5.806 - } 5.807 - return null; 5.808 - } 5.809 - } 5.810 - 5.811 - /** optimization: To save allocating a new operand/operator stack 5.812 - * for every binary operation, we use supplys. 5.813 - */ 5.814 - ListBuffer<JCExpression[]> odStackSupply = new ListBuffer<JCExpression[]>(); 5.815 - ListBuffer<Token[]> opStackSupply = new ListBuffer<Token[]>(); 5.816 - 5.817 - private JCExpression[] newOdStack() { 5.818 - if (odStackSupply.elems == odStackSupply.last) 5.819 - odStackSupply.append(new JCExpression[infixPrecedenceLevels + 1]); 5.820 - JCExpression[] odStack = odStackSupply.elems.head; 5.821 - odStackSupply.elems = odStackSupply.elems.tail; 5.822 - return odStack; 5.823 - } 5.824 - 5.825 - private Token[] newOpStack() { 5.826 - if (opStackSupply.elems == opStackSupply.last) 5.827 - opStackSupply.append(new Token[infixPrecedenceLevels + 1]); 5.828 - Token[] opStack = opStackSupply.elems.head; 5.829 - opStackSupply.elems = opStackSupply.elems.tail; 5.830 - return opStack; 5.831 - } 5.832 - 5.833 - /** Expression3 = PrefixOp Expression3 5.834 - * | "(" Expr | TypeNoParams ")" Expression3 5.835 - * | Primary {Selector} {PostfixOp} 5.836 - * Primary = "(" Expression ")" 5.837 - * | Literal 5.838 - * | [TypeArguments] THIS [Arguments] 5.839 - * | [TypeArguments] SUPER SuperSuffix 5.840 - * | NEW [TypeArguments] Creator 5.841 - * | Ident { "." Ident } 5.842 - * [ "[" ( "]" BracketsOpt "." CLASS | Expression "]" ) 5.843 - * | Arguments 5.844 - * | "." ( CLASS | THIS | [TypeArguments] SUPER Arguments | NEW [TypeArguments] InnerCreator ) 5.845 - * ] 5.846 - * | BasicType BracketsOpt "." CLASS 5.847 - * PrefixOp = "++" | "--" | "!" | "~" | "+" | "-" 5.848 - * PostfixOp = "++" | "--" 5.849 - * Type3 = Ident { "." Ident } [TypeArguments] {TypeSelector} BracketsOpt 5.850 - * | BasicType 5.851 - * TypeNoParams3 = Ident { "." Ident } BracketsOpt 5.852 - * Selector = "." [TypeArguments] Ident [Arguments] 5.853 - * | "." THIS 5.854 - * | "." [TypeArguments] SUPER SuperSuffix 5.855 - * | "." NEW [TypeArguments] InnerCreator 5.856 - * | "[" Expression "]" 5.857 - * TypeSelector = "." Ident [TypeArguments] 5.858 - * SuperSuffix = Arguments | "." Ident [Arguments] 5.859 - */ 5.860 - protected JCExpression term3() { 5.861 - int pos = S.pos(); 5.862 - JCExpression t; 5.863 - List<JCExpression> typeArgs = typeArgumentsOpt(EXPR); 5.864 - switch (S.token()) { 5.865 - case QUES: 5.866 - if ((mode & TYPE) != 0 && (mode & (TYPEARG|NOPARAMS)) == TYPEARG) { 5.867 - mode = TYPE; 5.868 - return typeArgument(); 5.869 - } else 5.870 - return illegal(); 5.871 - case PLUSPLUS: case SUBSUB: case BANG: case TILDE: case PLUS: case SUB: 5.872 - if (typeArgs == null && (mode & EXPR) != 0) { 5.873 - Token token = S.token(); 5.874 - S.nextToken(); 5.875 - mode = EXPR; 5.876 - if (token == SUB && 5.877 - (S.token() == INTLITERAL || S.token() == LONGLITERAL) && 5.878 - S.radix() == 10) { 5.879 - mode = EXPR; 5.880 - t = literal(names.hyphen); 5.881 - } else { 5.882 - t = term3(); 5.883 - return F.at(pos).Unary(unoptag(token), t); 5.884 - } 5.885 - } else return illegal(); 5.886 - break; 5.887 - case LPAREN: 5.888 - if (typeArgs == null && (mode & EXPR) != 0) { 5.889 - S.nextToken(); 5.890 - mode = EXPR | TYPE | NOPARAMS; 5.891 - t = term3(); 5.892 - if ((mode & TYPE) != 0 && S.token() == LT) { 5.893 - // Could be a cast to a parameterized type 5.894 - int op = JCTree.LT; 5.895 - int pos1 = S.pos(); 5.896 - S.nextToken(); 5.897 - mode &= (EXPR | TYPE); 5.898 - mode |= TYPEARG; 5.899 - JCExpression t1 = term3(); 5.900 - if ((mode & TYPE) != 0 && 5.901 - (S.token() == COMMA || S.token() == GT)) { 5.902 - mode = TYPE; 5.903 - ListBuffer<JCExpression> args = new ListBuffer<JCExpression>(); 5.904 - args.append(t1); 5.905 - while (S.token() == COMMA) { 5.906 - S.nextToken(); 5.907 - args.append(typeArgument()); 5.908 - } 5.909 - accept(GT); 5.910 - t = F.at(pos1).TypeApply(t, args.toList()); 5.911 - checkGenerics(); 5.912 - t = bracketsOpt(toP(t)); 5.913 - } else if ((mode & EXPR) != 0) { 5.914 - mode = EXPR; 5.915 - t = F.at(pos1).Binary(op, t, term2Rest(t1, TreeInfo.shiftPrec)); 5.916 - t = termRest(term1Rest(term2Rest(t, TreeInfo.orPrec))); 5.917 - } else { 5.918 - accept(GT); 5.919 - } 5.920 - } else { 5.921 - t = termRest(term1Rest(term2Rest(t, TreeInfo.orPrec))); 5.922 - } 5.923 - accept(RPAREN); 5.924 - lastmode = mode; 5.925 - mode = EXPR; 5.926 - if ((lastmode & EXPR) == 0) { 5.927 - JCExpression t1 = term3(); 5.928 - return F.at(pos).TypeCast(t, t1); 5.929 - } else if ((lastmode & TYPE) != 0) { 5.930 - switch (S.token()) { 5.931 - /*case PLUSPLUS: case SUBSUB: */ 5.932 - case BANG: case TILDE: 5.933 - case LPAREN: case THIS: case SUPER: 5.934 - case INTLITERAL: case LONGLITERAL: case FLOATLITERAL: 5.935 - case DOUBLELITERAL: case CHARLITERAL: case STRINGLITERAL: 5.936 - case TRUE: case FALSE: case NULL: 5.937 - case NEW: case IDENTIFIER: case ASSERT: case ENUM: 5.938 - case BYTE: case SHORT: case CHAR: case INT: 5.939 - case LONG: case FLOAT: case DOUBLE: case BOOLEAN: case VOID: 5.940 - JCExpression t1 = term3(); 5.941 - return F.at(pos).TypeCast(t, t1); 5.942 - } 5.943 - } 5.944 - } else return illegal(); 5.945 - t = toP(F.at(pos).Parens(t)); 5.946 - break; 5.947 - case THIS: 5.948 - if ((mode & EXPR) != 0) { 5.949 - mode = EXPR; 5.950 - t = to(F.at(pos).Ident(names._this)); 5.951 - S.nextToken(); 5.952 - if (typeArgs == null) 5.953 - t = argumentsOpt(null, t); 5.954 - else 5.955 - t = arguments(typeArgs, t); 5.956 - typeArgs = null; 5.957 - } else return illegal(); 5.958 - break; 5.959 - case SUPER: 5.960 - if ((mode & EXPR) != 0) { 5.961 - mode = EXPR; 5.962 - t = to(superSuffix(typeArgs, F.at(pos).Ident(names._super))); 5.963 - typeArgs = null; 5.964 - } else return illegal(); 5.965 - break; 5.966 - case INTLITERAL: case LONGLITERAL: case FLOATLITERAL: case DOUBLELITERAL: 5.967 - case CHARLITERAL: case STRINGLITERAL: 5.968 - case TRUE: case FALSE: case NULL: 5.969 - if (typeArgs == null && (mode & EXPR) != 0) { 5.970 - mode = EXPR; 5.971 - t = literal(names.empty); 5.972 - } else return illegal(); 5.973 - break; 5.974 - case NEW: 5.975 - if (typeArgs != null) return illegal(); 5.976 - if ((mode & EXPR) != 0) { 5.977 - mode = EXPR; 5.978 - S.nextToken(); 5.979 - if (S.token() == LT) typeArgs = typeArguments(); 5.980 - t = creator(pos, typeArgs); 5.981 - typeArgs = null; 5.982 - } else return illegal(); 5.983 - break; 5.984 - case IDENTIFIER: case ASSERT: case ENUM: 5.985 - if (typeArgs != null) return illegal(); 5.986 - t = toP(F.at(S.pos()).Ident(ident())); 5.987 - loop: while (true) { 5.988 - pos = S.pos(); 5.989 - switch (S.token()) { 5.990 - case LBRACKET: 5.991 - S.nextToken(); 5.992 - if (S.token() == RBRACKET) { 5.993 - S.nextToken(); 5.994 - t = bracketsOpt(t); 5.995 - t = toP(F.at(pos).TypeArray(t)); 5.996 - t = bracketsSuffix(t); 5.997 - } else { 5.998 - if ((mode & EXPR) != 0) { 5.999 - mode = EXPR; 5.1000 - JCExpression t1 = term(); 5.1001 - t = to(F.at(pos).Indexed(t, t1)); 5.1002 - } 5.1003 - accept(RBRACKET); 5.1004 - } 5.1005 - break loop; 5.1006 - case LPAREN: 5.1007 - if ((mode & EXPR) != 0) { 5.1008 - mode = EXPR; 5.1009 - t = arguments(typeArgs, t); 5.1010 - typeArgs = null; 5.1011 - } 5.1012 - break loop; 5.1013 - case DOT: 5.1014 - S.nextToken(); 5.1015 - int oldmode = mode; 5.1016 - mode &= ~NOPARAMS; 5.1017 - typeArgs = typeArgumentsOpt(EXPR); 5.1018 - mode = oldmode; 5.1019 - if ((mode & EXPR) != 0) { 5.1020 - switch (S.token()) { 5.1021 - case CLASS: 5.1022 - if (typeArgs != null) return illegal(); 5.1023 - mode = EXPR; 5.1024 - t = to(F.at(pos).Select(t, names._class)); 5.1025 - S.nextToken(); 5.1026 - break loop; 5.1027 - case THIS: 5.1028 - if (typeArgs != null) return illegal(); 5.1029 - mode = EXPR; 5.1030 - t = to(F.at(pos).Select(t, names._this)); 5.1031 - S.nextToken(); 5.1032 - break loop; 5.1033 - case SUPER: 5.1034 - mode = EXPR; 5.1035 - t = to(F.at(pos).Select(t, names._super)); 5.1036 - t = superSuffix(typeArgs, t); 5.1037 - typeArgs = null; 5.1038 - break loop; 5.1039 - case NEW: 5.1040 - if (typeArgs != null) return illegal(); 5.1041 - mode = EXPR; 5.1042 - int pos1 = S.pos(); 5.1043 - S.nextToken(); 5.1044 - if (S.token() == LT) typeArgs = typeArguments(); 5.1045 - t = innerCreator(pos1, typeArgs, t); 5.1046 - typeArgs = null; 5.1047 - break loop; 5.1048 - } 5.1049 - } 5.1050 - // typeArgs saved for next loop iteration. 5.1051 - t = toP(F.at(pos).Select(t, ident())); 5.1052 - break; 5.1053 - default: 5.1054 - break loop; 5.1055 - } 5.1056 - } 5.1057 - if (typeArgs != null) illegal(); 5.1058 - t = typeArgumentsOpt(t); 5.1059 - break; 5.1060 - case BYTE: case SHORT: case CHAR: case INT: case LONG: case FLOAT: 5.1061 - case DOUBLE: case BOOLEAN: 5.1062 - if (typeArgs != null) illegal(); 5.1063 - t = bracketsSuffix(bracketsOpt(basicType())); 5.1064 - break; 5.1065 - case VOID: 5.1066 - if (typeArgs != null) illegal(); 5.1067 - if ((mode & EXPR) != 0) { 5.1068 - S.nextToken(); 5.1069 - if (S.token() == DOT) { 5.1070 - JCPrimitiveTypeTree ti = toP(F.at(pos).TypeIdent(TypeTags.VOID)); 5.1071 - t = bracketsSuffix(ti); 5.1072 - } else { 5.1073 - return illegal(pos); 5.1074 - } 5.1075 - } else { 5.1076 - return illegal(); 5.1077 - } 5.1078 - break; 5.1079 - default: 5.1080 - return illegal(); 5.1081 - } 5.1082 - if (typeArgs != null) illegal(); 5.1083 - while (true) { 5.1084 - int pos1 = S.pos(); 5.1085 - if (S.token() == LBRACKET) { 5.1086 - S.nextToken(); 5.1087 - if ((mode & TYPE) != 0) { 5.1088 - int oldmode = mode; 5.1089 - mode = TYPE; 5.1090 - if (S.token() == RBRACKET) { 5.1091 - S.nextToken(); 5.1092 - t = bracketsOpt(t); 5.1093 - t = toP(F.at(pos1).TypeArray(t)); 5.1094 - return t; 5.1095 - } 5.1096 - mode = oldmode; 5.1097 - } 5.1098 - if ((mode & EXPR) != 0) { 5.1099 - mode = EXPR; 5.1100 - JCExpression t1 = term(); 5.1101 - t = to(F.at(pos1).Indexed(t, t1)); 5.1102 - } 5.1103 - accept(RBRACKET); 5.1104 - } else if (S.token() == DOT) { 5.1105 - S.nextToken(); 5.1106 - typeArgs = typeArgumentsOpt(EXPR); 5.1107 - if (S.token() == SUPER && (mode & EXPR) != 0) { 5.1108 - mode = EXPR; 5.1109 - t = to(F.at(pos1).Select(t, names._super)); 5.1110 - S.nextToken(); 5.1111 - t = arguments(typeArgs, t); 5.1112 - typeArgs = null; 5.1113 - } else if (S.token() == NEW && (mode & EXPR) != 0) { 5.1114 - if (typeArgs != null) return illegal(); 5.1115 - mode = EXPR; 5.1116 - int pos2 = S.pos(); 5.1117 - S.nextToken(); 5.1118 - if (S.token() == LT) typeArgs = typeArguments(); 5.1119 - t = innerCreator(pos2, typeArgs, t); 5.1120 - typeArgs = null; 5.1121 - } else { 5.1122 - t = toP(F.at(pos1).Select(t, ident())); 5.1123 - t = argumentsOpt(typeArgs, typeArgumentsOpt(t)); 5.1124 - typeArgs = null; 5.1125 - } 5.1126 - } else { 5.1127 - break; 5.1128 - } 5.1129 - } 5.1130 - while ((S.token() == PLUSPLUS || S.token() == SUBSUB) && (mode & EXPR) != 0) { 5.1131 - mode = EXPR; 5.1132 - t = to(F.at(S.pos()).Unary( 5.1133 - S.token() == PLUSPLUS ? JCTree.POSTINC : JCTree.POSTDEC, t)); 5.1134 - S.nextToken(); 5.1135 - } 5.1136 - return toP(t); 5.1137 - } 5.1138 - 5.1139 - /** SuperSuffix = Arguments | "." [TypeArguments] Ident [Arguments] 5.1140 - */ 5.1141 - JCExpression superSuffix(List<JCExpression> typeArgs, JCExpression t) { 5.1142 - S.nextToken(); 5.1143 - if (S.token() == LPAREN || typeArgs != null) { 5.1144 - t = arguments(typeArgs, t); 5.1145 - } else { 5.1146 - int pos = S.pos(); 5.1147 - accept(DOT); 5.1148 - typeArgs = (S.token() == LT) ? typeArguments() : null; 5.1149 - t = toP(F.at(pos).Select(t, ident())); 5.1150 - t = argumentsOpt(typeArgs, t); 5.1151 - } 5.1152 - return t; 5.1153 - } 5.1154 - 5.1155 - /** BasicType = BYTE | SHORT | CHAR | INT | LONG | FLOAT | DOUBLE | BOOLEAN 5.1156 - */ 5.1157 - JCPrimitiveTypeTree basicType() { 5.1158 - JCPrimitiveTypeTree t = to(F.at(S.pos()).TypeIdent(typetag(S.token()))); 5.1159 - S.nextToken(); 5.1160 - return t; 5.1161 - } 5.1162 - 5.1163 - /** ArgumentsOpt = [ Arguments ] 5.1164 - */ 5.1165 - JCExpression argumentsOpt(List<JCExpression> typeArgs, JCExpression t) { 5.1166 - if ((mode & EXPR) != 0 && S.token() == LPAREN || typeArgs != null) { 5.1167 - mode = EXPR; 5.1168 - return arguments(typeArgs, t); 5.1169 - } else { 5.1170 - return t; 5.1171 - } 5.1172 - } 5.1173 - 5.1174 - /** Arguments = "(" [Expression { COMMA Expression }] ")" 5.1175 - */ 5.1176 - List<JCExpression> arguments() { 5.1177 - ListBuffer<JCExpression> args = lb(); 5.1178 - if (S.token() == LPAREN) { 5.1179 - S.nextToken(); 5.1180 - if (S.token() != RPAREN) { 5.1181 - args.append(expression()); 5.1182 - while (S.token() == COMMA) { 5.1183 - S.nextToken(); 5.1184 - args.append(expression()); 5.1185 - } 5.1186 - } 5.1187 - accept(RPAREN); 5.1188 - } else { 5.1189 - syntaxError(S.pos(), "expected", LPAREN); 5.1190 - } 5.1191 - return args.toList(); 5.1192 - } 5.1193 - 5.1194 - JCMethodInvocation arguments(List<JCExpression> typeArgs, JCExpression t) { 5.1195 - int pos = S.pos(); 5.1196 - List<JCExpression> args = arguments(); 5.1197 - return toP(F.at(pos).Apply(typeArgs, t, args)); 5.1198 - } 5.1199 - 5.1200 - /** TypeArgumentsOpt = [ TypeArguments ] 5.1201 - */ 5.1202 - JCExpression typeArgumentsOpt(JCExpression t) { 5.1203 - if (S.token() == LT && 5.1204 - (mode & TYPE) != 0 && 5.1205 - (mode & NOPARAMS) == 0) { 5.1206 - mode = TYPE; 5.1207 - checkGenerics(); 5.1208 - return typeArguments(t); 5.1209 - } else { 5.1210 - return t; 5.1211 - } 5.1212 - } 5.1213 - List<JCExpression> typeArgumentsOpt() { 5.1214 - return typeArgumentsOpt(TYPE); 5.1215 - } 5.1216 - 5.1217 - List<JCExpression> typeArgumentsOpt(int useMode) { 5.1218 - if (S.token() == LT) { 5.1219 - checkGenerics(); 5.1220 - if ((mode & useMode) == 0 || 5.1221 - (mode & NOPARAMS) != 0) { 5.1222 - illegal(); 5.1223 - } 5.1224 - mode = useMode; 5.1225 - return typeArguments(); 5.1226 - } 5.1227 - return null; 5.1228 - } 5.1229 - 5.1230 - /** TypeArguments = "<" TypeArgument {"," TypeArgument} ">" 5.1231 - */ 5.1232 - List<JCExpression> typeArguments() { 5.1233 - ListBuffer<JCExpression> args = lb(); 5.1234 - if (S.token() == LT) { 5.1235 - S.nextToken(); 5.1236 - args.append(((mode & EXPR) == 0) ? typeArgument() : type()); 5.1237 - while (S.token() == COMMA) { 5.1238 - S.nextToken(); 5.1239 - args.append(((mode & EXPR) == 0) ? typeArgument() : type()); 5.1240 - } 5.1241 - switch (S.token()) { 5.1242 - case GTGTGTEQ: 5.1243 - S.token(GTGTEQ); 5.1244 - break; 5.1245 - case GTGTEQ: 5.1246 - S.token(GTEQ); 5.1247 - break; 5.1248 - case GTEQ: 5.1249 - S.token(EQ); 5.1250 - break; 5.1251 - case GTGTGT: 5.1252 - S.token(GTGT); 5.1253 - break; 5.1254 - case GTGT: 5.1255 - S.token(GT); 5.1256 - break; 5.1257 - default: 5.1258 - accept(GT); 5.1259 - break; 5.1260 - } 5.1261 - } else { 5.1262 - syntaxError(S.pos(), "expected", LT); 5.1263 - } 5.1264 - return args.toList(); 5.1265 - } 5.1266 - 5.1267 - /** TypeArgument = Type 5.1268 - * | "?" 5.1269 - * | "?" EXTENDS Type {"&" Type} 5.1270 - * | "?" SUPER Type 5.1271 - */ 5.1272 - JCExpression typeArgument() { 5.1273 - if (S.token() != QUES) return type(); 5.1274 - int pos = S.pos(); 5.1275 - S.nextToken(); 5.1276 - if (S.token() == EXTENDS) { 5.1277 - TypeBoundKind t = to(F.at(S.pos()).TypeBoundKind(BoundKind.EXTENDS)); 5.1278 - S.nextToken(); 5.1279 - return F.at(pos).Wildcard(t, type()); 5.1280 - } else if (S.token() == SUPER) { 5.1281 - TypeBoundKind t = to(F.at(S.pos()).TypeBoundKind(BoundKind.SUPER)); 5.1282 - S.nextToken(); 5.1283 - return F.at(pos).Wildcard(t, type()); 5.1284 - } else if (S.token() == IDENTIFIER) { 5.1285 - //error recovery 5.1286 - reportSyntaxError(S.prevEndPos(), "expected3", 5.1287 - GT, EXTENDS, SUPER); 5.1288 - TypeBoundKind t = F.at(Position.NOPOS).TypeBoundKind(BoundKind.UNBOUND); 5.1289 - JCExpression wc = toP(F.at(pos).Wildcard(t, null)); 5.1290 - JCIdent id = toP(F.at(S.pos()).Ident(ident())); 5.1291 - return F.at(pos).Erroneous(List.<JCTree>of(wc, id)); 5.1292 - } else { 5.1293 - TypeBoundKind t = F.at(Position.NOPOS).TypeBoundKind(BoundKind.UNBOUND); 5.1294 - return toP(F.at(pos).Wildcard(t, null)); 5.1295 - } 5.1296 - } 5.1297 - 5.1298 - JCTypeApply typeArguments(JCExpression t) { 5.1299 - int pos = S.pos(); 5.1300 - List<JCExpression> args = typeArguments(); 5.1301 - return toP(F.at(pos).TypeApply(t, args)); 5.1302 - } 5.1303 - 5.1304 - /** BracketsOpt = {"[" "]"} 5.1305 - */ 5.1306 - private JCExpression bracketsOpt(JCExpression t) { 5.1307 - if (S.token() == LBRACKET) { 5.1308 - int pos = S.pos(); 5.1309 - S.nextToken(); 5.1310 - t = bracketsOptCont(t, pos); 5.1311 - F.at(pos); 5.1312 - } 5.1313 - return t; 5.1314 - } 5.1315 - 5.1316 - private JCArrayTypeTree bracketsOptCont(JCExpression t, int pos) { 5.1317 - accept(RBRACKET); 5.1318 - t = bracketsOpt(t); 5.1319 - return toP(F.at(pos).TypeArray(t)); 5.1320 - } 5.1321 - 5.1322 - /** BracketsSuffixExpr = "." CLASS 5.1323 - * BracketsSuffixType = 5.1324 - */ 5.1325 - JCExpression bracketsSuffix(JCExpression t) { 5.1326 - if ((mode & EXPR) != 0 && S.token() == DOT) { 5.1327 - mode = EXPR; 5.1328 - int pos = S.pos(); 5.1329 - S.nextToken(); 5.1330 - accept(CLASS); 5.1331 - if (S.pos() == errorEndPos) { 5.1332 - // error recovery 5.1333 - Name name = null; 5.1334 - if (S.token() == IDENTIFIER) { 5.1335 - name = S.name(); 5.1336 - S.nextToken(); 5.1337 - } else { 5.1338 - name = names.error; 5.1339 - } 5.1340 - t = F.at(pos).Erroneous(List.<JCTree>of(toP(F.at(pos).Select(t, name)))); 5.1341 - } else { 5.1342 - t = toP(F.at(pos).Select(t, names._class)); 5.1343 - } 5.1344 - } else if ((mode & TYPE) != 0) { 5.1345 - mode = TYPE; 5.1346 - } else { 5.1347 - syntaxError(S.pos(), "dot.class.expected"); 5.1348 - } 5.1349 - return t; 5.1350 - } 5.1351 - 5.1352 - /** Creator = Qualident [TypeArguments] ( ArrayCreatorRest | ClassCreatorRest ) 5.1353 - */ 5.1354 - JCExpression creator(int newpos, List<JCExpression> typeArgs) { 5.1355 - switch (S.token()) { 5.1356 - case BYTE: case SHORT: case CHAR: case INT: case LONG: case FLOAT: 5.1357 - case DOUBLE: case BOOLEAN: 5.1358 - if (typeArgs == null) 5.1359 - return arrayCreatorRest(newpos, basicType()); 5.1360 - break; 5.1361 - default: 5.1362 - } 5.1363 - JCExpression t = qualident(); 5.1364 - int oldmode = mode; 5.1365 - mode = TYPE; 5.1366 - if (S.token() == LT) { 5.1367 - checkGenerics(); 5.1368 - t = typeArguments(t); 5.1369 - } 5.1370 - while (S.token() == DOT) { 5.1371 - int pos = S.pos(); 5.1372 - S.nextToken(); 5.1373 - t = toP(F.at(pos).Select(t, ident())); 5.1374 - if (S.token() == LT) { 5.1375 - checkGenerics(); 5.1376 - t = typeArguments(t); 5.1377 - } 5.1378 - } 5.1379 - mode = oldmode; 5.1380 - if (S.token() == LBRACKET) { 5.1381 - JCExpression e = arrayCreatorRest(newpos, t); 5.1382 - if (typeArgs != null) { 5.1383 - int pos = newpos; 5.1384 - if (!typeArgs.isEmpty() && typeArgs.head.pos != Position.NOPOS) { 5.1385 - // note: this should always happen but we should 5.1386 - // not rely on this as the parser is continuously 5.1387 - // modified to improve error recovery. 5.1388 - pos = typeArgs.head.pos; 5.1389 - } 5.1390 - setErrorEndPos(S.prevEndPos()); 5.1391 - reportSyntaxError(pos, "cannot.create.array.with.type.arguments"); 5.1392 - return toP(F.at(newpos).Erroneous(typeArgs.prepend(e))); 5.1393 - } 5.1394 - return e; 5.1395 - } else if (S.token() == LPAREN) { 5.1396 - return classCreatorRest(newpos, null, typeArgs, t); 5.1397 - } else { 5.1398 - reportSyntaxError(S.pos(), "expected2", 5.1399 - LPAREN, LBRACKET); 5.1400 - t = toP(F.at(newpos).NewClass(null, typeArgs, t, List.<JCExpression>nil(), null)); 5.1401 - return toP(F.at(newpos).Erroneous(List.<JCTree>of(t))); 5.1402 - } 5.1403 - } 5.1404 - 5.1405 - /** InnerCreator = Ident [TypeArguments] ClassCreatorRest 5.1406 - */ 5.1407 - JCExpression innerCreator(int newpos, List<JCExpression> typeArgs, JCExpression encl) { 5.1408 - JCExpression t = toP(F.at(S.pos()).Ident(ident())); 5.1409 - if (S.token() == LT) { 5.1410 - checkGenerics(); 5.1411 - t = typeArguments(t); 5.1412 - } 5.1413 - return classCreatorRest(newpos, encl, typeArgs, t); 5.1414 - } 5.1415 - 5.1416 - /** ArrayCreatorRest = "[" ( "]" BracketsOpt ArrayInitializer 5.1417 - * | Expression "]" {"[" Expression "]"} BracketsOpt ) 5.1418 - */ 5.1419 - JCExpression arrayCreatorRest(int newpos, JCExpression elemtype) { 5.1420 - accept(LBRACKET); 5.1421 - if (S.token() == RBRACKET) { 5.1422 - accept(RBRACKET); 5.1423 - elemtype = bracketsOpt(elemtype); 5.1424 - if (S.token() == LBRACE) { 5.1425 - return arrayInitializer(newpos, elemtype); 5.1426 - } else { 5.1427 - return syntaxError(S.pos(), "array.dimension.missing"); 5.1428 - } 5.1429 - } else { 5.1430 - ListBuffer<JCExpression> dims = new ListBuffer<JCExpression>(); 5.1431 - dims.append(expression()); 5.1432 - accept(RBRACKET); 5.1433 - while (S.token() == LBRACKET) { 5.1434 - int pos = S.pos(); 5.1435 - S.nextToken(); 5.1436 - if (S.token() == RBRACKET) { 5.1437 - elemtype = bracketsOptCont(elemtype, pos); 5.1438 - } else { 5.1439 - dims.append(expression()); 5.1440 - accept(RBRACKET); 5.1441 - } 5.1442 - } 5.1443 - return toP(F.at(newpos).NewArray(elemtype, dims.toList(), null)); 5.1444 - } 5.1445 - } 5.1446 - 5.1447 - /** ClassCreatorRest = Arguments [ClassBody] 5.1448 - */ 5.1449 - JCExpression classCreatorRest(int newpos, 5.1450 - JCExpression encl, 5.1451 - List<JCExpression> typeArgs, 5.1452 - JCExpression t) 5.1453 - { 5.1454 - List<JCExpression> args = arguments(); 5.1455 - JCClassDecl body = null; 5.1456 - if (S.token() == LBRACE) { 5.1457 - int pos = S.pos(); 5.1458 - List<JCTree> defs = classOrInterfaceBody(names.empty, false); 5.1459 - JCModifiers mods = F.at(Position.NOPOS).Modifiers(0); 5.1460 - body = toP(F.at(pos).AnonymousClassDef(mods, defs)); 5.1461 - } 5.1462 - return toP(F.at(newpos).NewClass(encl, typeArgs, t, args, body)); 5.1463 - } 5.1464 - 5.1465 - /** ArrayInitializer = "{" [VariableInitializer {"," VariableInitializer}] [","] "}" 5.1466 - */ 5.1467 - JCExpression arrayInitializer(int newpos, JCExpression t) { 5.1468 - accept(LBRACE); 5.1469 - ListBuffer<JCExpression> elems = new ListBuffer<JCExpression>(); 5.1470 - if (S.token() == COMMA) { 5.1471 - S.nextToken(); 5.1472 - } else if (S.token() != RBRACE) { 5.1473 - elems.append(variableInitializer()); 5.1474 - while (S.token() == COMMA) { 5.1475 - S.nextToken(); 5.1476 - if (S.token() == RBRACE) break; 5.1477 - elems.append(variableInitializer()); 5.1478 - } 5.1479 - } 5.1480 - accept(RBRACE); 5.1481 - return toP(F.at(newpos).NewArray(t, List.<JCExpression>nil(), elems.toList())); 5.1482 - } 5.1483 - 5.1484 - /** VariableInitializer = ArrayInitializer | Expression 5.1485 - */ 5.1486 - public JCExpression variableInitializer() { 5.1487 - return S.token() == LBRACE ? arrayInitializer(S.pos(), null) : expression(); 5.1488 - } 5.1489 - 5.1490 - /** ParExpression = "(" Expression ")" 5.1491 - */ 5.1492 - JCExpression parExpression() { 5.1493 - accept(LPAREN); 5.1494 - JCExpression t = expression(); 5.1495 - accept(RPAREN); 5.1496 - return t; 5.1497 - } 5.1498 - 5.1499 - /** Block = "{" BlockStatements "}" 5.1500 - */ 5.1501 - JCBlock block(int pos, long flags) { 5.1502 - accept(LBRACE); 5.1503 - List<JCStatement> stats = blockStatements(); 5.1504 - JCBlock t = F.at(pos).Block(flags, stats); 5.1505 - while (S.token() == CASE || S.token() == DEFAULT) { 5.1506 - syntaxError("orphaned", S.token()); 5.1507 - switchBlockStatementGroups(); 5.1508 - } 5.1509 - // the Block node has a field "endpos" for first char of last token, which is 5.1510 - // usually but not necessarily the last char of the last token. 5.1511 - t.endpos = S.pos(); 5.1512 - accept(RBRACE); 5.1513 - return toP(t); 5.1514 - } 5.1515 - 5.1516 - public JCBlock block() { 5.1517 - return block(S.pos(), 0); 5.1518 - } 5.1519 - 5.1520 - /** BlockStatements = { BlockStatement } 5.1521 - * BlockStatement = LocalVariableDeclarationStatement 5.1522 - * | ClassOrInterfaceOrEnumDeclaration 5.1523 - * | [Ident ":"] Statement 5.1524 - * LocalVariableDeclarationStatement 5.1525 - * = { FINAL | '@' Annotation } Type VariableDeclarators ";" 5.1526 - */ 5.1527 - @SuppressWarnings("fallthrough") 5.1528 - List<JCStatement> blockStatements() { 5.1529 -//todo: skip to anchor on error(?) 5.1530 - int lastErrPos = -1; 5.1531 - ListBuffer<JCStatement> stats = new ListBuffer<JCStatement>(); 5.1532 - while (true) { 5.1533 - int pos = S.pos(); 5.1534 - switch (S.token()) { 5.1535 - case RBRACE: case CASE: case DEFAULT: case EOF: 5.1536 - return stats.toList(); 5.1537 - case LBRACE: case IF: case FOR: case WHILE: case DO: case TRY: 5.1538 - case SWITCH: case SYNCHRONIZED: case RETURN: case THROW: case BREAK: 5.1539 - case CONTINUE: case SEMI: case ELSE: case FINALLY: case CATCH: 5.1540 - stats.append(statement()); 5.1541 - break; 5.1542 - case MONKEYS_AT: 5.1543 - case FINAL: { 5.1544 - String dc = S.docComment(); 5.1545 - JCModifiers mods = modifiersOpt(); 5.1546 - if (S.token() == INTERFACE || 5.1547 - S.token() == CLASS || 5.1548 - allowEnums && S.token() == ENUM) { 5.1549 - stats.append(classOrInterfaceOrEnumDeclaration(mods, dc)); 5.1550 - } else { 5.1551 - JCExpression t = type(); 5.1552 - stats.appendList(variableDeclarators(mods, t, 5.1553 - new ListBuffer<JCStatement>())); 5.1554 - // A "LocalVariableDeclarationStatement" subsumes the terminating semicolon 5.1555 - storeEnd(stats.elems.last(), S.endPos()); 5.1556 - accept(SEMI); 5.1557 - } 5.1558 - break; 5.1559 - } 5.1560 - case ABSTRACT: case STRICTFP: { 5.1561 - String dc = S.docComment(); 5.1562 - JCModifiers mods = modifiersOpt(); 5.1563 - stats.append(classOrInterfaceOrEnumDeclaration(mods, dc)); 5.1564 - break; 5.1565 - } 5.1566 - case INTERFACE: 5.1567 - case CLASS: 5.1568 - stats.append(classOrInterfaceOrEnumDeclaration(modifiersOpt(), 5.1569 - S.docComment())); 5.1570 - break; 5.1571 - case ENUM: 5.1572 - case ASSERT: 5.1573 - if (allowEnums && S.token() == ENUM) { 5.1574 - log.error(S.pos(), "local.enum"); 5.1575 - stats. 5.1576 - append(classOrInterfaceOrEnumDeclaration(modifiersOpt(), 5.1577 - S.docComment())); 5.1578 - break; 5.1579 - } else if (allowAsserts && S.token() == ASSERT) { 5.1580 - stats.append(statement()); 5.1581 - break; 5.1582 - } 5.1583 - /* fall through to default */ 5.1584 - default: 5.1585 - Name name = S.name(); 5.1586 - JCExpression t = term(EXPR | TYPE); 5.1587 - if (S.token() == COLON && t.getTag() == JCTree.IDENT) { 5.1588 - S.nextToken(); 5.1589 - JCStatement stat = statement(); 5.1590 - stats.append(F.at(pos).Labelled(name, stat)); 5.1591 - } else if ((lastmode & TYPE) != 0 && 5.1592 - (S.token() == IDENTIFIER || 5.1593 - S.token() == ASSERT || 5.1594 - S.token() == ENUM)) { 5.1595 - pos = S.pos(); 5.1596 - JCModifiers mods = F.at(Position.NOPOS).Modifiers(0); 5.1597 - F.at(pos); 5.1598 - stats.appendList(variableDeclarators(mods, t, 5.1599 - new ListBuffer<JCStatement>())); 5.1600 - // A "LocalVariableDeclarationStatement" subsumes the terminating semicolon 5.1601 - storeEnd(stats.elems.last(), S.endPos()); 5.1602 - accept(SEMI); 5.1603 - } else { 5.1604 - // This Exec is an "ExpressionStatement"; it subsumes the terminating semicolon 5.1605 - stats.append(to(F.at(pos).Exec(checkExprStat(t)))); 5.1606 - accept(SEMI); 5.1607 - } 5.1608 - } 5.1609 - 5.1610 - // error recovery 5.1611 - if (S.pos() == lastErrPos) 5.1612 - return stats.toList(); 5.1613 - if (S.pos() <= errorEndPos) { 5.1614 - skip(false, true, true, true); 5.1615 - lastErrPos = S.pos(); 5.1616 - } 5.1617 - 5.1618 - // ensure no dangling /** @deprecated */ active 5.1619 - S.resetDeprecatedFlag(); 5.1620 - } 5.1621 - } 5.1622 - 5.1623 - /** Statement = 5.1624 - * Block 5.1625 - * | IF ParExpression Statement [ELSE Statement] 5.1626 - * | FOR "(" ForInitOpt ";" [Expression] ";" ForUpdateOpt ")" Statement 5.1627 - * | FOR "(" FormalParameter : Expression ")" Statement 5.1628 - * | WHILE ParExpression Statement 5.1629 - * | DO Statement WHILE ParExpression ";" 5.1630 - * | TRY Block ( Catches | [Catches] FinallyPart ) 5.1631 - * | SWITCH ParExpression "{" SwitchBlockStatementGroups "}" 5.1632 - * | SYNCHRONIZED ParExpression Block 5.1633 - * | RETURN [Expression] ";" 5.1634 - * | THROW Expression ";" 5.1635 - * | BREAK [Ident] ";" 5.1636 - * | CONTINUE [Ident] ";" 5.1637 - * | ASSERT Expression [ ":" Expression ] ";" 5.1638 - * | ";" 5.1639 - * | ExpressionStatement 5.1640 - * | Ident ":" Statement 5.1641 - */ 5.1642 - @SuppressWarnings("fallthrough") 5.1643 - public JCStatement statement() { 5.1644 - int pos = S.pos(); 5.1645 - switch (S.token()) { 5.1646 - case LBRACE: 5.1647 - return block(); 5.1648 - case IF: { 5.1649 - S.nextToken(); 5.1650 - JCExpression cond = parExpression(); 5.1651 - JCStatement thenpart = statement(); 5.1652 - JCStatement elsepart = null; 5.1653 - if (S.token() == ELSE) { 5.1654 - S.nextToken(); 5.1655 - elsepart = statement(); 5.1656 - } 5.1657 - return F.at(pos).If(cond, thenpart, elsepart); 5.1658 - } 5.1659 - case FOR: { 5.1660 - S.nextToken(); 5.1661 - accept(LPAREN); 5.1662 - List<JCStatement> inits = S.token() == SEMI ? List.<JCStatement>nil() : forInit(); 5.1663 - if (inits.length() == 1 && 5.1664 - inits.head.getTag() == JCTree.VARDEF && 5.1665 - ((JCVariableDecl) inits.head).init == null && 5.1666 - S.token() == COLON) { 5.1667 - checkForeach(); 5.1668 - JCVariableDecl var = (JCVariableDecl)inits.head; 5.1669 - accept(COLON); 5.1670 - JCExpression expr = expression(); 5.1671 - accept(RPAREN); 5.1672 - JCStatement body = statement(); 5.1673 - return F.at(pos).ForeachLoop(var, expr, body); 5.1674 - } else { 5.1675 - accept(SEMI); 5.1676 - JCExpression cond = S.token() == SEMI ? null : expression(); 5.1677 - accept(SEMI); 5.1678 - List<JCExpressionStatement> steps = S.token() == RPAREN ? List.<JCExpressionStatement>nil() : forUpdate(); 5.1679 - accept(RPAREN); 5.1680 - JCStatement body = statement(); 5.1681 - return F.at(pos).ForLoop(inits, cond, steps, body); 5.1682 - } 5.1683 - } 5.1684 - case WHILE: { 5.1685 - S.nextToken(); 5.1686 - JCExpression cond = parExpression(); 5.1687 - JCStatement body = statement(); 5.1688 - return F.at(pos).WhileLoop(cond, body); 5.1689 - } 5.1690 - case DO: { 5.1691 - S.nextToken(); 5.1692 - JCStatement body = statement(); 5.1693 - accept(WHILE); 5.1694 - JCExpression cond = parExpression(); 5.1695 - JCDoWhileLoop t = to(F.at(pos).DoLoop(body, cond)); 5.1696 - accept(SEMI); 5.1697 - return t; 5.1698 - } 5.1699 - case TRY: { 5.1700 - S.nextToken(); 5.1701 - JCBlock body = block(); 5.1702 - ListBuffer<JCCatch> catchers = new ListBuffer<JCCatch>(); 5.1703 - JCBlock finalizer = null; 5.1704 - if (S.token() == CATCH || S.token() == FINALLY) { 5.1705 - while (S.token() == CATCH) catchers.append(catchClause()); 5.1706 - if (S.token() == FINALLY) { 5.1707 - S.nextToken(); 5.1708 - finalizer = block(); 5.1709 - } 5.1710 - } else { 5.1711 - log.error(pos, "try.without.catch.or.finally"); 5.1712 - } 5.1713 - return F.at(pos).Try(body, catchers.toList(), finalizer); 5.1714 - } 5.1715 - case SWITCH: { 5.1716 - S.nextToken(); 5.1717 - JCExpression selector = parExpression(); 5.1718 - accept(LBRACE); 5.1719 - List<JCCase> cases = switchBlockStatementGroups(); 5.1720 - JCSwitch t = to(F.at(pos).Switch(selector, cases)); 5.1721 - accept(RBRACE); 5.1722 - return t; 5.1723 - } 5.1724 - case SYNCHRONIZED: { 5.1725 - S.nextToken(); 5.1726 - JCExpression lock = parExpression(); 5.1727 - JCBlock body = block(); 5.1728 - return F.at(pos).Synchronized(lock, body); 5.1729 - } 5.1730 - case RETURN: { 5.1731 - S.nextToken(); 5.1732 - JCExpression result = S.token() == SEMI ? null : expression(); 5.1733 - JCReturn t = to(F.at(pos).Return(result)); 5.1734 - accept(SEMI); 5.1735 - return t; 5.1736 - } 5.1737 - case THROW: { 5.1738 - S.nextToken(); 5.1739 - JCExpression exc = expression(); 5.1740 - JCThrow t = to(F.at(pos).Throw(exc)); 5.1741 - accept(SEMI); 5.1742 - return t; 5.1743 - } 5.1744 - case BREAK: { 5.1745 - S.nextToken(); 5.1746 - Name label = (S.token() == IDENTIFIER || S.token() == ASSERT || S.token() == ENUM) ? ident() : null; 5.1747 - JCBreak t = to(F.at(pos).Break(label)); 5.1748 - accept(SEMI); 5.1749 - return t; 5.1750 - } 5.1751 - case CONTINUE: { 5.1752 - S.nextToken(); 5.1753 - Name label = (S.token() == IDENTIFIER || S.token() == ASSERT || S.token() == ENUM) ? ident() : null; 5.1754 - JCContinue t = to(F.at(pos).Continue(label)); 5.1755 - accept(SEMI); 5.1756 - return t; 5.1757 - } 5.1758 - case SEMI: 5.1759 - S.nextToken(); 5.1760 - return toP(F.at(pos).Skip()); 5.1761 - case ELSE: 5.1762 - return toP(F.Exec(syntaxError("else.without.if"))); 5.1763 - case FINALLY: 5.1764 - return toP(F.Exec(syntaxError("finally.without.try"))); 5.1765 - case CATCH: 5.1766 - return toP(F.Exec(syntaxError("catch.without.try"))); 5.1767 - case ASSERT: { 5.1768 - if (allowAsserts && S.token() == ASSERT) { 5.1769 - S.nextToken(); 5.1770 - JCExpression assertion = expression(); 5.1771 - JCExpression message = null; 5.1772 - if (S.token() == COLON) { 5.1773 - S.nextToken(); 5.1774 - message = expression(); 5.1775 - } 5.1776 - JCAssert t = to(F.at(pos).Assert(assertion, message)); 5.1777 - accept(SEMI); 5.1778 - return t; 5.1779 - } 5.1780 - /* else fall through to default case */ 5.1781 - } 5.1782 - case ENUM: 5.1783 - default: 5.1784 - Name name = S.name(); 5.1785 - JCExpression expr = expression(); 5.1786 - if (S.token() == COLON && expr.getTag() == JCTree.IDENT) { 5.1787 - S.nextToken(); 5.1788 - JCStatement stat = statement(); 5.1789 - return F.at(pos).Labelled(name, stat); 5.1790 - } else { 5.1791 - // This Exec is an "ExpressionStatement"; it subsumes the terminating semicolon 5.1792 - JCExpressionStatement stat = to(F.at(pos).Exec(checkExprStat(expr))); 5.1793 - accept(SEMI); 5.1794 - return stat; 5.1795 - } 5.1796 - } 5.1797 - } 5.1798 - 5.1799 - /** CatchClause = CATCH "(" FormalParameter ")" Block 5.1800 - */ 5.1801 - JCCatch catchClause() { 5.1802 - int pos = S.pos(); 5.1803 - accept(CATCH); 5.1804 - accept(LPAREN); 5.1805 - JCVariableDecl formal = 5.1806 - variableDeclaratorId(optFinal(Flags.PARAMETER), 5.1807 - qualident()); 5.1808 - accept(RPAREN); 5.1809 - JCBlock body = block(); 5.1810 - return F.at(pos).Catch(formal, body); 5.1811 - } 5.1812 - 5.1813 - /** SwitchBlockStatementGroups = { SwitchBlockStatementGroup } 5.1814 - * SwitchBlockStatementGroup = SwitchLabel BlockStatements 5.1815 - * SwitchLabel = CASE ConstantExpression ":" | DEFAULT ":" 5.1816 - */ 5.1817 - List<JCCase> switchBlockStatementGroups() { 5.1818 - ListBuffer<JCCase> cases = new ListBuffer<JCCase>(); 5.1819 - while (true) { 5.1820 - int pos = S.pos(); 5.1821 - switch (S.token()) { 5.1822 - case CASE: { 5.1823 - S.nextToken(); 5.1824 - JCExpression pat = expression(); 5.1825 - accept(COLON); 5.1826 - List<JCStatement> stats = blockStatements(); 5.1827 - JCCase c = F.at(pos).Case(pat, stats); 5.1828 - if (stats.isEmpty()) 5.1829 - storeEnd(c, S.prevEndPos()); 5.1830 - cases.append(c); 5.1831 - break; 5.1832 - } 5.1833 - case DEFAULT: { 5.1834 - S.nextToken(); 5.1835 - accept(COLON); 5.1836 - List<JCStatement> stats = blockStatements(); 5.1837 - JCCase c = F.at(pos).Case(null, stats); 5.1838 - if (stats.isEmpty()) 5.1839 - storeEnd(c, S.prevEndPos()); 5.1840 - cases.append(c); 5.1841 - break; 5.1842 - } 5.1843 - case RBRACE: case EOF: 5.1844 - return cases.toList(); 5.1845 - default: 5.1846 - S.nextToken(); // to ensure progress 5.1847 - syntaxError(pos, "expected3", 5.1848 - CASE, DEFAULT, RBRACE); 5.1849 - } 5.1850 - } 5.1851 - } 5.1852 - 5.1853 - /** MoreStatementExpressions = { COMMA StatementExpression } 5.1854 - */ 5.1855 - <T extends ListBuffer<? super JCExpressionStatement>> T moreStatementExpressions(int pos, 5.1856 - JCExpression first, 5.1857 - T stats) { 5.1858 - // This Exec is a "StatementExpression"; it subsumes no terminating token 5.1859 - stats.append(toP(F.at(pos).Exec(checkExprStat(first)))); 5.1860 - while (S.token() == COMMA) { 5.1861 - S.nextToken(); 5.1862 - pos = S.pos(); 5.1863 - JCExpression t = expression(); 5.1864 - // This Exec is a "StatementExpression"; it subsumes no terminating token 5.1865 - stats.append(toP(F.at(pos).Exec(checkExprStat(t)))); 5.1866 - } 5.1867 - return stats; 5.1868 - } 5.1869 - 5.1870 - /** ForInit = StatementExpression MoreStatementExpressions 5.1871 - * | { FINAL | '@' Annotation } Type VariableDeclarators 5.1872 - */ 5.1873 - List<JCStatement> forInit() { 5.1874 - ListBuffer<JCStatement> stats = lb(); 5.1875 - int pos = S.pos(); 5.1876 - if (S.token() == FINAL || S.token() == MONKEYS_AT) { 5.1877 - return variableDeclarators(optFinal(0), type(), stats).toList(); 5.1878 - } else { 5.1879 - JCExpression t = term(EXPR | TYPE); 5.1880 - if ((lastmode & TYPE) != 0 && 5.1881 - (S.token() == IDENTIFIER || S.token() == ASSERT || S.token() == ENUM)) 5.1882 - return variableDeclarators(modifiersOpt(), t, stats).toList(); 5.1883 - else 5.1884 - return moreStatementExpressions(pos, t, stats).toList(); 5.1885 - } 5.1886 - } 5.1887 - 5.1888 - /** ForUpdate = StatementExpression MoreStatementExpressions 5.1889 - */ 5.1890 - List<JCExpressionStatement> forUpdate() { 5.1891 - return moreStatementExpressions(S.pos(), 5.1892 - expression(), 5.1893 - new ListBuffer<JCExpressionStatement>()).toList(); 5.1894 - } 5.1895 - 5.1896 - /** AnnotationsOpt = { '@' Annotation } 5.1897 - */ 5.1898 - List<JCAnnotation> annotationsOpt() { 5.1899 - if (S.token() != MONKEYS_AT) return List.nil(); // optimization 5.1900 - ListBuffer<JCAnnotation> buf = new ListBuffer<JCAnnotation>(); 5.1901 - while (S.token() == MONKEYS_AT) { 5.1902 - int pos = S.pos(); 5.1903 - S.nextToken(); 5.1904 - buf.append(annotation(pos)); 5.1905 - } 5.1906 - return buf.toList(); 5.1907 - } 5.1908 - 5.1909 - /** ModifiersOpt = { Modifier } 5.1910 - * Modifier = PUBLIC | PROTECTED | PRIVATE | STATIC | ABSTRACT | FINAL 5.1911 - * | NATIVE | SYNCHRONIZED | TRANSIENT | VOLATILE | "@" 5.1912 - * | "@" Annotation 5.1913 - */ 5.1914 - JCModifiers modifiersOpt() { 5.1915 - return modifiersOpt(null); 5.1916 - } 5.1917 - JCModifiers modifiersOpt(JCModifiers partial) { 5.1918 - long flags = (partial == null) ? 0 : partial.flags; 5.1919 - if (S.deprecatedFlag()) { 5.1920 - flags |= Flags.DEPRECATED; 5.1921 - S.resetDeprecatedFlag(); 5.1922 - } 5.1923 - ListBuffer<JCAnnotation> annotations = new ListBuffer<JCAnnotation>(); 5.1924 - if (partial != null) annotations.appendList(partial.annotations); 5.1925 - int pos = S.pos(); 5.1926 - int lastPos = Position.NOPOS; 5.1927 - loop: 5.1928 - while (true) { 5.1929 - long flag; 5.1930 - switch (S.token()) { 5.1931 - case PRIVATE : flag = Flags.PRIVATE; break; 5.1932 - case PROTECTED : flag = Flags.PROTECTED; break; 5.1933 - case PUBLIC : flag = Flags.PUBLIC; break; 5.1934 - case STATIC : flag = Flags.STATIC; break; 5.1935 - case TRANSIENT : flag = Flags.TRANSIENT; break; 5.1936 - case FINAL : flag = Flags.FINAL; break; 5.1937 - case ABSTRACT : flag = Flags.ABSTRACT; break; 5.1938 - case NATIVE : flag = Flags.NATIVE; break; 5.1939 - case VOLATILE : flag = Flags.VOLATILE; break; 5.1940 - case SYNCHRONIZED: flag = Flags.SYNCHRONIZED; break; 5.1941 - case STRICTFP : flag = Flags.STRICTFP; break; 5.1942 - case MONKEYS_AT : flag = Flags.ANNOTATION; break; 5.1943 - default: break loop; 5.1944 - } 5.1945 - if ((flags & flag) != 0) log.error(S.pos(), "repeated.modifier"); 5.1946 - lastPos = S.pos(); 5.1947 - S.nextToken(); 5.1948 - if (flag == Flags.ANNOTATION) { 5.1949 - checkAnnotations(); 5.1950 - if (S.token() != INTERFACE) { 5.1951 - JCAnnotation ann = annotation(lastPos); 5.1952 - // if first modifier is an annotation, set pos to annotation's. 5.1953 - if (flags == 0 && annotations.isEmpty()) 5.1954 - pos = ann.pos; 5.1955 - annotations.append(ann); 5.1956 - lastPos = ann.pos; 5.1957 - flag = 0; 5.1958 - } 5.1959 - } 5.1960 - flags |= flag; 5.1961 - } 5.1962 - switch (S.token()) { 5.1963 - case ENUM: flags |= Flags.ENUM; break; 5.1964 - case INTERFACE: flags |= Flags.INTERFACE; break; 5.1965 - default: break; 5.1966 - } 5.1967 - 5.1968 - /* A modifiers tree with no modifier tokens or annotations 5.1969 - * has no text position. */ 5.1970 - if (flags == 0 && annotations.isEmpty()) 5.1971 - pos = Position.NOPOS; 5.1972 - 5.1973 - JCModifiers mods = F.at(pos).Modifiers(flags, annotations.toList()); 5.1974 - if (pos != Position.NOPOS) 5.1975 - storeEnd(mods, S.prevEndPos()); 5.1976 - return mods; 5.1977 - } 5.1978 - 5.1979 - /** Annotation = "@" Qualident [ "(" AnnotationFieldValues ")" ] 5.1980 - * @param pos position of "@" token 5.1981 - */ 5.1982 - JCAnnotation annotation(int pos) { 5.1983 - // accept(AT); // AT consumed by caller 5.1984 - checkAnnotations(); 5.1985 - JCTree ident = qualident(); 5.1986 - List<JCExpression> fieldValues = annotationFieldValuesOpt(); 5.1987 - JCAnnotation ann = F.at(pos).Annotation(ident, fieldValues); 5.1988 - storeEnd(ann, S.prevEndPos()); 5.1989 - return ann; 5.1990 - } 5.1991 - 5.1992 - List<JCExpression> annotationFieldValuesOpt() { 5.1993 - return (S.token() == LPAREN) ? annotationFieldValues() : List.<JCExpression>nil(); 5.1994 - } 5.1995 - 5.1996 - /** AnnotationFieldValues = "(" [ AnnotationFieldValue { "," AnnotationFieldValue } ] ")" */ 5.1997 - List<JCExpression> annotationFieldValues() { 5.1998 - accept(LPAREN); 5.1999 - ListBuffer<JCExpression> buf = new ListBuffer<JCExpression>(); 5.2000 - if (S.token() != RPAREN) { 5.2001 - buf.append(annotationFieldValue()); 5.2002 - while (S.token() == COMMA) { 5.2003 - S.nextToken(); 5.2004 - buf.append(annotationFieldValue()); 5.2005 - } 5.2006 - } 5.2007 - accept(RPAREN); 5.2008 - return buf.toList(); 5.2009 - } 5.2010 - 5.2011 - /** AnnotationFieldValue = AnnotationValue 5.2012 - * | Identifier "=" AnnotationValue 5.2013 - */ 5.2014 - JCExpression annotationFieldValue() { 5.2015 - if (S.token() == IDENTIFIER) { 5.2016 - mode = EXPR; 5.2017 - JCExpression t1 = term1(); 5.2018 - if (t1.getTag() == JCTree.IDENT && S.token() == EQ) { 5.2019 - int pos = S.pos(); 5.2020 - accept(EQ); 5.2021 - return toP(F.at(pos).Assign(t1, annotationValue())); 5.2022 - } else { 5.2023 - return t1; 5.2024 - } 5.2025 - } 5.2026 - return annotationValue(); 5.2027 - } 5.2028 - 5.2029 - /* AnnotationValue = ConditionalExpression 5.2030 - * | Annotation 5.2031 - * | "{" [ AnnotationValue { "," AnnotationValue } ] "}" 5.2032 - */ 5.2033 - JCExpression annotationValue() { 5.2034 - int pos; 5.2035 - switch (S.token()) { 5.2036 - case MONKEYS_AT: 5.2037 - pos = S.pos(); 5.2038 - S.nextToken(); 5.2039 - return annotation(pos); 5.2040 - case LBRACE: 5.2041 - pos = S.pos(); 5.2042 - accept(LBRACE); 5.2043 - ListBuffer<JCExpression> buf = new ListBuffer<JCExpression>(); 5.2044 - if (S.token() != RBRACE) { 5.2045 - buf.append(annotationValue()); 5.2046 - while (S.token() == COMMA) { 5.2047 - S.nextToken(); 5.2048 - if (S.token() == RPAREN) break; 5.2049 - buf.append(annotationValue()); 5.2050 - } 5.2051 - } 5.2052 - accept(RBRACE); 5.2053 - return toP(F.at(pos).NewArray(null, List.<JCExpression>nil(), buf.toList())); 5.2054 - default: 5.2055 - mode = EXPR; 5.2056 - return term1(); 5.2057 - } 5.2058 - } 5.2059 - 5.2060 - /** VariableDeclarators = VariableDeclarator { "," VariableDeclarator } 5.2061 - */ 5.2062 - public <T extends ListBuffer<? super JCVariableDecl>> T variableDeclarators(JCModifiers mods, 5.2063 - JCExpression type, 5.2064 - T vdefs) 5.2065 - { 5.2066 - return variableDeclaratorsRest(S.pos(), mods, type, ident(), false, null, vdefs); 5.2067 - } 5.2068 - 5.2069 - /** VariableDeclaratorsRest = VariableDeclaratorRest { "," VariableDeclarator } 5.2070 - * ConstantDeclaratorsRest = ConstantDeclaratorRest { "," ConstantDeclarator } 5.2071 - * 5.2072 - * @param reqInit Is an initializer always required? 5.2073 - * @param dc The documentation comment for the variable declarations, or null. 5.2074 - */ 5.2075 - <T extends ListBuffer<? super JCVariableDecl>> T variableDeclaratorsRest(int pos, 5.2076 - JCModifiers mods, 5.2077 - JCExpression type, 5.2078 - Name name, 5.2079 - boolean reqInit, 5.2080 - String dc, 5.2081 - T vdefs) 5.2082 - { 5.2083 - vdefs.append(variableDeclaratorRest(pos, mods, type, name, reqInit, dc)); 5.2084 - while (S.token() == COMMA) { 5.2085 - // All but last of multiple declarators subsume a comma 5.2086 - storeEnd((JCTree)vdefs.elems.last(), S.endPos()); 5.2087 - S.nextToken(); 5.2088 - vdefs.append(variableDeclarator(mods, type, reqInit, dc)); 5.2089 - } 5.2090 - return vdefs; 5.2091 - } 5.2092 - 5.2093 - /** VariableDeclarator = Ident VariableDeclaratorRest 5.2094 - * ConstantDeclarator = Ident ConstantDeclaratorRest 5.2095 - */ 5.2096 - JCVariableDecl variableDeclarator(JCModifiers mods, JCExpression type, boolean reqInit, String dc) { 5.2097 - return variableDeclaratorRest(S.pos(), mods, type, ident(), reqInit, dc); 5.2098 - } 5.2099 - 5.2100 - /** VariableDeclaratorRest = BracketsOpt ["=" VariableInitializer] 5.2101 - * ConstantDeclaratorRest = BracketsOpt "=" VariableInitializer 5.2102 - * 5.2103 - * @param reqInit Is an initializer always required? 5.2104 - * @param dc The documentation comment for the variable declarations, or null. 5.2105 - */ 5.2106 - JCVariableDecl variableDeclaratorRest(int pos, JCModifiers mods, JCExpression type, Name name, 5.2107 - boolean reqInit, String dc) { 5.2108 - type = bracketsOpt(type); 5.2109 - JCExpression init = null; 5.2110 - if (S.token() == EQ) { 5.2111 - S.nextToken(); 5.2112 - init = variableInitializer(); 5.2113 - } 5.2114 - else if (reqInit) syntaxError(S.pos(), "expected", EQ); 5.2115 - JCVariableDecl result = 5.2116 - toP(F.at(pos).VarDef(mods, name, type, init)); 5.2117 - attach(result, dc); 5.2118 - return result; 5.2119 - } 5.2120 - 5.2121 - /** VariableDeclaratorId = Ident BracketsOpt 5.2122 - */ 5.2123 - JCVariableDecl variableDeclaratorId(JCModifiers mods, JCExpression type) { 5.2124 - int pos = S.pos(); 5.2125 - Name name = ident(); 5.2126 - if ((mods.flags & Flags.VARARGS) == 0) 5.2127 - type = bracketsOpt(type); 5.2128 - return toP(F.at(pos).VarDef(mods, name, type, null)); 5.2129 - } 5.2130 - 5.2131 - /** CompilationUnit = [ { "@" Annotation } PACKAGE Qualident ";"] {ImportDeclaration} {TypeDeclaration} 5.2132 - */ 5.2133 - public JCTree.JCCompilationUnit compilationUnit() { 5.2134 - int pos = S.pos(); 5.2135 - JCExpression pid = null; 5.2136 - String dc = S.docComment(); 5.2137 - JCModifiers mods = null; 5.2138 - List<JCAnnotation> packageAnnotations = List.nil(); 5.2139 - if (S.token() == MONKEYS_AT) 5.2140 - mods = modifiersOpt(); 5.2141 - 5.2142 - if (S.token() == PACKAGE) { 5.2143 - if (mods != null) { 5.2144 - checkNoMods(mods.flags); 5.2145 - packageAnnotations = mods.annotations; 5.2146 - mods = null; 5.2147 - } 5.2148 - S.nextToken(); 5.2149 - pid = qualident(); 5.2150 - accept(SEMI); 5.2151 - } 5.2152 - ListBuffer<JCTree> defs = new ListBuffer<JCTree>(); 5.2153 - boolean checkForImports = true; 5.2154 - while (S.token() != EOF) { 5.2155 - if (S.pos() <= errorEndPos) { 5.2156 - // error recovery 5.2157 - skip(checkForImports, false, false, false); 5.2158 - if (S.token() == EOF) 5.2159 - break; 5.2160 - } 5.2161 - if (checkForImports && mods == null && S.token() == IMPORT) { 5.2162 - defs.append(importDeclaration()); 5.2163 - } else { 5.2164 - JCTree def = typeDeclaration(mods); 5.2165 - if (def instanceof JCExpressionStatement) 5.2166 - def = ((JCExpressionStatement)def).expr; 5.2167 - defs.append(def); 5.2168 - if (def instanceof JCClassDecl) 5.2169 - checkForImports = false; 5.2170 - mods = null; 5.2171 - } 5.2172 - } 5.2173 - JCTree.JCCompilationUnit toplevel = F.at(pos).TopLevel(packageAnnotations, pid, defs.toList()); 5.2174 - attach(toplevel, dc); 5.2175 - if (defs.elems.isEmpty()) 5.2176 - storeEnd(toplevel, S.prevEndPos()); 5.2177 - if (keepDocComments) toplevel.docComments = docComments; 5.2178 - return toplevel; 5.2179 - } 5.2180 - 5.2181 - /** ImportDeclaration = IMPORT [ STATIC ] Ident { "." Ident } [ "." "*" ] ";" 5.2182 - */ 5.2183 - JCTree importDeclaration() { 5.2184 - int pos = S.pos(); 5.2185 - S.nextToken(); 5.2186 - boolean importStatic = false; 5.2187 - if (S.token() == STATIC) { 5.2188 - checkStaticImports(); 5.2189 - importStatic = true; 5.2190 - S.nextToken(); 5.2191 - } 5.2192 - JCExpression pid = toP(F.at(S.pos()).Ident(ident())); 5.2193 - do { 5.2194 - int pos1 = S.pos(); 5.2195 - accept(DOT); 5.2196 - if (S.token() == STAR) { 5.2197 - pid = to(F.at(pos1).Select(pid, names.asterisk)); 5.2198 - S.nextToken(); 5.2199 - break; 5.2200 - } else { 5.2201 - pid = toP(F.at(pos1).Select(pid, ident())); 5.2202 - } 5.2203 - } while (S.token() == DOT); 5.2204 - accept(SEMI); 5.2205 - return toP(F.at(pos).Import(pid, importStatic)); 5.2206 - } 5.2207 - 5.2208 - /** TypeDeclaration = ClassOrInterfaceOrEnumDeclaration 5.2209 - * | ";" 5.2210 - */ 5.2211 - JCTree typeDeclaration(JCModifiers mods) { 5.2212 - int pos = S.pos(); 5.2213 - if (mods == null && S.token() == SEMI) { 5.2214 - S.nextToken(); 5.2215 - return toP(F.at(pos).Skip()); 5.2216 - } else { 5.2217 - String dc = S.docComment(); 5.2218 - return classOrInterfaceOrEnumDeclaration(modifiersOpt(mods), dc); 5.2219 - } 5.2220 - } 5.2221 - 5.2222 - /** ClassOrInterfaceOrEnumDeclaration = ModifiersOpt 5.2223 - * (ClassDeclaration | InterfaceDeclaration | EnumDeclaration) 5.2224 - * @param mods Any modifiers starting the class or interface declaration 5.2225 - * @param dc The documentation comment for the class, or null. 5.2226 - */ 5.2227 - JCStatement classOrInterfaceOrEnumDeclaration(JCModifiers mods, String dc) { 5.2228 - if (S.token() == CLASS) { 5.2229 - return classDeclaration(mods, dc); 5.2230 - } else if (S.token() == INTERFACE) { 5.2231 - return interfaceDeclaration(mods, dc); 5.2232 - } else if (allowEnums) { 5.2233 - if (S.token() == ENUM) { 5.2234 - return enumDeclaration(mods, dc); 5.2235 - } else { 5.2236 - int pos = S.pos(); 5.2237 - List<JCTree> errs; 5.2238 - if (S.token() == IDENTIFIER) { 5.2239 - errs = List.<JCTree>of(mods, toP(F.at(pos).Ident(ident()))); 5.2240 - setErrorEndPos(S.pos()); 5.2241 - } else { 5.2242 - errs = List.<JCTree>of(mods); 5.2243 - } 5.2244 - return toP(F.Exec(syntaxError(pos, errs, "expected3", 5.2245 - CLASS, INTERFACE, ENUM))); 5.2246 - } 5.2247 - } else { 5.2248 - if (S.token() == ENUM) { 5.2249 - log.error(S.pos(), "enums.not.supported.in.source", source.name); 5.2250 - allowEnums = true; 5.2251 - return enumDeclaration(mods, dc); 5.2252 - } 5.2253 - int pos = S.pos(); 5.2254 - List<JCTree> errs; 5.2255 - if (S.token() == IDENTIFIER) { 5.2256 - errs = List.<JCTree>of(mods, toP(F.at(pos).Ident(ident()))); 5.2257 - setErrorEndPos(S.pos()); 5.2258 - } else { 5.2259 - errs = List.<JCTree>of(mods); 5.2260 - } 5.2261 - return toP(F.Exec(syntaxError(pos, errs, "expected2", 5.2262 - CLASS, INTERFACE))); 5.2263 - } 5.2264 - } 5.2265 - 5.2266 - /** ClassDeclaration = CLASS Ident TypeParametersOpt [EXTENDS Type] 5.2267 - * [IMPLEMENTS TypeList] ClassBody 5.2268 - * @param mods The modifiers starting the class declaration 5.2269 - * @param dc The documentation comment for the class, or null. 5.2270 - */ 5.2271 - JCClassDecl classDeclaration(JCModifiers mods, String dc) { 5.2272 - int pos = S.pos(); 5.2273 - accept(CLASS); 5.2274 - Name name = ident(); 5.2275 - 5.2276 - List<JCTypeParameter> typarams = typeParametersOpt(); 5.2277 - 5.2278 - JCTree extending = null; 5.2279 - if (S.token() == EXTENDS) { 5.2280 - S.nextToken(); 5.2281 - extending = type(); 5.2282 - } 5.2283 - List<JCExpression> implementing = List.nil(); 5.2284 - if (S.token() == IMPLEMENTS) { 5.2285 - S.nextToken(); 5.2286 - implementing = typeList(); 5.2287 - } 5.2288 - List<JCTree> defs = classOrInterfaceBody(name, false); 5.2289 - JCClassDecl result = toP(F.at(pos).ClassDef( 5.2290 - mods, name, typarams, extending, implementing, defs)); 5.2291 - attach(result, dc); 5.2292 - return result; 5.2293 - } 5.2294 - 5.2295 - /** InterfaceDeclaration = INTERFACE Ident TypeParametersOpt 5.2296 - * [EXTENDS TypeList] InterfaceBody 5.2297 - * @param mods The modifiers starting the interface declaration 5.2298 - * @param dc The documentation comment for the interface, or null. 5.2299 - */ 5.2300 - JCClassDecl interfaceDeclaration(JCModifiers mods, String dc) { 5.2301 - int pos = S.pos(); 5.2302 - accept(INTERFACE); 5.2303 - Name name = ident(); 5.2304 - 5.2305 - List<JCTypeParameter> typarams = typeParametersOpt(); 5.2306 - 5.2307 - List<JCExpression> extending = List.nil(); 5.2308 - if (S.token() == EXTENDS) { 5.2309 - S.nextToken(); 5.2310 - extending = typeList(); 5.2311 - } 5.2312 - List<JCTree> defs = classOrInterfaceBody(name, true); 5.2313 - JCClassDecl result = toP(F.at(pos).ClassDef( 5.2314 - mods, name, typarams, null, extending, defs)); 5.2315 - attach(result, dc); 5.2316 - return result; 5.2317 - } 5.2318 - 5.2319 - /** EnumDeclaration = ENUM Ident [IMPLEMENTS TypeList] EnumBody 5.2320 - * @param mods The modifiers starting the enum declaration 5.2321 - * @param dc The documentation comment for the enum, or null. 5.2322 - */ 5.2323 - JCClassDecl enumDeclaration(JCModifiers mods, String dc) { 5.2324 - int pos = S.pos(); 5.2325 - accept(ENUM); 5.2326 - Name name = ident(); 5.2327 - 5.2328 - List<JCExpression> implementing = List.nil(); 5.2329 - if (S.token() == IMPLEMENTS) { 5.2330 - S.nextToken(); 5.2331 - implementing = typeList(); 5.2332 - } 5.2333 - 5.2334 - List<JCTree> defs = enumBody(name); 5.2335 - JCModifiers newMods = 5.2336 - F.at(mods.pos).Modifiers(mods.flags|Flags.ENUM, mods.annotations); 5.2337 - JCClassDecl result = toP(F.at(pos). 5.2338 - ClassDef(newMods, name, List.<JCTypeParameter>nil(), 5.2339 - null, implementing, defs)); 5.2340 - attach(result, dc); 5.2341 - return result; 5.2342 - } 5.2343 - 5.2344 - /** EnumBody = "{" { EnumeratorDeclarationList } [","] 5.2345 - * [ ";" {ClassBodyDeclaration} ] "}" 5.2346 - */ 5.2347 - List<JCTree> enumBody(Name enumName) { 5.2348 - accept(LBRACE); 5.2349 - ListBuffer<JCTree> defs = new ListBuffer<JCTree>(); 5.2350 - if (S.token() == COMMA) { 5.2351 - S.nextToken(); 5.2352 - } else if (S.token() != RBRACE && S.token() != SEMI) { 5.2353 - defs.append(enumeratorDeclaration(enumName)); 5.2354 - while (S.token() == COMMA) { 5.2355 - S.nextToken(); 5.2356 - if (S.token() == RBRACE || S.token() == SEMI) break; 5.2357 - defs.append(enumeratorDeclaration(enumName)); 5.2358 - } 5.2359 - if (S.token() != SEMI && S.token() != RBRACE) { 5.2360 - defs.append(syntaxError(S.pos(), "expected3", 5.2361 - COMMA, RBRACE, SEMI)); 5.2362 - S.nextToken(); 5.2363 - } 5.2364 - } 5.2365 - if (S.token() == SEMI) { 5.2366 - S.nextToken(); 5.2367 - while (S.token() != RBRACE && S.token() != EOF) { 5.2368 - defs.appendList(classOrInterfaceBodyDeclaration(enumName, 5.2369 - false)); 5.2370 - if (S.pos() <= errorEndPos) { 5.2371 - // error recovery 5.2372 - skip(false, true, true, false); 5.2373 - } 5.2374 - } 5.2375 - } 5.2376 - accept(RBRACE); 5.2377 - return defs.toList(); 5.2378 - } 5.2379 - 5.2380 - /** EnumeratorDeclaration = AnnotationsOpt [TypeArguments] IDENTIFIER [ Arguments ] [ "{" ClassBody "}" ] 5.2381 - */ 5.2382 - JCTree enumeratorDeclaration(Name enumName) { 5.2383 - String dc = S.docComment(); 5.2384 - int flags = Flags.PUBLIC|Flags.STATIC|Flags.FINAL|Flags.ENUM; 5.2385 - if (S.deprecatedFlag()) { 5.2386 - flags |= Flags.DEPRECATED; 5.2387 - S.resetDeprecatedFlag(); 5.2388 - } 5.2389 - int pos = S.pos(); 5.2390 - List<JCAnnotation> annotations = annotationsOpt(); 5.2391 - JCModifiers mods = F.at(annotations.isEmpty() ? Position.NOPOS : pos).Modifiers(flags, annotations); 5.2392 - List<JCExpression> typeArgs = typeArgumentsOpt(); 5.2393 - int identPos = S.pos(); 5.2394 - Name name = ident(); 5.2395 - int createPos = S.pos(); 5.2396 - List<JCExpression> args = (S.token() == LPAREN) 5.2397 - ? arguments() : List.<JCExpression>nil(); 5.2398 - JCClassDecl body = null; 5.2399 - if (S.token() == LBRACE) { 5.2400 - JCModifiers mods1 = F.at(Position.NOPOS).Modifiers(Flags.ENUM | Flags.STATIC); 5.2401 - List<JCTree> defs = classOrInterfaceBody(names.empty, false); 5.2402 - body = toP(F.at(identPos).AnonymousClassDef(mods1, defs)); 5.2403 - } 5.2404 - if (args.isEmpty() && body == null) 5.2405 - createPos = Position.NOPOS; 5.2406 - JCIdent ident = F.at(Position.NOPOS).Ident(enumName); 5.2407 - JCNewClass create = F.at(createPos).NewClass(null, typeArgs, ident, args, body); 5.2408 - if (createPos != Position.NOPOS) 5.2409 - storeEnd(create, S.prevEndPos()); 5.2410 - ident = F.at(Position.NOPOS).Ident(enumName); 5.2411 - JCTree result = toP(F.at(pos).VarDef(mods, name, ident, create)); 5.2412 - attach(result, dc); 5.2413 - return result; 5.2414 - } 5.2415 - 5.2416 - /** TypeList = Type {"," Type} 5.2417 - */ 5.2418 - List<JCExpression> typeList() { 5.2419 - ListBuffer<JCExpression> ts = new ListBuffer<JCExpression>(); 5.2420 - ts.append(type()); 5.2421 - while (S.token() == COMMA) { 5.2422 - S.nextToken(); 5.2423 - ts.append(type()); 5.2424 - } 5.2425 - return ts.toList(); 5.2426 - } 5.2427 - 5.2428 - /** ClassBody = "{" {ClassBodyDeclaration} "}" 5.2429 - * InterfaceBody = "{" {InterfaceBodyDeclaration} "}" 5.2430 - */ 5.2431 - List<JCTree> classOrInterfaceBody(Name className, boolean isInterface) { 5.2432 - accept(LBRACE); 5.2433 - if (S.pos() <= errorEndPos) { 5.2434 - // error recovery 5.2435 - skip(false, true, false, false); 5.2436 - if (S.token() == LBRACE) 5.2437 - S.nextToken(); 5.2438 - } 5.2439 - ListBuffer<JCTree> defs = new ListBuffer<JCTree>(); 5.2440 - while (S.token() != RBRACE && S.token() != EOF) { 5.2441 - defs.appendList(classOrInterfaceBodyDeclaration(className, isInterface)); 5.2442 - if (S.pos() <= errorEndPos) { 5.2443 - // error recovery 5.2444 - skip(false, true, true, false); 5.2445 - } 5.2446 - } 5.2447 - accept(RBRACE); 5.2448 - return defs.toList(); 5.2449 - } 5.2450 - 5.2451 - /** ClassBodyDeclaration = 5.2452 - * ";" 5.2453 - * | [STATIC] Block 5.2454 - * | ModifiersOpt 5.2455 - * ( Type Ident 5.2456 - * ( VariableDeclaratorsRest ";" | MethodDeclaratorRest ) 5.2457 - * | VOID Ident MethodDeclaratorRest 5.2458 - * | TypeParameters (Type | VOID) Ident MethodDeclaratorRest 5.2459 - * | Ident ConstructorDeclaratorRest 5.2460 - * | TypeParameters Ident ConstructorDeclaratorRest 5.2461 - * | ClassOrInterfaceOrEnumDeclaration 5.2462 - * ) 5.2463 - * InterfaceBodyDeclaration = 5.2464 - * ";" 5.2465 - * | ModifiersOpt Type Ident 5.2466 - * ( ConstantDeclaratorsRest | InterfaceMethodDeclaratorRest ";" ) 5.2467 - */ 5.2468 - List<JCTree> classOrInterfaceBodyDeclaration(Name className, boolean isInterface) { 5.2469 - if (S.token() == SEMI) { 5.2470 - S.nextToken(); 5.2471 - return List.<JCTree>of(F.at(Position.NOPOS).Block(0, List.<JCStatement>nil())); 5.2472 - } else { 5.2473 - String dc = S.docComment(); 5.2474 - int pos = S.pos(); 5.2475 - JCModifiers mods = modifiersOpt(); 5.2476 - if (S.token() == CLASS || 5.2477 - S.token() == INTERFACE || 5.2478 - allowEnums && S.token() == ENUM) { 5.2479 - return List.<JCTree>of(classOrInterfaceOrEnumDeclaration(mods, dc)); 5.2480 - } else if (S.token() == LBRACE && !isInterface && 5.2481 - (mods.flags & Flags.StandardFlags & ~Flags.STATIC) == 0 && 5.2482 - mods.annotations.isEmpty()) { 5.2483 - return List.<JCTree>of(block(pos, mods.flags)); 5.2484 - } else { 5.2485 - pos = S.pos(); 5.2486 - List<JCTypeParameter> typarams = typeParametersOpt(); 5.2487 - // Hack alert: if there are type arguments but no Modifiers, the start 5.2488 - // position will be lost unless we set the Modifiers position. There 5.2489 - // should be an AST node for type parameters (BugId 5005090). 5.2490 - if (typarams.length() > 0 && mods.pos == Position.NOPOS) { 5.2491 - mods.pos = pos; 5.2492 - } 5.2493 - Token token = S.token(); 5.2494 - Name name = S.name(); 5.2495 - pos = S.pos(); 5.2496 - JCExpression type; 5.2497 - boolean isVoid = S.token() == VOID; 5.2498 - if (isVoid) { 5.2499 - type = to(F.at(pos).TypeIdent(TypeTags.VOID)); 5.2500 - S.nextToken(); 5.2501 - } else { 5.2502 - type = type(); 5.2503 - } 5.2504 - if (S.token() == LPAREN && !isInterface && type.getTag() == JCTree.IDENT) { 5.2505 - if (isInterface || name != className) 5.2506 - log.error(pos, "invalid.meth.decl.ret.type.req"); 5.2507 - return List.of(methodDeclaratorRest( 5.2508 - pos, mods, null, names.init, typarams, 5.2509 - isInterface, true, dc)); 5.2510 - } else { 5.2511 - pos = S.pos(); 5.2512 - name = ident(); 5.2513 - if (S.token() == LPAREN) { 5.2514 - return List.of(methodDeclaratorRest( 5.2515 - pos, mods, type, name, typarams, 5.2516 - isInterface, isVoid, dc)); 5.2517 - } else if (!isVoid && typarams.isEmpty()) { 5.2518 - List<JCTree> defs = 5.2519 - variableDeclaratorsRest(pos, mods, type, name, isInterface, dc, 5.2520 - new ListBuffer<JCTree>()).toList(); 5.2521 - storeEnd(defs.last(), S.endPos()); 5.2522 - accept(SEMI); 5.2523 - return defs; 5.2524 - } else { 5.2525 - pos = S.pos(); 5.2526 - List<JCTree> err = isVoid 5.2527 - ? List.<JCTree>of(toP(F.at(pos).MethodDef(mods, name, type, typarams, 5.2528 - List.<JCVariableDecl>nil(), List.<JCExpression>nil(), null, null))) 5.2529 - : null; 5.2530 - return List.<JCTree>of(syntaxError(S.pos(), err, "expected", LPAREN)); 5.2531 - } 5.2532 - } 5.2533 - } 5.2534 - } 5.2535 - } 5.2536 - 5.2537 - /** MethodDeclaratorRest = 5.2538 - * FormalParameters BracketsOpt [Throws TypeList] ( MethodBody | [DEFAULT AnnotationValue] ";") 5.2539 - * VoidMethodDeclaratorRest = 5.2540 - * FormalParameters [Throws TypeList] ( MethodBody | ";") 5.2541 - * InterfaceMethodDeclaratorRest = 5.2542 - * FormalParameters BracketsOpt [THROWS TypeList] ";" 5.2543 - * VoidInterfaceMethodDeclaratorRest = 5.2544 - * FormalParameters [THROWS TypeList] ";" 5.2545 - * ConstructorDeclaratorRest = 5.2546 - * "(" FormalParameterListOpt ")" [THROWS TypeList] MethodBody 5.2547 - */ 5.2548 - JCTree methodDeclaratorRest(int pos, 5.2549 - JCModifiers mods, 5.2550 - JCExpression type, 5.2551 - Name name, 5.2552 - List<JCTypeParameter> typarams, 5.2553 - boolean isInterface, boolean isVoid, 5.2554 - String dc) { 5.2555 - List<JCVariableDecl> params = formalParameters(); 5.2556 - if (!isVoid) type = bracketsOpt(type); 5.2557 - List<JCExpression> thrown = List.nil(); 5.2558 - if (S.token() == THROWS) { 5.2559 - S.nextToken(); 5.2560 - thrown = qualidentList(); 5.2561 - } 5.2562 - JCBlock body = null; 5.2563 - JCExpression defaultValue; 5.2564 - if (S.token() == LBRACE) { 5.2565 - body = block(); 5.2566 - defaultValue = null; 5.2567 - } else { 5.2568 - if (S.token() == DEFAULT) { 5.2569 - accept(DEFAULT); 5.2570 - defaultValue = annotationValue(); 5.2571 - } else { 5.2572 - defaultValue = null; 5.2573 - } 5.2574 - accept(SEMI); 5.2575 - if (S.pos() <= errorEndPos) { 5.2576 - // error recovery 5.2577 - skip(false, true, false, false); 5.2578 - if (S.token() == LBRACE) { 5.2579 - body = block(); 5.2580 - } 5.2581 - } 5.2582 - } 5.2583 - JCMethodDecl result = 5.2584 - toP(F.at(pos).MethodDef(mods, name, type, typarams, 5.2585 - params, thrown, 5.2586 - body, defaultValue)); 5.2587 - attach(result, dc); 5.2588 - return result; 5.2589 - } 5.2590 - 5.2591 - /** QualidentList = Qualident {"," Qualident} 5.2592 - */ 5.2593 - List<JCExpression> qualidentList() { 5.2594 - ListBuffer<JCExpression> ts = new ListBuffer<JCExpression>(); 5.2595 - ts.append(qualident()); 5.2596 - while (S.token() == COMMA) { 5.2597 - S.nextToken(); 5.2598 - ts.append(qualident()); 5.2599 - } 5.2600 - return ts.toList(); 5.2601 - } 5.2602 - 5.2603 - /** TypeParametersOpt = ["<" TypeParameter {"," TypeParameter} ">"] 5.2604 - */ 5.2605 - List<JCTypeParameter> typeParametersOpt() { 5.2606 - if (S.token() == LT) { 5.2607 - checkGenerics(); 5.2608 - ListBuffer<JCTypeParameter> typarams = new ListBuffer<JCTypeParameter>(); 5.2609 - S.nextToken(); 5.2610 - typarams.append(typeParameter()); 5.2611 - while (S.token() == COMMA) { 5.2612 - S.nextToken(); 5.2613 - typarams.append(typeParameter()); 5.2614 - } 5.2615 - accept(GT); 5.2616 - return typarams.toList(); 5.2617 - } else { 5.2618 - return List.nil(); 5.2619 - } 5.2620 - } 5.2621 - 5.2622 - /** TypeParameter = TypeVariable [TypeParameterBound] 5.2623 - * TypeParameterBound = EXTENDS Type {"&" Type} 5.2624 - * TypeVariable = Ident 5.2625 - */ 5.2626 - JCTypeParameter typeParameter() { 5.2627 - int pos = S.pos(); 5.2628 - Name name = ident(); 5.2629 - ListBuffer<JCExpression> bounds = new ListBuffer<JCExpression>(); 5.2630 - if (S.token() == EXTENDS) { 5.2631 - S.nextToken(); 5.2632 - bounds.append(type()); 5.2633 - while (S.token() == AMP) { 5.2634 - S.nextToken(); 5.2635 - bounds.append(type()); 5.2636 - } 5.2637 - } 5.2638 - return toP(F.at(pos).TypeParameter(name, bounds.toList())); 5.2639 - } 5.2640 - 5.2641 - /** FormalParameters = "(" [ FormalParameterList ] ")" 5.2642 - * FormalParameterList = [ FormalParameterListNovarargs , ] LastFormalParameter 5.2643 - * FormalParameterListNovarargs = [ FormalParameterListNovarargs , ] FormalParameter 5.2644 - */ 5.2645 - List<JCVariableDecl> formalParameters() { 5.2646 - ListBuffer<JCVariableDecl> params = new ListBuffer<JCVariableDecl>(); 5.2647 - JCVariableDecl lastParam = null; 5.2648 - accept(LPAREN); 5.2649 - if (S.token() != RPAREN) { 5.2650 - params.append(lastParam = formalParameter()); 5.2651 - while ((lastParam.mods.flags & Flags.VARARGS) == 0 && S.token() == COMMA) { 5.2652 - S.nextToken(); 5.2653 - params.append(lastParam = formalParameter()); 5.2654 - } 5.2655 - } 5.2656 - accept(RPAREN); 5.2657 - return params.toList(); 5.2658 - } 5.2659 - 5.2660 - JCModifiers optFinal(long flags) { 5.2661 - JCModifiers mods = modifiersOpt(); 5.2662 - checkNoMods(mods.flags & ~(Flags.FINAL | Flags.DEPRECATED)); 5.2663 - mods.flags |= flags; 5.2664 - return mods; 5.2665 - } 5.2666 - 5.2667 - /** FormalParameter = { FINAL | '@' Annotation } Type VariableDeclaratorId 5.2668 - * LastFormalParameter = { FINAL | '@' Annotation } Type '...' Ident | FormalParameter 5.2669 - */ 5.2670 - JCVariableDecl formalParameter() { 5.2671 - JCModifiers mods = optFinal(Flags.PARAMETER); 5.2672 - JCExpression type = type(); 5.2673 - if (S.token() == ELLIPSIS) { 5.2674 - checkVarargs(); 5.2675 - mods.flags |= Flags.VARARGS; 5.2676 - type = to(F.at(S.pos()).TypeArray(type)); 5.2677 - S.nextToken(); 5.2678 - } 5.2679 - return variableDeclaratorId(mods, type); 5.2680 - } 5.2681 - 5.2682 -/* ---------- auxiliary methods -------------- */ 5.2683 - 5.2684 - /** Check that given tree is a legal expression statement. 5.2685 - */ 5.2686 - protected JCExpression checkExprStat(JCExpression t) { 5.2687 - switch(t.getTag()) { 5.2688 - case JCTree.PREINC: case JCTree.PREDEC: 5.2689 - case JCTree.POSTINC: case JCTree.POSTDEC: 5.2690 - case JCTree.ASSIGN: 5.2691 - case JCTree.BITOR_ASG: case JCTree.BITXOR_ASG: case JCTree.BITAND_ASG: 5.2692 - case JCTree.SL_ASG: case JCTree.SR_ASG: case JCTree.USR_ASG: 5.2693 - case JCTree.PLUS_ASG: case JCTree.MINUS_ASG: 5.2694 - case JCTree.MUL_ASG: case JCTree.DIV_ASG: case JCTree.MOD_ASG: 5.2695 - case JCTree.APPLY: case JCTree.NEWCLASS: 5.2696 - case JCTree.ERRONEOUS: 5.2697 - return t; 5.2698 - default: 5.2699 - log.error(t.pos, "not.stmt"); 5.2700 - return F.at(t.pos).Erroneous(List.<JCTree>of(t)); 5.2701 - } 5.2702 - } 5.2703 - 5.2704 - /** Return precedence of operator represented by token, 5.2705 - * -1 if token is not a binary operator. @see TreeInfo.opPrec 5.2706 - */ 5.2707 - static int prec(Token token) { 5.2708 - int oc = optag(token); 5.2709 - return (oc >= 0) ? TreeInfo.opPrec(oc) : -1; 5.2710 - } 5.2711 - 5.2712 - /** Return operation tag of binary operator represented by token, 5.2713 - * -1 if token is not a binary operator. 5.2714 - */ 5.2715 - static int optag(Token token) { 5.2716 - switch (token) { 5.2717 - case BARBAR: 5.2718 - return JCTree.OR; 5.2719 - case AMPAMP: 5.2720 - return JCTree.AND; 5.2721 - case BAR: 5.2722 - return JCTree.BITOR; 5.2723 - case BAREQ: 5.2724 - return JCTree.BITOR_ASG; 5.2725 - case CARET: 5.2726 - return JCTree.BITXOR; 5.2727 - case CARETEQ: 5.2728 - return JCTree.BITXOR_ASG; 5.2729 - case AMP: 5.2730 - return JCTree.BITAND; 5.2731 - case AMPEQ: 5.2732 - return JCTree.BITAND_ASG; 5.2733 - case EQEQ: 5.2734 - return JCTree.EQ; 5.2735 - case BANGEQ: 5.2736 - return JCTree.NE; 5.2737 - case LT: 5.2738 - return JCTree.LT; 5.2739 - case GT: 5.2740 - return JCTree.GT; 5.2741 - case LTEQ: 5.2742 - return JCTree.LE; 5.2743 - case GTEQ: 5.2744 - return JCTree.GE; 5.2745 - case LTLT: 5.2746 - return JCTree.SL; 5.2747 - case LTLTEQ: 5.2748 - return JCTree.SL_ASG; 5.2749 - case GTGT: 5.2750 - return JCTree.SR; 5.2751 - case GTGTEQ: 5.2752 - return JCTree.SR_ASG; 5.2753 - case GTGTGT: 5.2754 - return JCTree.USR; 5.2755 - case GTGTGTEQ: 5.2756 - return JCTree.USR_ASG; 5.2757 - case PLUS: 5.2758 - return JCTree.PLUS; 5.2759 - case PLUSEQ: 5.2760 - return JCTree.PLUS_ASG; 5.2761 - case SUB: 5.2762 - return JCTree.MINUS; 5.2763 - case SUBEQ: 5.2764 - return JCTree.MINUS_ASG; 5.2765 - case STAR: 5.2766 - return JCTree.MUL; 5.2767 - case STAREQ: 5.2768 - return JCTree.MUL_ASG; 5.2769 - case SLASH: 5.2770 - return JCTree.DIV; 5.2771 - case SLASHEQ: 5.2772 - return JCTree.DIV_ASG; 5.2773 - case PERCENT: 5.2774 - return JCTree.MOD; 5.2775 - case PERCENTEQ: 5.2776 - return JCTree.MOD_ASG; 5.2777 - case INSTANCEOF: 5.2778 - return JCTree.TYPETEST; 5.2779 - default: 5.2780 - return -1; 5.2781 - } 5.2782 - } 5.2783 - 5.2784 - /** Return operation tag of unary operator represented by token, 5.2785 - * -1 if token is not a binary operator. 5.2786 - */ 5.2787 - static int unoptag(Token token) { 5.2788 - switch (token) { 5.2789 - case PLUS: 5.2790 - return JCTree.POS; 5.2791 - case SUB: 5.2792 - return JCTree.NEG; 5.2793 - case BANG: 5.2794 - return JCTree.NOT; 5.2795 - case TILDE: 5.2796 - return JCTree.COMPL; 5.2797 - case PLUSPLUS: 5.2798 - return JCTree.PREINC; 5.2799 - case SUBSUB: 5.2800 - return JCTree.PREDEC; 5.2801 - default: 5.2802 - return -1; 5.2803 - } 5.2804 - } 5.2805 - 5.2806 - /** Return type tag of basic type represented by token, 5.2807 - * -1 if token is not a basic type identifier. 5.2808 - */ 5.2809 - static int typetag(Token token) { 5.2810 - switch (token) { 5.2811 - case BYTE: 5.2812 - return TypeTags.BYTE; 5.2813 - case CHAR: 5.2814 - return TypeTags.CHAR; 5.2815 - case SHORT: 5.2816 - return TypeTags.SHORT; 5.2817 - case INT: 5.2818 - return TypeTags.INT; 5.2819 - case LONG: 5.2820 - return TypeTags.LONG; 5.2821 - case FLOAT: 5.2822 - return TypeTags.FLOAT; 5.2823 - case DOUBLE: 5.2824 - return TypeTags.DOUBLE; 5.2825 - case BOOLEAN: 5.2826 - return TypeTags.BOOLEAN; 5.2827 - default: 5.2828 - return -1; 5.2829 - } 5.2830 - } 5.2831 - 5.2832 - void checkGenerics() { 5.2833 - if (!allowGenerics) { 5.2834 - log.error(S.pos(), "generics.not.supported.in.source", source.name); 5.2835 - allowGenerics = true; 5.2836 - } 5.2837 - } 5.2838 - void checkVarargs() { 5.2839 - if (!allowVarargs) { 5.2840 - log.error(S.pos(), "varargs.not.supported.in.source", source.name); 5.2841 - allowVarargs = true; 5.2842 - } 5.2843 - } 5.2844 - void checkForeach() { 5.2845 - if (!allowForeach) { 5.2846 - log.error(S.pos(), "foreach.not.supported.in.source", source.name); 5.2847 - allowForeach = true; 5.2848 - } 5.2849 - } 5.2850 - void checkStaticImports() { 5.2851 - if (!allowStaticImport) { 5.2852 - log.error(S.pos(), "static.import.not.supported.in.source", source.name); 5.2853 - allowStaticImport = true; 5.2854 - } 5.2855 - } 5.2856 - void checkAnnotations() { 5.2857 - if (!allowAnnotations) { 5.2858 - log.error(S.pos(), "annotations.not.supported.in.source", source.name); 5.2859 - allowAnnotations = true; 5.2860 - } 5.2861 - } 5.2862 -}
6.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 6.2 +++ b/src/share/classes/com/sun/tools/javac/parser/ParserFactory.java Tue Sep 09 10:40:50 2008 -0700 6.3 @@ -0,0 +1,79 @@ 6.4 +/* 6.5 + * Copyright 1999-2008 Sun Microsystems, Inc. All Rights Reserved. 6.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 6.7 + * 6.8 + * This code is free software; you can redistribute it and/or modify it 6.9 + * under the terms of the GNU General Public License version 2 only, as 6.10 + * published by the Free Software Foundation. Sun designates this 6.11 + * particular file as subject to the "Classpath" exception as provided 6.12 + * by Sun in the LICENSE file that accompanied this code. 6.13 + * 6.14 + * This code is distributed in the hope that it will be useful, but WITHOUT 6.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 6.16 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 6.17 + * version 2 for more details (a copy is included in the LICENSE file that 6.18 + * accompanied this code). 6.19 + * 6.20 + * You should have received a copy of the GNU General Public License version 6.21 + * 2 along with this work; if not, write to the Free Software Foundation, 6.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 6.23 + * 6.24 + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, 6.25 + * CA 95054 USA or visit www.sun.com if you need additional information or 6.26 + * have any questions. 6.27 + */ 6.28 + 6.29 +package com.sun.tools.javac.parser; 6.30 + 6.31 +import com.sun.tools.javac.code.Source; 6.32 +import com.sun.tools.javac.tree.TreeMaker; 6.33 +import com.sun.tools.javac.util.Context; 6.34 +import com.sun.tools.javac.util.Log; 6.35 +import com.sun.tools.javac.util.Name; 6.36 +import com.sun.tools.javac.util.Options; 6.37 + 6.38 +/** 6.39 + * A factory for creating parsers. 6.40 + */ 6.41 +public class ParserFactory { 6.42 + 6.43 + /** The context key for the parser factory. */ 6.44 + protected static final Context.Key<ParserFactory> parserFactoryKey = new Context.Key<ParserFactory>(); 6.45 + 6.46 + public static ParserFactory instance(Context context) { 6.47 + ParserFactory instance = context.get(parserFactoryKey); 6.48 + if (instance == null) { 6.49 + instance = new ParserFactory(context); 6.50 + } 6.51 + return instance; 6.52 + } 6.53 + 6.54 + final TreeMaker F; 6.55 + final Log log; 6.56 + final Keywords keywords; 6.57 + final Source source; 6.58 + final Name.Table names; 6.59 + final Options options; 6.60 + final Scanner.Factory scannerFactory; 6.61 + 6.62 + protected ParserFactory(Context context) { 6.63 + super(); 6.64 + context.put(parserFactoryKey, this); 6.65 + this.F = TreeMaker.instance(context); 6.66 + this.log = Log.instance(context); 6.67 + this.names = Name.Table.instance(context); 6.68 + this.keywords = Keywords.instance(context); 6.69 + this.source = Source.instance(context); 6.70 + this.options = Options.instance(context); 6.71 + this.scannerFactory = Scanner.Factory.instance(context); 6.72 + } 6.73 + 6.74 + public Parser newParser(CharSequence input, boolean keepDocComments, boolean keepEndPos, boolean keepLineMap) { 6.75 + Lexer lexer = scannerFactory.newScanner(input); 6.76 + if (keepEndPos) { 6.77 + return new EndPosParser(this, lexer, keepDocComments, keepLineMap); 6.78 + } else { 6.79 + return new JavacParser(this, lexer, keepDocComments, keepLineMap); 6.80 + } 6.81 + } 6.82 +}
7.1 --- a/test/tools/javac/6304921/TestLog.java Tue Sep 09 10:28:21 2008 -0700 7.2 +++ b/test/tools/javac/6304921/TestLog.java Tue Sep 09 10:40:50 2008 -0700 7.3 @@ -34,6 +34,7 @@ 7.4 import javax.tools.SimpleJavaFileObject; 7.5 import com.sun.tools.javac.file.JavacFileManager; 7.6 import com.sun.tools.javac.parser.Parser; 7.7 +import com.sun.tools.javac.parser.ParserFactory; 7.8 import com.sun.tools.javac.parser.Scanner; 7.9 import com.sun.tools.javac.tree.JCTree; 7.10 import com.sun.tools.javac.tree.TreeScanner; 7.11 @@ -60,7 +61,7 @@ 7.12 7.13 JavacFileManager.preRegister(context); 7.14 Scanner.Factory sfac = Scanner.Factory.instance(context); 7.15 - Parser.Factory pfac = Parser.Factory.instance(context); 7.16 + ParserFactory pfac = ParserFactory.instance(context); 7.17 7.18 final String text = 7.19 "public class Foo {\n" 7.20 @@ -74,9 +75,9 @@ 7.21 JavaFileObject fo = new StringJavaFileObject("Foo", text); 7.22 log.useSource(fo); 7.23 7.24 - Scanner s = sfac.newScanner(fo.getCharContent(true)); 7.25 - Parser parser = pfac.newParser(s, false, genEndPos); 7.26 - JCTree.JCCompilationUnit tree = parser.compilationUnit(); 7.27 + CharSequence cs = fo.getCharContent(true); 7.28 + Parser parser = pfac.newParser(cs, false, genEndPos, false); 7.29 + JCTree.JCCompilationUnit tree = parser.parseCompilationUnit(); 7.30 log.setEndPosTable(fo, tree.endPositions); 7.31 7.32 TreeScanner ts = new LogTester(log, tree.endPositions);