--- a/langtools/src/share/classes/com/sun/source/util/Trees.java Wed Jul 05 16:41:36 2017 +0200
+++ b/langtools/src/share/classes/com/sun/source/util/Trees.java Fri Sep 12 23:32:51 2008 -0700
@@ -33,6 +33,7 @@
import javax.lang.model.element.ExecutableElement;
import javax.lang.model.element.TypeElement;
import javax.lang.model.type.DeclaredType;
+import javax.lang.model.type.ErrorType;
import javax.lang.model.type.TypeMirror;
import javax.tools.JavaCompiler.CompilationTask;
@@ -177,4 +178,11 @@
* @return true if {@code member} is accessible in {@code type}
*/
public abstract boolean isAccessible(Scope scope, Element member, DeclaredType type);
+
+ /**
+ * Gets the original type from the ErrorType object.
+ * @param errorType The errorType for which we want to get the original type.
+ * @returns javax.lang.model.type.TypeMirror corresponding to the original type, replaced by the ErrorType.
+ */
+ public abstract TypeMirror getOriginalType(ErrorType errorType);
}
--- a/langtools/src/share/classes/com/sun/tools/javac/api/JavacTaskImpl.java Wed Jul 05 16:41:36 2017 +0200
+++ b/langtools/src/share/classes/com/sun/tools/javac/api/JavacTaskImpl.java Fri Sep 12 23:32:51 2008 -0700
@@ -27,6 +27,7 @@
import java.io.File;
import java.io.IOException;
+import java.nio.CharBuffer;
import java.util.*;
import java.util.concurrent.atomic.AtomicBoolean;
@@ -45,7 +46,7 @@
import com.sun.tools.javac.main.*;
import com.sun.tools.javac.model.*;
import com.sun.tools.javac.parser.Parser;
-import com.sun.tools.javac.parser.Scanner;
+import com.sun.tools.javac.parser.ParserFactory;
import com.sun.tools.javac.tree.*;
import com.sun.tools.javac.tree.JCTree.*;
import com.sun.tools.javac.util.*;
@@ -93,6 +94,9 @@
args.getClass();
context.getClass();
fileObjects.getClass();
+
+ // force the use of the scanner that captures Javadoc comments
+ com.sun.tools.javac.parser.DocCommentScanner.Factory.preRegister(context);
}
JavacTaskImpl(JavacTool tool,
@@ -166,8 +170,6 @@
if (!filenames.isEmpty())
throw new IllegalArgumentException("Malformed arguments " + filenames.toString(" "));
compiler = JavaCompiler.instance(context);
- // force the use of the scanner that captures Javadoc comments
- com.sun.tools.javac.parser.DocCommentScanner.Factory.preRegister(context);
compiler.keepComments = true;
compiler.genEndPos = true;
// NOTE: this value will be updated after annotation processing
@@ -519,14 +521,12 @@
throw new IllegalArgumentException();
compiler = JavaCompiler.instance(context);
JavaFileObject prev = compiler.log.useSource(null);
- Scanner.Factory scannerFactory = Scanner.Factory.instance(context);
- Parser.Factory parserFactory = Parser.Factory.instance(context);
+ ParserFactory parserFactory = ParserFactory.instance(context);
Attr attr = Attr.instance(context);
try {
- Scanner scanner = scannerFactory.newScanner((expr+"\u0000").toCharArray(),
- expr.length());
- Parser parser = parserFactory.newParser(scanner, false, false);
- JCTree tree = parser.type();
+ CharBuffer buf = CharBuffer.wrap((expr+"\u0000").toCharArray(), 0, expr.length());
+ Parser parser = parserFactory.newParser(buf, false, false, false);
+ JCTree tree = parser.parseType();
return attr.attribType(tree, (Symbol.TypeSymbol)scope);
} finally {
compiler.log.useSource(prev);
--- a/langtools/src/share/classes/com/sun/tools/javac/api/JavacTrees.java Wed Jul 05 16:41:36 2017 +0200
+++ b/langtools/src/share/classes/com/sun/tools/javac/api/JavacTrees.java Fri Sep 12 23:32:51 2008 -0700
@@ -322,4 +322,18 @@
return t2;
}
}
+
+ /**
+ * Gets the original type from the ErrorType object.
+ * @param errorType The errorType for which we want to get the original type.
+ * @returns TypeMirror corresponding to the original type, replaced by the ErrorType.
+ * noType (type.tag == NONE) is returned if there is no original type.
+ */
+ public TypeMirror getOriginalType(javax.lang.model.type.ErrorType errorType) {
+ if (errorType instanceof com.sun.tools.javac.code.Type.ErrorType) {
+ return ((com.sun.tools.javac.code.Type.ErrorType)errorType).getOriginalType();
+ }
+
+ return com.sun.tools.javac.code.Type.noType;
+ }
}
--- a/langtools/src/share/classes/com/sun/tools/javac/code/Symbol.java Wed Jul 05 16:41:36 2017 +0200
+++ b/langtools/src/share/classes/com/sun/tools/javac/code/Symbol.java Fri Sep 12 23:32:51 2008 -0700
@@ -776,7 +776,7 @@
} catch (CompletionFailure ex) {
// quiet error recovery
flags_field |= (PUBLIC|STATIC);
- this.type = new ErrorType(this);
+ this.type = new ErrorType(this, Type.noType);
throw ex;
}
}
--- a/langtools/src/share/classes/com/sun/tools/javac/code/Symtab.java Wed Jul 05 16:41:36 2017 +0200
+++ b/langtools/src/share/classes/com/sun/tools/javac/code/Symtab.java Fri Sep 12 23:32:51 2008 -0700
@@ -93,8 +93,7 @@
*/
public final ClassSymbol errSymbol;
- /** An instance of the error type.
- */
+ /** A value for the errType, with a originalType of noType */
public final Type errType;
/** A value for the unknown type. */
@@ -348,7 +347,7 @@
// create the error symbols
errSymbol = new ClassSymbol(PUBLIC|STATIC|ACYCLIC, names.any, null, rootPackage);
- errType = new ErrorType(errSymbol);
+ errType = new ErrorType(errSymbol, Type.noType);
// initialize builtin types
initType(byteType, "byte", "Byte");
@@ -389,6 +388,9 @@
scope.enter(booleanType.tsym);
scope.enter(errType.tsym);
+ // Enter symbol for the errSymbol
+ scope.enter(errSymbol);
+
classes.put(predefClass.fullname, predefClass);
reader = ClassReader.instance(context);
--- a/langtools/src/share/classes/com/sun/tools/javac/code/Type.java Wed Jul 05 16:41:36 2017 +0200
+++ b/langtools/src/share/classes/com/sun/tools/javac/code/Type.java Fri Sep 12 23:32:51 2008 -0700
@@ -1194,21 +1194,24 @@
public static class ErrorType extends ClassType
implements javax.lang.model.type.ErrorType {
- public ErrorType() {
+ private Type originalType = null;
+
+ public ErrorType(Type originalType, TypeSymbol tsym) {
super(noType, List.<Type>nil(), null);
tag = ERROR;
+ this.tsym = tsym;
+ this.originalType = (originalType == null ? noType : originalType);
}
- public ErrorType(ClassSymbol c) {
- this();
- tsym = c;
+ public ErrorType(ClassSymbol c, Type originalType) {
+ this(originalType, c);
c.type = this;
c.kind = ERR;
c.members_field = new Scope.ErrorScope(c);
}
- public ErrorType(Name name, TypeSymbol container) {
- this(new ClassSymbol(PUBLIC|STATIC|ACYCLIC, name, null, container));
+ public ErrorType(Name name, TypeSymbol container, Type originalType) {
+ this(new ClassSymbol(PUBLIC|STATIC|ACYCLIC, name, null, container), originalType);
}
@Override
@@ -1234,6 +1237,10 @@
return TypeKind.ERROR;
}
+ public Type getOriginalType() {
+ return originalType;
+ }
+
public <R, P> R accept(TypeVisitor<R, P> v, P p) {
return v.visitError(this, p);
}
--- a/langtools/src/share/classes/com/sun/tools/javac/code/Types.java Wed Jul 05 16:41:36 2017 +0200
+++ b/langtools/src/share/classes/com/sun/tools/javac/code/Types.java Fri Sep 12 23:32:51 2008 -0700
@@ -2187,6 +2187,20 @@
};
// </editor-fold>
+ // <editor-fold defaultstate="collapsed" desc="createErrorType">
+ public Type createErrorType(Type originalType) {
+ return new ErrorType(originalType, syms.errSymbol);
+ }
+
+ public Type createErrorType(ClassSymbol c, Type originalType) {
+ return new ErrorType(c, originalType);
+ }
+
+ public Type createErrorType(Name name, TypeSymbol container, Type originalType) {
+ return new ErrorType(name, container, originalType);
+ }
+ // </editor-fold>
+
// <editor-fold defaultstate="collapsed" desc="rank">
/**
* The rank of a class is the length of the longest path between
@@ -2604,7 +2618,7 @@
if (!bound.isInterface())
classCount++;
if (classCount > 1)
- return syms.errType;
+ return createErrorType(t);
}
return makeCompoundType(bounds);
}
--- a/langtools/src/share/classes/com/sun/tools/javac/comp/Attr.java Wed Jul 05 16:41:36 2017 +0200
+++ b/langtools/src/share/classes/com/sun/tools/javac/comp/Attr.java Fri Sep 12 23:32:51 2008 -0700
@@ -159,7 +159,7 @@
* If check succeeds, store type in tree and return it.
* If check fails, store errType in tree and return it.
* No checks are performed if the prototype is a method type.
- * Its not necessary in this case since we know that kind and type
+ * It is not necessary in this case since we know that kind and type
* are correct.
*
* @param tree The tree whose kind and type is checked
@@ -176,7 +176,7 @@
log.error(tree.pos(), "unexpected.type",
kindNames(pkind),
kindName(ownkind));
- owntype = syms.errType;
+ owntype = types.createErrorType(owntype);
}
}
tree.type = owntype;
@@ -524,7 +524,7 @@
// check that type variable is already visible
if (t.getUpperBound() == null) {
log.error(tree.pos(), "illegal.forward.ref");
- return syms.errType;
+ return types.createErrorType(t);
}
} else {
t = chk.checkClassType(tree.pos(), t, checkExtensible|!allowGenerics);
@@ -533,12 +533,12 @@
log.error(tree.pos(), "intf.expected.here");
// return errType is necessary since otherwise there might
// be undetected cycles which cause attribution to loop
- return syms.errType;
+ return types.createErrorType(t);
} else if (checkExtensible &&
classExpected &&
(t.tsym.flags() & INTERFACE) != 0) {
log.error(tree.pos(), "no.intf.expected.here");
- return syms.errType;
+ return types.createErrorType(t);
}
if (checkExtensible &&
((t.tsym.flags() & FINAL) != 0)) {
@@ -804,7 +804,7 @@
Type base = types.asSuper(exprType, syms.iterableType.tsym);
if (base == null) {
log.error(tree.expr.pos(), "foreach.not.applicable.to.type");
- elemtype = syms.errType;
+ elemtype = types.createErrorType(exprType);
} else {
List<Type> iterableParams = base.allparams();
elemtype = iterableParams.isEmpty()
@@ -1219,7 +1219,7 @@
if (methName == names._super) {
if (site == syms.objectType) {
log.error(tree.meth.pos(), "no.superclass", site);
- site = syms.errType;
+ site = types.createErrorType(syms.objectType);
} else {
site = types.supertype(site);
}
@@ -1351,7 +1351,7 @@
}
public void visitNewClass(JCNewClass tree) {
- Type owntype = syms.errType;
+ Type owntype = types.createErrorType(tree.type);
// The local environment of a class creation is
// a new environment nested in the current one.
@@ -1551,7 +1551,7 @@
}
public void visitNewArray(JCNewArray tree) {
- Type owntype = syms.errType;
+ Type owntype = types.createErrorType(tree.type);
Type elemtype;
if (tree.elemtype != null) {
elemtype = attribType(tree.elemtype, env);
@@ -1571,7 +1571,7 @@
log.error(tree.pos(), "illegal.initializer.for.type",
pt);
}
- elemtype = syms.errType;
+ elemtype = types.createErrorType(pt);
}
}
if (tree.elems != null) {
@@ -1631,7 +1631,7 @@
Symbol operator = tree.operator =
rs.resolveUnaryOperator(tree.pos(), tree.getTag(), env, argtype);
- Type owntype = syms.errType;
+ Type owntype = types.createErrorType(tree.type);
if (operator.kind == MTH) {
owntype = (JCTree.PREINC <= tree.getTag() && tree.getTag() <= JCTree.POSTDEC)
? tree.arg.type
@@ -1667,7 +1667,7 @@
Symbol operator = tree.operator =
rs.resolveBinaryOperator(tree.pos(), tree.getTag(), env, left, right);
- Type owntype = syms.errType;
+ Type owntype = types.createErrorType(tree.type);
if (operator.kind == MTH) {
owntype = operator.type.getReturnType();
int opc = chk.checkOperator(tree.lhs.pos(),
@@ -1728,7 +1728,7 @@
}
public void visitIndexed(JCArrayAccess tree) {
- Type owntype = syms.errType;
+ Type owntype = types.createErrorType(tree.type);
Type atype = attribExpr(tree.indexed, env);
attribExpr(tree.index, env, syms.intType);
if (types.isArray(atype))
@@ -1849,7 +1849,7 @@
elt = ((ArrayType)elt).elemtype;
if (elt.tag == TYPEVAR) {
log.error(tree.pos(), "type.var.cant.be.deref");
- result = syms.errType;
+ result = types.createErrorType(tree.type);
return;
}
}
@@ -2009,7 +2009,7 @@
}
case ERROR:
// preserve identifier names through errors
- return new ErrorType(name, site.tsym).tsym;
+ return types.createErrorType(name, site.tsym, site).tsym;
default:
// The qualifier expression is of a primitive type -- only
// .class is allowed for these.
@@ -2059,7 +2059,7 @@
int pkind,
Type pt,
boolean useVarargs) {
- if (pt.isErroneous()) return syms.errType;
+ if (pt.isErroneous()) return types.createErrorType(site);
Type owntype; // The computed type of this identifier occurrence.
switch (sym.kind) {
case TYP:
@@ -2129,7 +2129,7 @@
for (List<Type> l = env.info.tvars; l.nonEmpty(); l = l.tail)
if (!owntype.contains(l.head)) {
log.error(tree.pos(), "undetermined.type", owntype1);
- owntype1 = syms.errType;
+ owntype1 = types.createErrorType(owntype1);
}
owntype = owntype1;
}
@@ -2332,7 +2332,7 @@
"internal.error.cant.instantiate",
sym, site,
Type.toString(pt.getParameterTypes()));
- owntype = syms.errType;
+ owntype = types.createErrorType(site);
} else {
// System.out.println("call : " + env.tree);
// System.out.println("method : " + owntype);
@@ -2454,7 +2454,7 @@
* before supertype structure is completely known
*/
public void visitTypeApply(JCTypeApply tree) {
- Type owntype = syms.errType;
+ Type owntype = types.createErrorType(tree.type);
// Attribute functor part of application and make sure it's a class.
Type clazztype = chk.checkClassType(tree.clazz.pos(), attribType(tree.clazz, env));
@@ -2498,7 +2498,7 @@
} else {
log.error(tree.pos(), "type.doesnt.take.params", clazztype.tsym);
}
- owntype = syms.errType;
+ owntype = types.createErrorType(tree.type);
}
}
result = check(tree, owntype, TYP, pkind, pt);
--- a/langtools/src/share/classes/com/sun/tools/javac/comp/Check.java Wed Jul 05 16:41:36 2017 +0200
+++ b/langtools/src/share/classes/com/sun/tools/javac/comp/Check.java Fri Sep 12 23:32:51 2008 -0700
@@ -192,12 +192,12 @@
Type typeError(DiagnosticPosition pos, Object problem, Type found, Type req) {
log.error(pos, "prob.found.req",
problem, found, req);
- return syms.errType;
+ return types.createErrorType(found);
}
Type typeError(DiagnosticPosition pos, String problem, Type found, Type req, Object explanation) {
log.error(pos, "prob.found.req.1", problem, found, req, explanation);
- return syms.errType;
+ return types.createErrorType(found);
}
/** Report an error that wrong type tag was found.
@@ -208,7 +208,7 @@
*/
Type typeTagError(DiagnosticPosition pos, Object required, Object found) {
log.error(pos, "type.found.req", found, required);
- return syms.errType;
+ return types.createErrorType(found instanceof Type ? (Type)found : syms.errType);
}
/** Report an error that symbol cannot be referenced before super
@@ -348,11 +348,11 @@
return typeError(pos, diags.fragment("possible.loss.of.precision"), found, req);
if (found.isSuperBound()) {
log.error(pos, "assignment.from.super-bound", found);
- return syms.errType;
+ return types.createErrorType(found);
}
if (req.isExtendsBound()) {
log.error(pos, "assignment.to.extends-bound", req);
- return syms.errType;
+ return types.createErrorType(found);
}
return typeError(pos, diags.fragment("incompatible.types"), found, req);
}
@@ -378,7 +378,7 @@
log.error(pos,
"undetermined.type" + (d!=null ? ".1" : ""),
t, d);
- return syms.errType;
+ return types.createErrorType(pt);
} else {
JCDiagnostic d = ex.getDiagnostic();
return typeError(pos,
@@ -469,7 +469,7 @@
Type checkNonVoid(DiagnosticPosition pos, Type t) {
if (t.tag == VOID) {
log.error(pos, "void.not.allowed.here");
- return syms.errType;
+ return types.createErrorType(t);
} else {
return t;
}
@@ -521,7 +521,7 @@
t);
} else if (!types.isReifiable(t)) {
log.error(pos, "illegal.generic.type.for.instof");
- return syms.errType;
+ return types.createErrorType(t);
} else {
return t;
}
@@ -1542,7 +1542,7 @@
return;
if (seen.contains(t)) {
tv = (TypeVar)t;
- tv.bound = new ErrorType();
+ tv.bound = types.createErrorType(t);
log.error(pos, "cyclic.inheritance", t);
} else if (t.tag == TYPEVAR) {
tv = (TypeVar)t;
@@ -1597,11 +1597,11 @@
private void noteCyclic(DiagnosticPosition pos, ClassSymbol c) {
log.error(pos, "cyclic.inheritance", c);
for (List<Type> l=types.interfaces(c.type); l.nonEmpty(); l=l.tail)
- l.head = new ErrorType((ClassSymbol)l.head.tsym);
+ l.head = types.createErrorType((ClassSymbol)l.head.tsym, Type.noType);
Type st = types.supertype(c.type);
if (st.tag == CLASS)
- ((ClassType)c.type).supertype_field = new ErrorType((ClassSymbol)st.tsym);
- c.type = new ErrorType(c);
+ ((ClassType)c.type).supertype_field = types.createErrorType((ClassSymbol)st.tsym, Type.noType);
+ c.type = types.createErrorType(c, c.type);
c.flags_field |= ACYCLIC;
}
--- a/langtools/src/share/classes/com/sun/tools/javac/comp/Enter.java Wed Jul 05 16:41:36 2017 +0200
+++ b/langtools/src/share/classes/com/sun/tools/javac/comp/Enter.java Fri Sep 12 23:32:51 2008 -0700
@@ -98,6 +98,7 @@
ClassReader reader;
Annotate annotate;
MemberEnter memberEnter;
+ Types types;
Lint lint;
JavaFileManager fileManager;
@@ -119,6 +120,7 @@
syms = Symtab.instance(context);
chk = Check.instance(context);
memberEnter = MemberEnter.instance(context);
+ types = Types.instance(context);
annotate = Annotate.instance(context);
lint = Lint.instance(context);
@@ -355,7 +357,7 @@
// Enter class into `compiled' table and enclosing scope.
if (chk.compiled.get(c.flatname) != null) {
duplicateClass(tree.pos(), c);
- result = new ErrorType(tree.name, (TypeSymbol)owner);
+ result = types.createErrorType(tree.name, (TypeSymbol)owner, Type.noType);
tree.sym = (ClassSymbol)result.tsym;
return;
}
--- a/langtools/src/share/classes/com/sun/tools/javac/comp/Infer.java Wed Jul 05 16:41:36 2017 +0200
+++ b/langtools/src/share/classes/com/sun/tools/javac/comp/Infer.java Fri Sep 12 23:32:51 2008 -0700
@@ -204,7 +204,7 @@
return true;
}
- /** Instaniate undetermined type variable to the lub of all its lower bounds.
+ /** Instantiate undetermined type variable to the lub of all its lower bounds.
* Throw a NoInstanceException if this not possible.
*/
void minimizeInst(UndetVar that, Warner warn) throws NoInstanceException {
@@ -216,7 +216,7 @@
else {
that.inst = types.lub(that.lobounds);
}
- if (that.inst == null || that.inst == syms.errType)
+ if (that.inst == null || that.inst.tag == ERROR)
throw ambiguousNoInstanceException
.setMessage("no.unique.minimal.instance.exists",
that.qtype, that.lobounds);
--- a/langtools/src/share/classes/com/sun/tools/javac/comp/Resolve.java Wed Jul 05 16:41:36 2017 +0200
+++ b/langtools/src/share/classes/com/sun/tools/javac/comp/Resolve.java Fri Sep 12 23:32:51 2008 -0700
@@ -656,7 +656,7 @@
return new AmbiguityError(m1, m2);
// both abstract, neither overridden; merge throws clause and result type
Symbol result;
- Type result2 = mt2.getReturnType();;
+ Type result2 = mt2.getReturnType();
if (mt2.tag == FORALL)
result2 = types.subst(result2, ((ForAll)mt2).tvars, ((ForAll)mt1).tvars);
if (types.isSubtype(mt1.getReturnType(), result2)) {
@@ -1099,7 +1099,7 @@
if (sym == syms.errSymbol // preserve the symbol name through errors
|| ((sym.kind & ERRONEOUS) == 0 // make sure an error symbol is returned
&& (sym.kind & TYP) != 0))
- sym = new ErrorType(name, qualified?site.tsym:syms.noSymbol).tsym;
+ sym = types.createErrorType(name, qualified ? site.tsym : syms.noSymbol, sym.type).tsym;
}
return sym;
}
--- a/langtools/src/share/classes/com/sun/tools/javac/main/JavaCompiler.java Wed Jul 05 16:41:36 2017 +0200
+++ b/langtools/src/share/classes/com/sun/tools/javac/main/JavaCompiler.java Fri Sep 12 23:32:51 2008 -0700
@@ -276,7 +276,7 @@
/** Factory for parsers.
*/
- protected Parser.Factory parserFactory;
+ protected ParserFactory parserFactory;
/** Optional listener for progress events
*/
@@ -320,7 +320,7 @@
todo = Todo.instance(context);
fileManager = context.get(JavaFileManager.class);
- parserFactory = Parser.Factory.instance(context);
+ parserFactory = ParserFactory.instance(context);
try {
// catch completion problems with predefineds
@@ -510,10 +510,6 @@
return parseErrors;
}
- protected Scanner.Factory getScannerFactory() {
- return Scanner.Factory.instance(context);
- }
-
/** Try to open input stream with given name.
* Report an error if this fails.
* @param filename The file name of the input stream to be opened.
@@ -545,13 +541,9 @@
taskListener.started(e);
}
int initialErrorCount = log.nerrors;
- Scanner scanner = getScannerFactory().newScanner(content);
- Parser parser = parserFactory.newParser(scanner, keepComments(), genEndPos);
- tree = parser.compilationUnit();
+ Parser parser = parserFactory.newParser(content, keepComments(), genEndPos, lineDebugInfo);
+ tree = parser.parseCompilationUnit();
parseErrors |= (log.nerrors > initialErrorCount);
- if (lineDebugInfo) {
- tree.lineMap = scanner.getLineMap();
- }
if (verbose) {
printVerbose("parsing.done", Long.toString(elapsed(msec)));
}
--- a/langtools/src/share/classes/com/sun/tools/javac/parser/EndPosParser.java Wed Jul 05 16:41:36 2017 +0200
+++ b/langtools/src/share/classes/com/sun/tools/javac/parser/EndPosParser.java Fri Sep 12 23:32:51 2008 -0700
@@ -41,10 +41,10 @@
* This code and its internal interfaces are subject to change or
* deletion without notice.</b></p>
*/
-public class EndPosParser extends Parser {
+public class EndPosParser extends JavacParser {
- public EndPosParser(Factory fac, Lexer S, boolean keepDocComments) {
- super(fac, S, keepDocComments);
+ public EndPosParser(ParserFactory fac, Lexer S, boolean keepDocComments, boolean keepLineMap) {
+ super(fac, S, keepDocComments, keepLineMap);
this.S = S;
endPositions = new HashMap<JCTree,Integer>();
}
@@ -79,8 +79,8 @@
}
@Override
- public JCCompilationUnit compilationUnit() {
- JCCompilationUnit t = super.compilationUnit();
+ public JCCompilationUnit parseCompilationUnit() {
+ JCCompilationUnit t = super.parseCompilationUnit();
t.endPositions = endPositions;
return t;
}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/src/share/classes/com/sun/tools/javac/parser/JavacParser.java Fri Sep 12 23:32:51 2008 -0700
@@ -0,0 +1,2819 @@
+/*
+ * Copyright 1999-2008 Sun Microsystems, Inc. All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+package com.sun.tools.javac.parser;
+
+import java.util.*;
+
+import com.sun.tools.javac.tree.*;
+import com.sun.tools.javac.code.*;
+import com.sun.tools.javac.util.*;
+import com.sun.tools.javac.util.List;
+import static com.sun.tools.javac.util.ListBuffer.lb;
+
+import com.sun.tools.javac.tree.JCTree.*;
+
+import static com.sun.tools.javac.parser.Token.*;
+
+/** The parser maps a token sequence into an abstract syntax
+ * tree. It operates by recursive descent, with code derived
+ * systematically from an LL(1) grammar. For efficiency reasons, an
+ * operator precedence scheme is used for parsing binary operation
+ * expressions.
+ *
+ * <p><b>This is NOT part of any API supported by Sun Microsystems. If
+ * you write code that depends on this, you do so at your own risk.
+ * This code and its internal interfaces are subject to change or
+ * deletion without notice.</b>
+ */
+public class JavacParser implements Parser {
+
+ /** The number of precedence levels of infix operators.
+ */
+ private static final int infixPrecedenceLevels = 10;
+
+ /** The scanner used for lexical analysis.
+ */
+ private Lexer S;
+
+ /** The factory to be used for abstract syntax tree construction.
+ */
+ protected TreeMaker F;
+
+ /** The log to be used for error diagnostics.
+ */
+ private Log log;
+
+ /** The keyword table. */
+ private Keywords keywords;
+
+ /** The Source language setting. */
+ private Source source;
+
+ /** The name table. */
+ private Name.Table names;
+
+ /** Construct a parser from a given scanner, tree factory and log.
+ */
+ protected JavacParser(ParserFactory fac,
+ Lexer S,
+ boolean keepDocComments,
+ boolean keepLineMap) {
+ this.S = S;
+ S.nextToken(); // prime the pump
+ this.F = fac.F;
+ this.log = fac.log;
+ this.names = fac.names;
+ this.keywords = fac.keywords;
+ this.source = fac.source;
+ this.allowGenerics = source.allowGenerics();
+ this.allowVarargs = source.allowVarargs();
+ this.allowAsserts = source.allowAsserts();
+ this.allowEnums = source.allowEnums();
+ this.allowForeach = source.allowForeach();
+ this.allowStaticImport = source.allowStaticImport();
+ this.allowAnnotations = source.allowAnnotations();
+ this.keepDocComments = keepDocComments;
+ if (keepDocComments)
+ docComments = new HashMap<JCTree,String>();
+ this.keepLineMap = keepLineMap;
+ this.errorTree = F.Erroneous();
+ }
+
+ /** Switch: Should generics be recognized?
+ */
+ boolean allowGenerics;
+
+ /** Switch: Should varargs be recognized?
+ */
+ boolean allowVarargs;
+
+ /** Switch: should we recognize assert statements, or just give a warning?
+ */
+ boolean allowAsserts;
+
+ /** Switch: should we recognize enums, or just give a warning?
+ */
+ boolean allowEnums;
+
+ /** Switch: should we recognize foreach?
+ */
+ boolean allowForeach;
+
+ /** Switch: should we recognize foreach?
+ */
+ boolean allowStaticImport;
+
+ /** Switch: should we recognize annotations?
+ */
+ boolean allowAnnotations;
+
+ /** Switch: should we keep docComments?
+ */
+ boolean keepDocComments;
+
+ /** Switch: should we keep line table?
+ */
+ boolean keepLineMap;
+
+ /** When terms are parsed, the mode determines which is expected:
+ * mode = EXPR : an expression
+ * mode = TYPE : a type
+ * mode = NOPARAMS : no parameters allowed for type
+ * mode = TYPEARG : type argument
+ */
+ static final int EXPR = 1;
+ static final int TYPE = 2;
+ static final int NOPARAMS = 4;
+ static final int TYPEARG = 8;
+
+ /** The current mode.
+ */
+ private int mode = 0;
+
+ /** The mode of the term that was parsed last.
+ */
+ private int lastmode = 0;
+
+/* ---------- error recovery -------------- */
+
+ private JCErroneous errorTree;
+
+ /** Skip forward until a suitable stop token is found.
+ */
+ private void skip(boolean stopAtImport, boolean stopAtMemberDecl, boolean stopAtIdentifier, boolean stopAtStatement) {
+ while (true) {
+ switch (S.token()) {
+ case SEMI:
+ S.nextToken();
+ return;
+ case PUBLIC:
+ case FINAL:
+ case ABSTRACT:
+ case MONKEYS_AT:
+ case EOF:
+ case CLASS:
+ case INTERFACE:
+ case ENUM:
+ return;
+ case IMPORT:
+ if (stopAtImport)
+ return;
+ break;
+ case LBRACE:
+ case RBRACE:
+ case PRIVATE:
+ case PROTECTED:
+ case STATIC:
+ case TRANSIENT:
+ case NATIVE:
+ case VOLATILE:
+ case SYNCHRONIZED:
+ case STRICTFP:
+ case LT:
+ case BYTE:
+ case SHORT:
+ case CHAR:
+ case INT:
+ case LONG:
+ case FLOAT:
+ case DOUBLE:
+ case BOOLEAN:
+ case VOID:
+ if (stopAtMemberDecl)
+ return;
+ break;
+ case IDENTIFIER:
+ if (stopAtIdentifier)
+ return;
+ break;
+ case CASE:
+ case DEFAULT:
+ case IF:
+ case FOR:
+ case WHILE:
+ case DO:
+ case TRY:
+ case SWITCH:
+ case RETURN:
+ case THROW:
+ case BREAK:
+ case CONTINUE:
+ case ELSE:
+ case FINALLY:
+ case CATCH:
+ if (stopAtStatement)
+ return;
+ break;
+ }
+ S.nextToken();
+ }
+ }
+
+ private JCErroneous syntaxError(int pos, String key, Token... args) {
+ return syntaxError(pos, null, key, args);
+ }
+
+ private JCErroneous syntaxError(int pos, List<JCTree> errs, String key, Token... args) {
+ setErrorEndPos(pos);
+ reportSyntaxError(pos, key, (Object[])args);
+ return toP(F.at(pos).Erroneous(errs));
+ }
+
+ private int errorPos = Position.NOPOS;
+ /**
+ * Report a syntax error at given position using the given
+ * argument unless one was already reported at the same position.
+ */
+ private void reportSyntaxError(int pos, String key, Object... args) {
+ if (pos > S.errPos() || pos == Position.NOPOS) {
+ if (S.token() == EOF)
+ log.error(pos, "premature.eof");
+ else
+ log.error(pos, key, args);
+ }
+ S.errPos(pos);
+ if (S.pos() == errorPos)
+ S.nextToken(); // guarantee progress
+ errorPos = S.pos();
+ }
+
+
+ /** Generate a syntax error at current position unless one was already
+ * reported at the same position.
+ */
+ private JCErroneous syntaxError(String key) {
+ return syntaxError(S.pos(), key);
+ }
+
+ /** Generate a syntax error at current position unless one was
+ * already reported at the same position.
+ */
+ private JCErroneous syntaxError(String key, Token arg) {
+ return syntaxError(S.pos(), key, arg);
+ }
+
+ /** If next input token matches given token, skip it, otherwise report
+ * an error.
+ */
+ public void accept(Token token) {
+ if (S.token() == token) {
+ S.nextToken();
+ } else {
+ setErrorEndPos(S.pos());
+ reportSyntaxError(S.prevEndPos(), "expected", token);
+ }
+ }
+
+ /** Report an illegal start of expression/type error at given position.
+ */
+ JCExpression illegal(int pos) {
+ setErrorEndPos(S.pos());
+ if ((mode & EXPR) != 0)
+ return syntaxError(pos, "illegal.start.of.expr");
+ else
+ return syntaxError(pos, "illegal.start.of.type");
+
+ }
+
+ /** Report an illegal start of expression/type error at current position.
+ */
+ JCExpression illegal() {
+ return illegal(S.pos());
+ }
+
+ /** Diagnose a modifier flag from the set, if any. */
+ void checkNoMods(long mods) {
+ if (mods != 0) {
+ long lowestMod = mods & -mods;
+ log.error(S.pos(), "mod.not.allowed.here",
+ Flags.asFlagSet(lowestMod));
+ }
+ }
+
+/* ---------- doc comments --------- */
+
+ /** A hashtable to store all documentation comments
+ * indexed by the tree nodes they refer to.
+ * defined only if option flag keepDocComment is set.
+ */
+ Map<JCTree, String> docComments;
+
+ /** Make an entry into docComments hashtable,
+ * provided flag keepDocComments is set and given doc comment is non-null.
+ * @param tree The tree to be used as index in the hashtable
+ * @param dc The doc comment to associate with the tree, or null.
+ */
+ void attach(JCTree tree, String dc) {
+ if (keepDocComments && dc != null) {
+// System.out.println("doc comment = ");System.out.println(dc);//DEBUG
+ docComments.put(tree, dc);
+ }
+ }
+
+/* -------- source positions ------- */
+
+ private int errorEndPos = -1;
+
+ private void setErrorEndPos(int errPos) {
+ if (errPos > errorEndPos)
+ errorEndPos = errPos;
+ }
+
+ protected int getErrorEndPos() {
+ return errorEndPos;
+ }
+
+ /**
+ * Store ending position for a tree.
+ * @param tree The tree.
+ * @param endpos The ending position to associate with the tree.
+ */
+ protected void storeEnd(JCTree tree, int endpos) {}
+
+ /**
+ * Store ending position for a tree. The ending position should
+ * be the ending position of the current token.
+ * @param t The tree.
+ */
+ protected <T extends JCTree> T to(T t) { return t; }
+
+ /**
+ * Store ending position for a tree. The ending position should
+ * be greater of the ending position of the previous token and errorEndPos.
+ * @param t The tree.
+ */
+ protected <T extends JCTree> T toP(T t) { return t; }
+
+ /** Get the start position for a tree node. The start position is
+ * defined to be the position of the first character of the first
+ * token of the node's source text.
+ * @param tree The tree node
+ */
+ public int getStartPos(JCTree tree) {
+ return TreeInfo.getStartPos(tree);
+ }
+
+ /**
+ * Get the end position for a tree node. The end position is
+ * defined to be the position of the last character of the last
+ * token of the node's source text. Returns Position.NOPOS if end
+ * positions are not generated or the position is otherwise not
+ * found.
+ * @param tree The tree node
+ */
+ public int getEndPos(JCTree tree) {
+ return Position.NOPOS;
+ }
+
+
+
+/* ---------- parsing -------------- */
+
+ /**
+ * Ident = IDENTIFIER
+ */
+ Name ident() {
+ if (S.token() == IDENTIFIER) {
+ Name name = S.name();
+ S.nextToken();
+ return name;
+ } else if (S.token() == ASSERT) {
+ if (allowAsserts) {
+ log.error(S.pos(), "assert.as.identifier");
+ S.nextToken();
+ return names.error;
+ } else {
+ log.warning(S.pos(), "assert.as.identifier");
+ Name name = S.name();
+ S.nextToken();
+ return name;
+ }
+ } else if (S.token() == ENUM) {
+ if (allowEnums) {
+ log.error(S.pos(), "enum.as.identifier");
+ S.nextToken();
+ return names.error;
+ } else {
+ log.warning(S.pos(), "enum.as.identifier");
+ Name name = S.name();
+ S.nextToken();
+ return name;
+ }
+ } else {
+ accept(IDENTIFIER);
+ return names.error;
+ }
+}
+
+ /**
+ * Qualident = Ident { DOT Ident }
+ */
+ public JCExpression qualident() {
+ JCExpression t = toP(F.at(S.pos()).Ident(ident()));
+ while (S.token() == DOT) {
+ int pos = S.pos();
+ S.nextToken();
+ t = toP(F.at(pos).Select(t, ident()));
+ }
+ return t;
+ }
+
+ /**
+ * Literal =
+ * INTLITERAL
+ * | LONGLITERAL
+ * | FLOATLITERAL
+ * | DOUBLELITERAL
+ * | CHARLITERAL
+ * | STRINGLITERAL
+ * | TRUE
+ * | FALSE
+ * | NULL
+ */
+ JCExpression literal(Name prefix) {
+ int pos = S.pos();
+ JCExpression t = errorTree;
+ switch (S.token()) {
+ case INTLITERAL:
+ try {
+ t = F.at(pos).Literal(
+ TypeTags.INT,
+ Convert.string2int(strval(prefix), S.radix()));
+ } catch (NumberFormatException ex) {
+ log.error(S.pos(), "int.number.too.large", strval(prefix));
+ }
+ break;
+ case LONGLITERAL:
+ try {
+ t = F.at(pos).Literal(
+ TypeTags.LONG,
+ new Long(Convert.string2long(strval(prefix), S.radix())));
+ } catch (NumberFormatException ex) {
+ log.error(S.pos(), "int.number.too.large", strval(prefix));
+ }
+ break;
+ case FLOATLITERAL: {
+ String proper = (S.radix() == 16 ? ("0x"+ S.stringVal()) : S.stringVal());
+ Float n;
+ try {
+ n = Float.valueOf(proper);
+ } catch (NumberFormatException ex) {
+ // error already repoted in scanner
+ n = Float.NaN;
+ }
+ if (n.floatValue() == 0.0f && !isZero(proper))
+ log.error(S.pos(), "fp.number.too.small");
+ else if (n.floatValue() == Float.POSITIVE_INFINITY)
+ log.error(S.pos(), "fp.number.too.large");
+ else
+ t = F.at(pos).Literal(TypeTags.FLOAT, n);
+ break;
+ }
+ case DOUBLELITERAL: {
+ String proper = (S.radix() == 16 ? ("0x"+ S.stringVal()) : S.stringVal());
+ Double n;
+ try {
+ n = Double.valueOf(proper);
+ } catch (NumberFormatException ex) {
+ // error already reported in scanner
+ n = Double.NaN;
+ }
+ if (n.doubleValue() == 0.0d && !isZero(proper))
+ log.error(S.pos(), "fp.number.too.small");
+ else if (n.doubleValue() == Double.POSITIVE_INFINITY)
+ log.error(S.pos(), "fp.number.too.large");
+ else
+ t = F.at(pos).Literal(TypeTags.DOUBLE, n);
+ break;
+ }
+ case CHARLITERAL:
+ t = F.at(pos).Literal(
+ TypeTags.CHAR,
+ S.stringVal().charAt(0) + 0);
+ break;
+ case STRINGLITERAL:
+ t = F.at(pos).Literal(
+ TypeTags.CLASS,
+ S.stringVal());
+ break;
+ case TRUE: case FALSE:
+ t = F.at(pos).Literal(
+ TypeTags.BOOLEAN,
+ (S.token() == TRUE ? 1 : 0));
+ break;
+ case NULL:
+ t = F.at(pos).Literal(
+ TypeTags.BOT,
+ null);
+ break;
+ default:
+ assert false;
+ }
+ if (t == errorTree)
+ t = F.at(pos).Erroneous();
+ storeEnd(t, S.endPos());
+ S.nextToken();
+ return t;
+ }
+//where
+ boolean isZero(String s) {
+ char[] cs = s.toCharArray();
+ int base = ((Character.toLowerCase(s.charAt(1)) == 'x') ? 16 : 10);
+ int i = ((base==16) ? 2 : 0);
+ while (i < cs.length && (cs[i] == '0' || cs[i] == '.')) i++;
+ return !(i < cs.length && (Character.digit(cs[i], base) > 0));
+ }
+
+ String strval(Name prefix) {
+ String s = S.stringVal();
+ return (prefix.len == 0) ? s : prefix + s;
+ }
+
+ /** terms can be either expressions or types.
+ */
+ public JCExpression parseExpression() {
+ return term(EXPR);
+ }
+
+ public JCExpression parseType() {
+ return term(TYPE);
+ }
+
+ JCExpression term(int newmode) {
+ int prevmode = mode;
+ mode = newmode;
+ JCExpression t = term();
+ lastmode = mode;
+ mode = prevmode;
+ return t;
+ }
+
+ /**
+ * Expression = Expression1 [ExpressionRest]
+ * ExpressionRest = [AssignmentOperator Expression1]
+ * AssignmentOperator = "=" | "+=" | "-=" | "*=" | "/=" |
+ * "&=" | "|=" | "^=" |
+ * "%=" | "<<=" | ">>=" | ">>>="
+ * Type = Type1
+ * TypeNoParams = TypeNoParams1
+ * StatementExpression = Expression
+ * ConstantExpression = Expression
+ */
+ JCExpression term() {
+ JCExpression t = term1();
+ if ((mode & EXPR) != 0 &&
+ S.token() == EQ || PLUSEQ.compareTo(S.token()) <= 0 && S.token().compareTo(GTGTGTEQ) <= 0)
+ return termRest(t);
+ else
+ return t;
+ }
+
+ JCExpression termRest(JCExpression t) {
+ switch (S.token()) {
+ case EQ: {
+ int pos = S.pos();
+ S.nextToken();
+ mode = EXPR;
+ JCExpression t1 = term();
+ return toP(F.at(pos).Assign(t, t1));
+ }
+ case PLUSEQ:
+ case SUBEQ:
+ case STAREQ:
+ case SLASHEQ:
+ case PERCENTEQ:
+ case AMPEQ:
+ case BAREQ:
+ case CARETEQ:
+ case LTLTEQ:
+ case GTGTEQ:
+ case GTGTGTEQ:
+ int pos = S.pos();
+ Token token = S.token();
+ S.nextToken();
+ mode = EXPR;
+ JCExpression t1 = term();
+ return F.at(pos).Assignop(optag(token), t, t1);
+ default:
+ return t;
+ }
+ }
+
+ /** Expression1 = Expression2 [Expression1Rest]
+ * Type1 = Type2
+ * TypeNoParams1 = TypeNoParams2
+ */
+ JCExpression term1() {
+ JCExpression t = term2();
+ if ((mode & EXPR) != 0 && S.token() == QUES) {
+ mode = EXPR;
+ return term1Rest(t);
+ } else {
+ return t;
+ }
+ }
+
+ /** Expression1Rest = ["?" Expression ":" Expression1]
+ */
+ JCExpression term1Rest(JCExpression t) {
+ if (S.token() == QUES) {
+ int pos = S.pos();
+ S.nextToken();
+ JCExpression t1 = term();
+ accept(COLON);
+ JCExpression t2 = term1();
+ return F.at(pos).Conditional(t, t1, t2);
+ } else {
+ return t;
+ }
+ }
+
+ /** Expression2 = Expression3 [Expression2Rest]
+ * Type2 = Type3
+ * TypeNoParams2 = TypeNoParams3
+ */
+ JCExpression term2() {
+ JCExpression t = term3();
+ if ((mode & EXPR) != 0 && prec(S.token()) >= TreeInfo.orPrec) {
+ mode = EXPR;
+ return term2Rest(t, TreeInfo.orPrec);
+ } else {
+ return t;
+ }
+ }
+
+ /* Expression2Rest = {infixop Expression3}
+ * | Expression3 instanceof Type
+ * infixop = "||"
+ * | "&&"
+ * | "|"
+ * | "^"
+ * | "&"
+ * | "==" | "!="
+ * | "<" | ">" | "<=" | ">="
+ * | "<<" | ">>" | ">>>"
+ * | "+" | "-"
+ * | "*" | "/" | "%"
+ */
+ JCExpression term2Rest(JCExpression t, int minprec) {
+ List<JCExpression[]> savedOd = odStackSupply.elems;
+ JCExpression[] odStack = newOdStack();
+ List<Token[]> savedOp = opStackSupply.elems;
+ Token[] opStack = newOpStack();
+ // optimization, was odStack = new Tree[...]; opStack = new Tree[...];
+ int top = 0;
+ odStack[0] = t;
+ int startPos = S.pos();
+ Token topOp = ERROR;
+ while (prec(S.token()) >= minprec) {
+ opStack[top] = topOp;
+ top++;
+ topOp = S.token();
+ int pos = S.pos();
+ S.nextToken();
+ odStack[top] = topOp == INSTANCEOF ? parseType() : term3();
+ while (top > 0 && prec(topOp) >= prec(S.token())) {
+ odStack[top-1] = makeOp(pos, topOp, odStack[top-1],
+ odStack[top]);
+ top--;
+ topOp = opStack[top];
+ }
+ }
+ assert top == 0;
+ t = odStack[0];
+
+ if (t.getTag() == JCTree.PLUS) {
+ StringBuffer buf = foldStrings(t);
+ if (buf != null) {
+ t = toP(F.at(startPos).Literal(TypeTags.CLASS, buf.toString()));
+ }
+ }
+
+ odStackSupply.elems = savedOd; // optimization
+ opStackSupply.elems = savedOp; // optimization
+ return t;
+ }
+//where
+ /** Construct a binary or type test node.
+ */
+ private JCExpression makeOp(int pos,
+ Token topOp,
+ JCExpression od1,
+ JCExpression od2)
+ {
+ if (topOp == INSTANCEOF) {
+ return F.at(pos).TypeTest(od1, od2);
+ } else {
+ return F.at(pos).Binary(optag(topOp), od1, od2);
+ }
+ }
+ /** If tree is a concatenation of string literals, replace it
+ * by a single literal representing the concatenated string.
+ */
+ protected StringBuffer foldStrings(JCTree tree) {
+ List<String> buf = List.nil();
+ while (true) {
+ if (tree.getTag() == JCTree.LITERAL) {
+ JCLiteral lit = (JCLiteral) tree;
+ if (lit.typetag == TypeTags.CLASS) {
+ StringBuffer sbuf =
+ new StringBuffer((String)lit.value);
+ while (buf.nonEmpty()) {
+ sbuf.append(buf.head);
+ buf = buf.tail;
+ }
+ return sbuf;
+ }
+ } else if (tree.getTag() == JCTree.PLUS) {
+ JCBinary op = (JCBinary)tree;
+ if (op.rhs.getTag() == JCTree.LITERAL) {
+ JCLiteral lit = (JCLiteral) op.rhs;
+ if (lit.typetag == TypeTags.CLASS) {
+ buf = buf.prepend((String) lit.value);
+ tree = op.lhs;
+ continue;
+ }
+ }
+ }
+ return null;
+ }
+ }
+
+ /** optimization: To save allocating a new operand/operator stack
+ * for every binary operation, we use supplys.
+ */
+ ListBuffer<JCExpression[]> odStackSupply = new ListBuffer<JCExpression[]>();
+ ListBuffer<Token[]> opStackSupply = new ListBuffer<Token[]>();
+
+ private JCExpression[] newOdStack() {
+ if (odStackSupply.elems == odStackSupply.last)
+ odStackSupply.append(new JCExpression[infixPrecedenceLevels + 1]);
+ JCExpression[] odStack = odStackSupply.elems.head;
+ odStackSupply.elems = odStackSupply.elems.tail;
+ return odStack;
+ }
+
+ private Token[] newOpStack() {
+ if (opStackSupply.elems == opStackSupply.last)
+ opStackSupply.append(new Token[infixPrecedenceLevels + 1]);
+ Token[] opStack = opStackSupply.elems.head;
+ opStackSupply.elems = opStackSupply.elems.tail;
+ return opStack;
+ }
+
+ /** Expression3 = PrefixOp Expression3
+ * | "(" Expr | TypeNoParams ")" Expression3
+ * | Primary {Selector} {PostfixOp}
+ * Primary = "(" Expression ")"
+ * | Literal
+ * | [TypeArguments] THIS [Arguments]
+ * | [TypeArguments] SUPER SuperSuffix
+ * | NEW [TypeArguments] Creator
+ * | Ident { "." Ident }
+ * [ "[" ( "]" BracketsOpt "." CLASS | Expression "]" )
+ * | Arguments
+ * | "." ( CLASS | THIS | [TypeArguments] SUPER Arguments | NEW [TypeArguments] InnerCreator )
+ * ]
+ * | BasicType BracketsOpt "." CLASS
+ * PrefixOp = "++" | "--" | "!" | "~" | "+" | "-"
+ * PostfixOp = "++" | "--"
+ * Type3 = Ident { "." Ident } [TypeArguments] {TypeSelector} BracketsOpt
+ * | BasicType
+ * TypeNoParams3 = Ident { "." Ident } BracketsOpt
+ * Selector = "." [TypeArguments] Ident [Arguments]
+ * | "." THIS
+ * | "." [TypeArguments] SUPER SuperSuffix
+ * | "." NEW [TypeArguments] InnerCreator
+ * | "[" Expression "]"
+ * TypeSelector = "." Ident [TypeArguments]
+ * SuperSuffix = Arguments | "." Ident [Arguments]
+ */
+ protected JCExpression term3() {
+ int pos = S.pos();
+ JCExpression t;
+ List<JCExpression> typeArgs = typeArgumentsOpt(EXPR);
+ switch (S.token()) {
+ case QUES:
+ if ((mode & TYPE) != 0 && (mode & (TYPEARG|NOPARAMS)) == TYPEARG) {
+ mode = TYPE;
+ return typeArgument();
+ } else
+ return illegal();
+ case PLUSPLUS: case SUBSUB: case BANG: case TILDE: case PLUS: case SUB:
+ if (typeArgs == null && (mode & EXPR) != 0) {
+ Token token = S.token();
+ S.nextToken();
+ mode = EXPR;
+ if (token == SUB &&
+ (S.token() == INTLITERAL || S.token() == LONGLITERAL) &&
+ S.radix() == 10) {
+ mode = EXPR;
+ t = literal(names.hyphen);
+ } else {
+ t = term3();
+ return F.at(pos).Unary(unoptag(token), t);
+ }
+ } else return illegal();
+ break;
+ case LPAREN:
+ if (typeArgs == null && (mode & EXPR) != 0) {
+ S.nextToken();
+ mode = EXPR | TYPE | NOPARAMS;
+ t = term3();
+ if ((mode & TYPE) != 0 && S.token() == LT) {
+ // Could be a cast to a parameterized type
+ int op = JCTree.LT;
+ int pos1 = S.pos();
+ S.nextToken();
+ mode &= (EXPR | TYPE);
+ mode |= TYPEARG;
+ JCExpression t1 = term3();
+ if ((mode & TYPE) != 0 &&
+ (S.token() == COMMA || S.token() == GT)) {
+ mode = TYPE;
+ ListBuffer<JCExpression> args = new ListBuffer<JCExpression>();
+ args.append(t1);
+ while (S.token() == COMMA) {
+ S.nextToken();
+ args.append(typeArgument());
+ }
+ accept(GT);
+ t = F.at(pos1).TypeApply(t, args.toList());
+ checkGenerics();
+ t = bracketsOpt(toP(t));
+ } else if ((mode & EXPR) != 0) {
+ mode = EXPR;
+ t = F.at(pos1).Binary(op, t, term2Rest(t1, TreeInfo.shiftPrec));
+ t = termRest(term1Rest(term2Rest(t, TreeInfo.orPrec)));
+ } else {
+ accept(GT);
+ }
+ } else {
+ t = termRest(term1Rest(term2Rest(t, TreeInfo.orPrec)));
+ }
+ accept(RPAREN);
+ lastmode = mode;
+ mode = EXPR;
+ if ((lastmode & EXPR) == 0) {
+ JCExpression t1 = term3();
+ return F.at(pos).TypeCast(t, t1);
+ } else if ((lastmode & TYPE) != 0) {
+ switch (S.token()) {
+ /*case PLUSPLUS: case SUBSUB: */
+ case BANG: case TILDE:
+ case LPAREN: case THIS: case SUPER:
+ case INTLITERAL: case LONGLITERAL: case FLOATLITERAL:
+ case DOUBLELITERAL: case CHARLITERAL: case STRINGLITERAL:
+ case TRUE: case FALSE: case NULL:
+ case NEW: case IDENTIFIER: case ASSERT: case ENUM:
+ case BYTE: case SHORT: case CHAR: case INT:
+ case LONG: case FLOAT: case DOUBLE: case BOOLEAN: case VOID:
+ JCExpression t1 = term3();
+ return F.at(pos).TypeCast(t, t1);
+ }
+ }
+ } else return illegal();
+ t = toP(F.at(pos).Parens(t));
+ break;
+ case THIS:
+ if ((mode & EXPR) != 0) {
+ mode = EXPR;
+ t = to(F.at(pos).Ident(names._this));
+ S.nextToken();
+ if (typeArgs == null)
+ t = argumentsOpt(null, t);
+ else
+ t = arguments(typeArgs, t);
+ typeArgs = null;
+ } else return illegal();
+ break;
+ case SUPER:
+ if ((mode & EXPR) != 0) {
+ mode = EXPR;
+ t = to(superSuffix(typeArgs, F.at(pos).Ident(names._super)));
+ typeArgs = null;
+ } else return illegal();
+ break;
+ case INTLITERAL: case LONGLITERAL: case FLOATLITERAL: case DOUBLELITERAL:
+ case CHARLITERAL: case STRINGLITERAL:
+ case TRUE: case FALSE: case NULL:
+ if (typeArgs == null && (mode & EXPR) != 0) {
+ mode = EXPR;
+ t = literal(names.empty);
+ } else return illegal();
+ break;
+ case NEW:
+ if (typeArgs != null) return illegal();
+ if ((mode & EXPR) != 0) {
+ mode = EXPR;
+ S.nextToken();
+ if (S.token() == LT) typeArgs = typeArguments();
+ t = creator(pos, typeArgs);
+ typeArgs = null;
+ } else return illegal();
+ break;
+ case IDENTIFIER: case ASSERT: case ENUM:
+ if (typeArgs != null) return illegal();
+ t = toP(F.at(S.pos()).Ident(ident()));
+ loop: while (true) {
+ pos = S.pos();
+ switch (S.token()) {
+ case LBRACKET:
+ S.nextToken();
+ if (S.token() == RBRACKET) {
+ S.nextToken();
+ t = bracketsOpt(t);
+ t = toP(F.at(pos).TypeArray(t));
+ t = bracketsSuffix(t);
+ } else {
+ if ((mode & EXPR) != 0) {
+ mode = EXPR;
+ JCExpression t1 = term();
+ t = to(F.at(pos).Indexed(t, t1));
+ }
+ accept(RBRACKET);
+ }
+ break loop;
+ case LPAREN:
+ if ((mode & EXPR) != 0) {
+ mode = EXPR;
+ t = arguments(typeArgs, t);
+ typeArgs = null;
+ }
+ break loop;
+ case DOT:
+ S.nextToken();
+ int oldmode = mode;
+ mode &= ~NOPARAMS;
+ typeArgs = typeArgumentsOpt(EXPR);
+ mode = oldmode;
+ if ((mode & EXPR) != 0) {
+ switch (S.token()) {
+ case CLASS:
+ if (typeArgs != null) return illegal();
+ mode = EXPR;
+ t = to(F.at(pos).Select(t, names._class));
+ S.nextToken();
+ break loop;
+ case THIS:
+ if (typeArgs != null) return illegal();
+ mode = EXPR;
+ t = to(F.at(pos).Select(t, names._this));
+ S.nextToken();
+ break loop;
+ case SUPER:
+ mode = EXPR;
+ t = to(F.at(pos).Select(t, names._super));
+ t = superSuffix(typeArgs, t);
+ typeArgs = null;
+ break loop;
+ case NEW:
+ if (typeArgs != null) return illegal();
+ mode = EXPR;
+ int pos1 = S.pos();
+ S.nextToken();
+ if (S.token() == LT) typeArgs = typeArguments();
+ t = innerCreator(pos1, typeArgs, t);
+ typeArgs = null;
+ break loop;
+ }
+ }
+ // typeArgs saved for next loop iteration.
+ t = toP(F.at(pos).Select(t, ident()));
+ break;
+ default:
+ break loop;
+ }
+ }
+ if (typeArgs != null) illegal();
+ t = typeArgumentsOpt(t);
+ break;
+ case BYTE: case SHORT: case CHAR: case INT: case LONG: case FLOAT:
+ case DOUBLE: case BOOLEAN:
+ if (typeArgs != null) illegal();
+ t = bracketsSuffix(bracketsOpt(basicType()));
+ break;
+ case VOID:
+ if (typeArgs != null) illegal();
+ if ((mode & EXPR) != 0) {
+ S.nextToken();
+ if (S.token() == DOT) {
+ JCPrimitiveTypeTree ti = toP(F.at(pos).TypeIdent(TypeTags.VOID));
+ t = bracketsSuffix(ti);
+ } else {
+ return illegal(pos);
+ }
+ } else {
+ return illegal();
+ }
+ break;
+ default:
+ return illegal();
+ }
+ if (typeArgs != null) illegal();
+ while (true) {
+ int pos1 = S.pos();
+ if (S.token() == LBRACKET) {
+ S.nextToken();
+ if ((mode & TYPE) != 0) {
+ int oldmode = mode;
+ mode = TYPE;
+ if (S.token() == RBRACKET) {
+ S.nextToken();
+ t = bracketsOpt(t);
+ t = toP(F.at(pos1).TypeArray(t));
+ return t;
+ }
+ mode = oldmode;
+ }
+ if ((mode & EXPR) != 0) {
+ mode = EXPR;
+ JCExpression t1 = term();
+ t = to(F.at(pos1).Indexed(t, t1));
+ }
+ accept(RBRACKET);
+ } else if (S.token() == DOT) {
+ S.nextToken();
+ typeArgs = typeArgumentsOpt(EXPR);
+ if (S.token() == SUPER && (mode & EXPR) != 0) {
+ mode = EXPR;
+ t = to(F.at(pos1).Select(t, names._super));
+ S.nextToken();
+ t = arguments(typeArgs, t);
+ typeArgs = null;
+ } else if (S.token() == NEW && (mode & EXPR) != 0) {
+ if (typeArgs != null) return illegal();
+ mode = EXPR;
+ int pos2 = S.pos();
+ S.nextToken();
+ if (S.token() == LT) typeArgs = typeArguments();
+ t = innerCreator(pos2, typeArgs, t);
+ typeArgs = null;
+ } else {
+ t = toP(F.at(pos1).Select(t, ident()));
+ t = argumentsOpt(typeArgs, typeArgumentsOpt(t));
+ typeArgs = null;
+ }
+ } else {
+ break;
+ }
+ }
+ while ((S.token() == PLUSPLUS || S.token() == SUBSUB) && (mode & EXPR) != 0) {
+ mode = EXPR;
+ t = to(F.at(S.pos()).Unary(
+ S.token() == PLUSPLUS ? JCTree.POSTINC : JCTree.POSTDEC, t));
+ S.nextToken();
+ }
+ return toP(t);
+ }
+
+ /** SuperSuffix = Arguments | "." [TypeArguments] Ident [Arguments]
+ */
+ JCExpression superSuffix(List<JCExpression> typeArgs, JCExpression t) {
+ S.nextToken();
+ if (S.token() == LPAREN || typeArgs != null) {
+ t = arguments(typeArgs, t);
+ } else {
+ int pos = S.pos();
+ accept(DOT);
+ typeArgs = (S.token() == LT) ? typeArguments() : null;
+ t = toP(F.at(pos).Select(t, ident()));
+ t = argumentsOpt(typeArgs, t);
+ }
+ return t;
+ }
+
+ /** BasicType = BYTE | SHORT | CHAR | INT | LONG | FLOAT | DOUBLE | BOOLEAN
+ */
+ JCPrimitiveTypeTree basicType() {
+ JCPrimitiveTypeTree t = to(F.at(S.pos()).TypeIdent(typetag(S.token())));
+ S.nextToken();
+ return t;
+ }
+
+ /** ArgumentsOpt = [ Arguments ]
+ */
+ JCExpression argumentsOpt(List<JCExpression> typeArgs, JCExpression t) {
+ if ((mode & EXPR) != 0 && S.token() == LPAREN || typeArgs != null) {
+ mode = EXPR;
+ return arguments(typeArgs, t);
+ } else {
+ return t;
+ }
+ }
+
+ /** Arguments = "(" [Expression { COMMA Expression }] ")"
+ */
+ List<JCExpression> arguments() {
+ ListBuffer<JCExpression> args = lb();
+ if (S.token() == LPAREN) {
+ S.nextToken();
+ if (S.token() != RPAREN) {
+ args.append(parseExpression());
+ while (S.token() == COMMA) {
+ S.nextToken();
+ args.append(parseExpression());
+ }
+ }
+ accept(RPAREN);
+ } else {
+ syntaxError(S.pos(), "expected", LPAREN);
+ }
+ return args.toList();
+ }
+
+ JCMethodInvocation arguments(List<JCExpression> typeArgs, JCExpression t) {
+ int pos = S.pos();
+ List<JCExpression> args = arguments();
+ return toP(F.at(pos).Apply(typeArgs, t, args));
+ }
+
+ /** TypeArgumentsOpt = [ TypeArguments ]
+ */
+ JCExpression typeArgumentsOpt(JCExpression t) {
+ if (S.token() == LT &&
+ (mode & TYPE) != 0 &&
+ (mode & NOPARAMS) == 0) {
+ mode = TYPE;
+ checkGenerics();
+ return typeArguments(t);
+ } else {
+ return t;
+ }
+ }
+ List<JCExpression> typeArgumentsOpt() {
+ return typeArgumentsOpt(TYPE);
+ }
+
+ List<JCExpression> typeArgumentsOpt(int useMode) {
+ if (S.token() == LT) {
+ checkGenerics();
+ if ((mode & useMode) == 0 ||
+ (mode & NOPARAMS) != 0) {
+ illegal();
+ }
+ mode = useMode;
+ return typeArguments();
+ }
+ return null;
+ }
+
+ /** TypeArguments = "<" TypeArgument {"," TypeArgument} ">"
+ */
+ List<JCExpression> typeArguments() {
+ ListBuffer<JCExpression> args = lb();
+ if (S.token() == LT) {
+ S.nextToken();
+ args.append(((mode & EXPR) == 0) ? typeArgument() : parseType());
+ while (S.token() == COMMA) {
+ S.nextToken();
+ args.append(((mode & EXPR) == 0) ? typeArgument() : parseType());
+ }
+ switch (S.token()) {
+ case GTGTGTEQ:
+ S.token(GTGTEQ);
+ break;
+ case GTGTEQ:
+ S.token(GTEQ);
+ break;
+ case GTEQ:
+ S.token(EQ);
+ break;
+ case GTGTGT:
+ S.token(GTGT);
+ break;
+ case GTGT:
+ S.token(GT);
+ break;
+ default:
+ accept(GT);
+ break;
+ }
+ } else {
+ syntaxError(S.pos(), "expected", LT);
+ }
+ return args.toList();
+ }
+
+ /** TypeArgument = Type
+ * | "?"
+ * | "?" EXTENDS Type {"&" Type}
+ * | "?" SUPER Type
+ */
+ JCExpression typeArgument() {
+ if (S.token() != QUES) return parseType();
+ int pos = S.pos();
+ S.nextToken();
+ if (S.token() == EXTENDS) {
+ TypeBoundKind t = to(F.at(S.pos()).TypeBoundKind(BoundKind.EXTENDS));
+ S.nextToken();
+ return F.at(pos).Wildcard(t, parseType());
+ } else if (S.token() == SUPER) {
+ TypeBoundKind t = to(F.at(S.pos()).TypeBoundKind(BoundKind.SUPER));
+ S.nextToken();
+ return F.at(pos).Wildcard(t, parseType());
+ } else if (S.token() == IDENTIFIER) {
+ //error recovery
+ reportSyntaxError(S.prevEndPos(), "expected3",
+ GT, EXTENDS, SUPER);
+ TypeBoundKind t = F.at(Position.NOPOS).TypeBoundKind(BoundKind.UNBOUND);
+ JCExpression wc = toP(F.at(pos).Wildcard(t, null));
+ JCIdent id = toP(F.at(S.pos()).Ident(ident()));
+ return F.at(pos).Erroneous(List.<JCTree>of(wc, id));
+ } else {
+ TypeBoundKind t = F.at(Position.NOPOS).TypeBoundKind(BoundKind.UNBOUND);
+ return toP(F.at(pos).Wildcard(t, null));
+ }
+ }
+
+ JCTypeApply typeArguments(JCExpression t) {
+ int pos = S.pos();
+ List<JCExpression> args = typeArguments();
+ return toP(F.at(pos).TypeApply(t, args));
+ }
+
+ /** BracketsOpt = {"[" "]"}
+ */
+ private JCExpression bracketsOpt(JCExpression t) {
+ if (S.token() == LBRACKET) {
+ int pos = S.pos();
+ S.nextToken();
+ t = bracketsOptCont(t, pos);
+ F.at(pos);
+ }
+ return t;
+ }
+
+ private JCArrayTypeTree bracketsOptCont(JCExpression t, int pos) {
+ accept(RBRACKET);
+ t = bracketsOpt(t);
+ return toP(F.at(pos).TypeArray(t));
+ }
+
+ /** BracketsSuffixExpr = "." CLASS
+ * BracketsSuffixType =
+ */
+ JCExpression bracketsSuffix(JCExpression t) {
+ if ((mode & EXPR) != 0 && S.token() == DOT) {
+ mode = EXPR;
+ int pos = S.pos();
+ S.nextToken();
+ accept(CLASS);
+ if (S.pos() == errorEndPos) {
+ // error recovery
+ Name name = null;
+ if (S.token() == IDENTIFIER) {
+ name = S.name();
+ S.nextToken();
+ } else {
+ name = names.error;
+ }
+ t = F.at(pos).Erroneous(List.<JCTree>of(toP(F.at(pos).Select(t, name))));
+ } else {
+ t = toP(F.at(pos).Select(t, names._class));
+ }
+ } else if ((mode & TYPE) != 0) {
+ mode = TYPE;
+ } else {
+ syntaxError(S.pos(), "dot.class.expected");
+ }
+ return t;
+ }
+
+ /** Creator = Qualident [TypeArguments] ( ArrayCreatorRest | ClassCreatorRest )
+ */
+ JCExpression creator(int newpos, List<JCExpression> typeArgs) {
+ switch (S.token()) {
+ case BYTE: case SHORT: case CHAR: case INT: case LONG: case FLOAT:
+ case DOUBLE: case BOOLEAN:
+ if (typeArgs == null)
+ return arrayCreatorRest(newpos, basicType());
+ break;
+ default:
+ }
+ JCExpression t = qualident();
+ int oldmode = mode;
+ mode = TYPE;
+ if (S.token() == LT) {
+ checkGenerics();
+ t = typeArguments(t);
+ }
+ while (S.token() == DOT) {
+ int pos = S.pos();
+ S.nextToken();
+ t = toP(F.at(pos).Select(t, ident()));
+ if (S.token() == LT) {
+ checkGenerics();
+ t = typeArguments(t);
+ }
+ }
+ mode = oldmode;
+ if (S.token() == LBRACKET) {
+ JCExpression e = arrayCreatorRest(newpos, t);
+ if (typeArgs != null) {
+ int pos = newpos;
+ if (!typeArgs.isEmpty() && typeArgs.head.pos != Position.NOPOS) {
+ // note: this should always happen but we should
+ // not rely on this as the parser is continuously
+ // modified to improve error recovery.
+ pos = typeArgs.head.pos;
+ }
+ setErrorEndPos(S.prevEndPos());
+ reportSyntaxError(pos, "cannot.create.array.with.type.arguments");
+ return toP(F.at(newpos).Erroneous(typeArgs.prepend(e)));
+ }
+ return e;
+ } else if (S.token() == LPAREN) {
+ return classCreatorRest(newpos, null, typeArgs, t);
+ } else {
+ reportSyntaxError(S.pos(), "expected2",
+ LPAREN, LBRACKET);
+ t = toP(F.at(newpos).NewClass(null, typeArgs, t, List.<JCExpression>nil(), null));
+ return toP(F.at(newpos).Erroneous(List.<JCTree>of(t)));
+ }
+ }
+
+ /** InnerCreator = Ident [TypeArguments] ClassCreatorRest
+ */
+ JCExpression innerCreator(int newpos, List<JCExpression> typeArgs, JCExpression encl) {
+ JCExpression t = toP(F.at(S.pos()).Ident(ident()));
+ if (S.token() == LT) {
+ checkGenerics();
+ t = typeArguments(t);
+ }
+ return classCreatorRest(newpos, encl, typeArgs, t);
+ }
+
+ /** ArrayCreatorRest = "[" ( "]" BracketsOpt ArrayInitializer
+ * | Expression "]" {"[" Expression "]"} BracketsOpt )
+ */
+ JCExpression arrayCreatorRest(int newpos, JCExpression elemtype) {
+ accept(LBRACKET);
+ if (S.token() == RBRACKET) {
+ accept(RBRACKET);
+ elemtype = bracketsOpt(elemtype);
+ if (S.token() == LBRACE) {
+ return arrayInitializer(newpos, elemtype);
+ } else {
+ return syntaxError(S.pos(), "array.dimension.missing");
+ }
+ } else {
+ ListBuffer<JCExpression> dims = new ListBuffer<JCExpression>();
+ dims.append(parseExpression());
+ accept(RBRACKET);
+ while (S.token() == LBRACKET) {
+ int pos = S.pos();
+ S.nextToken();
+ if (S.token() == RBRACKET) {
+ elemtype = bracketsOptCont(elemtype, pos);
+ } else {
+ dims.append(parseExpression());
+ accept(RBRACKET);
+ }
+ }
+ return toP(F.at(newpos).NewArray(elemtype, dims.toList(), null));
+ }
+ }
+
+ /** ClassCreatorRest = Arguments [ClassBody]
+ */
+ JCExpression classCreatorRest(int newpos,
+ JCExpression encl,
+ List<JCExpression> typeArgs,
+ JCExpression t)
+ {
+ List<JCExpression> args = arguments();
+ JCClassDecl body = null;
+ if (S.token() == LBRACE) {
+ int pos = S.pos();
+ List<JCTree> defs = classOrInterfaceBody(names.empty, false);
+ JCModifiers mods = F.at(Position.NOPOS).Modifiers(0);
+ body = toP(F.at(pos).AnonymousClassDef(mods, defs));
+ }
+ return toP(F.at(newpos).NewClass(encl, typeArgs, t, args, body));
+ }
+
+ /** ArrayInitializer = "{" [VariableInitializer {"," VariableInitializer}] [","] "}"
+ */
+ JCExpression arrayInitializer(int newpos, JCExpression t) {
+ accept(LBRACE);
+ ListBuffer<JCExpression> elems = new ListBuffer<JCExpression>();
+ if (S.token() == COMMA) {
+ S.nextToken();
+ } else if (S.token() != RBRACE) {
+ elems.append(variableInitializer());
+ while (S.token() == COMMA) {
+ S.nextToken();
+ if (S.token() == RBRACE) break;
+ elems.append(variableInitializer());
+ }
+ }
+ accept(RBRACE);
+ return toP(F.at(newpos).NewArray(t, List.<JCExpression>nil(), elems.toList()));
+ }
+
+ /** VariableInitializer = ArrayInitializer | Expression
+ */
+ public JCExpression variableInitializer() {
+ return S.token() == LBRACE ? arrayInitializer(S.pos(), null) : parseExpression();
+ }
+
+ /** ParExpression = "(" Expression ")"
+ */
+ JCExpression parExpression() {
+ accept(LPAREN);
+ JCExpression t = parseExpression();
+ accept(RPAREN);
+ return t;
+ }
+
+ /** Block = "{" BlockStatements "}"
+ */
+ JCBlock block(int pos, long flags) {
+ accept(LBRACE);
+ List<JCStatement> stats = blockStatements();
+ JCBlock t = F.at(pos).Block(flags, stats);
+ while (S.token() == CASE || S.token() == DEFAULT) {
+ syntaxError("orphaned", S.token());
+ switchBlockStatementGroups();
+ }
+ // the Block node has a field "endpos" for first char of last token, which is
+ // usually but not necessarily the last char of the last token.
+ t.endpos = S.pos();
+ accept(RBRACE);
+ return toP(t);
+ }
+
+ public JCBlock block() {
+ return block(S.pos(), 0);
+ }
+
+ /** BlockStatements = { BlockStatement }
+ * BlockStatement = LocalVariableDeclarationStatement
+ * | ClassOrInterfaceOrEnumDeclaration
+ * | [Ident ":"] Statement
+ * LocalVariableDeclarationStatement
+ * = { FINAL | '@' Annotation } Type VariableDeclarators ";"
+ */
+ @SuppressWarnings("fallthrough")
+ List<JCStatement> blockStatements() {
+//todo: skip to anchor on error(?)
+ int lastErrPos = -1;
+ ListBuffer<JCStatement> stats = new ListBuffer<JCStatement>();
+ while (true) {
+ int pos = S.pos();
+ switch (S.token()) {
+ case RBRACE: case CASE: case DEFAULT: case EOF:
+ return stats.toList();
+ case LBRACE: case IF: case FOR: case WHILE: case DO: case TRY:
+ case SWITCH: case SYNCHRONIZED: case RETURN: case THROW: case BREAK:
+ case CONTINUE: case SEMI: case ELSE: case FINALLY: case CATCH:
+ stats.append(parseStatement());
+ break;
+ case MONKEYS_AT:
+ case FINAL: {
+ String dc = S.docComment();
+ JCModifiers mods = modifiersOpt();
+ if (S.token() == INTERFACE ||
+ S.token() == CLASS ||
+ allowEnums && S.token() == ENUM) {
+ stats.append(classOrInterfaceOrEnumDeclaration(mods, dc));
+ } else {
+ JCExpression t = parseType();
+ stats.appendList(variableDeclarators(mods, t,
+ new ListBuffer<JCStatement>()));
+ // A "LocalVariableDeclarationStatement" subsumes the terminating semicolon
+ storeEnd(stats.elems.last(), S.endPos());
+ accept(SEMI);
+ }
+ break;
+ }
+ case ABSTRACT: case STRICTFP: {
+ String dc = S.docComment();
+ JCModifiers mods = modifiersOpt();
+ stats.append(classOrInterfaceOrEnumDeclaration(mods, dc));
+ break;
+ }
+ case INTERFACE:
+ case CLASS:
+ stats.append(classOrInterfaceOrEnumDeclaration(modifiersOpt(),
+ S.docComment()));
+ break;
+ case ENUM:
+ case ASSERT:
+ if (allowEnums && S.token() == ENUM) {
+ log.error(S.pos(), "local.enum");
+ stats.
+ append(classOrInterfaceOrEnumDeclaration(modifiersOpt(),
+ S.docComment()));
+ break;
+ } else if (allowAsserts && S.token() == ASSERT) {
+ stats.append(parseStatement());
+ break;
+ }
+ /* fall through to default */
+ default:
+ Name name = S.name();
+ JCExpression t = term(EXPR | TYPE);
+ if (S.token() == COLON && t.getTag() == JCTree.IDENT) {
+ S.nextToken();
+ JCStatement stat = parseStatement();
+ stats.append(F.at(pos).Labelled(name, stat));
+ } else if ((lastmode & TYPE) != 0 &&
+ (S.token() == IDENTIFIER ||
+ S.token() == ASSERT ||
+ S.token() == ENUM)) {
+ pos = S.pos();
+ JCModifiers mods = F.at(Position.NOPOS).Modifiers(0);
+ F.at(pos);
+ stats.appendList(variableDeclarators(mods, t,
+ new ListBuffer<JCStatement>()));
+ // A "LocalVariableDeclarationStatement" subsumes the terminating semicolon
+ storeEnd(stats.elems.last(), S.endPos());
+ accept(SEMI);
+ } else {
+ // This Exec is an "ExpressionStatement"; it subsumes the terminating semicolon
+ stats.append(to(F.at(pos).Exec(checkExprStat(t))));
+ accept(SEMI);
+ }
+ }
+
+ // error recovery
+ if (S.pos() == lastErrPos)
+ return stats.toList();
+ if (S.pos() <= errorEndPos) {
+ skip(false, true, true, true);
+ lastErrPos = S.pos();
+ }
+
+ // ensure no dangling /** @deprecated */ active
+ S.resetDeprecatedFlag();
+ }
+ }
+
+ /** Statement =
+ * Block
+ * | IF ParExpression Statement [ELSE Statement]
+ * | FOR "(" ForInitOpt ";" [Expression] ";" ForUpdateOpt ")" Statement
+ * | FOR "(" FormalParameter : Expression ")" Statement
+ * | WHILE ParExpression Statement
+ * | DO Statement WHILE ParExpression ";"
+ * | TRY Block ( Catches | [Catches] FinallyPart )
+ * | SWITCH ParExpression "{" SwitchBlockStatementGroups "}"
+ * | SYNCHRONIZED ParExpression Block
+ * | RETURN [Expression] ";"
+ * | THROW Expression ";"
+ * | BREAK [Ident] ";"
+ * | CONTINUE [Ident] ";"
+ * | ASSERT Expression [ ":" Expression ] ";"
+ * | ";"
+ * | ExpressionStatement
+ * | Ident ":" Statement
+ */
+ @SuppressWarnings("fallthrough")
+ public JCStatement parseStatement() {
+ int pos = S.pos();
+ switch (S.token()) {
+ case LBRACE:
+ return block();
+ case IF: {
+ S.nextToken();
+ JCExpression cond = parExpression();
+ JCStatement thenpart = parseStatement();
+ JCStatement elsepart = null;
+ if (S.token() == ELSE) {
+ S.nextToken();
+ elsepart = parseStatement();
+ }
+ return F.at(pos).If(cond, thenpart, elsepart);
+ }
+ case FOR: {
+ S.nextToken();
+ accept(LPAREN);
+ List<JCStatement> inits = S.token() == SEMI ? List.<JCStatement>nil() : forInit();
+ if (inits.length() == 1 &&
+ inits.head.getTag() == JCTree.VARDEF &&
+ ((JCVariableDecl) inits.head).init == null &&
+ S.token() == COLON) {
+ checkForeach();
+ JCVariableDecl var = (JCVariableDecl)inits.head;
+ accept(COLON);
+ JCExpression expr = parseExpression();
+ accept(RPAREN);
+ JCStatement body = parseStatement();
+ return F.at(pos).ForeachLoop(var, expr, body);
+ } else {
+ accept(SEMI);
+ JCExpression cond = S.token() == SEMI ? null : parseExpression();
+ accept(SEMI);
+ List<JCExpressionStatement> steps = S.token() == RPAREN ? List.<JCExpressionStatement>nil() : forUpdate();
+ accept(RPAREN);
+ JCStatement body = parseStatement();
+ return F.at(pos).ForLoop(inits, cond, steps, body);
+ }
+ }
+ case WHILE: {
+ S.nextToken();
+ JCExpression cond = parExpression();
+ JCStatement body = parseStatement();
+ return F.at(pos).WhileLoop(cond, body);
+ }
+ case DO: {
+ S.nextToken();
+ JCStatement body = parseStatement();
+ accept(WHILE);
+ JCExpression cond = parExpression();
+ JCDoWhileLoop t = to(F.at(pos).DoLoop(body, cond));
+ accept(SEMI);
+ return t;
+ }
+ case TRY: {
+ S.nextToken();
+ JCBlock body = block();
+ ListBuffer<JCCatch> catchers = new ListBuffer<JCCatch>();
+ JCBlock finalizer = null;
+ if (S.token() == CATCH || S.token() == FINALLY) {
+ while (S.token() == CATCH) catchers.append(catchClause());
+ if (S.token() == FINALLY) {
+ S.nextToken();
+ finalizer = block();
+ }
+ } else {
+ log.error(pos, "try.without.catch.or.finally");
+ }
+ return F.at(pos).Try(body, catchers.toList(), finalizer);
+ }
+ case SWITCH: {
+ S.nextToken();
+ JCExpression selector = parExpression();
+ accept(LBRACE);
+ List<JCCase> cases = switchBlockStatementGroups();
+ JCSwitch t = to(F.at(pos).Switch(selector, cases));
+ accept(RBRACE);
+ return t;
+ }
+ case SYNCHRONIZED: {
+ S.nextToken();
+ JCExpression lock = parExpression();
+ JCBlock body = block();
+ return F.at(pos).Synchronized(lock, body);
+ }
+ case RETURN: {
+ S.nextToken();
+ JCExpression result = S.token() == SEMI ? null : parseExpression();
+ JCReturn t = to(F.at(pos).Return(result));
+ accept(SEMI);
+ return t;
+ }
+ case THROW: {
+ S.nextToken();
+ JCExpression exc = parseExpression();
+ JCThrow t = to(F.at(pos).Throw(exc));
+ accept(SEMI);
+ return t;
+ }
+ case BREAK: {
+ S.nextToken();
+ Name label = (S.token() == IDENTIFIER || S.token() == ASSERT || S.token() == ENUM) ? ident() : null;
+ JCBreak t = to(F.at(pos).Break(label));
+ accept(SEMI);
+ return t;
+ }
+ case CONTINUE: {
+ S.nextToken();
+ Name label = (S.token() == IDENTIFIER || S.token() == ASSERT || S.token() == ENUM) ? ident() : null;
+ JCContinue t = to(F.at(pos).Continue(label));
+ accept(SEMI);
+ return t;
+ }
+ case SEMI:
+ S.nextToken();
+ return toP(F.at(pos).Skip());
+ case ELSE:
+ return toP(F.Exec(syntaxError("else.without.if")));
+ case FINALLY:
+ return toP(F.Exec(syntaxError("finally.without.try")));
+ case CATCH:
+ return toP(F.Exec(syntaxError("catch.without.try")));
+ case ASSERT: {
+ if (allowAsserts && S.token() == ASSERT) {
+ S.nextToken();
+ JCExpression assertion = parseExpression();
+ JCExpression message = null;
+ if (S.token() == COLON) {
+ S.nextToken();
+ message = parseExpression();
+ }
+ JCAssert t = to(F.at(pos).Assert(assertion, message));
+ accept(SEMI);
+ return t;
+ }
+ /* else fall through to default case */
+ }
+ case ENUM:
+ default:
+ Name name = S.name();
+ JCExpression expr = parseExpression();
+ if (S.token() == COLON && expr.getTag() == JCTree.IDENT) {
+ S.nextToken();
+ JCStatement stat = parseStatement();
+ return F.at(pos).Labelled(name, stat);
+ } else {
+ // This Exec is an "ExpressionStatement"; it subsumes the terminating semicolon
+ JCExpressionStatement stat = to(F.at(pos).Exec(checkExprStat(expr)));
+ accept(SEMI);
+ return stat;
+ }
+ }
+ }
+
+ /** CatchClause = CATCH "(" FormalParameter ")" Block
+ */
+ JCCatch catchClause() {
+ int pos = S.pos();
+ accept(CATCH);
+ accept(LPAREN);
+ JCVariableDecl formal =
+ variableDeclaratorId(optFinal(Flags.PARAMETER),
+ qualident());
+ accept(RPAREN);
+ JCBlock body = block();
+ return F.at(pos).Catch(formal, body);
+ }
+
+ /** SwitchBlockStatementGroups = { SwitchBlockStatementGroup }
+ * SwitchBlockStatementGroup = SwitchLabel BlockStatements
+ * SwitchLabel = CASE ConstantExpression ":" | DEFAULT ":"
+ */
+ List<JCCase> switchBlockStatementGroups() {
+ ListBuffer<JCCase> cases = new ListBuffer<JCCase>();
+ while (true) {
+ int pos = S.pos();
+ switch (S.token()) {
+ case CASE: {
+ S.nextToken();
+ JCExpression pat = parseExpression();
+ accept(COLON);
+ List<JCStatement> stats = blockStatements();
+ JCCase c = F.at(pos).Case(pat, stats);
+ if (stats.isEmpty())
+ storeEnd(c, S.prevEndPos());
+ cases.append(c);
+ break;
+ }
+ case DEFAULT: {
+ S.nextToken();
+ accept(COLON);
+ List<JCStatement> stats = blockStatements();
+ JCCase c = F.at(pos).Case(null, stats);
+ if (stats.isEmpty())
+ storeEnd(c, S.prevEndPos());
+ cases.append(c);
+ break;
+ }
+ case RBRACE: case EOF:
+ return cases.toList();
+ default:
+ S.nextToken(); // to ensure progress
+ syntaxError(pos, "expected3",
+ CASE, DEFAULT, RBRACE);
+ }
+ }
+ }
+
+ /** MoreStatementExpressions = { COMMA StatementExpression }
+ */
+ <T extends ListBuffer<? super JCExpressionStatement>> T moreStatementExpressions(int pos,
+ JCExpression first,
+ T stats) {
+ // This Exec is a "StatementExpression"; it subsumes no terminating token
+ stats.append(toP(F.at(pos).Exec(checkExprStat(first))));
+ while (S.token() == COMMA) {
+ S.nextToken();
+ pos = S.pos();
+ JCExpression t = parseExpression();
+ // This Exec is a "StatementExpression"; it subsumes no terminating token
+ stats.append(toP(F.at(pos).Exec(checkExprStat(t))));
+ }
+ return stats;
+ }
+
+ /** ForInit = StatementExpression MoreStatementExpressions
+ * | { FINAL | '@' Annotation } Type VariableDeclarators
+ */
+ List<JCStatement> forInit() {
+ ListBuffer<JCStatement> stats = lb();
+ int pos = S.pos();
+ if (S.token() == FINAL || S.token() == MONKEYS_AT) {
+ return variableDeclarators(optFinal(0), parseType(), stats).toList();
+ } else {
+ JCExpression t = term(EXPR | TYPE);
+ if ((lastmode & TYPE) != 0 &&
+ (S.token() == IDENTIFIER || S.token() == ASSERT || S.token() == ENUM))
+ return variableDeclarators(modifiersOpt(), t, stats).toList();
+ else
+ return moreStatementExpressions(pos, t, stats).toList();
+ }
+ }
+
+ /** ForUpdate = StatementExpression MoreStatementExpressions
+ */
+ List<JCExpressionStatement> forUpdate() {
+ return moreStatementExpressions(S.pos(),
+ parseExpression(),
+ new ListBuffer<JCExpressionStatement>()).toList();
+ }
+
+ /** AnnotationsOpt = { '@' Annotation }
+ */
+ List<JCAnnotation> annotationsOpt() {
+ if (S.token() != MONKEYS_AT) return List.nil(); // optimization
+ ListBuffer<JCAnnotation> buf = new ListBuffer<JCAnnotation>();
+ while (S.token() == MONKEYS_AT) {
+ int pos = S.pos();
+ S.nextToken();
+ buf.append(annotation(pos));
+ }
+ return buf.toList();
+ }
+
+ /** ModifiersOpt = { Modifier }
+ * Modifier = PUBLIC | PROTECTED | PRIVATE | STATIC | ABSTRACT | FINAL
+ * | NATIVE | SYNCHRONIZED | TRANSIENT | VOLATILE | "@"
+ * | "@" Annotation
+ */
+ JCModifiers modifiersOpt() {
+ return modifiersOpt(null);
+ }
+ JCModifiers modifiersOpt(JCModifiers partial) {
+ long flags = (partial == null) ? 0 : partial.flags;
+ if (S.deprecatedFlag()) {
+ flags |= Flags.DEPRECATED;
+ S.resetDeprecatedFlag();
+ }
+ ListBuffer<JCAnnotation> annotations = new ListBuffer<JCAnnotation>();
+ if (partial != null) annotations.appendList(partial.annotations);
+ int pos = S.pos();
+ int lastPos = Position.NOPOS;
+ loop:
+ while (true) {
+ long flag;
+ switch (S.token()) {
+ case PRIVATE : flag = Flags.PRIVATE; break;
+ case PROTECTED : flag = Flags.PROTECTED; break;
+ case PUBLIC : flag = Flags.PUBLIC; break;
+ case STATIC : flag = Flags.STATIC; break;
+ case TRANSIENT : flag = Flags.TRANSIENT; break;
+ case FINAL : flag = Flags.FINAL; break;
+ case ABSTRACT : flag = Flags.ABSTRACT; break;
+ case NATIVE : flag = Flags.NATIVE; break;
+ case VOLATILE : flag = Flags.VOLATILE; break;
+ case SYNCHRONIZED: flag = Flags.SYNCHRONIZED; break;
+ case STRICTFP : flag = Flags.STRICTFP; break;
+ case MONKEYS_AT : flag = Flags.ANNOTATION; break;
+ default: break loop;
+ }
+ if ((flags & flag) != 0) log.error(S.pos(), "repeated.modifier");
+ lastPos = S.pos();
+ S.nextToken();
+ if (flag == Flags.ANNOTATION) {
+ checkAnnotations();
+ if (S.token() != INTERFACE) {
+ JCAnnotation ann = annotation(lastPos);
+ // if first modifier is an annotation, set pos to annotation's.
+ if (flags == 0 && annotations.isEmpty())
+ pos = ann.pos;
+ annotations.append(ann);
+ lastPos = ann.pos;
+ flag = 0;
+ }
+ }
+ flags |= flag;
+ }
+ switch (S.token()) {
+ case ENUM: flags |= Flags.ENUM; break;
+ case INTERFACE: flags |= Flags.INTERFACE; break;
+ default: break;
+ }
+
+ /* A modifiers tree with no modifier tokens or annotations
+ * has no text position. */
+ if (flags == 0 && annotations.isEmpty())
+ pos = Position.NOPOS;
+
+ JCModifiers mods = F.at(pos).Modifiers(flags, annotations.toList());
+ if (pos != Position.NOPOS)
+ storeEnd(mods, S.prevEndPos());
+ return mods;
+ }
+
+ /** Annotation = "@" Qualident [ "(" AnnotationFieldValues ")" ]
+ * @param pos position of "@" token
+ */
+ JCAnnotation annotation(int pos) {
+ // accept(AT); // AT consumed by caller
+ checkAnnotations();
+ JCTree ident = qualident();
+ List<JCExpression> fieldValues = annotationFieldValuesOpt();
+ JCAnnotation ann = F.at(pos).Annotation(ident, fieldValues);
+ storeEnd(ann, S.prevEndPos());
+ return ann;
+ }
+
+ List<JCExpression> annotationFieldValuesOpt() {
+ return (S.token() == LPAREN) ? annotationFieldValues() : List.<JCExpression>nil();
+ }
+
+ /** AnnotationFieldValues = "(" [ AnnotationFieldValue { "," AnnotationFieldValue } ] ")" */
+ List<JCExpression> annotationFieldValues() {
+ accept(LPAREN);
+ ListBuffer<JCExpression> buf = new ListBuffer<JCExpression>();
+ if (S.token() != RPAREN) {
+ buf.append(annotationFieldValue());
+ while (S.token() == COMMA) {
+ S.nextToken();
+ buf.append(annotationFieldValue());
+ }
+ }
+ accept(RPAREN);
+ return buf.toList();
+ }
+
+ /** AnnotationFieldValue = AnnotationValue
+ * | Identifier "=" AnnotationValue
+ */
+ JCExpression annotationFieldValue() {
+ if (S.token() == IDENTIFIER) {
+ mode = EXPR;
+ JCExpression t1 = term1();
+ if (t1.getTag() == JCTree.IDENT && S.token() == EQ) {
+ int pos = S.pos();
+ accept(EQ);
+ return toP(F.at(pos).Assign(t1, annotationValue()));
+ } else {
+ return t1;
+ }
+ }
+ return annotationValue();
+ }
+
+ /* AnnotationValue = ConditionalExpression
+ * | Annotation
+ * | "{" [ AnnotationValue { "," AnnotationValue } ] "}"
+ */
+ JCExpression annotationValue() {
+ int pos;
+ switch (S.token()) {
+ case MONKEYS_AT:
+ pos = S.pos();
+ S.nextToken();
+ return annotation(pos);
+ case LBRACE:
+ pos = S.pos();
+ accept(LBRACE);
+ ListBuffer<JCExpression> buf = new ListBuffer<JCExpression>();
+ if (S.token() != RBRACE) {
+ buf.append(annotationValue());
+ while (S.token() == COMMA) {
+ S.nextToken();
+ if (S.token() == RPAREN) break;
+ buf.append(annotationValue());
+ }
+ }
+ accept(RBRACE);
+ return toP(F.at(pos).NewArray(null, List.<JCExpression>nil(), buf.toList()));
+ default:
+ mode = EXPR;
+ return term1();
+ }
+ }
+
+ /** VariableDeclarators = VariableDeclarator { "," VariableDeclarator }
+ */
+ public <T extends ListBuffer<? super JCVariableDecl>> T variableDeclarators(JCModifiers mods,
+ JCExpression type,
+ T vdefs)
+ {
+ return variableDeclaratorsRest(S.pos(), mods, type, ident(), false, null, vdefs);
+ }
+
+ /** VariableDeclaratorsRest = VariableDeclaratorRest { "," VariableDeclarator }
+ * ConstantDeclaratorsRest = ConstantDeclaratorRest { "," ConstantDeclarator }
+ *
+ * @param reqInit Is an initializer always required?
+ * @param dc The documentation comment for the variable declarations, or null.
+ */
+ <T extends ListBuffer<? super JCVariableDecl>> T variableDeclaratorsRest(int pos,
+ JCModifiers mods,
+ JCExpression type,
+ Name name,
+ boolean reqInit,
+ String dc,
+ T vdefs)
+ {
+ vdefs.append(variableDeclaratorRest(pos, mods, type, name, reqInit, dc));
+ while (S.token() == COMMA) {
+ // All but last of multiple declarators subsume a comma
+ storeEnd((JCTree)vdefs.elems.last(), S.endPos());
+ S.nextToken();
+ vdefs.append(variableDeclarator(mods, type, reqInit, dc));
+ }
+ return vdefs;
+ }
+
+ /** VariableDeclarator = Ident VariableDeclaratorRest
+ * ConstantDeclarator = Ident ConstantDeclaratorRest
+ */
+ JCVariableDecl variableDeclarator(JCModifiers mods, JCExpression type, boolean reqInit, String dc) {
+ return variableDeclaratorRest(S.pos(), mods, type, ident(), reqInit, dc);
+ }
+
+ /** VariableDeclaratorRest = BracketsOpt ["=" VariableInitializer]
+ * ConstantDeclaratorRest = BracketsOpt "=" VariableInitializer
+ *
+ * @param reqInit Is an initializer always required?
+ * @param dc The documentation comment for the variable declarations, or null.
+ */
+ JCVariableDecl variableDeclaratorRest(int pos, JCModifiers mods, JCExpression type, Name name,
+ boolean reqInit, String dc) {
+ type = bracketsOpt(type);
+ JCExpression init = null;
+ if (S.token() == EQ) {
+ S.nextToken();
+ init = variableInitializer();
+ }
+ else if (reqInit) syntaxError(S.pos(), "expected", EQ);
+ JCVariableDecl result =
+ toP(F.at(pos).VarDef(mods, name, type, init));
+ attach(result, dc);
+ return result;
+ }
+
+ /** VariableDeclaratorId = Ident BracketsOpt
+ */
+ JCVariableDecl variableDeclaratorId(JCModifiers mods, JCExpression type) {
+ int pos = S.pos();
+ Name name = ident();
+ if ((mods.flags & Flags.VARARGS) == 0)
+ type = bracketsOpt(type);
+ return toP(F.at(pos).VarDef(mods, name, type, null));
+ }
+
+ /** CompilationUnit = [ { "@" Annotation } PACKAGE Qualident ";"] {ImportDeclaration} {TypeDeclaration}
+ */
+ public JCTree.JCCompilationUnit parseCompilationUnit() {
+ int pos = S.pos();
+ JCExpression pid = null;
+ String dc = S.docComment();
+ JCModifiers mods = null;
+ List<JCAnnotation> packageAnnotations = List.nil();
+ if (S.token() == MONKEYS_AT)
+ mods = modifiersOpt();
+
+ if (S.token() == PACKAGE) {
+ if (mods != null) {
+ checkNoMods(mods.flags);
+ packageAnnotations = mods.annotations;
+ mods = null;
+ }
+ S.nextToken();
+ pid = qualident();
+ accept(SEMI);
+ }
+ ListBuffer<JCTree> defs = new ListBuffer<JCTree>();
+ boolean checkForImports = true;
+ while (S.token() != EOF) {
+ if (S.pos() <= errorEndPos) {
+ // error recovery
+ skip(checkForImports, false, false, false);
+ if (S.token() == EOF)
+ break;
+ }
+ if (checkForImports && mods == null && S.token() == IMPORT) {
+ defs.append(importDeclaration());
+ } else {
+ JCTree def = typeDeclaration(mods);
+ if (def instanceof JCExpressionStatement)
+ def = ((JCExpressionStatement)def).expr;
+ defs.append(def);
+ if (def instanceof JCClassDecl)
+ checkForImports = false;
+ mods = null;
+ }
+ }
+ JCTree.JCCompilationUnit toplevel = F.at(pos).TopLevel(packageAnnotations, pid, defs.toList());
+ attach(toplevel, dc);
+ if (defs.elems.isEmpty())
+ storeEnd(toplevel, S.prevEndPos());
+ if (keepDocComments)
+ toplevel.docComments = docComments;
+ if (keepLineMap)
+ toplevel.lineMap = S.getLineMap();
+ return toplevel;
+ }
+
+ /** ImportDeclaration = IMPORT [ STATIC ] Ident { "." Ident } [ "." "*" ] ";"
+ */
+ JCTree importDeclaration() {
+ int pos = S.pos();
+ S.nextToken();
+ boolean importStatic = false;
+ if (S.token() == STATIC) {
+ checkStaticImports();
+ importStatic = true;
+ S.nextToken();
+ }
+ JCExpression pid = toP(F.at(S.pos()).Ident(ident()));
+ do {
+ int pos1 = S.pos();
+ accept(DOT);
+ if (S.token() == STAR) {
+ pid = to(F.at(pos1).Select(pid, names.asterisk));
+ S.nextToken();
+ break;
+ } else {
+ pid = toP(F.at(pos1).Select(pid, ident()));
+ }
+ } while (S.token() == DOT);
+ accept(SEMI);
+ return toP(F.at(pos).Import(pid, importStatic));
+ }
+
+ /** TypeDeclaration = ClassOrInterfaceOrEnumDeclaration
+ * | ";"
+ */
+ JCTree typeDeclaration(JCModifiers mods) {
+ int pos = S.pos();
+ if (mods == null && S.token() == SEMI) {
+ S.nextToken();
+ return toP(F.at(pos).Skip());
+ } else {
+ String dc = S.docComment();
+ return classOrInterfaceOrEnumDeclaration(modifiersOpt(mods), dc);
+ }
+ }
+
+ /** ClassOrInterfaceOrEnumDeclaration = ModifiersOpt
+ * (ClassDeclaration | InterfaceDeclaration | EnumDeclaration)
+ * @param mods Any modifiers starting the class or interface declaration
+ * @param dc The documentation comment for the class, or null.
+ */
+ JCStatement classOrInterfaceOrEnumDeclaration(JCModifiers mods, String dc) {
+ if (S.token() == CLASS) {
+ return classDeclaration(mods, dc);
+ } else if (S.token() == INTERFACE) {
+ return interfaceDeclaration(mods, dc);
+ } else if (allowEnums) {
+ if (S.token() == ENUM) {
+ return enumDeclaration(mods, dc);
+ } else {
+ int pos = S.pos();
+ List<JCTree> errs;
+ if (S.token() == IDENTIFIER) {
+ errs = List.<JCTree>of(mods, toP(F.at(pos).Ident(ident())));
+ setErrorEndPos(S.pos());
+ } else {
+ errs = List.<JCTree>of(mods);
+ }
+ return toP(F.Exec(syntaxError(pos, errs, "expected3",
+ CLASS, INTERFACE, ENUM)));
+ }
+ } else {
+ if (S.token() == ENUM) {
+ log.error(S.pos(), "enums.not.supported.in.source", source.name);
+ allowEnums = true;
+ return enumDeclaration(mods, dc);
+ }
+ int pos = S.pos();
+ List<JCTree> errs;
+ if (S.token() == IDENTIFIER) {
+ errs = List.<JCTree>of(mods, toP(F.at(pos).Ident(ident())));
+ setErrorEndPos(S.pos());
+ } else {
+ errs = List.<JCTree>of(mods);
+ }
+ return toP(F.Exec(syntaxError(pos, errs, "expected2",
+ CLASS, INTERFACE)));
+ }
+ }
+
+ /** ClassDeclaration = CLASS Ident TypeParametersOpt [EXTENDS Type]
+ * [IMPLEMENTS TypeList] ClassBody
+ * @param mods The modifiers starting the class declaration
+ * @param dc The documentation comment for the class, or null.
+ */
+ JCClassDecl classDeclaration(JCModifiers mods, String dc) {
+ int pos = S.pos();
+ accept(CLASS);
+ Name name = ident();
+
+ List<JCTypeParameter> typarams = typeParametersOpt();
+
+ JCTree extending = null;
+ if (S.token() == EXTENDS) {
+ S.nextToken();
+ extending = parseType();
+ }
+ List<JCExpression> implementing = List.nil();
+ if (S.token() == IMPLEMENTS) {
+ S.nextToken();
+ implementing = typeList();
+ }
+ List<JCTree> defs = classOrInterfaceBody(name, false);
+ JCClassDecl result = toP(F.at(pos).ClassDef(
+ mods, name, typarams, extending, implementing, defs));
+ attach(result, dc);
+ return result;
+ }
+
+ /** InterfaceDeclaration = INTERFACE Ident TypeParametersOpt
+ * [EXTENDS TypeList] InterfaceBody
+ * @param mods The modifiers starting the interface declaration
+ * @param dc The documentation comment for the interface, or null.
+ */
+ JCClassDecl interfaceDeclaration(JCModifiers mods, String dc) {
+ int pos = S.pos();
+ accept(INTERFACE);
+ Name name = ident();
+
+ List<JCTypeParameter> typarams = typeParametersOpt();
+
+ List<JCExpression> extending = List.nil();
+ if (S.token() == EXTENDS) {
+ S.nextToken();
+ extending = typeList();
+ }
+ List<JCTree> defs = classOrInterfaceBody(name, true);
+ JCClassDecl result = toP(F.at(pos).ClassDef(
+ mods, name, typarams, null, extending, defs));
+ attach(result, dc);
+ return result;
+ }
+
+ /** EnumDeclaration = ENUM Ident [IMPLEMENTS TypeList] EnumBody
+ * @param mods The modifiers starting the enum declaration
+ * @param dc The documentation comment for the enum, or null.
+ */
+ JCClassDecl enumDeclaration(JCModifiers mods, String dc) {
+ int pos = S.pos();
+ accept(ENUM);
+ Name name = ident();
+
+ List<JCExpression> implementing = List.nil();
+ if (S.token() == IMPLEMENTS) {
+ S.nextToken();
+ implementing = typeList();
+ }
+
+ List<JCTree> defs = enumBody(name);
+ JCModifiers newMods =
+ F.at(mods.pos).Modifiers(mods.flags|Flags.ENUM, mods.annotations);
+ JCClassDecl result = toP(F.at(pos).
+ ClassDef(newMods, name, List.<JCTypeParameter>nil(),
+ null, implementing, defs));
+ attach(result, dc);
+ return result;
+ }
+
+ /** EnumBody = "{" { EnumeratorDeclarationList } [","]
+ * [ ";" {ClassBodyDeclaration} ] "}"
+ */
+ List<JCTree> enumBody(Name enumName) {
+ accept(LBRACE);
+ ListBuffer<JCTree> defs = new ListBuffer<JCTree>();
+ if (S.token() == COMMA) {
+ S.nextToken();
+ } else if (S.token() != RBRACE && S.token() != SEMI) {
+ defs.append(enumeratorDeclaration(enumName));
+ while (S.token() == COMMA) {
+ S.nextToken();
+ if (S.token() == RBRACE || S.token() == SEMI) break;
+ defs.append(enumeratorDeclaration(enumName));
+ }
+ if (S.token() != SEMI && S.token() != RBRACE) {
+ defs.append(syntaxError(S.pos(), "expected3",
+ COMMA, RBRACE, SEMI));
+ S.nextToken();
+ }
+ }
+ if (S.token() == SEMI) {
+ S.nextToken();
+ while (S.token() != RBRACE && S.token() != EOF) {
+ defs.appendList(classOrInterfaceBodyDeclaration(enumName,
+ false));
+ if (S.pos() <= errorEndPos) {
+ // error recovery
+ skip(false, true, true, false);
+ }
+ }
+ }
+ accept(RBRACE);
+ return defs.toList();
+ }
+
+ /** EnumeratorDeclaration = AnnotationsOpt [TypeArguments] IDENTIFIER [ Arguments ] [ "{" ClassBody "}" ]
+ */
+ JCTree enumeratorDeclaration(Name enumName) {
+ String dc = S.docComment();
+ int flags = Flags.PUBLIC|Flags.STATIC|Flags.FINAL|Flags.ENUM;
+ if (S.deprecatedFlag()) {
+ flags |= Flags.DEPRECATED;
+ S.resetDeprecatedFlag();
+ }
+ int pos = S.pos();
+ List<JCAnnotation> annotations = annotationsOpt();
+ JCModifiers mods = F.at(annotations.isEmpty() ? Position.NOPOS : pos).Modifiers(flags, annotations);
+ List<JCExpression> typeArgs = typeArgumentsOpt();
+ int identPos = S.pos();
+ Name name = ident();
+ int createPos = S.pos();
+ List<JCExpression> args = (S.token() == LPAREN)
+ ? arguments() : List.<JCExpression>nil();
+ JCClassDecl body = null;
+ if (S.token() == LBRACE) {
+ JCModifiers mods1 = F.at(Position.NOPOS).Modifiers(Flags.ENUM | Flags.STATIC);
+ List<JCTree> defs = classOrInterfaceBody(names.empty, false);
+ body = toP(F.at(identPos).AnonymousClassDef(mods1, defs));
+ }
+ if (args.isEmpty() && body == null)
+ createPos = Position.NOPOS;
+ JCIdent ident = F.at(Position.NOPOS).Ident(enumName);
+ JCNewClass create = F.at(createPos).NewClass(null, typeArgs, ident, args, body);
+ if (createPos != Position.NOPOS)
+ storeEnd(create, S.prevEndPos());
+ ident = F.at(Position.NOPOS).Ident(enumName);
+ JCTree result = toP(F.at(pos).VarDef(mods, name, ident, create));
+ attach(result, dc);
+ return result;
+ }
+
+ /** TypeList = Type {"," Type}
+ */
+ List<JCExpression> typeList() {
+ ListBuffer<JCExpression> ts = new ListBuffer<JCExpression>();
+ ts.append(parseType());
+ while (S.token() == COMMA) {
+ S.nextToken();
+ ts.append(parseType());
+ }
+ return ts.toList();
+ }
+
+ /** ClassBody = "{" {ClassBodyDeclaration} "}"
+ * InterfaceBody = "{" {InterfaceBodyDeclaration} "}"
+ */
+ List<JCTree> classOrInterfaceBody(Name className, boolean isInterface) {
+ accept(LBRACE);
+ if (S.pos() <= errorEndPos) {
+ // error recovery
+ skip(false, true, false, false);
+ if (S.token() == LBRACE)
+ S.nextToken();
+ }
+ ListBuffer<JCTree> defs = new ListBuffer<JCTree>();
+ while (S.token() != RBRACE && S.token() != EOF) {
+ defs.appendList(classOrInterfaceBodyDeclaration(className, isInterface));
+ if (S.pos() <= errorEndPos) {
+ // error recovery
+ skip(false, true, true, false);
+ }
+ }
+ accept(RBRACE);
+ return defs.toList();
+ }
+
+ /** ClassBodyDeclaration =
+ * ";"
+ * | [STATIC] Block
+ * | ModifiersOpt
+ * ( Type Ident
+ * ( VariableDeclaratorsRest ";" | MethodDeclaratorRest )
+ * | VOID Ident MethodDeclaratorRest
+ * | TypeParameters (Type | VOID) Ident MethodDeclaratorRest
+ * | Ident ConstructorDeclaratorRest
+ * | TypeParameters Ident ConstructorDeclaratorRest
+ * | ClassOrInterfaceOrEnumDeclaration
+ * )
+ * InterfaceBodyDeclaration =
+ * ";"
+ * | ModifiersOpt Type Ident
+ * ( ConstantDeclaratorsRest | InterfaceMethodDeclaratorRest ";" )
+ */
+ List<JCTree> classOrInterfaceBodyDeclaration(Name className, boolean isInterface) {
+ if (S.token() == SEMI) {
+ S.nextToken();
+ return List.<JCTree>of(F.at(Position.NOPOS).Block(0, List.<JCStatement>nil()));
+ } else {
+ String dc = S.docComment();
+ int pos = S.pos();
+ JCModifiers mods = modifiersOpt();
+ if (S.token() == CLASS ||
+ S.token() == INTERFACE ||
+ allowEnums && S.token() == ENUM) {
+ return List.<JCTree>of(classOrInterfaceOrEnumDeclaration(mods, dc));
+ } else if (S.token() == LBRACE && !isInterface &&
+ (mods.flags & Flags.StandardFlags & ~Flags.STATIC) == 0 &&
+ mods.annotations.isEmpty()) {
+ return List.<JCTree>of(block(pos, mods.flags));
+ } else {
+ pos = S.pos();
+ List<JCTypeParameter> typarams = typeParametersOpt();
+ // Hack alert: if there are type arguments but no Modifiers, the start
+ // position will be lost unless we set the Modifiers position. There
+ // should be an AST node for type parameters (BugId 5005090).
+ if (typarams.length() > 0 && mods.pos == Position.NOPOS) {
+ mods.pos = pos;
+ }
+ Token token = S.token();
+ Name name = S.name();
+ pos = S.pos();
+ JCExpression type;
+ boolean isVoid = S.token() == VOID;
+ if (isVoid) {
+ type = to(F.at(pos).TypeIdent(TypeTags.VOID));
+ S.nextToken();
+ } else {
+ type = parseType();
+ }
+ if (S.token() == LPAREN && !isInterface && type.getTag() == JCTree.IDENT) {
+ if (isInterface || name != className)
+ log.error(pos, "invalid.meth.decl.ret.type.req");
+ return List.of(methodDeclaratorRest(
+ pos, mods, null, names.init, typarams,
+ isInterface, true, dc));
+ } else {
+ pos = S.pos();
+ name = ident();
+ if (S.token() == LPAREN) {
+ return List.of(methodDeclaratorRest(
+ pos, mods, type, name, typarams,
+ isInterface, isVoid, dc));
+ } else if (!isVoid && typarams.isEmpty()) {
+ List<JCTree> defs =
+ variableDeclaratorsRest(pos, mods, type, name, isInterface, dc,
+ new ListBuffer<JCTree>()).toList();
+ storeEnd(defs.last(), S.endPos());
+ accept(SEMI);
+ return defs;
+ } else {
+ pos = S.pos();
+ List<JCTree> err = isVoid
+ ? List.<JCTree>of(toP(F.at(pos).MethodDef(mods, name, type, typarams,
+ List.<JCVariableDecl>nil(), List.<JCExpression>nil(), null, null)))
+ : null;
+ return List.<JCTree>of(syntaxError(S.pos(), err, "expected", LPAREN));
+ }
+ }
+ }
+ }
+ }
+
+ /** MethodDeclaratorRest =
+ * FormalParameters BracketsOpt [Throws TypeList] ( MethodBody | [DEFAULT AnnotationValue] ";")
+ * VoidMethodDeclaratorRest =
+ * FormalParameters [Throws TypeList] ( MethodBody | ";")
+ * InterfaceMethodDeclaratorRest =
+ * FormalParameters BracketsOpt [THROWS TypeList] ";"
+ * VoidInterfaceMethodDeclaratorRest =
+ * FormalParameters [THROWS TypeList] ";"
+ * ConstructorDeclaratorRest =
+ * "(" FormalParameterListOpt ")" [THROWS TypeList] MethodBody
+ */
+ JCTree methodDeclaratorRest(int pos,
+ JCModifiers mods,
+ JCExpression type,
+ Name name,
+ List<JCTypeParameter> typarams,
+ boolean isInterface, boolean isVoid,
+ String dc) {
+ List<JCVariableDecl> params = formalParameters();
+ if (!isVoid) type = bracketsOpt(type);
+ List<JCExpression> thrown = List.nil();
+ if (S.token() == THROWS) {
+ S.nextToken();
+ thrown = qualidentList();
+ }
+ JCBlock body = null;
+ JCExpression defaultValue;
+ if (S.token() == LBRACE) {
+ body = block();
+ defaultValue = null;
+ } else {
+ if (S.token() == DEFAULT) {
+ accept(DEFAULT);
+ defaultValue = annotationValue();
+ } else {
+ defaultValue = null;
+ }
+ accept(SEMI);
+ if (S.pos() <= errorEndPos) {
+ // error recovery
+ skip(false, true, false, false);
+ if (S.token() == LBRACE) {
+ body = block();
+ }
+ }
+ }
+ JCMethodDecl result =
+ toP(F.at(pos).MethodDef(mods, name, type, typarams,
+ params, thrown,
+ body, defaultValue));
+ attach(result, dc);
+ return result;
+ }
+
+ /** QualidentList = Qualident {"," Qualident}
+ */
+ List<JCExpression> qualidentList() {
+ ListBuffer<JCExpression> ts = new ListBuffer<JCExpression>();
+ ts.append(qualident());
+ while (S.token() == COMMA) {
+ S.nextToken();
+ ts.append(qualident());
+ }
+ return ts.toList();
+ }
+
+ /** TypeParametersOpt = ["<" TypeParameter {"," TypeParameter} ">"]
+ */
+ List<JCTypeParameter> typeParametersOpt() {
+ if (S.token() == LT) {
+ checkGenerics();
+ ListBuffer<JCTypeParameter> typarams = new ListBuffer<JCTypeParameter>();
+ S.nextToken();
+ typarams.append(typeParameter());
+ while (S.token() == COMMA) {
+ S.nextToken();
+ typarams.append(typeParameter());
+ }
+ accept(GT);
+ return typarams.toList();
+ } else {
+ return List.nil();
+ }
+ }
+
+ /** TypeParameter = TypeVariable [TypeParameterBound]
+ * TypeParameterBound = EXTENDS Type {"&" Type}
+ * TypeVariable = Ident
+ */
+ JCTypeParameter typeParameter() {
+ int pos = S.pos();
+ Name name = ident();
+ ListBuffer<JCExpression> bounds = new ListBuffer<JCExpression>();
+ if (S.token() == EXTENDS) {
+ S.nextToken();
+ bounds.append(parseType());
+ while (S.token() == AMP) {
+ S.nextToken();
+ bounds.append(parseType());
+ }
+ }
+ return toP(F.at(pos).TypeParameter(name, bounds.toList()));
+ }
+
+ /** FormalParameters = "(" [ FormalParameterList ] ")"
+ * FormalParameterList = [ FormalParameterListNovarargs , ] LastFormalParameter
+ * FormalParameterListNovarargs = [ FormalParameterListNovarargs , ] FormalParameter
+ */
+ List<JCVariableDecl> formalParameters() {
+ ListBuffer<JCVariableDecl> params = new ListBuffer<JCVariableDecl>();
+ JCVariableDecl lastParam = null;
+ accept(LPAREN);
+ if (S.token() != RPAREN) {
+ params.append(lastParam = formalParameter());
+ while ((lastParam.mods.flags & Flags.VARARGS) == 0 && S.token() == COMMA) {
+ S.nextToken();
+ params.append(lastParam = formalParameter());
+ }
+ }
+ accept(RPAREN);
+ return params.toList();
+ }
+
+ JCModifiers optFinal(long flags) {
+ JCModifiers mods = modifiersOpt();
+ checkNoMods(mods.flags & ~(Flags.FINAL | Flags.DEPRECATED));
+ mods.flags |= flags;
+ return mods;
+ }
+
+ /** FormalParameter = { FINAL | '@' Annotation } Type VariableDeclaratorId
+ * LastFormalParameter = { FINAL | '@' Annotation } Type '...' Ident | FormalParameter
+ */
+ JCVariableDecl formalParameter() {
+ JCModifiers mods = optFinal(Flags.PARAMETER);
+ JCExpression type = parseType();
+ if (S.token() == ELLIPSIS) {
+ checkVarargs();
+ mods.flags |= Flags.VARARGS;
+ type = to(F.at(S.pos()).TypeArray(type));
+ S.nextToken();
+ }
+ return variableDeclaratorId(mods, type);
+ }
+
+/* ---------- auxiliary methods -------------- */
+
+ /** Check that given tree is a legal expression statement.
+ */
+ protected JCExpression checkExprStat(JCExpression t) {
+ switch(t.getTag()) {
+ case JCTree.PREINC: case JCTree.PREDEC:
+ case JCTree.POSTINC: case JCTree.POSTDEC:
+ case JCTree.ASSIGN:
+ case JCTree.BITOR_ASG: case JCTree.BITXOR_ASG: case JCTree.BITAND_ASG:
+ case JCTree.SL_ASG: case JCTree.SR_ASG: case JCTree.USR_ASG:
+ case JCTree.PLUS_ASG: case JCTree.MINUS_ASG:
+ case JCTree.MUL_ASG: case JCTree.DIV_ASG: case JCTree.MOD_ASG:
+ case JCTree.APPLY: case JCTree.NEWCLASS:
+ case JCTree.ERRONEOUS:
+ return t;
+ default:
+ log.error(t.pos, "not.stmt");
+ return F.at(t.pos).Erroneous(List.<JCTree>of(t));
+ }
+ }
+
+ /** Return precedence of operator represented by token,
+ * -1 if token is not a binary operator. @see TreeInfo.opPrec
+ */
+ static int prec(Token token) {
+ int oc = optag(token);
+ return (oc >= 0) ? TreeInfo.opPrec(oc) : -1;
+ }
+
+ /** Return operation tag of binary operator represented by token,
+ * -1 if token is not a binary operator.
+ */
+ static int optag(Token token) {
+ switch (token) {
+ case BARBAR:
+ return JCTree.OR;
+ case AMPAMP:
+ return JCTree.AND;
+ case BAR:
+ return JCTree.BITOR;
+ case BAREQ:
+ return JCTree.BITOR_ASG;
+ case CARET:
+ return JCTree.BITXOR;
+ case CARETEQ:
+ return JCTree.BITXOR_ASG;
+ case AMP:
+ return JCTree.BITAND;
+ case AMPEQ:
+ return JCTree.BITAND_ASG;
+ case EQEQ:
+ return JCTree.EQ;
+ case BANGEQ:
+ return JCTree.NE;
+ case LT:
+ return JCTree.LT;
+ case GT:
+ return JCTree.GT;
+ case LTEQ:
+ return JCTree.LE;
+ case GTEQ:
+ return JCTree.GE;
+ case LTLT:
+ return JCTree.SL;
+ case LTLTEQ:
+ return JCTree.SL_ASG;
+ case GTGT:
+ return JCTree.SR;
+ case GTGTEQ:
+ return JCTree.SR_ASG;
+ case GTGTGT:
+ return JCTree.USR;
+ case GTGTGTEQ:
+ return JCTree.USR_ASG;
+ case PLUS:
+ return JCTree.PLUS;
+ case PLUSEQ:
+ return JCTree.PLUS_ASG;
+ case SUB:
+ return JCTree.MINUS;
+ case SUBEQ:
+ return JCTree.MINUS_ASG;
+ case STAR:
+ return JCTree.MUL;
+ case STAREQ:
+ return JCTree.MUL_ASG;
+ case SLASH:
+ return JCTree.DIV;
+ case SLASHEQ:
+ return JCTree.DIV_ASG;
+ case PERCENT:
+ return JCTree.MOD;
+ case PERCENTEQ:
+ return JCTree.MOD_ASG;
+ case INSTANCEOF:
+ return JCTree.TYPETEST;
+ default:
+ return -1;
+ }
+ }
+
+ /** Return operation tag of unary operator represented by token,
+ * -1 if token is not a binary operator.
+ */
+ static int unoptag(Token token) {
+ switch (token) {
+ case PLUS:
+ return JCTree.POS;
+ case SUB:
+ return JCTree.NEG;
+ case BANG:
+ return JCTree.NOT;
+ case TILDE:
+ return JCTree.COMPL;
+ case PLUSPLUS:
+ return JCTree.PREINC;
+ case SUBSUB:
+ return JCTree.PREDEC;
+ default:
+ return -1;
+ }
+ }
+
+ /** Return type tag of basic type represented by token,
+ * -1 if token is not a basic type identifier.
+ */
+ static int typetag(Token token) {
+ switch (token) {
+ case BYTE:
+ return TypeTags.BYTE;
+ case CHAR:
+ return TypeTags.CHAR;
+ case SHORT:
+ return TypeTags.SHORT;
+ case INT:
+ return TypeTags.INT;
+ case LONG:
+ return TypeTags.LONG;
+ case FLOAT:
+ return TypeTags.FLOAT;
+ case DOUBLE:
+ return TypeTags.DOUBLE;
+ case BOOLEAN:
+ return TypeTags.BOOLEAN;
+ default:
+ return -1;
+ }
+ }
+
+ void checkGenerics() {
+ if (!allowGenerics) {
+ log.error(S.pos(), "generics.not.supported.in.source", source.name);
+ allowGenerics = true;
+ }
+ }
+ void checkVarargs() {
+ if (!allowVarargs) {
+ log.error(S.pos(), "varargs.not.supported.in.source", source.name);
+ allowVarargs = true;
+ }
+ }
+ void checkForeach() {
+ if (!allowForeach) {
+ log.error(S.pos(), "foreach.not.supported.in.source", source.name);
+ allowForeach = true;
+ }
+ }
+ void checkStaticImports() {
+ if (!allowStaticImport) {
+ log.error(S.pos(), "static.import.not.supported.in.source", source.name);
+ allowStaticImport = true;
+ }
+ }
+ void checkAnnotations() {
+ if (!allowAnnotations) {
+ log.error(S.pos(), "annotations.not.supported.in.source", source.name);
+ allowAnnotations = true;
+ }
+ }
+}
--- a/langtools/src/share/classes/com/sun/tools/javac/parser/Parser.java Wed Jul 05 16:41:36 2017 +0200
+++ b/langtools/src/share/classes/com/sun/tools/javac/parser/Parser.java Fri Sep 12 23:32:51 2008 -0700
@@ -23,2834 +23,44 @@
* have any questions.
*/
+
package com.sun.tools.javac.parser;
-import java.util.*;
-
-import com.sun.tools.javac.tree.*;
-import com.sun.tools.javac.code.*;
-import com.sun.tools.javac.util.*;
-import com.sun.tools.javac.util.List;
-import static com.sun.tools.javac.util.ListBuffer.lb;
-
-import com.sun.tools.javac.tree.JCTree.*;
-
-import static com.sun.tools.javac.parser.Token.*;
-
-/** The parser maps a token sequence into an abstract syntax
- * tree. It operates by recursive descent, with code derived
- * systematically from an LL(1) grammar. For efficiency reasons, an
- * operator precedence scheme is used for parsing binary operation
- * expressions.
- *
- * <p><b>This is NOT part of any API supported by Sun Microsystems. If
- * you write code that depends on this, you do so at your own risk.
- * This code and its internal interfaces are subject to change or
- * deletion without notice.</b>
- */
-public class Parser {
-
- /** A factory for creating parsers. */
- public static class Factory {
- /** The context key for the parser factory. */
- protected static final Context.Key<Parser.Factory> parserFactoryKey =
- new Context.Key<Parser.Factory>();
-
- /** Get the Factory instance for this context. */
- public static Factory instance(Context context) {
- Factory instance = context.get(parserFactoryKey);
- if (instance == null)
- instance = new Factory(context);
- return instance;
- }
-
- final TreeMaker F;
- final Log log;
- final Keywords keywords;
- final Source source;
- final Name.Table names;
- final Options options;
-
- /** Create a new parser factory. */
- protected Factory(Context context) {
- context.put(parserFactoryKey, this);
- this.F = TreeMaker.instance(context);
- this.log = Log.instance(context);
- this.names = Name.Table.instance(context);
- this.keywords = Keywords.instance(context);
- this.source = Source.instance(context);
- this.options = Options.instance(context);
- }
-
- /**
- * Create a new Parser.
- * @param S Lexer for getting tokens while parsing
- * @param keepDocComments true if javadoc comments should be kept
- * @param genEndPos true if end positions should be generated
- */
- public Parser newParser(Lexer S, boolean keepDocComments, boolean genEndPos) {
- if (!genEndPos)
- return new Parser(this, S, keepDocComments);
- else
- return new EndPosParser(this, S, keepDocComments);
- }
- }
-
- /** The number of precedence levels of infix operators.
- */
- private static final int infixPrecedenceLevels = 10;
-
- /** The scanner used for lexical analysis.
- */
- private Lexer S;
-
- /** The factory to be used for abstract syntax tree construction.
- */
- protected TreeMaker F;
-
- /** The log to be used for error diagnostics.
- */
- private Log log;
-
- /** The keyword table. */
- private Keywords keywords;
-
- /** The Source language setting. */
- private Source source;
-
- /** The name table. */
- private Name.Table names;
-
- /** Construct a parser from a given scanner, tree factory and log.
- */
- protected Parser(Factory fac,
- Lexer S,
- boolean keepDocComments) {
- this.S = S;
- S.nextToken(); // prime the pump
- this.F = fac.F;
- this.log = fac.log;
- this.names = fac.names;
- this.keywords = fac.keywords;
- this.source = fac.source;
- Options options = fac.options;
- this.allowGenerics = source.allowGenerics();
- this.allowVarargs = source.allowVarargs();
- this.allowAsserts = source.allowAsserts();
- this.allowEnums = source.allowEnums();
- this.allowForeach = source.allowForeach();
- this.allowStaticImport = source.allowStaticImport();
- this.allowAnnotations = source.allowAnnotations();
- this.keepDocComments = keepDocComments;
- if (keepDocComments) docComments = new HashMap<JCTree,String>();
- this.errorTree = F.Erroneous();
- }
-
- /** Switch: Should generics be recognized?
- */
- boolean allowGenerics;
-
- /** Switch: Should varargs be recognized?
- */
- boolean allowVarargs;
-
- /** Switch: should we recognize assert statements, or just give a warning?
- */
- boolean allowAsserts;
-
- /** Switch: should we recognize enums, or just give a warning?
- */
- boolean allowEnums;
-
- /** Switch: should we recognize foreach?
- */
- boolean allowForeach;
-
- /** Switch: should we recognize foreach?
- */
- boolean allowStaticImport;
+import com.sun.tools.javac.tree.JCTree.JCCompilationUnit;
+import com.sun.tools.javac.tree.JCTree.JCExpression;
+import com.sun.tools.javac.tree.JCTree.JCStatement;
- /** Switch: should we recognize annotations?
- */
- boolean allowAnnotations;
-
- /** Switch: should we keep docComments?
- */
- boolean keepDocComments;
-
- /** When terms are parsed, the mode determines which is expected:
- * mode = EXPR : an expression
- * mode = TYPE : a type
- * mode = NOPARAMS : no parameters allowed for type
- * mode = TYPEARG : type argument
- */
- static final int EXPR = 1;
- static final int TYPE = 2;
- static final int NOPARAMS = 4;
- static final int TYPEARG = 8;
-
- /** The current mode.
- */
- private int mode = 0;
-
- /** The mode of the term that was parsed last.
- */
- private int lastmode = 0;
-
-/* ---------- error recovery -------------- */
-
- private JCErroneous errorTree;
-
- /** Skip forward until a suitable stop token is found.
- */
- private void skip(boolean stopAtImport, boolean stopAtMemberDecl, boolean stopAtIdentifier, boolean stopAtStatement) {
- while (true) {
- switch (S.token()) {
- case SEMI:
- S.nextToken();
- return;
- case PUBLIC:
- case FINAL:
- case ABSTRACT:
- case MONKEYS_AT:
- case EOF:
- case CLASS:
- case INTERFACE:
- case ENUM:
- return;
- case IMPORT:
- if (stopAtImport)
- return;
- break;
- case LBRACE:
- case RBRACE:
- case PRIVATE:
- case PROTECTED:
- case STATIC:
- case TRANSIENT:
- case NATIVE:
- case VOLATILE:
- case SYNCHRONIZED:
- case STRICTFP:
- case LT:
- case BYTE:
- case SHORT:
- case CHAR:
- case INT:
- case LONG:
- case FLOAT:
- case DOUBLE:
- case BOOLEAN:
- case VOID:
- if (stopAtMemberDecl)
- return;
- break;
- case IDENTIFIER:
- if (stopAtIdentifier)
- return;
- break;
- case CASE:
- case DEFAULT:
- case IF:
- case FOR:
- case WHILE:
- case DO:
- case TRY:
- case SWITCH:
- case RETURN:
- case THROW:
- case BREAK:
- case CONTINUE:
- case ELSE:
- case FINALLY:
- case CATCH:
- if (stopAtStatement)
- return;
- break;
- }
- S.nextToken();
- }
- }
-
- private JCErroneous syntaxError(int pos, String key, Token... args) {
- return syntaxError(pos, null, key, args);
- }
-
- private JCErroneous syntaxError(int pos, List<JCTree> errs, String key, Token... args) {
- setErrorEndPos(pos);
- reportSyntaxError(pos, key, (Object[])args);
- return toP(F.at(pos).Erroneous(errs));
- }
-
- private int errorPos = Position.NOPOS;
+/**
+ * Reads syntactic units from source code.
+ * Parsers are normally created from a ParserFactory.
+ *
+ * <p><b>This is NOT part of any API supported by Sun Microsystems.
+ * If you write code that depends on this, you do so at your own risk.
+ * This code and its internal interfaces are subject to change or
+ * deletion without notice.</b>
+ */
+public interface Parser {
/**
- * Report a syntax error at given position using the given
- * argument unless one was already reported at the same position.
- */
- private void reportSyntaxError(int pos, String key, Object... args) {
- if (pos > S.errPos() || pos == Position.NOPOS) {
- if (S.token() == EOF)
- log.error(pos, "premature.eof");
- else
- log.error(pos, key, args);
- }
- S.errPos(pos);
- if (S.pos() == errorPos)
- S.nextToken(); // guarantee progress
- errorPos = S.pos();
- }
-
-
- /** Generate a syntax error at current position unless one was already
- * reported at the same position.
- */
- private JCErroneous syntaxError(String key) {
- return syntaxError(S.pos(), key);
- }
-
- /** Generate a syntax error at current position unless one was
- * already reported at the same position.
- */
- private JCErroneous syntaxError(String key, Token arg) {
- return syntaxError(S.pos(), key, arg);
- }
-
- /** If next input token matches given token, skip it, otherwise report
- * an error.
+ * Parse a compilation unit.
+ * @return a compilation unit
*/
- public void accept(Token token) {
- if (S.token() == token) {
- S.nextToken();
- } else {
- setErrorEndPos(S.pos());
- reportSyntaxError(S.prevEndPos(), "expected", token);
- }
- }
-
- /** Report an illegal start of expression/type error at given position.
- */
- JCExpression illegal(int pos) {
- setErrorEndPos(S.pos());
- if ((mode & EXPR) != 0)
- return syntaxError(pos, "illegal.start.of.expr");
- else
- return syntaxError(pos, "illegal.start.of.type");
-
- }
-
- /** Report an illegal start of expression/type error at current position.
- */
- JCExpression illegal() {
- return illegal(S.pos());
- }
-
- /** Diagnose a modifier flag from the set, if any. */
- void checkNoMods(long mods) {
- if (mods != 0) {
- long lowestMod = mods & -mods;
- log.error(S.pos(), "mod.not.allowed.here",
- Flags.asFlagSet(lowestMod));
- }
- }
-
-/* ---------- doc comments --------- */
-
- /** A hashtable to store all documentation comments
- * indexed by the tree nodes they refer to.
- * defined only if option flag keepDocComment is set.
- */
- Map<JCTree, String> docComments;
-
- /** Make an entry into docComments hashtable,
- * provided flag keepDocComments is set and given doc comment is non-null.
- * @param tree The tree to be used as index in the hashtable
- * @param dc The doc comment to associate with the tree, or null.
- */
- void attach(JCTree tree, String dc) {
- if (keepDocComments && dc != null) {
-// System.out.println("doc comment = ");System.out.println(dc);//DEBUG
- docComments.put(tree, dc);
- }
- }
-
-/* -------- source positions ------- */
-
- private int errorEndPos = -1;
-
- private void setErrorEndPos(int errPos) {
- if (errPos > errorEndPos)
- errorEndPos = errPos;
- }
-
- protected int getErrorEndPos() {
- return errorEndPos;
- }
-
- /**
- * Store ending position for a tree.
- * @param tree The tree.
- * @param endpos The ending position to associate with the tree.
- */
- protected void storeEnd(JCTree tree, int endpos) {}
-
- /**
- * Store ending position for a tree. The ending position should
- * be the ending position of the current token.
- * @param t The tree.
- */
- protected <T extends JCTree> T to(T t) { return t; }
-
- /**
- * Store ending position for a tree. The ending position should
- * be greater of the ending position of the previous token and errorEndPos.
- * @param t The tree.
- */
- protected <T extends JCTree> T toP(T t) { return t; }
-
- /** Get the start position for a tree node. The start position is
- * defined to be the position of the first character of the first
- * token of the node's source text.
- * @param tree The tree node
- */
- public int getStartPos(JCTree tree) {
- return TreeInfo.getStartPos(tree);
- }
-
- /**
- * Get the end position for a tree node. The end position is
- * defined to be the position of the last character of the last
- * token of the node's source text. Returns Position.NOPOS if end
- * positions are not generated or the position is otherwise not
- * found.
- * @param tree The tree node
- */
- public int getEndPos(JCTree tree) {
- return Position.NOPOS;
- }
-
-
-
-/* ---------- parsing -------------- */
-
- /**
- * Ident = IDENTIFIER
- */
- Name ident() {
- if (S.token() == IDENTIFIER) {
- Name name = S.name();
- S.nextToken();
- return name;
- } else if (S.token() == ASSERT) {
- if (allowAsserts) {
- log.error(S.pos(), "assert.as.identifier");
- S.nextToken();
- return names.error;
- } else {
- log.warning(S.pos(), "assert.as.identifier");
- Name name = S.name();
- S.nextToken();
- return name;
- }
- } else if (S.token() == ENUM) {
- if (allowEnums) {
- log.error(S.pos(), "enum.as.identifier");
- S.nextToken();
- return names.error;
- } else {
- log.warning(S.pos(), "enum.as.identifier");
- Name name = S.name();
- S.nextToken();
- return name;
- }
- } else {
- accept(IDENTIFIER);
- return names.error;
- }
-}
-
- /**
- * Qualident = Ident { DOT Ident }
- */
- public JCExpression qualident() {
- JCExpression t = toP(F.at(S.pos()).Ident(ident()));
- while (S.token() == DOT) {
- int pos = S.pos();
- S.nextToken();
- t = toP(F.at(pos).Select(t, ident()));
- }
- return t;
- }
-
- /**
- * Literal =
- * INTLITERAL
- * | LONGLITERAL
- * | FLOATLITERAL
- * | DOUBLELITERAL
- * | CHARLITERAL
- * | STRINGLITERAL
- * | TRUE
- * | FALSE
- * | NULL
- */
- JCExpression literal(Name prefix) {
- int pos = S.pos();
- JCExpression t = errorTree;
- switch (S.token()) {
- case INTLITERAL:
- try {
- t = F.at(pos).Literal(
- TypeTags.INT,
- Convert.string2int(strval(prefix), S.radix()));
- } catch (NumberFormatException ex) {
- log.error(S.pos(), "int.number.too.large", strval(prefix));
- }
- break;
- case LONGLITERAL:
- try {
- t = F.at(pos).Literal(
- TypeTags.LONG,
- new Long(Convert.string2long(strval(prefix), S.radix())));
- } catch (NumberFormatException ex) {
- log.error(S.pos(), "int.number.too.large", strval(prefix));
- }
- break;
- case FLOATLITERAL: {
- String proper = (S.radix() == 16 ? ("0x"+ S.stringVal()) : S.stringVal());
- Float n;
- try {
- n = Float.valueOf(proper);
- } catch (NumberFormatException ex) {
- // error already repoted in scanner
- n = Float.NaN;
- }
- if (n.floatValue() == 0.0f && !isZero(proper))
- log.error(S.pos(), "fp.number.too.small");
- else if (n.floatValue() == Float.POSITIVE_INFINITY)
- log.error(S.pos(), "fp.number.too.large");
- else
- t = F.at(pos).Literal(TypeTags.FLOAT, n);
- break;
- }
- case DOUBLELITERAL: {
- String proper = (S.radix() == 16 ? ("0x"+ S.stringVal()) : S.stringVal());
- Double n;
- try {
- n = Double.valueOf(proper);
- } catch (NumberFormatException ex) {
- // error already reported in scanner
- n = Double.NaN;
- }
- if (n.doubleValue() == 0.0d && !isZero(proper))
- log.error(S.pos(), "fp.number.too.small");
- else if (n.doubleValue() == Double.POSITIVE_INFINITY)
- log.error(S.pos(), "fp.number.too.large");
- else
- t = F.at(pos).Literal(TypeTags.DOUBLE, n);
- break;
- }
- case CHARLITERAL:
- t = F.at(pos).Literal(
- TypeTags.CHAR,
- S.stringVal().charAt(0) + 0);
- break;
- case STRINGLITERAL:
- t = F.at(pos).Literal(
- TypeTags.CLASS,
- S.stringVal());
- break;
- case TRUE: case FALSE:
- t = F.at(pos).Literal(
- TypeTags.BOOLEAN,
- (S.token() == TRUE ? 1 : 0));
- break;
- case NULL:
- t = F.at(pos).Literal(
- TypeTags.BOT,
- null);
- break;
- default:
- assert false;
- }
- if (t == errorTree)
- t = F.at(pos).Erroneous();
- storeEnd(t, S.endPos());
- S.nextToken();
- return t;
- }
-//where
- boolean isZero(String s) {
- char[] cs = s.toCharArray();
- int base = ((Character.toLowerCase(s.charAt(1)) == 'x') ? 16 : 10);
- int i = ((base==16) ? 2 : 0);
- while (i < cs.length && (cs[i] == '0' || cs[i] == '.')) i++;
- return !(i < cs.length && (Character.digit(cs[i], base) > 0));
- }
-
- String strval(Name prefix) {
- String s = S.stringVal();
- return (prefix.len == 0) ? s : prefix + s;
- }
-
- /** terms can be either expressions or types.
- */
- public JCExpression expression() {
- return term(EXPR);
- }
-
- public JCExpression type() {
- return term(TYPE);
- }
-
- JCExpression term(int newmode) {
- int prevmode = mode;
- mode = newmode;
- JCExpression t = term();
- lastmode = mode;
- mode = prevmode;
- return t;
- }
+ JCCompilationUnit parseCompilationUnit();
/**
- * Expression = Expression1 [ExpressionRest]
- * ExpressionRest = [AssignmentOperator Expression1]
- * AssignmentOperator = "=" | "+=" | "-=" | "*=" | "/=" |
- * "&=" | "|=" | "^=" |
- * "%=" | "<<=" | ">>=" | ">>>="
- * Type = Type1
- * TypeNoParams = TypeNoParams1
- * StatementExpression = Expression
- * ConstantExpression = Expression
- */
- JCExpression term() {
- JCExpression t = term1();
- if ((mode & EXPR) != 0 &&
- S.token() == EQ || PLUSEQ.compareTo(S.token()) <= 0 && S.token().compareTo(GTGTGTEQ) <= 0)
- return termRest(t);
- else
- return t;
- }
-
- JCExpression termRest(JCExpression t) {
- switch (S.token()) {
- case EQ: {
- int pos = S.pos();
- S.nextToken();
- mode = EXPR;
- JCExpression t1 = term();
- return toP(F.at(pos).Assign(t, t1));
- }
- case PLUSEQ:
- case SUBEQ:
- case STAREQ:
- case SLASHEQ:
- case PERCENTEQ:
- case AMPEQ:
- case BAREQ:
- case CARETEQ:
- case LTLTEQ:
- case GTGTEQ:
- case GTGTGTEQ:
- int pos = S.pos();
- Token token = S.token();
- S.nextToken();
- mode = EXPR;
- JCExpression t1 = term();
- return F.at(pos).Assignop(optag(token), t, t1);
- default:
- return t;
- }
- }
-
- /** Expression1 = Expression2 [Expression1Rest]
- * Type1 = Type2
- * TypeNoParams1 = TypeNoParams2
- */
- JCExpression term1() {
- JCExpression t = term2();
- if ((mode & EXPR) != 0 && S.token() == QUES) {
- mode = EXPR;
- return term1Rest(t);
- } else {
- return t;
- }
- }
-
- /** Expression1Rest = ["?" Expression ":" Expression1]
- */
- JCExpression term1Rest(JCExpression t) {
- if (S.token() == QUES) {
- int pos = S.pos();
- S.nextToken();
- JCExpression t1 = term();
- accept(COLON);
- JCExpression t2 = term1();
- return F.at(pos).Conditional(t, t1, t2);
- } else {
- return t;
- }
- }
-
- /** Expression2 = Expression3 [Expression2Rest]
- * Type2 = Type3
- * TypeNoParams2 = TypeNoParams3
- */
- JCExpression term2() {
- JCExpression t = term3();
- if ((mode & EXPR) != 0 && prec(S.token()) >= TreeInfo.orPrec) {
- mode = EXPR;
- return term2Rest(t, TreeInfo.orPrec);
- } else {
- return t;
- }
- }
-
- /* Expression2Rest = {infixop Expression3}
- * | Expression3 instanceof Type
- * infixop = "||"
- * | "&&"
- * | "|"
- * | "^"
- * | "&"
- * | "==" | "!="
- * | "<" | ">" | "<=" | ">="
- * | "<<" | ">>" | ">>>"
- * | "+" | "-"
- * | "*" | "/" | "%"
- */
- JCExpression term2Rest(JCExpression t, int minprec) {
- List<JCExpression[]> savedOd = odStackSupply.elems;
- JCExpression[] odStack = newOdStack();
- List<Token[]> savedOp = opStackSupply.elems;
- Token[] opStack = newOpStack();
- // optimization, was odStack = new Tree[...]; opStack = new Tree[...];
- int top = 0;
- odStack[0] = t;
- int startPos = S.pos();
- Token topOp = ERROR;
- while (prec(S.token()) >= minprec) {
- opStack[top] = topOp;
- top++;
- topOp = S.token();
- int pos = S.pos();
- S.nextToken();
- odStack[top] = topOp == INSTANCEOF ? type() : term3();
- while (top > 0 && prec(topOp) >= prec(S.token())) {
- odStack[top-1] = makeOp(pos, topOp, odStack[top-1],
- odStack[top]);
- top--;
- topOp = opStack[top];
- }
- }
- assert top == 0;
- t = odStack[0];
-
- if (t.getTag() == JCTree.PLUS) {
- StringBuffer buf = foldStrings(t);
- if (buf != null) {
- t = toP(F.at(startPos).Literal(TypeTags.CLASS, buf.toString()));
- }
- }
-
- odStackSupply.elems = savedOd; // optimization
- opStackSupply.elems = savedOp; // optimization
- return t;
- }
-//where
- /** Construct a binary or type test node.
- */
- private JCExpression makeOp(int pos,
- Token topOp,
- JCExpression od1,
- JCExpression od2)
- {
- if (topOp == INSTANCEOF) {
- return F.at(pos).TypeTest(od1, od2);
- } else {
- return F.at(pos).Binary(optag(topOp), od1, od2);
- }
- }
- /** If tree is a concatenation of string literals, replace it
- * by a single literal representing the concatenated string.
- */
- protected StringBuffer foldStrings(JCTree tree) {
- List<String> buf = List.nil();
- while (true) {
- if (tree.getTag() == JCTree.LITERAL) {
- JCLiteral lit = (JCLiteral) tree;
- if (lit.typetag == TypeTags.CLASS) {
- StringBuffer sbuf =
- new StringBuffer((String)lit.value);
- while (buf.nonEmpty()) {
- sbuf.append(buf.head);
- buf = buf.tail;
- }
- return sbuf;
- }
- } else if (tree.getTag() == JCTree.PLUS) {
- JCBinary op = (JCBinary)tree;
- if (op.rhs.getTag() == JCTree.LITERAL) {
- JCLiteral lit = (JCLiteral) op.rhs;
- if (lit.typetag == TypeTags.CLASS) {
- buf = buf.prepend((String) lit.value);
- tree = op.lhs;
- continue;
- }
- }
- }
- return null;
- }
- }
-
- /** optimization: To save allocating a new operand/operator stack
- * for every binary operation, we use supplys.
- */
- ListBuffer<JCExpression[]> odStackSupply = new ListBuffer<JCExpression[]>();
- ListBuffer<Token[]> opStackSupply = new ListBuffer<Token[]>();
-
- private JCExpression[] newOdStack() {
- if (odStackSupply.elems == odStackSupply.last)
- odStackSupply.append(new JCExpression[infixPrecedenceLevels + 1]);
- JCExpression[] odStack = odStackSupply.elems.head;
- odStackSupply.elems = odStackSupply.elems.tail;
- return odStack;
- }
-
- private Token[] newOpStack() {
- if (opStackSupply.elems == opStackSupply.last)
- opStackSupply.append(new Token[infixPrecedenceLevels + 1]);
- Token[] opStack = opStackSupply.elems.head;
- opStackSupply.elems = opStackSupply.elems.tail;
- return opStack;
- }
-
- /** Expression3 = PrefixOp Expression3
- * | "(" Expr | TypeNoParams ")" Expression3
- * | Primary {Selector} {PostfixOp}
- * Primary = "(" Expression ")"
- * | Literal
- * | [TypeArguments] THIS [Arguments]
- * | [TypeArguments] SUPER SuperSuffix
- * | NEW [TypeArguments] Creator
- * | Ident { "." Ident }
- * [ "[" ( "]" BracketsOpt "." CLASS | Expression "]" )
- * | Arguments
- * | "." ( CLASS | THIS | [TypeArguments] SUPER Arguments | NEW [TypeArguments] InnerCreator )
- * ]
- * | BasicType BracketsOpt "." CLASS
- * PrefixOp = "++" | "--" | "!" | "~" | "+" | "-"
- * PostfixOp = "++" | "--"
- * Type3 = Ident { "." Ident } [TypeArguments] {TypeSelector} BracketsOpt
- * | BasicType
- * TypeNoParams3 = Ident { "." Ident } BracketsOpt
- * Selector = "." [TypeArguments] Ident [Arguments]
- * | "." THIS
- * | "." [TypeArguments] SUPER SuperSuffix
- * | "." NEW [TypeArguments] InnerCreator
- * | "[" Expression "]"
- * TypeSelector = "." Ident [TypeArguments]
- * SuperSuffix = Arguments | "." Ident [Arguments]
+ * Parse an expression.
+ * @return an expression
*/
- protected JCExpression term3() {
- int pos = S.pos();
- JCExpression t;
- List<JCExpression> typeArgs = typeArgumentsOpt(EXPR);
- switch (S.token()) {
- case QUES:
- if ((mode & TYPE) != 0 && (mode & (TYPEARG|NOPARAMS)) == TYPEARG) {
- mode = TYPE;
- return typeArgument();
- } else
- return illegal();
- case PLUSPLUS: case SUBSUB: case BANG: case TILDE: case PLUS: case SUB:
- if (typeArgs == null && (mode & EXPR) != 0) {
- Token token = S.token();
- S.nextToken();
- mode = EXPR;
- if (token == SUB &&
- (S.token() == INTLITERAL || S.token() == LONGLITERAL) &&
- S.radix() == 10) {
- mode = EXPR;
- t = literal(names.hyphen);
- } else {
- t = term3();
- return F.at(pos).Unary(unoptag(token), t);
- }
- } else return illegal();
- break;
- case LPAREN:
- if (typeArgs == null && (mode & EXPR) != 0) {
- S.nextToken();
- mode = EXPR | TYPE | NOPARAMS;
- t = term3();
- if ((mode & TYPE) != 0 && S.token() == LT) {
- // Could be a cast to a parameterized type
- int op = JCTree.LT;
- int pos1 = S.pos();
- S.nextToken();
- mode &= (EXPR | TYPE);
- mode |= TYPEARG;
- JCExpression t1 = term3();
- if ((mode & TYPE) != 0 &&
- (S.token() == COMMA || S.token() == GT)) {
- mode = TYPE;
- ListBuffer<JCExpression> args = new ListBuffer<JCExpression>();
- args.append(t1);
- while (S.token() == COMMA) {
- S.nextToken();
- args.append(typeArgument());
- }
- accept(GT);
- t = F.at(pos1).TypeApply(t, args.toList());
- checkGenerics();
- t = bracketsOpt(toP(t));
- } else if ((mode & EXPR) != 0) {
- mode = EXPR;
- t = F.at(pos1).Binary(op, t, term2Rest(t1, TreeInfo.shiftPrec));
- t = termRest(term1Rest(term2Rest(t, TreeInfo.orPrec)));
- } else {
- accept(GT);
- }
- } else {
- t = termRest(term1Rest(term2Rest(t, TreeInfo.orPrec)));
- }
- accept(RPAREN);
- lastmode = mode;
- mode = EXPR;
- if ((lastmode & EXPR) == 0) {
- JCExpression t1 = term3();
- return F.at(pos).TypeCast(t, t1);
- } else if ((lastmode & TYPE) != 0) {
- switch (S.token()) {
- /*case PLUSPLUS: case SUBSUB: */
- case BANG: case TILDE:
- case LPAREN: case THIS: case SUPER:
- case INTLITERAL: case LONGLITERAL: case FLOATLITERAL:
- case DOUBLELITERAL: case CHARLITERAL: case STRINGLITERAL:
- case TRUE: case FALSE: case NULL:
- case NEW: case IDENTIFIER: case ASSERT: case ENUM:
- case BYTE: case SHORT: case CHAR: case INT:
- case LONG: case FLOAT: case DOUBLE: case BOOLEAN: case VOID:
- JCExpression t1 = term3();
- return F.at(pos).TypeCast(t, t1);
- }
- }
- } else return illegal();
- t = toP(F.at(pos).Parens(t));
- break;
- case THIS:
- if ((mode & EXPR) != 0) {
- mode = EXPR;
- t = to(F.at(pos).Ident(names._this));
- S.nextToken();
- if (typeArgs == null)
- t = argumentsOpt(null, t);
- else
- t = arguments(typeArgs, t);
- typeArgs = null;
- } else return illegal();
- break;
- case SUPER:
- if ((mode & EXPR) != 0) {
- mode = EXPR;
- t = to(superSuffix(typeArgs, F.at(pos).Ident(names._super)));
- typeArgs = null;
- } else return illegal();
- break;
- case INTLITERAL: case LONGLITERAL: case FLOATLITERAL: case DOUBLELITERAL:
- case CHARLITERAL: case STRINGLITERAL:
- case TRUE: case FALSE: case NULL:
- if (typeArgs == null && (mode & EXPR) != 0) {
- mode = EXPR;
- t = literal(names.empty);
- } else return illegal();
- break;
- case NEW:
- if (typeArgs != null) return illegal();
- if ((mode & EXPR) != 0) {
- mode = EXPR;
- S.nextToken();
- if (S.token() == LT) typeArgs = typeArguments();
- t = creator(pos, typeArgs);
- typeArgs = null;
- } else return illegal();
- break;
- case IDENTIFIER: case ASSERT: case ENUM:
- if (typeArgs != null) return illegal();
- t = toP(F.at(S.pos()).Ident(ident()));
- loop: while (true) {
- pos = S.pos();
- switch (S.token()) {
- case LBRACKET:
- S.nextToken();
- if (S.token() == RBRACKET) {
- S.nextToken();
- t = bracketsOpt(t);
- t = toP(F.at(pos).TypeArray(t));
- t = bracketsSuffix(t);
- } else {
- if ((mode & EXPR) != 0) {
- mode = EXPR;
- JCExpression t1 = term();
- t = to(F.at(pos).Indexed(t, t1));
- }
- accept(RBRACKET);
- }
- break loop;
- case LPAREN:
- if ((mode & EXPR) != 0) {
- mode = EXPR;
- t = arguments(typeArgs, t);
- typeArgs = null;
- }
- break loop;
- case DOT:
- S.nextToken();
- int oldmode = mode;
- mode &= ~NOPARAMS;
- typeArgs = typeArgumentsOpt(EXPR);
- mode = oldmode;
- if ((mode & EXPR) != 0) {
- switch (S.token()) {
- case CLASS:
- if (typeArgs != null) return illegal();
- mode = EXPR;
- t = to(F.at(pos).Select(t, names._class));
- S.nextToken();
- break loop;
- case THIS:
- if (typeArgs != null) return illegal();
- mode = EXPR;
- t = to(F.at(pos).Select(t, names._this));
- S.nextToken();
- break loop;
- case SUPER:
- mode = EXPR;
- t = to(F.at(pos).Select(t, names._super));
- t = superSuffix(typeArgs, t);
- typeArgs = null;
- break loop;
- case NEW:
- if (typeArgs != null) return illegal();
- mode = EXPR;
- int pos1 = S.pos();
- S.nextToken();
- if (S.token() == LT) typeArgs = typeArguments();
- t = innerCreator(pos1, typeArgs, t);
- typeArgs = null;
- break loop;
- }
- }
- // typeArgs saved for next loop iteration.
- t = toP(F.at(pos).Select(t, ident()));
- break;
- default:
- break loop;
- }
- }
- if (typeArgs != null) illegal();
- t = typeArgumentsOpt(t);
- break;
- case BYTE: case SHORT: case CHAR: case INT: case LONG: case FLOAT:
- case DOUBLE: case BOOLEAN:
- if (typeArgs != null) illegal();
- t = bracketsSuffix(bracketsOpt(basicType()));
- break;
- case VOID:
- if (typeArgs != null) illegal();
- if ((mode & EXPR) != 0) {
- S.nextToken();
- if (S.token() == DOT) {
- JCPrimitiveTypeTree ti = toP(F.at(pos).TypeIdent(TypeTags.VOID));
- t = bracketsSuffix(ti);
- } else {
- return illegal(pos);
- }
- } else {
- return illegal();
- }
- break;
- default:
- return illegal();
- }
- if (typeArgs != null) illegal();
- while (true) {
- int pos1 = S.pos();
- if (S.token() == LBRACKET) {
- S.nextToken();
- if ((mode & TYPE) != 0) {
- int oldmode = mode;
- mode = TYPE;
- if (S.token() == RBRACKET) {
- S.nextToken();
- t = bracketsOpt(t);
- t = toP(F.at(pos1).TypeArray(t));
- return t;
- }
- mode = oldmode;
- }
- if ((mode & EXPR) != 0) {
- mode = EXPR;
- JCExpression t1 = term();
- t = to(F.at(pos1).Indexed(t, t1));
- }
- accept(RBRACKET);
- } else if (S.token() == DOT) {
- S.nextToken();
- typeArgs = typeArgumentsOpt(EXPR);
- if (S.token() == SUPER && (mode & EXPR) != 0) {
- mode = EXPR;
- t = to(F.at(pos1).Select(t, names._super));
- S.nextToken();
- t = arguments(typeArgs, t);
- typeArgs = null;
- } else if (S.token() == NEW && (mode & EXPR) != 0) {
- if (typeArgs != null) return illegal();
- mode = EXPR;
- int pos2 = S.pos();
- S.nextToken();
- if (S.token() == LT) typeArgs = typeArguments();
- t = innerCreator(pos2, typeArgs, t);
- typeArgs = null;
- } else {
- t = toP(F.at(pos1).Select(t, ident()));
- t = argumentsOpt(typeArgs, typeArgumentsOpt(t));
- typeArgs = null;
- }
- } else {
- break;
- }
- }
- while ((S.token() == PLUSPLUS || S.token() == SUBSUB) && (mode & EXPR) != 0) {
- mode = EXPR;
- t = to(F.at(S.pos()).Unary(
- S.token() == PLUSPLUS ? JCTree.POSTINC : JCTree.POSTDEC, t));
- S.nextToken();
- }
- return toP(t);
- }
-
- /** SuperSuffix = Arguments | "." [TypeArguments] Ident [Arguments]
- */
- JCExpression superSuffix(List<JCExpression> typeArgs, JCExpression t) {
- S.nextToken();
- if (S.token() == LPAREN || typeArgs != null) {
- t = arguments(typeArgs, t);
- } else {
- int pos = S.pos();
- accept(DOT);
- typeArgs = (S.token() == LT) ? typeArguments() : null;
- t = toP(F.at(pos).Select(t, ident()));
- t = argumentsOpt(typeArgs, t);
- }
- return t;
- }
-
- /** BasicType = BYTE | SHORT | CHAR | INT | LONG | FLOAT | DOUBLE | BOOLEAN
- */
- JCPrimitiveTypeTree basicType() {
- JCPrimitiveTypeTree t = to(F.at(S.pos()).TypeIdent(typetag(S.token())));
- S.nextToken();
- return t;
- }
-
- /** ArgumentsOpt = [ Arguments ]
- */
- JCExpression argumentsOpt(List<JCExpression> typeArgs, JCExpression t) {
- if ((mode & EXPR) != 0 && S.token() == LPAREN || typeArgs != null) {
- mode = EXPR;
- return arguments(typeArgs, t);
- } else {
- return t;
- }
- }
-
- /** Arguments = "(" [Expression { COMMA Expression }] ")"
- */
- List<JCExpression> arguments() {
- ListBuffer<JCExpression> args = lb();
- if (S.token() == LPAREN) {
- S.nextToken();
- if (S.token() != RPAREN) {
- args.append(expression());
- while (S.token() == COMMA) {
- S.nextToken();
- args.append(expression());
- }
- }
- accept(RPAREN);
- } else {
- syntaxError(S.pos(), "expected", LPAREN);
- }
- return args.toList();
- }
-
- JCMethodInvocation arguments(List<JCExpression> typeArgs, JCExpression t) {
- int pos = S.pos();
- List<JCExpression> args = arguments();
- return toP(F.at(pos).Apply(typeArgs, t, args));
- }
-
- /** TypeArgumentsOpt = [ TypeArguments ]
- */
- JCExpression typeArgumentsOpt(JCExpression t) {
- if (S.token() == LT &&
- (mode & TYPE) != 0 &&
- (mode & NOPARAMS) == 0) {
- mode = TYPE;
- checkGenerics();
- return typeArguments(t);
- } else {
- return t;
- }
- }
- List<JCExpression> typeArgumentsOpt() {
- return typeArgumentsOpt(TYPE);
- }
-
- List<JCExpression> typeArgumentsOpt(int useMode) {
- if (S.token() == LT) {
- checkGenerics();
- if ((mode & useMode) == 0 ||
- (mode & NOPARAMS) != 0) {
- illegal();
- }
- mode = useMode;
- return typeArguments();
- }
- return null;
- }
+ JCExpression parseExpression();
- /** TypeArguments = "<" TypeArgument {"," TypeArgument} ">"
- */
- List<JCExpression> typeArguments() {
- ListBuffer<JCExpression> args = lb();
- if (S.token() == LT) {
- S.nextToken();
- args.append(((mode & EXPR) == 0) ? typeArgument() : type());
- while (S.token() == COMMA) {
- S.nextToken();
- args.append(((mode & EXPR) == 0) ? typeArgument() : type());
- }
- switch (S.token()) {
- case GTGTGTEQ:
- S.token(GTGTEQ);
- break;
- case GTGTEQ:
- S.token(GTEQ);
- break;
- case GTEQ:
- S.token(EQ);
- break;
- case GTGTGT:
- S.token(GTGT);
- break;
- case GTGT:
- S.token(GT);
- break;
- default:
- accept(GT);
- break;
- }
- } else {
- syntaxError(S.pos(), "expected", LT);
- }
- return args.toList();
- }
-
- /** TypeArgument = Type
- * | "?"
- * | "?" EXTENDS Type {"&" Type}
- * | "?" SUPER Type
- */
- JCExpression typeArgument() {
- if (S.token() != QUES) return type();
- int pos = S.pos();
- S.nextToken();
- if (S.token() == EXTENDS) {
- TypeBoundKind t = to(F.at(S.pos()).TypeBoundKind(BoundKind.EXTENDS));
- S.nextToken();
- return F.at(pos).Wildcard(t, type());
- } else if (S.token() == SUPER) {
- TypeBoundKind t = to(F.at(S.pos()).TypeBoundKind(BoundKind.SUPER));
- S.nextToken();
- return F.at(pos).Wildcard(t, type());
- } else if (S.token() == IDENTIFIER) {
- //error recovery
- reportSyntaxError(S.prevEndPos(), "expected3",
- GT, EXTENDS, SUPER);
- TypeBoundKind t = F.at(Position.NOPOS).TypeBoundKind(BoundKind.UNBOUND);
- JCExpression wc = toP(F.at(pos).Wildcard(t, null));
- JCIdent id = toP(F.at(S.pos()).Ident(ident()));
- return F.at(pos).Erroneous(List.<JCTree>of(wc, id));
- } else {
- TypeBoundKind t = F.at(Position.NOPOS).TypeBoundKind(BoundKind.UNBOUND);
- return toP(F.at(pos).Wildcard(t, null));
- }
- }
-
- JCTypeApply typeArguments(JCExpression t) {
- int pos = S.pos();
- List<JCExpression> args = typeArguments();
- return toP(F.at(pos).TypeApply(t, args));
- }
-
- /** BracketsOpt = {"[" "]"}
- */
- private JCExpression bracketsOpt(JCExpression t) {
- if (S.token() == LBRACKET) {
- int pos = S.pos();
- S.nextToken();
- t = bracketsOptCont(t, pos);
- F.at(pos);
- }
- return t;
- }
-
- private JCArrayTypeTree bracketsOptCont(JCExpression t, int pos) {
- accept(RBRACKET);
- t = bracketsOpt(t);
- return toP(F.at(pos).TypeArray(t));
- }
-
- /** BracketsSuffixExpr = "." CLASS
- * BracketsSuffixType =
- */
- JCExpression bracketsSuffix(JCExpression t) {
- if ((mode & EXPR) != 0 && S.token() == DOT) {
- mode = EXPR;
- int pos = S.pos();
- S.nextToken();
- accept(CLASS);
- if (S.pos() == errorEndPos) {
- // error recovery
- Name name = null;
- if (S.token() == IDENTIFIER) {
- name = S.name();
- S.nextToken();
- } else {
- name = names.error;
- }
- t = F.at(pos).Erroneous(List.<JCTree>of(toP(F.at(pos).Select(t, name))));
- } else {
- t = toP(F.at(pos).Select(t, names._class));
- }
- } else if ((mode & TYPE) != 0) {
- mode = TYPE;
- } else {
- syntaxError(S.pos(), "dot.class.expected");
- }
- return t;
- }
-
- /** Creator = Qualident [TypeArguments] ( ArrayCreatorRest | ClassCreatorRest )
- */
- JCExpression creator(int newpos, List<JCExpression> typeArgs) {
- switch (S.token()) {
- case BYTE: case SHORT: case CHAR: case INT: case LONG: case FLOAT:
- case DOUBLE: case BOOLEAN:
- if (typeArgs == null)
- return arrayCreatorRest(newpos, basicType());
- break;
- default:
- }
- JCExpression t = qualident();
- int oldmode = mode;
- mode = TYPE;
- if (S.token() == LT) {
- checkGenerics();
- t = typeArguments(t);
- }
- while (S.token() == DOT) {
- int pos = S.pos();
- S.nextToken();
- t = toP(F.at(pos).Select(t, ident()));
- if (S.token() == LT) {
- checkGenerics();
- t = typeArguments(t);
- }
- }
- mode = oldmode;
- if (S.token() == LBRACKET) {
- JCExpression e = arrayCreatorRest(newpos, t);
- if (typeArgs != null) {
- int pos = newpos;
- if (!typeArgs.isEmpty() && typeArgs.head.pos != Position.NOPOS) {
- // note: this should always happen but we should
- // not rely on this as the parser is continuously
- // modified to improve error recovery.
- pos = typeArgs.head.pos;
- }
- setErrorEndPos(S.prevEndPos());
- reportSyntaxError(pos, "cannot.create.array.with.type.arguments");
- return toP(F.at(newpos).Erroneous(typeArgs.prepend(e)));
- }
- return e;
- } else if (S.token() == LPAREN) {
- return classCreatorRest(newpos, null, typeArgs, t);
- } else {
- reportSyntaxError(S.pos(), "expected2",
- LPAREN, LBRACKET);
- t = toP(F.at(newpos).NewClass(null, typeArgs, t, List.<JCExpression>nil(), null));
- return toP(F.at(newpos).Erroneous(List.<JCTree>of(t)));
- }
- }
-
- /** InnerCreator = Ident [TypeArguments] ClassCreatorRest
- */
- JCExpression innerCreator(int newpos, List<JCExpression> typeArgs, JCExpression encl) {
- JCExpression t = toP(F.at(S.pos()).Ident(ident()));
- if (S.token() == LT) {
- checkGenerics();
- t = typeArguments(t);
- }
- return classCreatorRest(newpos, encl, typeArgs, t);
- }
-
- /** ArrayCreatorRest = "[" ( "]" BracketsOpt ArrayInitializer
- * | Expression "]" {"[" Expression "]"} BracketsOpt )
- */
- JCExpression arrayCreatorRest(int newpos, JCExpression elemtype) {
- accept(LBRACKET);
- if (S.token() == RBRACKET) {
- accept(RBRACKET);
- elemtype = bracketsOpt(elemtype);
- if (S.token() == LBRACE) {
- return arrayInitializer(newpos, elemtype);
- } else {
- return syntaxError(S.pos(), "array.dimension.missing");
- }
- } else {
- ListBuffer<JCExpression> dims = new ListBuffer<JCExpression>();
- dims.append(expression());
- accept(RBRACKET);
- while (S.token() == LBRACKET) {
- int pos = S.pos();
- S.nextToken();
- if (S.token() == RBRACKET) {
- elemtype = bracketsOptCont(elemtype, pos);
- } else {
- dims.append(expression());
- accept(RBRACKET);
- }
- }
- return toP(F.at(newpos).NewArray(elemtype, dims.toList(), null));
- }
- }
-
- /** ClassCreatorRest = Arguments [ClassBody]
- */
- JCExpression classCreatorRest(int newpos,
- JCExpression encl,
- List<JCExpression> typeArgs,
- JCExpression t)
- {
- List<JCExpression> args = arguments();
- JCClassDecl body = null;
- if (S.token() == LBRACE) {
- int pos = S.pos();
- List<JCTree> defs = classOrInterfaceBody(names.empty, false);
- JCModifiers mods = F.at(Position.NOPOS).Modifiers(0);
- body = toP(F.at(pos).AnonymousClassDef(mods, defs));
- }
- return toP(F.at(newpos).NewClass(encl, typeArgs, t, args, body));
- }
-
- /** ArrayInitializer = "{" [VariableInitializer {"," VariableInitializer}] [","] "}"
- */
- JCExpression arrayInitializer(int newpos, JCExpression t) {
- accept(LBRACE);
- ListBuffer<JCExpression> elems = new ListBuffer<JCExpression>();
- if (S.token() == COMMA) {
- S.nextToken();
- } else if (S.token() != RBRACE) {
- elems.append(variableInitializer());
- while (S.token() == COMMA) {
- S.nextToken();
- if (S.token() == RBRACE) break;
- elems.append(variableInitializer());
- }
- }
- accept(RBRACE);
- return toP(F.at(newpos).NewArray(t, List.<JCExpression>nil(), elems.toList()));
- }
-
- /** VariableInitializer = ArrayInitializer | Expression
- */
- public JCExpression variableInitializer() {
- return S.token() == LBRACE ? arrayInitializer(S.pos(), null) : expression();
- }
-
- /** ParExpression = "(" Expression ")"
- */
- JCExpression parExpression() {
- accept(LPAREN);
- JCExpression t = expression();
- accept(RPAREN);
- return t;
- }
-
- /** Block = "{" BlockStatements "}"
- */
- JCBlock block(int pos, long flags) {
- accept(LBRACE);
- List<JCStatement> stats = blockStatements();
- JCBlock t = F.at(pos).Block(flags, stats);
- while (S.token() == CASE || S.token() == DEFAULT) {
- syntaxError("orphaned", S.token());
- switchBlockStatementGroups();
- }
- // the Block node has a field "endpos" for first char of last token, which is
- // usually but not necessarily the last char of the last token.
- t.endpos = S.pos();
- accept(RBRACE);
- return toP(t);
- }
-
- public JCBlock block() {
- return block(S.pos(), 0);
- }
-
- /** BlockStatements = { BlockStatement }
- * BlockStatement = LocalVariableDeclarationStatement
- * | ClassOrInterfaceOrEnumDeclaration
- * | [Ident ":"] Statement
- * LocalVariableDeclarationStatement
- * = { FINAL | '@' Annotation } Type VariableDeclarators ";"
- */
- @SuppressWarnings("fallthrough")
- List<JCStatement> blockStatements() {
-//todo: skip to anchor on error(?)
- int lastErrPos = -1;
- ListBuffer<JCStatement> stats = new ListBuffer<JCStatement>();
- while (true) {
- int pos = S.pos();
- switch (S.token()) {
- case RBRACE: case CASE: case DEFAULT: case EOF:
- return stats.toList();
- case LBRACE: case IF: case FOR: case WHILE: case DO: case TRY:
- case SWITCH: case SYNCHRONIZED: case RETURN: case THROW: case BREAK:
- case CONTINUE: case SEMI: case ELSE: case FINALLY: case CATCH:
- stats.append(statement());
- break;
- case MONKEYS_AT:
- case FINAL: {
- String dc = S.docComment();
- JCModifiers mods = modifiersOpt();
- if (S.token() == INTERFACE ||
- S.token() == CLASS ||
- allowEnums && S.token() == ENUM) {
- stats.append(classOrInterfaceOrEnumDeclaration(mods, dc));
- } else {
- JCExpression t = type();
- stats.appendList(variableDeclarators(mods, t,
- new ListBuffer<JCStatement>()));
- // A "LocalVariableDeclarationStatement" subsumes the terminating semicolon
- storeEnd(stats.elems.last(), S.endPos());
- accept(SEMI);
- }
- break;
- }
- case ABSTRACT: case STRICTFP: {
- String dc = S.docComment();
- JCModifiers mods = modifiersOpt();
- stats.append(classOrInterfaceOrEnumDeclaration(mods, dc));
- break;
- }
- case INTERFACE:
- case CLASS:
- stats.append(classOrInterfaceOrEnumDeclaration(modifiersOpt(),
- S.docComment()));
- break;
- case ENUM:
- case ASSERT:
- if (allowEnums && S.token() == ENUM) {
- log.error(S.pos(), "local.enum");
- stats.
- append(classOrInterfaceOrEnumDeclaration(modifiersOpt(),
- S.docComment()));
- break;
- } else if (allowAsserts && S.token() == ASSERT) {
- stats.append(statement());
- break;
- }
- /* fall through to default */
- default:
- Name name = S.name();
- JCExpression t = term(EXPR | TYPE);
- if (S.token() == COLON && t.getTag() == JCTree.IDENT) {
- S.nextToken();
- JCStatement stat = statement();
- stats.append(F.at(pos).Labelled(name, stat));
- } else if ((lastmode & TYPE) != 0 &&
- (S.token() == IDENTIFIER ||
- S.token() == ASSERT ||
- S.token() == ENUM)) {
- pos = S.pos();
- JCModifiers mods = F.at(Position.NOPOS).Modifiers(0);
- F.at(pos);
- stats.appendList(variableDeclarators(mods, t,
- new ListBuffer<JCStatement>()));
- // A "LocalVariableDeclarationStatement" subsumes the terminating semicolon
- storeEnd(stats.elems.last(), S.endPos());
- accept(SEMI);
- } else {
- // This Exec is an "ExpressionStatement"; it subsumes the terminating semicolon
- stats.append(to(F.at(pos).Exec(checkExprStat(t))));
- accept(SEMI);
- }
- }
-
- // error recovery
- if (S.pos() == lastErrPos)
- return stats.toList();
- if (S.pos() <= errorEndPos) {
- skip(false, true, true, true);
- lastErrPos = S.pos();
- }
-
- // ensure no dangling /** @deprecated */ active
- S.resetDeprecatedFlag();
- }
- }
-
- /** Statement =
- * Block
- * | IF ParExpression Statement [ELSE Statement]
- * | FOR "(" ForInitOpt ";" [Expression] ";" ForUpdateOpt ")" Statement
- * | FOR "(" FormalParameter : Expression ")" Statement
- * | WHILE ParExpression Statement
- * | DO Statement WHILE ParExpression ";"
- * | TRY Block ( Catches | [Catches] FinallyPart )
- * | SWITCH ParExpression "{" SwitchBlockStatementGroups "}"
- * | SYNCHRONIZED ParExpression Block
- * | RETURN [Expression] ";"
- * | THROW Expression ";"
- * | BREAK [Ident] ";"
- * | CONTINUE [Ident] ";"
- * | ASSERT Expression [ ":" Expression ] ";"
- * | ";"
- * | ExpressionStatement
- * | Ident ":" Statement
+ /**
+ * Parse a statement.
+ * @return an expression
*/
- @SuppressWarnings("fallthrough")
- public JCStatement statement() {
- int pos = S.pos();
- switch (S.token()) {
- case LBRACE:
- return block();
- case IF: {
- S.nextToken();
- JCExpression cond = parExpression();
- JCStatement thenpart = statement();
- JCStatement elsepart = null;
- if (S.token() == ELSE) {
- S.nextToken();
- elsepart = statement();
- }
- return F.at(pos).If(cond, thenpart, elsepart);
- }
- case FOR: {
- S.nextToken();
- accept(LPAREN);
- List<JCStatement> inits = S.token() == SEMI ? List.<JCStatement>nil() : forInit();
- if (inits.length() == 1 &&
- inits.head.getTag() == JCTree.VARDEF &&
- ((JCVariableDecl) inits.head).init == null &&
- S.token() == COLON) {
- checkForeach();
- JCVariableDecl var = (JCVariableDecl)inits.head;
- accept(COLON);
- JCExpression expr = expression();
- accept(RPAREN);
- JCStatement body = statement();
- return F.at(pos).ForeachLoop(var, expr, body);
- } else {
- accept(SEMI);
- JCExpression cond = S.token() == SEMI ? null : expression();
- accept(SEMI);
- List<JCExpressionStatement> steps = S.token() == RPAREN ? List.<JCExpressionStatement>nil() : forUpdate();
- accept(RPAREN);
- JCStatement body = statement();
- return F.at(pos).ForLoop(inits, cond, steps, body);
- }
- }
- case WHILE: {
- S.nextToken();
- JCExpression cond = parExpression();
- JCStatement body = statement();
- return F.at(pos).WhileLoop(cond, body);
- }
- case DO: {
- S.nextToken();
- JCStatement body = statement();
- accept(WHILE);
- JCExpression cond = parExpression();
- JCDoWhileLoop t = to(F.at(pos).DoLoop(body, cond));
- accept(SEMI);
- return t;
- }
- case TRY: {
- S.nextToken();
- JCBlock body = block();
- ListBuffer<JCCatch> catchers = new ListBuffer<JCCatch>();
- JCBlock finalizer = null;
- if (S.token() == CATCH || S.token() == FINALLY) {
- while (S.token() == CATCH) catchers.append(catchClause());
- if (S.token() == FINALLY) {
- S.nextToken();
- finalizer = block();
- }
- } else {
- log.error(pos, "try.without.catch.or.finally");
- }
- return F.at(pos).Try(body, catchers.toList(), finalizer);
- }
- case SWITCH: {
- S.nextToken();
- JCExpression selector = parExpression();
- accept(LBRACE);
- List<JCCase> cases = switchBlockStatementGroups();
- JCSwitch t = to(F.at(pos).Switch(selector, cases));
- accept(RBRACE);
- return t;
- }
- case SYNCHRONIZED: {
- S.nextToken();
- JCExpression lock = parExpression();
- JCBlock body = block();
- return F.at(pos).Synchronized(lock, body);
- }
- case RETURN: {
- S.nextToken();
- JCExpression result = S.token() == SEMI ? null : expression();
- JCReturn t = to(F.at(pos).Return(result));
- accept(SEMI);
- return t;
- }
- case THROW: {
- S.nextToken();
- JCExpression exc = expression();
- JCThrow t = to(F.at(pos).Throw(exc));
- accept(SEMI);
- return t;
- }
- case BREAK: {
- S.nextToken();
- Name label = (S.token() == IDENTIFIER || S.token() == ASSERT || S.token() == ENUM) ? ident() : null;
- JCBreak t = to(F.at(pos).Break(label));
- accept(SEMI);
- return t;
- }
- case CONTINUE: {
- S.nextToken();
- Name label = (S.token() == IDENTIFIER || S.token() == ASSERT || S.token() == ENUM) ? ident() : null;
- JCContinue t = to(F.at(pos).Continue(label));
- accept(SEMI);
- return t;
- }
- case SEMI:
- S.nextToken();
- return toP(F.at(pos).Skip());
- case ELSE:
- return toP(F.Exec(syntaxError("else.without.if")));
- case FINALLY:
- return toP(F.Exec(syntaxError("finally.without.try")));
- case CATCH:
- return toP(F.Exec(syntaxError("catch.without.try")));
- case ASSERT: {
- if (allowAsserts && S.token() == ASSERT) {
- S.nextToken();
- JCExpression assertion = expression();
- JCExpression message = null;
- if (S.token() == COLON) {
- S.nextToken();
- message = expression();
- }
- JCAssert t = to(F.at(pos).Assert(assertion, message));
- accept(SEMI);
- return t;
- }
- /* else fall through to default case */
- }
- case ENUM:
- default:
- Name name = S.name();
- JCExpression expr = expression();
- if (S.token() == COLON && expr.getTag() == JCTree.IDENT) {
- S.nextToken();
- JCStatement stat = statement();
- return F.at(pos).Labelled(name, stat);
- } else {
- // This Exec is an "ExpressionStatement"; it subsumes the terminating semicolon
- JCExpressionStatement stat = to(F.at(pos).Exec(checkExprStat(expr)));
- accept(SEMI);
- return stat;
- }
- }
- }
-
- /** CatchClause = CATCH "(" FormalParameter ")" Block
- */
- JCCatch catchClause() {
- int pos = S.pos();
- accept(CATCH);
- accept(LPAREN);
- JCVariableDecl formal =
- variableDeclaratorId(optFinal(Flags.PARAMETER),
- qualident());
- accept(RPAREN);
- JCBlock body = block();
- return F.at(pos).Catch(formal, body);
- }
-
- /** SwitchBlockStatementGroups = { SwitchBlockStatementGroup }
- * SwitchBlockStatementGroup = SwitchLabel BlockStatements
- * SwitchLabel = CASE ConstantExpression ":" | DEFAULT ":"
- */
- List<JCCase> switchBlockStatementGroups() {
- ListBuffer<JCCase> cases = new ListBuffer<JCCase>();
- while (true) {
- int pos = S.pos();
- switch (S.token()) {
- case CASE: {
- S.nextToken();
- JCExpression pat = expression();
- accept(COLON);
- List<JCStatement> stats = blockStatements();
- JCCase c = F.at(pos).Case(pat, stats);
- if (stats.isEmpty())
- storeEnd(c, S.prevEndPos());
- cases.append(c);
- break;
- }
- case DEFAULT: {
- S.nextToken();
- accept(COLON);
- List<JCStatement> stats = blockStatements();
- JCCase c = F.at(pos).Case(null, stats);
- if (stats.isEmpty())
- storeEnd(c, S.prevEndPos());
- cases.append(c);
- break;
- }
- case RBRACE: case EOF:
- return cases.toList();
- default:
- S.nextToken(); // to ensure progress
- syntaxError(pos, "expected3",
- CASE, DEFAULT, RBRACE);
- }
- }
- }
-
- /** MoreStatementExpressions = { COMMA StatementExpression }
- */
- <T extends ListBuffer<? super JCExpressionStatement>> T moreStatementExpressions(int pos,
- JCExpression first,
- T stats) {
- // This Exec is a "StatementExpression"; it subsumes no terminating token
- stats.append(toP(F.at(pos).Exec(checkExprStat(first))));
- while (S.token() == COMMA) {
- S.nextToken();
- pos = S.pos();
- JCExpression t = expression();
- // This Exec is a "StatementExpression"; it subsumes no terminating token
- stats.append(toP(F.at(pos).Exec(checkExprStat(t))));
- }
- return stats;
- }
-
- /** ForInit = StatementExpression MoreStatementExpressions
- * | { FINAL | '@' Annotation } Type VariableDeclarators
- */
- List<JCStatement> forInit() {
- ListBuffer<JCStatement> stats = lb();
- int pos = S.pos();
- if (S.token() == FINAL || S.token() == MONKEYS_AT) {
- return variableDeclarators(optFinal(0), type(), stats).toList();
- } else {
- JCExpression t = term(EXPR | TYPE);
- if ((lastmode & TYPE) != 0 &&
- (S.token() == IDENTIFIER || S.token() == ASSERT || S.token() == ENUM))
- return variableDeclarators(modifiersOpt(), t, stats).toList();
- else
- return moreStatementExpressions(pos, t, stats).toList();
- }
- }
-
- /** ForUpdate = StatementExpression MoreStatementExpressions
- */
- List<JCExpressionStatement> forUpdate() {
- return moreStatementExpressions(S.pos(),
- expression(),
- new ListBuffer<JCExpressionStatement>()).toList();
- }
-
- /** AnnotationsOpt = { '@' Annotation }
- */
- List<JCAnnotation> annotationsOpt() {
- if (S.token() != MONKEYS_AT) return List.nil(); // optimization
- ListBuffer<JCAnnotation> buf = new ListBuffer<JCAnnotation>();
- while (S.token() == MONKEYS_AT) {
- int pos = S.pos();
- S.nextToken();
- buf.append(annotation(pos));
- }
- return buf.toList();
- }
+ JCStatement parseStatement();
- /** ModifiersOpt = { Modifier }
- * Modifier = PUBLIC | PROTECTED | PRIVATE | STATIC | ABSTRACT | FINAL
- * | NATIVE | SYNCHRONIZED | TRANSIENT | VOLATILE | "@"
- * | "@" Annotation
- */
- JCModifiers modifiersOpt() {
- return modifiersOpt(null);
- }
- JCModifiers modifiersOpt(JCModifiers partial) {
- long flags = (partial == null) ? 0 : partial.flags;
- if (S.deprecatedFlag()) {
- flags |= Flags.DEPRECATED;
- S.resetDeprecatedFlag();
- }
- ListBuffer<JCAnnotation> annotations = new ListBuffer<JCAnnotation>();
- if (partial != null) annotations.appendList(partial.annotations);
- int pos = S.pos();
- int lastPos = Position.NOPOS;
- loop:
- while (true) {
- long flag;
- switch (S.token()) {
- case PRIVATE : flag = Flags.PRIVATE; break;
- case PROTECTED : flag = Flags.PROTECTED; break;
- case PUBLIC : flag = Flags.PUBLIC; break;
- case STATIC : flag = Flags.STATIC; break;
- case TRANSIENT : flag = Flags.TRANSIENT; break;
- case FINAL : flag = Flags.FINAL; break;
- case ABSTRACT : flag = Flags.ABSTRACT; break;
- case NATIVE : flag = Flags.NATIVE; break;
- case VOLATILE : flag = Flags.VOLATILE; break;
- case SYNCHRONIZED: flag = Flags.SYNCHRONIZED; break;
- case STRICTFP : flag = Flags.STRICTFP; break;
- case MONKEYS_AT : flag = Flags.ANNOTATION; break;
- default: break loop;
- }
- if ((flags & flag) != 0) log.error(S.pos(), "repeated.modifier");
- lastPos = S.pos();
- S.nextToken();
- if (flag == Flags.ANNOTATION) {
- checkAnnotations();
- if (S.token() != INTERFACE) {
- JCAnnotation ann = annotation(lastPos);
- // if first modifier is an annotation, set pos to annotation's.
- if (flags == 0 && annotations.isEmpty())
- pos = ann.pos;
- annotations.append(ann);
- lastPos = ann.pos;
- flag = 0;
- }
- }
- flags |= flag;
- }
- switch (S.token()) {
- case ENUM: flags |= Flags.ENUM; break;
- case INTERFACE: flags |= Flags.INTERFACE; break;
- default: break;
- }
-
- /* A modifiers tree with no modifier tokens or annotations
- * has no text position. */
- if (flags == 0 && annotations.isEmpty())
- pos = Position.NOPOS;
-
- JCModifiers mods = F.at(pos).Modifiers(flags, annotations.toList());
- if (pos != Position.NOPOS)
- storeEnd(mods, S.prevEndPos());
- return mods;
- }
-
- /** Annotation = "@" Qualident [ "(" AnnotationFieldValues ")" ]
- * @param pos position of "@" token
- */
- JCAnnotation annotation(int pos) {
- // accept(AT); // AT consumed by caller
- checkAnnotations();
- JCTree ident = qualident();
- List<JCExpression> fieldValues = annotationFieldValuesOpt();
- JCAnnotation ann = F.at(pos).Annotation(ident, fieldValues);
- storeEnd(ann, S.prevEndPos());
- return ann;
- }
-
- List<JCExpression> annotationFieldValuesOpt() {
- return (S.token() == LPAREN) ? annotationFieldValues() : List.<JCExpression>nil();
- }
-
- /** AnnotationFieldValues = "(" [ AnnotationFieldValue { "," AnnotationFieldValue } ] ")" */
- List<JCExpression> annotationFieldValues() {
- accept(LPAREN);
- ListBuffer<JCExpression> buf = new ListBuffer<JCExpression>();
- if (S.token() != RPAREN) {
- buf.append(annotationFieldValue());
- while (S.token() == COMMA) {
- S.nextToken();
- buf.append(annotationFieldValue());
- }
- }
- accept(RPAREN);
- return buf.toList();
- }
-
- /** AnnotationFieldValue = AnnotationValue
- * | Identifier "=" AnnotationValue
- */
- JCExpression annotationFieldValue() {
- if (S.token() == IDENTIFIER) {
- mode = EXPR;
- JCExpression t1 = term1();
- if (t1.getTag() == JCTree.IDENT && S.token() == EQ) {
- int pos = S.pos();
- accept(EQ);
- return toP(F.at(pos).Assign(t1, annotationValue()));
- } else {
- return t1;
- }
- }
- return annotationValue();
- }
-
- /* AnnotationValue = ConditionalExpression
- * | Annotation
- * | "{" [ AnnotationValue { "," AnnotationValue } ] "}"
- */
- JCExpression annotationValue() {
- int pos;
- switch (S.token()) {
- case MONKEYS_AT:
- pos = S.pos();
- S.nextToken();
- return annotation(pos);
- case LBRACE:
- pos = S.pos();
- accept(LBRACE);
- ListBuffer<JCExpression> buf = new ListBuffer<JCExpression>();
- if (S.token() != RBRACE) {
- buf.append(annotationValue());
- while (S.token() == COMMA) {
- S.nextToken();
- if (S.token() == RPAREN) break;
- buf.append(annotationValue());
- }
- }
- accept(RBRACE);
- return toP(F.at(pos).NewArray(null, List.<JCExpression>nil(), buf.toList()));
- default:
- mode = EXPR;
- return term1();
- }
- }
-
- /** VariableDeclarators = VariableDeclarator { "," VariableDeclarator }
- */
- public <T extends ListBuffer<? super JCVariableDecl>> T variableDeclarators(JCModifiers mods,
- JCExpression type,
- T vdefs)
- {
- return variableDeclaratorsRest(S.pos(), mods, type, ident(), false, null, vdefs);
- }
-
- /** VariableDeclaratorsRest = VariableDeclaratorRest { "," VariableDeclarator }
- * ConstantDeclaratorsRest = ConstantDeclaratorRest { "," ConstantDeclarator }
- *
- * @param reqInit Is an initializer always required?
- * @param dc The documentation comment for the variable declarations, or null.
- */
- <T extends ListBuffer<? super JCVariableDecl>> T variableDeclaratorsRest(int pos,
- JCModifiers mods,
- JCExpression type,
- Name name,
- boolean reqInit,
- String dc,
- T vdefs)
- {
- vdefs.append(variableDeclaratorRest(pos, mods, type, name, reqInit, dc));
- while (S.token() == COMMA) {
- // All but last of multiple declarators subsume a comma
- storeEnd((JCTree)vdefs.elems.last(), S.endPos());
- S.nextToken();
- vdefs.append(variableDeclarator(mods, type, reqInit, dc));
- }
- return vdefs;
- }
-
- /** VariableDeclarator = Ident VariableDeclaratorRest
- * ConstantDeclarator = Ident ConstantDeclaratorRest
- */
- JCVariableDecl variableDeclarator(JCModifiers mods, JCExpression type, boolean reqInit, String dc) {
- return variableDeclaratorRest(S.pos(), mods, type, ident(), reqInit, dc);
- }
-
- /** VariableDeclaratorRest = BracketsOpt ["=" VariableInitializer]
- * ConstantDeclaratorRest = BracketsOpt "=" VariableInitializer
- *
- * @param reqInit Is an initializer always required?
- * @param dc The documentation comment for the variable declarations, or null.
- */
- JCVariableDecl variableDeclaratorRest(int pos, JCModifiers mods, JCExpression type, Name name,
- boolean reqInit, String dc) {
- type = bracketsOpt(type);
- JCExpression init = null;
- if (S.token() == EQ) {
- S.nextToken();
- init = variableInitializer();
- }
- else if (reqInit) syntaxError(S.pos(), "expected", EQ);
- JCVariableDecl result =
- toP(F.at(pos).VarDef(mods, name, type, init));
- attach(result, dc);
- return result;
- }
-
- /** VariableDeclaratorId = Ident BracketsOpt
- */
- JCVariableDecl variableDeclaratorId(JCModifiers mods, JCExpression type) {
- int pos = S.pos();
- Name name = ident();
- if ((mods.flags & Flags.VARARGS) == 0)
- type = bracketsOpt(type);
- return toP(F.at(pos).VarDef(mods, name, type, null));
- }
-
- /** CompilationUnit = [ { "@" Annotation } PACKAGE Qualident ";"] {ImportDeclaration} {TypeDeclaration}
- */
- public JCTree.JCCompilationUnit compilationUnit() {
- int pos = S.pos();
- JCExpression pid = null;
- String dc = S.docComment();
- JCModifiers mods = null;
- List<JCAnnotation> packageAnnotations = List.nil();
- if (S.token() == MONKEYS_AT)
- mods = modifiersOpt();
-
- if (S.token() == PACKAGE) {
- if (mods != null) {
- checkNoMods(mods.flags);
- packageAnnotations = mods.annotations;
- mods = null;
- }
- S.nextToken();
- pid = qualident();
- accept(SEMI);
- }
- ListBuffer<JCTree> defs = new ListBuffer<JCTree>();
- boolean checkForImports = true;
- while (S.token() != EOF) {
- if (S.pos() <= errorEndPos) {
- // error recovery
- skip(checkForImports, false, false, false);
- if (S.token() == EOF)
- break;
- }
- if (checkForImports && mods == null && S.token() == IMPORT) {
- defs.append(importDeclaration());
- } else {
- JCTree def = typeDeclaration(mods);
- if (def instanceof JCExpressionStatement)
- def = ((JCExpressionStatement)def).expr;
- defs.append(def);
- if (def instanceof JCClassDecl)
- checkForImports = false;
- mods = null;
- }
- }
- JCTree.JCCompilationUnit toplevel = F.at(pos).TopLevel(packageAnnotations, pid, defs.toList());
- attach(toplevel, dc);
- if (defs.elems.isEmpty())
- storeEnd(toplevel, S.prevEndPos());
- if (keepDocComments) toplevel.docComments = docComments;
- return toplevel;
- }
-
- /** ImportDeclaration = IMPORT [ STATIC ] Ident { "." Ident } [ "." "*" ] ";"
- */
- JCTree importDeclaration() {
- int pos = S.pos();
- S.nextToken();
- boolean importStatic = false;
- if (S.token() == STATIC) {
- checkStaticImports();
- importStatic = true;
- S.nextToken();
- }
- JCExpression pid = toP(F.at(S.pos()).Ident(ident()));
- do {
- int pos1 = S.pos();
- accept(DOT);
- if (S.token() == STAR) {
- pid = to(F.at(pos1).Select(pid, names.asterisk));
- S.nextToken();
- break;
- } else {
- pid = toP(F.at(pos1).Select(pid, ident()));
- }
- } while (S.token() == DOT);
- accept(SEMI);
- return toP(F.at(pos).Import(pid, importStatic));
- }
-
- /** TypeDeclaration = ClassOrInterfaceOrEnumDeclaration
- * | ";"
- */
- JCTree typeDeclaration(JCModifiers mods) {
- int pos = S.pos();
- if (mods == null && S.token() == SEMI) {
- S.nextToken();
- return toP(F.at(pos).Skip());
- } else {
- String dc = S.docComment();
- return classOrInterfaceOrEnumDeclaration(modifiersOpt(mods), dc);
- }
- }
-
- /** ClassOrInterfaceOrEnumDeclaration = ModifiersOpt
- * (ClassDeclaration | InterfaceDeclaration | EnumDeclaration)
- * @param mods Any modifiers starting the class or interface declaration
- * @param dc The documentation comment for the class, or null.
+ /**
+ * Parse a type.
+ * @return an expression for a type
*/
- JCStatement classOrInterfaceOrEnumDeclaration(JCModifiers mods, String dc) {
- if (S.token() == CLASS) {
- return classDeclaration(mods, dc);
- } else if (S.token() == INTERFACE) {
- return interfaceDeclaration(mods, dc);
- } else if (allowEnums) {
- if (S.token() == ENUM) {
- return enumDeclaration(mods, dc);
- } else {
- int pos = S.pos();
- List<JCTree> errs;
- if (S.token() == IDENTIFIER) {
- errs = List.<JCTree>of(mods, toP(F.at(pos).Ident(ident())));
- setErrorEndPos(S.pos());
- } else {
- errs = List.<JCTree>of(mods);
- }
- return toP(F.Exec(syntaxError(pos, errs, "expected3",
- CLASS, INTERFACE, ENUM)));
- }
- } else {
- if (S.token() == ENUM) {
- log.error(S.pos(), "enums.not.supported.in.source", source.name);
- allowEnums = true;
- return enumDeclaration(mods, dc);
- }
- int pos = S.pos();
- List<JCTree> errs;
- if (S.token() == IDENTIFIER) {
- errs = List.<JCTree>of(mods, toP(F.at(pos).Ident(ident())));
- setErrorEndPos(S.pos());
- } else {
- errs = List.<JCTree>of(mods);
- }
- return toP(F.Exec(syntaxError(pos, errs, "expected2",
- CLASS, INTERFACE)));
- }
- }
-
- /** ClassDeclaration = CLASS Ident TypeParametersOpt [EXTENDS Type]
- * [IMPLEMENTS TypeList] ClassBody
- * @param mods The modifiers starting the class declaration
- * @param dc The documentation comment for the class, or null.
- */
- JCClassDecl classDeclaration(JCModifiers mods, String dc) {
- int pos = S.pos();
- accept(CLASS);
- Name name = ident();
-
- List<JCTypeParameter> typarams = typeParametersOpt();
-
- JCTree extending = null;
- if (S.token() == EXTENDS) {
- S.nextToken();
- extending = type();
- }
- List<JCExpression> implementing = List.nil();
- if (S.token() == IMPLEMENTS) {
- S.nextToken();
- implementing = typeList();
- }
- List<JCTree> defs = classOrInterfaceBody(name, false);
- JCClassDecl result = toP(F.at(pos).ClassDef(
- mods, name, typarams, extending, implementing, defs));
- attach(result, dc);
- return result;
- }
-
- /** InterfaceDeclaration = INTERFACE Ident TypeParametersOpt
- * [EXTENDS TypeList] InterfaceBody
- * @param mods The modifiers starting the interface declaration
- * @param dc The documentation comment for the interface, or null.
- */
- JCClassDecl interfaceDeclaration(JCModifiers mods, String dc) {
- int pos = S.pos();
- accept(INTERFACE);
- Name name = ident();
-
- List<JCTypeParameter> typarams = typeParametersOpt();
-
- List<JCExpression> extending = List.nil();
- if (S.token() == EXTENDS) {
- S.nextToken();
- extending = typeList();
- }
- List<JCTree> defs = classOrInterfaceBody(name, true);
- JCClassDecl result = toP(F.at(pos).ClassDef(
- mods, name, typarams, null, extending, defs));
- attach(result, dc);
- return result;
- }
-
- /** EnumDeclaration = ENUM Ident [IMPLEMENTS TypeList] EnumBody
- * @param mods The modifiers starting the enum declaration
- * @param dc The documentation comment for the enum, or null.
- */
- JCClassDecl enumDeclaration(JCModifiers mods, String dc) {
- int pos = S.pos();
- accept(ENUM);
- Name name = ident();
-
- List<JCExpression> implementing = List.nil();
- if (S.token() == IMPLEMENTS) {
- S.nextToken();
- implementing = typeList();
- }
-
- List<JCTree> defs = enumBody(name);
- JCModifiers newMods =
- F.at(mods.pos).Modifiers(mods.flags|Flags.ENUM, mods.annotations);
- JCClassDecl result = toP(F.at(pos).
- ClassDef(newMods, name, List.<JCTypeParameter>nil(),
- null, implementing, defs));
- attach(result, dc);
- return result;
- }
-
- /** EnumBody = "{" { EnumeratorDeclarationList } [","]
- * [ ";" {ClassBodyDeclaration} ] "}"
- */
- List<JCTree> enumBody(Name enumName) {
- accept(LBRACE);
- ListBuffer<JCTree> defs = new ListBuffer<JCTree>();
- if (S.token() == COMMA) {
- S.nextToken();
- } else if (S.token() != RBRACE && S.token() != SEMI) {
- defs.append(enumeratorDeclaration(enumName));
- while (S.token() == COMMA) {
- S.nextToken();
- if (S.token() == RBRACE || S.token() == SEMI) break;
- defs.append(enumeratorDeclaration(enumName));
- }
- if (S.token() != SEMI && S.token() != RBRACE) {
- defs.append(syntaxError(S.pos(), "expected3",
- COMMA, RBRACE, SEMI));
- S.nextToken();
- }
- }
- if (S.token() == SEMI) {
- S.nextToken();
- while (S.token() != RBRACE && S.token() != EOF) {
- defs.appendList(classOrInterfaceBodyDeclaration(enumName,
- false));
- if (S.pos() <= errorEndPos) {
- // error recovery
- skip(false, true, true, false);
- }
- }
- }
- accept(RBRACE);
- return defs.toList();
- }
-
- /** EnumeratorDeclaration = AnnotationsOpt [TypeArguments] IDENTIFIER [ Arguments ] [ "{" ClassBody "}" ]
- */
- JCTree enumeratorDeclaration(Name enumName) {
- String dc = S.docComment();
- int flags = Flags.PUBLIC|Flags.STATIC|Flags.FINAL|Flags.ENUM;
- if (S.deprecatedFlag()) {
- flags |= Flags.DEPRECATED;
- S.resetDeprecatedFlag();
- }
- int pos = S.pos();
- List<JCAnnotation> annotations = annotationsOpt();
- JCModifiers mods = F.at(annotations.isEmpty() ? Position.NOPOS : pos).Modifiers(flags, annotations);
- List<JCExpression> typeArgs = typeArgumentsOpt();
- int identPos = S.pos();
- Name name = ident();
- int createPos = S.pos();
- List<JCExpression> args = (S.token() == LPAREN)
- ? arguments() : List.<JCExpression>nil();
- JCClassDecl body = null;
- if (S.token() == LBRACE) {
- JCModifiers mods1 = F.at(Position.NOPOS).Modifiers(Flags.ENUM | Flags.STATIC);
- List<JCTree> defs = classOrInterfaceBody(names.empty, false);
- body = toP(F.at(identPos).AnonymousClassDef(mods1, defs));
- }
- if (args.isEmpty() && body == null)
- createPos = Position.NOPOS;
- JCIdent ident = F.at(Position.NOPOS).Ident(enumName);
- JCNewClass create = F.at(createPos).NewClass(null, typeArgs, ident, args, body);
- if (createPos != Position.NOPOS)
- storeEnd(create, S.prevEndPos());
- ident = F.at(Position.NOPOS).Ident(enumName);
- JCTree result = toP(F.at(pos).VarDef(mods, name, ident, create));
- attach(result, dc);
- return result;
- }
-
- /** TypeList = Type {"," Type}
- */
- List<JCExpression> typeList() {
- ListBuffer<JCExpression> ts = new ListBuffer<JCExpression>();
- ts.append(type());
- while (S.token() == COMMA) {
- S.nextToken();
- ts.append(type());
- }
- return ts.toList();
- }
-
- /** ClassBody = "{" {ClassBodyDeclaration} "}"
- * InterfaceBody = "{" {InterfaceBodyDeclaration} "}"
- */
- List<JCTree> classOrInterfaceBody(Name className, boolean isInterface) {
- accept(LBRACE);
- if (S.pos() <= errorEndPos) {
- // error recovery
- skip(false, true, false, false);
- if (S.token() == LBRACE)
- S.nextToken();
- }
- ListBuffer<JCTree> defs = new ListBuffer<JCTree>();
- while (S.token() != RBRACE && S.token() != EOF) {
- defs.appendList(classOrInterfaceBodyDeclaration(className, isInterface));
- if (S.pos() <= errorEndPos) {
- // error recovery
- skip(false, true, true, false);
- }
- }
- accept(RBRACE);
- return defs.toList();
- }
-
- /** ClassBodyDeclaration =
- * ";"
- * | [STATIC] Block
- * | ModifiersOpt
- * ( Type Ident
- * ( VariableDeclaratorsRest ";" | MethodDeclaratorRest )
- * | VOID Ident MethodDeclaratorRest
- * | TypeParameters (Type | VOID) Ident MethodDeclaratorRest
- * | Ident ConstructorDeclaratorRest
- * | TypeParameters Ident ConstructorDeclaratorRest
- * | ClassOrInterfaceOrEnumDeclaration
- * )
- * InterfaceBodyDeclaration =
- * ";"
- * | ModifiersOpt Type Ident
- * ( ConstantDeclaratorsRest | InterfaceMethodDeclaratorRest ";" )
- */
- List<JCTree> classOrInterfaceBodyDeclaration(Name className, boolean isInterface) {
- if (S.token() == SEMI) {
- S.nextToken();
- return List.<JCTree>of(F.at(Position.NOPOS).Block(0, List.<JCStatement>nil()));
- } else {
- String dc = S.docComment();
- int pos = S.pos();
- JCModifiers mods = modifiersOpt();
- if (S.token() == CLASS ||
- S.token() == INTERFACE ||
- allowEnums && S.token() == ENUM) {
- return List.<JCTree>of(classOrInterfaceOrEnumDeclaration(mods, dc));
- } else if (S.token() == LBRACE && !isInterface &&
- (mods.flags & Flags.StandardFlags & ~Flags.STATIC) == 0 &&
- mods.annotations.isEmpty()) {
- return List.<JCTree>of(block(pos, mods.flags));
- } else {
- pos = S.pos();
- List<JCTypeParameter> typarams = typeParametersOpt();
- // Hack alert: if there are type arguments but no Modifiers, the start
- // position will be lost unless we set the Modifiers position. There
- // should be an AST node for type parameters (BugId 5005090).
- if (typarams.length() > 0 && mods.pos == Position.NOPOS) {
- mods.pos = pos;
- }
- Token token = S.token();
- Name name = S.name();
- pos = S.pos();
- JCExpression type;
- boolean isVoid = S.token() == VOID;
- if (isVoid) {
- type = to(F.at(pos).TypeIdent(TypeTags.VOID));
- S.nextToken();
- } else {
- type = type();
- }
- if (S.token() == LPAREN && !isInterface && type.getTag() == JCTree.IDENT) {
- if (isInterface || name != className)
- log.error(pos, "invalid.meth.decl.ret.type.req");
- return List.of(methodDeclaratorRest(
- pos, mods, null, names.init, typarams,
- isInterface, true, dc));
- } else {
- pos = S.pos();
- name = ident();
- if (S.token() == LPAREN) {
- return List.of(methodDeclaratorRest(
- pos, mods, type, name, typarams,
- isInterface, isVoid, dc));
- } else if (!isVoid && typarams.isEmpty()) {
- List<JCTree> defs =
- variableDeclaratorsRest(pos, mods, type, name, isInterface, dc,
- new ListBuffer<JCTree>()).toList();
- storeEnd(defs.last(), S.endPos());
- accept(SEMI);
- return defs;
- } else {
- pos = S.pos();
- List<JCTree> err = isVoid
- ? List.<JCTree>of(toP(F.at(pos).MethodDef(mods, name, type, typarams,
- List.<JCVariableDecl>nil(), List.<JCExpression>nil(), null, null)))
- : null;
- return List.<JCTree>of(syntaxError(S.pos(), err, "expected", LPAREN));
- }
- }
- }
- }
- }
-
- /** MethodDeclaratorRest =
- * FormalParameters BracketsOpt [Throws TypeList] ( MethodBody | [DEFAULT AnnotationValue] ";")
- * VoidMethodDeclaratorRest =
- * FormalParameters [Throws TypeList] ( MethodBody | ";")
- * InterfaceMethodDeclaratorRest =
- * FormalParameters BracketsOpt [THROWS TypeList] ";"
- * VoidInterfaceMethodDeclaratorRest =
- * FormalParameters [THROWS TypeList] ";"
- * ConstructorDeclaratorRest =
- * "(" FormalParameterListOpt ")" [THROWS TypeList] MethodBody
- */
- JCTree methodDeclaratorRest(int pos,
- JCModifiers mods,
- JCExpression type,
- Name name,
- List<JCTypeParameter> typarams,
- boolean isInterface, boolean isVoid,
- String dc) {
- List<JCVariableDecl> params = formalParameters();
- if (!isVoid) type = bracketsOpt(type);
- List<JCExpression> thrown = List.nil();
- if (S.token() == THROWS) {
- S.nextToken();
- thrown = qualidentList();
- }
- JCBlock body = null;
- JCExpression defaultValue;
- if (S.token() == LBRACE) {
- body = block();
- defaultValue = null;
- } else {
- if (S.token() == DEFAULT) {
- accept(DEFAULT);
- defaultValue = annotationValue();
- } else {
- defaultValue = null;
- }
- accept(SEMI);
- if (S.pos() <= errorEndPos) {
- // error recovery
- skip(false, true, false, false);
- if (S.token() == LBRACE) {
- body = block();
- }
- }
- }
- JCMethodDecl result =
- toP(F.at(pos).MethodDef(mods, name, type, typarams,
- params, thrown,
- body, defaultValue));
- attach(result, dc);
- return result;
- }
-
- /** QualidentList = Qualident {"," Qualident}
- */
- List<JCExpression> qualidentList() {
- ListBuffer<JCExpression> ts = new ListBuffer<JCExpression>();
- ts.append(qualident());
- while (S.token() == COMMA) {
- S.nextToken();
- ts.append(qualident());
- }
- return ts.toList();
- }
-
- /** TypeParametersOpt = ["<" TypeParameter {"," TypeParameter} ">"]
- */
- List<JCTypeParameter> typeParametersOpt() {
- if (S.token() == LT) {
- checkGenerics();
- ListBuffer<JCTypeParameter> typarams = new ListBuffer<JCTypeParameter>();
- S.nextToken();
- typarams.append(typeParameter());
- while (S.token() == COMMA) {
- S.nextToken();
- typarams.append(typeParameter());
- }
- accept(GT);
- return typarams.toList();
- } else {
- return List.nil();
- }
- }
-
- /** TypeParameter = TypeVariable [TypeParameterBound]
- * TypeParameterBound = EXTENDS Type {"&" Type}
- * TypeVariable = Ident
- */
- JCTypeParameter typeParameter() {
- int pos = S.pos();
- Name name = ident();
- ListBuffer<JCExpression> bounds = new ListBuffer<JCExpression>();
- if (S.token() == EXTENDS) {
- S.nextToken();
- bounds.append(type());
- while (S.token() == AMP) {
- S.nextToken();
- bounds.append(type());
- }
- }
- return toP(F.at(pos).TypeParameter(name, bounds.toList()));
- }
-
- /** FormalParameters = "(" [ FormalParameterList ] ")"
- * FormalParameterList = [ FormalParameterListNovarargs , ] LastFormalParameter
- * FormalParameterListNovarargs = [ FormalParameterListNovarargs , ] FormalParameter
- */
- List<JCVariableDecl> formalParameters() {
- ListBuffer<JCVariableDecl> params = new ListBuffer<JCVariableDecl>();
- JCVariableDecl lastParam = null;
- accept(LPAREN);
- if (S.token() != RPAREN) {
- params.append(lastParam = formalParameter());
- while ((lastParam.mods.flags & Flags.VARARGS) == 0 && S.token() == COMMA) {
- S.nextToken();
- params.append(lastParam = formalParameter());
- }
- }
- accept(RPAREN);
- return params.toList();
- }
-
- JCModifiers optFinal(long flags) {
- JCModifiers mods = modifiersOpt();
- checkNoMods(mods.flags & ~(Flags.FINAL | Flags.DEPRECATED));
- mods.flags |= flags;
- return mods;
- }
-
- /** FormalParameter = { FINAL | '@' Annotation } Type VariableDeclaratorId
- * LastFormalParameter = { FINAL | '@' Annotation } Type '...' Ident | FormalParameter
- */
- JCVariableDecl formalParameter() {
- JCModifiers mods = optFinal(Flags.PARAMETER);
- JCExpression type = type();
- if (S.token() == ELLIPSIS) {
- checkVarargs();
- mods.flags |= Flags.VARARGS;
- type = to(F.at(S.pos()).TypeArray(type));
- S.nextToken();
- }
- return variableDeclaratorId(mods, type);
- }
-
-/* ---------- auxiliary methods -------------- */
-
- /** Check that given tree is a legal expression statement.
- */
- protected JCExpression checkExprStat(JCExpression t) {
- switch(t.getTag()) {
- case JCTree.PREINC: case JCTree.PREDEC:
- case JCTree.POSTINC: case JCTree.POSTDEC:
- case JCTree.ASSIGN:
- case JCTree.BITOR_ASG: case JCTree.BITXOR_ASG: case JCTree.BITAND_ASG:
- case JCTree.SL_ASG: case JCTree.SR_ASG: case JCTree.USR_ASG:
- case JCTree.PLUS_ASG: case JCTree.MINUS_ASG:
- case JCTree.MUL_ASG: case JCTree.DIV_ASG: case JCTree.MOD_ASG:
- case JCTree.APPLY: case JCTree.NEWCLASS:
- case JCTree.ERRONEOUS:
- return t;
- default:
- log.error(t.pos, "not.stmt");
- return F.at(t.pos).Erroneous(List.<JCTree>of(t));
- }
- }
-
- /** Return precedence of operator represented by token,
- * -1 if token is not a binary operator. @see TreeInfo.opPrec
- */
- static int prec(Token token) {
- int oc = optag(token);
- return (oc >= 0) ? TreeInfo.opPrec(oc) : -1;
- }
-
- /** Return operation tag of binary operator represented by token,
- * -1 if token is not a binary operator.
- */
- static int optag(Token token) {
- switch (token) {
- case BARBAR:
- return JCTree.OR;
- case AMPAMP:
- return JCTree.AND;
- case BAR:
- return JCTree.BITOR;
- case BAREQ:
- return JCTree.BITOR_ASG;
- case CARET:
- return JCTree.BITXOR;
- case CARETEQ:
- return JCTree.BITXOR_ASG;
- case AMP:
- return JCTree.BITAND;
- case AMPEQ:
- return JCTree.BITAND_ASG;
- case EQEQ:
- return JCTree.EQ;
- case BANGEQ:
- return JCTree.NE;
- case LT:
- return JCTree.LT;
- case GT:
- return JCTree.GT;
- case LTEQ:
- return JCTree.LE;
- case GTEQ:
- return JCTree.GE;
- case LTLT:
- return JCTree.SL;
- case LTLTEQ:
- return JCTree.SL_ASG;
- case GTGT:
- return JCTree.SR;
- case GTGTEQ:
- return JCTree.SR_ASG;
- case GTGTGT:
- return JCTree.USR;
- case GTGTGTEQ:
- return JCTree.USR_ASG;
- case PLUS:
- return JCTree.PLUS;
- case PLUSEQ:
- return JCTree.PLUS_ASG;
- case SUB:
- return JCTree.MINUS;
- case SUBEQ:
- return JCTree.MINUS_ASG;
- case STAR:
- return JCTree.MUL;
- case STAREQ:
- return JCTree.MUL_ASG;
- case SLASH:
- return JCTree.DIV;
- case SLASHEQ:
- return JCTree.DIV_ASG;
- case PERCENT:
- return JCTree.MOD;
- case PERCENTEQ:
- return JCTree.MOD_ASG;
- case INSTANCEOF:
- return JCTree.TYPETEST;
- default:
- return -1;
- }
- }
-
- /** Return operation tag of unary operator represented by token,
- * -1 if token is not a binary operator.
- */
- static int unoptag(Token token) {
- switch (token) {
- case PLUS:
- return JCTree.POS;
- case SUB:
- return JCTree.NEG;
- case BANG:
- return JCTree.NOT;
- case TILDE:
- return JCTree.COMPL;
- case PLUSPLUS:
- return JCTree.PREINC;
- case SUBSUB:
- return JCTree.PREDEC;
- default:
- return -1;
- }
- }
-
- /** Return type tag of basic type represented by token,
- * -1 if token is not a basic type identifier.
- */
- static int typetag(Token token) {
- switch (token) {
- case BYTE:
- return TypeTags.BYTE;
- case CHAR:
- return TypeTags.CHAR;
- case SHORT:
- return TypeTags.SHORT;
- case INT:
- return TypeTags.INT;
- case LONG:
- return TypeTags.LONG;
- case FLOAT:
- return TypeTags.FLOAT;
- case DOUBLE:
- return TypeTags.DOUBLE;
- case BOOLEAN:
- return TypeTags.BOOLEAN;
- default:
- return -1;
- }
- }
-
- void checkGenerics() {
- if (!allowGenerics) {
- log.error(S.pos(), "generics.not.supported.in.source", source.name);
- allowGenerics = true;
- }
- }
- void checkVarargs() {
- if (!allowVarargs) {
- log.error(S.pos(), "varargs.not.supported.in.source", source.name);
- allowVarargs = true;
- }
- }
- void checkForeach() {
- if (!allowForeach) {
- log.error(S.pos(), "foreach.not.supported.in.source", source.name);
- allowForeach = true;
- }
- }
- void checkStaticImports() {
- if (!allowStaticImport) {
- log.error(S.pos(), "static.import.not.supported.in.source", source.name);
- allowStaticImport = true;
- }
- }
- void checkAnnotations() {
- if (!allowAnnotations) {
- log.error(S.pos(), "annotations.not.supported.in.source", source.name);
- allowAnnotations = true;
- }
- }
+ JCExpression parseType();
}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/src/share/classes/com/sun/tools/javac/parser/ParserFactory.java Fri Sep 12 23:32:51 2008 -0700
@@ -0,0 +1,79 @@
+/*
+ * Copyright 1999-2008 Sun Microsystems, Inc. All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+package com.sun.tools.javac.parser;
+
+import com.sun.tools.javac.code.Source;
+import com.sun.tools.javac.tree.TreeMaker;
+import com.sun.tools.javac.util.Context;
+import com.sun.tools.javac.util.Log;
+import com.sun.tools.javac.util.Name;
+import com.sun.tools.javac.util.Options;
+
+/**
+ * A factory for creating parsers.
+ */
+public class ParserFactory {
+
+ /** The context key for the parser factory. */
+ protected static final Context.Key<ParserFactory> parserFactoryKey = new Context.Key<ParserFactory>();
+
+ public static ParserFactory instance(Context context) {
+ ParserFactory instance = context.get(parserFactoryKey);
+ if (instance == null) {
+ instance = new ParserFactory(context);
+ }
+ return instance;
+ }
+
+ final TreeMaker F;
+ final Log log;
+ final Keywords keywords;
+ final Source source;
+ final Name.Table names;
+ final Options options;
+ final Scanner.Factory scannerFactory;
+
+ protected ParserFactory(Context context) {
+ super();
+ context.put(parserFactoryKey, this);
+ this.F = TreeMaker.instance(context);
+ this.log = Log.instance(context);
+ this.names = Name.Table.instance(context);
+ this.keywords = Keywords.instance(context);
+ this.source = Source.instance(context);
+ this.options = Options.instance(context);
+ this.scannerFactory = Scanner.Factory.instance(context);
+ }
+
+ public Parser newParser(CharSequence input, boolean keepDocComments, boolean keepEndPos, boolean keepLineMap) {
+ Lexer lexer = scannerFactory.newScanner(input);
+ if (keepEndPos) {
+ return new EndPosParser(this, lexer, keepDocComments, keepLineMap);
+ } else {
+ return new JavacParser(this, lexer, keepDocComments, keepLineMap);
+ }
+ }
+}
--- a/langtools/src/share/classes/javax/lang/model/type/ErrorType.java Wed Jul 05 16:41:36 2017 +0200
+++ b/langtools/src/share/classes/javax/lang/model/type/ErrorType.java Fri Sep 12 23:32:51 2008 -0700
@@ -25,10 +25,6 @@
package javax.lang.model.type;
-
-import javax.lang.model.element.TypeElement;
-
-
/**
* Represents a class or interface type that cannot be properly modeled.
* This may be the result of a processing error,
--- a/langtools/test/tools/javac/6304921/TestLog.java Wed Jul 05 16:41:36 2017 +0200
+++ b/langtools/test/tools/javac/6304921/TestLog.java Fri Sep 12 23:32:51 2008 -0700
@@ -34,6 +34,7 @@
import javax.tools.SimpleJavaFileObject;
import com.sun.tools.javac.file.JavacFileManager;
import com.sun.tools.javac.parser.Parser;
+import com.sun.tools.javac.parser.ParserFactory;
import com.sun.tools.javac.parser.Scanner;
import com.sun.tools.javac.tree.JCTree;
import com.sun.tools.javac.tree.TreeScanner;
@@ -60,7 +61,7 @@
JavacFileManager.preRegister(context);
Scanner.Factory sfac = Scanner.Factory.instance(context);
- Parser.Factory pfac = Parser.Factory.instance(context);
+ ParserFactory pfac = ParserFactory.instance(context);
final String text =
"public class Foo {\n"
@@ -74,9 +75,9 @@
JavaFileObject fo = new StringJavaFileObject("Foo", text);
log.useSource(fo);
- Scanner s = sfac.newScanner(fo.getCharContent(true));
- Parser parser = pfac.newParser(s, false, genEndPos);
- JCTree.JCCompilationUnit tree = parser.compilationUnit();
+ CharSequence cs = fo.getCharContent(true);
+ Parser parser = pfac.newParser(cs, false, genEndPos, false);
+ JCTree.JCCompilationUnit tree = parser.parseCompilationUnit();
log.setEndPosTable(fo, tree.endPositions);
TreeScanner ts = new LogTester(log, tree.endPositions);
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/api/6557752/T6557752.java Fri Sep 12 23:32:51 2008 -0700
@@ -0,0 +1,133 @@
+/*
+ * Copyright 2006 Sun Microsystems, Inc. All Rights Reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+
+/*
+ * @test
+ * @bug 6557752
+ * @summary Test for wrapping the original type in ErrorType.
+ * @library ../lib
+ * @compile T6557752.java
+ * @run main T6557752
+ */
+
+import com.sun.source.tree.AssignmentTree;
+import com.sun.source.tree.CompilationUnitTree;
+import com.sun.source.tree.MethodInvocationTree;
+import com.sun.source.util.JavacTask;
+import com.sun.source.util.TreePath;
+import com.sun.source.util.TreePathScanner;
+import com.sun.source.util.Trees;
+import com.sun.tools.javac.api.JavacTaskImpl;
+import com.sun.tools.javac.util.List;
+import java.io.IOException;
+import java.net.URI;
+import javax.lang.model.type.ErrorType;
+import javax.lang.model.type.TypeKind;
+import javax.lang.model.type.TypeMirror;
+import javax.tools.JavaCompiler;
+import javax.tools.JavaFileObject;
+import javax.tools.SimpleJavaFileObject;
+import javax.tools.ToolProvider;
+import javax.lang.model.util.Types;
+
+public class T6557752 {
+ static class MyFileObject extends SimpleJavaFileObject {
+ public MyFileObject() {
+ super(URI.create("myfo:/Test.java"), JavaFileObject.Kind.SOURCE);
+ }
+ public CharSequence getCharContent(boolean ignoreEncodingErrors) {
+ return "import java.util.*;\n"
+ + "public class Test {\n"
+ + " void foobar() {\n"
+ + " Iterator<Number> itr = null;\n"
+ + " String str = itr.next();\n"
+ + " FooBar fooBar = FooBar.foobar();\n"
+ + " }\n"
+ + "}";
+ }
+ }
+ static Trees trees;
+ static JavacTask task = null;
+ public static void main(String[] args) throws IOException {
+ JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
+ task = (JavacTask) compiler.getTask(null, null, null, null, null, List.of(new MyFileObject()));
+ Iterable<? extends CompilationUnitTree> asts = task.parse();
+ task.analyze();
+ trees = Trees.instance(task);
+ MyVisitor myVisitor = new MyVisitor();
+ for (CompilationUnitTree ast : asts) {
+ myVisitor.compilationUnit = ast;
+ myVisitor.scan(ast, null);
+ }
+
+ if (!myVisitor.foundError) {
+ throw new AssertionError("Expected error not found!");
+ }
+ }
+
+ static class MyVisitor extends TreePathScanner<Void,Void> {
+ public boolean foundError = false;
+ CompilationUnitTree compilationUnit = null;
+ int i = 0;
+ @Override
+ public Void visitMethodInvocation(MethodInvocationTree node, Void ignored) {
+ TreePath path = TreePath.getPath(compilationUnit, node);
+ TypeMirror typeMirror = trees.getTypeMirror(path);
+ if (typeMirror.getKind() == TypeKind.ERROR) {
+ if (i == 0) {
+ String str1 = trees.getOriginalType((ErrorType)typeMirror).toString();
+ if (!str1.equals("java.lang.Number")) {
+ throw new AssertionError("Trees.getOriginalType() error!");
+ }
+
+ Types types = task.getTypes();
+
+ str1 = types.asElement(trees.getOriginalType((ErrorType)typeMirror)).toString();
+ if (!str1.equals("java.lang.Number")) {
+ throw new AssertionError("Types.asElement() error!");
+ }
+
+ i++;
+ }
+ else if (i == 1) {
+ String str1 = trees.getOriginalType((ErrorType)typeMirror).toString();
+ if (!str1.equals("FooBar")) {
+ throw new AssertionError("Trees.getOriginalType() error!");
+ }
+
+ Types types = task.getTypes();
+
+ if (types.asElement(trees.getOriginalType((ErrorType)typeMirror)) != null) {
+ throw new AssertionError("Ttypes.asElement() error!");
+ }
+ foundError = true;
+ }
+ }
+
+
+ return null;
+ }
+
+ }
+}