langtools/src/share/classes/com/sun/tools/javac/parser/JavacParser.java
changeset 10815 a719aa5f1631
parent 10455 3d070be0fff8
child 10948 063463f6535f
--- a/langtools/src/share/classes/com/sun/tools/javac/parser/JavacParser.java	Fri Oct 21 14:14:29 2011 -0700
+++ b/langtools/src/share/classes/com/sun/tools/javac/parser/JavacParser.java	Mon Oct 24 13:00:20 2011 +0100
@@ -28,6 +28,7 @@
 import java.util.*;
 
 import com.sun.tools.javac.code.*;
+import com.sun.tools.javac.parser.Tokens.*;
 import com.sun.tools.javac.tree.*;
 import com.sun.tools.javac.tree.JCTree.*;
 import com.sun.tools.javac.util.*;
@@ -36,7 +37,7 @@
 import com.sun.tools.javac.util.List;
 
 import static com.sun.tools.javac.util.ListBuffer.lb;
-import static com.sun.tools.javac.parser.Token.*;
+import static com.sun.tools.javac.parser.Tokens.TokenKind.*;
 
 /** The parser maps a token sequence into an abstract syntax
  *  tree. It operates by recursive descent, with code derived
@@ -67,9 +68,6 @@
      */
     private Log log;
 
-    /** The keyword table. */
-    private Keywords keywords;
-
     /** The Source language setting. */
     private Source source;
 
@@ -83,11 +81,10 @@
                      boolean keepDocComments,
                      boolean keepLineMap) {
         this.S = S;
-        S.nextToken(); // prime the pump
+        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();
@@ -178,7 +175,16 @@
      */
     private int lastmode = 0;
 
-/* ---------- error recovery -------------- */
+    /* ---------- token management -------------- */
+
+    protected Token token;
+
+    protected void nextToken() {
+        S.nextToken();
+        token = S.token();
+    }
+
+    /* ---------- error recovery -------------- */
 
     private JCErroneous errorTree;
 
@@ -186,9 +192,9 @@
      */
     private void skip(boolean stopAtImport, boolean stopAtMemberDecl, boolean stopAtIdentifier, boolean stopAtStatement) {
          while (true) {
-             switch (S.token()) {
+             switch (token.kind) {
                 case SEMI:
-                    S.nextToken();
+                    nextToken();
                     return;
                 case PUBLIC:
                 case FINAL:
@@ -249,15 +255,15 @@
                         return;
                     break;
             }
-            S.nextToken();
+            nextToken();
         }
     }
 
-    private JCErroneous syntaxError(int pos, String key, Token... args) {
+    private JCErroneous syntaxError(int pos, String key, TokenKind... args) {
         return syntaxError(pos, List.<JCTree>nil(), key, args);
     }
 
-    private JCErroneous syntaxError(int pos, List<JCTree> errs, String key, Token... args) {
+    private JCErroneous syntaxError(int pos, List<JCTree> errs, String key, TokenKind... args) {
         setErrorEndPos(pos);
         JCErroneous err = F.at(pos).Erroneous(errs);
         reportSyntaxError(err, key, (Object[])args);
@@ -287,16 +293,16 @@
     private void reportSyntaxError(JCDiagnostic.DiagnosticPosition diagPos, String key, Object... args) {
         int pos = diagPos.getPreferredPosition();
         if (pos > S.errPos() || pos == Position.NOPOS) {
-            if (S.token() == EOF) {
+            if (token.kind == EOF) {
                 error(diagPos, "premature.eof");
             } else {
                 error(diagPos, key, args);
             }
         }
         S.errPos(pos);
-        if (S.pos() == errorPos)
-            S.nextToken(); // guarantee progress
-        errorPos = S.pos();
+        if (token.pos == errorPos)
+            nextToken(); // guarantee progress
+        errorPos = token.pos;
     }
 
 
@@ -304,25 +310,25 @@
      *  reported at the same position.
      */
     private JCErroneous syntaxError(String key) {
-        return syntaxError(S.pos(), key);
+        return syntaxError(token.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);
+    private JCErroneous syntaxError(String key, TokenKind arg) {
+        return syntaxError(token.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();
+    public void accept(TokenKind tk) {
+        if (token.kind == tk) {
+            nextToken();
         } else {
-            setErrorEndPos(S.pos());
-            reportSyntaxError(S.prevEndPos(), "expected", token);
+            setErrorEndPos(token.pos);
+            reportSyntaxError(S.prevToken().endPos, "expected", tk);
         }
     }
 
@@ -340,14 +346,14 @@
     /** Report an illegal start of expression/type error at current position.
      */
     JCExpression illegal() {
-        return illegal(S.pos());
+        return illegal(token.pos);
     }
 
     /** Diagnose a modifier flag from the set, if any. */
     void checkNoMods(long mods) {
         if (mods != 0) {
             long lowestMod = mods & -mods;
-            error(S.pos(), "mod.not.allowed.here",
+            error(token.pos, "mod.not.allowed.here",
                       Flags.asFlagSet(lowestMod));
         }
     }
@@ -435,30 +441,30 @@
      * Ident = IDENTIFIER
      */
     Name ident() {
-        if (S.token() == IDENTIFIER) {
-            Name name = S.name();
-            S.nextToken();
+        if (token.kind == IDENTIFIER) {
+            Name name = token.name();
+            nextToken();
             return name;
-        } else if (S.token() == ASSERT) {
+        } else if (token.kind == ASSERT) {
             if (allowAsserts) {
-                error(S.pos(), "assert.as.identifier");
-                S.nextToken();
+                error(token.pos, "assert.as.identifier");
+                nextToken();
                 return names.error;
             } else {
-                warning(S.pos(), "assert.as.identifier");
-                Name name = S.name();
-                S.nextToken();
+                warning(token.pos, "assert.as.identifier");
+                Name name = token.name();
+                nextToken();
                 return name;
             }
-        } else if (S.token() == ENUM) {
+        } else if (token.kind == ENUM) {
             if (allowEnums) {
-                error(S.pos(), "enum.as.identifier");
-                S.nextToken();
+                error(token.pos, "enum.as.identifier");
+                nextToken();
                 return names.error;
             } else {
-                warning(S.pos(), "enum.as.identifier");
-                Name name = S.name();
-                S.nextToken();
+                warning(token.pos, "enum.as.identifier");
+                Name name = token.name();
+                nextToken();
                 return name;
             }
         } else {
@@ -471,17 +477,17 @@
      * 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();
+        JCExpression t = toP(F.at(token.pos).Ident(ident()));
+        while (token.kind == DOT) {
+            int pos = token.pos;
+            nextToken();
             t = toP(F.at(pos).Select(t, ident()));
         }
         return t;
     }
 
     JCExpression literal(Name prefix) {
-        return literal(prefix, S.pos());
+        return literal(prefix, token.pos);
     }
 
     /**
@@ -498,27 +504,29 @@
      */
     JCExpression literal(Name prefix, int pos) {
         JCExpression t = errorTree;
-        switch (S.token()) {
+        switch (token.kind) {
         case INTLITERAL:
             try {
                 t = F.at(pos).Literal(
                     TypeTags.INT,
-                    Convert.string2int(strval(prefix), S.radix()));
+                    Convert.string2int(strval(prefix), token.radix()));
             } catch (NumberFormatException ex) {
-                error(S.pos(), "int.number.too.large", strval(prefix));
+                error(token.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())));
+                    new Long(Convert.string2long(strval(prefix), token.radix())));
             } catch (NumberFormatException ex) {
-                error(S.pos(), "int.number.too.large", strval(prefix));
+                error(token.pos, "int.number.too.large", strval(prefix));
             }
             break;
         case FLOATLITERAL: {
-            String proper = (S.radix() == 16 ? ("0x"+ S.stringVal()) : S.stringVal());
+            String proper = token.radix() == 16 ?
+                    ("0x"+ token.stringVal()) :
+                    token.stringVal();
             Float n;
             try {
                 n = Float.valueOf(proper);
@@ -527,15 +535,17 @@
                 n = Float.NaN;
             }
             if (n.floatValue() == 0.0f && !isZero(proper))
-                error(S.pos(), "fp.number.too.small");
+                error(token.pos, "fp.number.too.small");
             else if (n.floatValue() == Float.POSITIVE_INFINITY)
-                error(S.pos(), "fp.number.too.large");
+                error(token.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());
+            String proper = token.radix() == 16 ?
+                    ("0x"+ token.stringVal()) :
+                    token.stringVal();
             Double n;
             try {
                 n = Double.valueOf(proper);
@@ -544,9 +554,9 @@
                 n = Double.NaN;
             }
             if (n.doubleValue() == 0.0d && !isZero(proper))
-                error(S.pos(), "fp.number.too.small");
+                error(token.pos, "fp.number.too.small");
             else if (n.doubleValue() == Double.POSITIVE_INFINITY)
-                error(S.pos(), "fp.number.too.large");
+                error(token.pos, "fp.number.too.large");
             else
                 t = F.at(pos).Literal(TypeTags.DOUBLE, n);
             break;
@@ -554,17 +564,17 @@
         case CHARLITERAL:
             t = F.at(pos).Literal(
                 TypeTags.CHAR,
-                S.stringVal().charAt(0) + 0);
+                token.stringVal().charAt(0) + 0);
             break;
         case STRINGLITERAL:
             t = F.at(pos).Literal(
                 TypeTags.CLASS,
-                S.stringVal());
+                token.stringVal());
             break;
         case TRUE: case FALSE:
             t = F.at(pos).Literal(
                 TypeTags.BOOLEAN,
-                (S.token() == TRUE ? 1 : 0));
+                (token.kind == TRUE ? 1 : 0));
             break;
         case NULL:
             t = F.at(pos).Literal(
@@ -576,8 +586,8 @@
         }
         if (t == errorTree)
             t = F.at(pos).Erroneous();
-        storeEnd(t, S.endPos());
-        S.nextToken();
+        storeEnd(t, token.endPos);
+        nextToken();
         return t;
     }
 //where
@@ -590,7 +600,7 @@
         }
 
         String strval(Name prefix) {
-            String s = S.stringVal();
+            String s = token.stringVal();
             return prefix.isEmpty() ? s : prefix + s;
         }
 
@@ -627,17 +637,17 @@
     JCExpression term() {
         JCExpression t = term1();
         if ((mode & EXPR) != 0 &&
-            S.token() == EQ || PLUSEQ.compareTo(S.token()) <= 0 && S.token().compareTo(GTGTGTEQ) <= 0)
+            token.kind == EQ || PLUSEQ.compareTo(token.kind) <= 0 && token.kind.compareTo(GTGTGTEQ) <= 0)
             return termRest(t);
         else
             return t;
     }
 
     JCExpression termRest(JCExpression t) {
-        switch (S.token()) {
+        switch (token.kind) {
         case EQ: {
-            int pos = S.pos();
-            S.nextToken();
+            int pos = token.pos;
+            nextToken();
             mode = EXPR;
             JCExpression t1 = term();
             return toP(F.at(pos).Assign(t, t1));
@@ -653,12 +663,12 @@
         case LTLTEQ:
         case GTGTEQ:
         case GTGTGTEQ:
-            int pos = S.pos();
-            Token token = S.token();
-            S.nextToken();
+            int pos = token.pos;
+            TokenKind tk = token.kind;
+            nextToken();
             mode = EXPR;
             JCExpression t1 = term();
-            return F.at(pos).Assignop(optag(token), t, t1);
+            return F.at(pos).Assignop(optag(tk), t, t1);
         default:
             return t;
         }
@@ -670,7 +680,7 @@
      */
     JCExpression term1() {
         JCExpression t = term2();
-        if ((mode & EXPR) != 0 && S.token() == QUES) {
+        if ((mode & EXPR) != 0 && token.kind == QUES) {
             mode = EXPR;
             return term1Rest(t);
         } else {
@@ -681,9 +691,9 @@
     /** Expression1Rest = ["?" Expression ":" Expression1]
      */
     JCExpression term1Rest(JCExpression t) {
-        if (S.token() == QUES) {
-            int pos = S.pos();
-            S.nextToken();
+        if (token.kind == QUES) {
+            int pos = token.pos;
+            nextToken();
             JCExpression t1 = term();
             accept(COLON);
             JCExpression t2 = term1();
@@ -699,7 +709,7 @@
      */
     JCExpression term2() {
         JCExpression t = term3();
-        if ((mode & EXPR) != 0 && prec(S.token()) >= TreeInfo.orPrec) {
+        if ((mode & EXPR) != 0 && prec(token.kind) >= TreeInfo.orPrec) {
             mode = EXPR;
             return term2Rest(t, TreeInfo.orPrec);
         } else {
@@ -725,28 +735,23 @@
         JCExpression[] odStack = newOdStack();
         List<Token[]> savedOp = opStackSupply.elems;
         Token[] opStack = newOpStack();
-        List<int[]> savedPos = posStackSupply.elems;
-        int[] posStack = newPosStack();
+
         // optimization, was odStack = new Tree[...]; opStack = new Tree[...];
         int top = 0;
         odStack[0] = t;
-        int startPos = S.pos();
-        Token topOp = ERROR;
-        int topOpPos = Position.NOPOS;
-        while (prec(S.token()) >= minprec) {
-            posStack[top] = topOpPos;
+        int startPos = token.pos;
+        Token topOp = Tokens.DUMMY;
+        while (prec(token.kind) >= minprec) {
             opStack[top] = topOp;
             top++;
-            topOp = S.token();
-            topOpPos = S.pos();
-            S.nextToken();
-            odStack[top] = (topOp == INSTANCEOF) ? parseType() : term3();
-            while (top > 0 && prec(topOp) >= prec(S.token())) {
-                odStack[top-1] = makeOp(topOpPos, topOp, odStack[top-1],
+            topOp = token;
+            nextToken();
+            odStack[top] = (topOp.kind == INSTANCEOF) ? parseType() : term3();
+            while (top > 0 && prec(topOp.kind) >= prec(token.kind)) {
+                odStack[top-1] = makeOp(topOp.pos, topOp.kind, odStack[top-1],
                                         odStack[top]);
                 top--;
                 topOp = opStack[top];
-                topOpPos = posStack[top];
             }
         }
         Assert.check(top == 0);
@@ -761,14 +766,13 @@
 
         odStackSupply.elems = savedOd; // optimization
         opStackSupply.elems = savedOp; // optimization
-        posStackSupply.elems = savedPos; // optimization
         return t;
     }
 //where
         /** Construct a binary or type test node.
          */
         private JCExpression makeOp(int pos,
-                                    Token topOp,
+                                    TokenKind topOp,
                                     JCExpression od1,
                                     JCExpression od2)
         {
@@ -817,7 +821,6 @@
          */
         ListBuffer<JCExpression[]> odStackSupply = new ListBuffer<JCExpression[]>();
         ListBuffer<Token[]> opStackSupply = new ListBuffer<Token[]>();
-        ListBuffer<int[]> posStackSupply = new ListBuffer<int[]>();
 
         private JCExpression[] newOdStack() {
             if (odStackSupply.elems == odStackSupply.last)
@@ -835,14 +838,6 @@
             return opStack;
         }
 
-        private int[] newPosStack() {
-            if (posStackSupply.elems == posStackSupply.last)
-                posStackSupply.append(new int[infixPrecedenceLevels + 1]);
-            int[] posStack = posStackSupply.elems.head;
-            posStackSupply.elems = posStackSupply.elems.tail;
-            return posStack;
-        }
-
     /** Expression3    = PrefixOp Expression3
      *                 | "(" Expr | TypeNoParams ")" Expression3
      *                 | Primary {Selector} {PostfixOp}
@@ -871,10 +866,10 @@
      *  SuperSuffix    = Arguments | "." Ident [Arguments]
      */
     protected JCExpression term3() {
-        int pos = S.pos();
+        int pos = token.pos;
         JCExpression t;
         List<JCExpression> typeArgs = typeArgumentsOpt(EXPR);
-        switch (S.token()) {
+        switch (token.kind) {
         case QUES:
             if ((mode & TYPE) != 0 && (mode & (TYPEARG|NOPARAMS)) == TYPEARG) {
                 mode = TYPE;
@@ -883,49 +878,49 @@
                 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();
+                TokenKind tk = token.kind;
+                nextToken();
                 mode = EXPR;
-                if (token == SUB &&
-                    (S.token() == INTLITERAL || S.token() == LONGLITERAL) &&
-                    S.radix() == 10) {
+                if (tk == SUB &&
+                    (token.kind == INTLITERAL || token.kind == LONGLITERAL) &&
+                    token.radix() == 10) {
                     mode = EXPR;
                     t = literal(names.hyphen, pos);
                 } else {
                     t = term3();
-                    return F.at(pos).Unary(unoptag(token), t);
+                    return F.at(pos).Unary(unoptag(tk), t);
                 }
             } else return illegal();
             break;
         case LPAREN:
             if (typeArgs == null && (mode & EXPR) != 0) {
-                S.nextToken();
+                nextToken();
                 mode = EXPR | TYPE | NOPARAMS;
                 t = term3();
-                if ((mode & TYPE) != 0 && S.token() == LT) {
+                if ((mode & TYPE) != 0 && token.kind == LT) {
                     // Could be a cast to a parameterized type
                     int op = JCTree.LT;
-                    int pos1 = S.pos();
-                    S.nextToken();
+                    int pos1 = token.pos;
+                    nextToken();
                     mode &= (EXPR | TYPE);
                     mode |= TYPEARG;
                     JCExpression t1 = term3();
                     if ((mode & TYPE) != 0 &&
-                        (S.token() == COMMA || S.token() == GT)) {
+                        (token.kind == COMMA || token.kind == GT)) {
                         mode = TYPE;
                         ListBuffer<JCExpression> args = new ListBuffer<JCExpression>();
                         args.append(t1);
-                        while (S.token() == COMMA) {
-                            S.nextToken();
+                        while (token.kind == COMMA) {
+                            nextToken();
                             args.append(typeArgument());
                         }
                         accept(GT);
                         t = toP(F.at(pos1).TypeApply(t, args.toList()));
                         checkGenerics();
-                        while (S.token() == DOT) {
-                            S.nextToken();
+                        while (token.kind == DOT) {
+                            nextToken();
                             mode = TYPE;
-                            t = toP(F.at(S.pos()).Select(t, ident()));
+                            t = toP(F.at(token.pos).Select(t, ident()));
                             t = typeArgumentsOpt(t);
                         }
                         t = bracketsOpt(toP(t));
@@ -948,7 +943,7 @@
                     JCExpression t1 = term3();
                     return F.at(pos).TypeCast(t, t1);
                 } else if ((lastmode & TYPE) != 0) {
-                    switch (S.token()) {
+                    switch (token.kind) {
                     /*case PLUSPLUS: case SUBSUB: */
                     case BANG: case TILDE:
                     case LPAREN: case THIS: case SUPER:
@@ -969,7 +964,7 @@
             if ((mode & EXPR) != 0) {
                 mode = EXPR;
                 t = to(F.at(pos).Ident(names._this));
-                S.nextToken();
+                nextToken();
                 if (typeArgs == null)
                     t = argumentsOpt(null, t);
                 else
@@ -997,22 +992,22 @@
             if (typeArgs != null) return illegal();
             if ((mode & EXPR) != 0) {
                 mode = EXPR;
-                S.nextToken();
-                if (S.token() == LT) typeArgs = typeArguments(false);
+                nextToken();
+                if (token.kind == LT) typeArgs = typeArguments(false);
                 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()));
+            t = toP(F.at(token.pos).Ident(ident()));
             loop: while (true) {
-                pos = S.pos();
-                switch (S.token()) {
+                pos = token.pos;
+                switch (token.kind) {
                 case LBRACKET:
-                    S.nextToken();
-                    if (S.token() == RBRACKET) {
-                        S.nextToken();
+                    nextToken();
+                    if (token.kind == RBRACKET) {
+                        nextToken();
                         t = bracketsOpt(t);
                         t = toP(F.at(pos).TypeArray(t));
                         t = bracketsSuffix(t);
@@ -1033,24 +1028,24 @@
                     }
                     break loop;
                 case DOT:
-                    S.nextToken();
+                    nextToken();
                     int oldmode = mode;
                     mode &= ~NOPARAMS;
                     typeArgs = typeArgumentsOpt(EXPR);
                     mode = oldmode;
                     if ((mode & EXPR) != 0) {
-                        switch (S.token()) {
+                        switch (token.kind) {
                         case CLASS:
                             if (typeArgs != null) return illegal();
                             mode = EXPR;
                             t = to(F.at(pos).Select(t, names._class));
-                            S.nextToken();
+                            nextToken();
                             break loop;
                         case THIS:
                             if (typeArgs != null) return illegal();
                             mode = EXPR;
                             t = to(F.at(pos).Select(t, names._this));
-                            S.nextToken();
+                            nextToken();
                             break loop;
                         case SUPER:
                             mode = EXPR;
@@ -1061,9 +1056,9 @@
                         case NEW:
                             if (typeArgs != null) return illegal();
                             mode = EXPR;
-                            int pos1 = S.pos();
-                            S.nextToken();
-                            if (S.token() == LT) typeArgs = typeArguments(false);
+                            int pos1 = token.pos;
+                            nextToken();
+                            if (token.kind == LT) typeArgs = typeArguments(false);
                             t = innerCreator(pos1, typeArgs, t);
                             typeArgs = null;
                             break loop;
@@ -1087,8 +1082,8 @@
         case VOID:
             if (typeArgs != null) illegal();
             if ((mode & EXPR) != 0) {
-                S.nextToken();
-                if (S.token() == DOT) {
+                nextToken();
+                if (token.kind == DOT) {
                     JCPrimitiveTypeTree ti = toP(F.at(pos).TypeIdent(TypeTags.VOID));
                     t = bracketsSuffix(ti);
                 } else {
@@ -1099,7 +1094,7 @@
                 // a void type (like other primitive types) to the next phase.
                 // The error will be reported in Attr.attribTypes or Attr.visitApply.
                 JCPrimitiveTypeTree ti = to(F.at(pos).TypeIdent(TypeTags.VOID));
-                S.nextToken();
+                nextToken();
                 return ti;
                 //return illegal();
             }
@@ -1109,14 +1104,14 @@
         }
         if (typeArgs != null) illegal();
         while (true) {
-            int pos1 = S.pos();
-            if (S.token() == LBRACKET) {
-                S.nextToken();
+            int pos1 = token.pos;
+            if (token.kind == LBRACKET) {
+                nextToken();
                 if ((mode & TYPE) != 0) {
                     int oldmode = mode;
                     mode = TYPE;
-                    if (S.token() == RBRACKET) {
-                        S.nextToken();
+                    if (token.kind == RBRACKET) {
+                        nextToken();
                         t = bracketsOpt(t);
                         t = toP(F.at(pos1).TypeArray(t));
                         return t;
@@ -1129,21 +1124,21 @@
                     t = to(F.at(pos1).Indexed(t, t1));
                 }
                 accept(RBRACKET);
-            } else if (S.token() == DOT) {
-                S.nextToken();
+            } else if (token.kind == DOT) {
+                nextToken();
                 typeArgs = typeArgumentsOpt(EXPR);
-                if (S.token() == SUPER && (mode & EXPR) != 0) {
+                if (token.kind == SUPER && (mode & EXPR) != 0) {
                     mode = EXPR;
                     t = to(F.at(pos1).Select(t, names._super));
-                    S.nextToken();
+                    nextToken();
                     t = arguments(typeArgs, t);
                     typeArgs = null;
-                } else if (S.token() == NEW && (mode & EXPR) != 0) {
+                } else if (token.kind == NEW && (mode & EXPR) != 0) {
                     if (typeArgs != null) return illegal();
                     mode = EXPR;
-                    int pos2 = S.pos();
-                    S.nextToken();
-                    if (S.token() == LT) typeArgs = typeArguments(false);
+                    int pos2 = token.pos;
+                    nextToken();
+                    if (token.kind == LT) typeArgs = typeArguments(false);
                     t = innerCreator(pos2, typeArgs, t);
                     typeArgs = null;
                 } else {
@@ -1155,11 +1150,11 @@
                 break;
             }
         }
-        while ((S.token() == PLUSPLUS || S.token() == SUBSUB) && (mode & EXPR) != 0) {
+        while ((token.kind == PLUSPLUS || token.kind == SUBSUB) && (mode & EXPR) != 0) {
             mode = EXPR;
-            t = to(F.at(S.pos()).Unary(
-                  S.token() == PLUSPLUS ? JCTree.POSTINC : JCTree.POSTDEC, t));
-            S.nextToken();
+            t = to(F.at(token.pos).Unary(
+                  token.kind == PLUSPLUS ? JCTree.POSTINC : JCTree.POSTDEC, t));
+            nextToken();
         }
         return toP(t);
     }
@@ -1167,13 +1162,13 @@
     /** SuperSuffix = Arguments | "." [TypeArguments] Ident [Arguments]
      */
     JCExpression superSuffix(List<JCExpression> typeArgs, JCExpression t) {
-        S.nextToken();
-        if (S.token() == LPAREN || typeArgs != null) {
+        nextToken();
+        if (token.kind == LPAREN || typeArgs != null) {
             t = arguments(typeArgs, t);
         } else {
-            int pos = S.pos();
+            int pos = token.pos;
             accept(DOT);
-            typeArgs = (S.token() == LT) ? typeArguments(false) : null;
+            typeArgs = (token.kind == LT) ? typeArguments(false) : null;
             t = toP(F.at(pos).Select(t, ident()));
             t = argumentsOpt(typeArgs, t);
         }
@@ -1183,15 +1178,15 @@
     /** BasicType = BYTE | SHORT | CHAR | INT | LONG | FLOAT | DOUBLE | BOOLEAN
      */
     JCPrimitiveTypeTree basicType() {
-        JCPrimitiveTypeTree t = to(F.at(S.pos()).TypeIdent(typetag(S.token())));
-        S.nextToken();
+        JCPrimitiveTypeTree t = to(F.at(token.pos).TypeIdent(typetag(token.kind)));
+        nextToken();
         return t;
     }
 
     /** ArgumentsOpt = [ Arguments ]
      */
     JCExpression argumentsOpt(List<JCExpression> typeArgs, JCExpression t) {
-        if ((mode & EXPR) != 0 && S.token() == LPAREN || typeArgs != null) {
+        if ((mode & EXPR) != 0 && token.kind == LPAREN || typeArgs != null) {
             mode = EXPR;
             return arguments(typeArgs, t);
         } else {
@@ -1203,24 +1198,24 @@
      */
     List<JCExpression> arguments() {
         ListBuffer<JCExpression> args = lb();
-        if (S.token() == LPAREN) {
-            S.nextToken();
-            if (S.token() != RPAREN) {
+        if (token.kind == LPAREN) {
+            nextToken();
+            if (token.kind != RPAREN) {
                 args.append(parseExpression());
-                while (S.token() == COMMA) {
-                    S.nextToken();
+                while (token.kind == COMMA) {
+                    nextToken();
                     args.append(parseExpression());
                 }
             }
             accept(RPAREN);
         } else {
-            syntaxError(S.pos(), "expected", LPAREN);
+            syntaxError(token.pos, "expected", LPAREN);
         }
         return args.toList();
     }
 
     JCMethodInvocation arguments(List<JCExpression> typeArgs, JCExpression t) {
-        int pos = S.pos();
+        int pos = token.pos;
         List<JCExpression> args = arguments();
         return toP(F.at(pos).Apply(typeArgs, t, args));
     }
@@ -1228,7 +1223,7 @@
     /**  TypeArgumentsOpt = [ TypeArguments ]
      */
     JCExpression typeArgumentsOpt(JCExpression t) {
-        if (S.token() == LT &&
+        if (token.kind == LT &&
             (mode & TYPE) != 0 &&
             (mode & NOPARAMS) == 0) {
             mode = TYPE;
@@ -1243,7 +1238,7 @@
     }
 
     List<JCExpression> typeArgumentsOpt(int useMode) {
-        if (S.token() == LT) {
+        if (token.kind == LT) {
             checkGenerics();
             if ((mode & useMode) == 0 ||
                 (mode & NOPARAMS) != 0) {
@@ -1258,47 +1253,37 @@
     /**  TypeArguments  = "<" TypeArgument {"," TypeArgument} ">"
      */
     List<JCExpression> typeArguments(boolean diamondAllowed) {
-        if (S.token() == LT) {
-            S.nextToken();
-            if (S.token() == GT && diamondAllowed) {
+        if (token.kind == LT) {
+            nextToken();
+            if (token.kind == GT && diamondAllowed) {
                 checkDiamond();
                 mode |= DIAMOND;
-                S.nextToken();
+                nextToken();
                 return List.nil();
             } else {
                 ListBuffer<JCExpression> args = ListBuffer.lb();
                 args.append(((mode & EXPR) == 0) ? typeArgument() : parseType());
-                while (S.token() == COMMA) {
-                    S.nextToken();
+                while (token.kind == COMMA) {
+                    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);
+                switch (token.kind) {
+
+                case GTGTGTEQ: case GTGTEQ: case GTEQ:
+                case GTGTGT: case GTGT:
+                    token = S.split();
                     break;
                 case GT:
-                    S.nextToken();
+                    nextToken();
                     break;
                 default:
-                    args.append(syntaxError(S.pos(), "expected", GT));
+                    args.append(syntaxError(token.pos, "expected", GT));
                     break;
                 }
                 return args.toList();
             }
         } else {
-            return List.<JCExpression>of(syntaxError(S.pos(), "expected", LT));
+            return List.<JCExpression>of(syntaxError(token.pos, "expected", LT));
         }
     }
 
@@ -1308,24 +1293,24 @@
      *               | "?" SUPER Type
      */
     JCExpression typeArgument() {
-        if (S.token() != QUES) return parseType();
-        int pos = S.pos();
-        S.nextToken();
-        if (S.token() == EXTENDS) {
+        if (token.kind != QUES) return parseType();
+        int pos = token.pos;
+        nextToken();
+        if (token.kind == EXTENDS) {
             TypeBoundKind t = to(F.at(pos).TypeBoundKind(BoundKind.EXTENDS));
-            S.nextToken();
+            nextToken();
             JCExpression bound = parseType();
             return F.at(pos).Wildcard(t, bound);
-        } else if (S.token() == SUPER) {
+        } else if (token.kind == SUPER) {
             TypeBoundKind t = to(F.at(pos).TypeBoundKind(BoundKind.SUPER));
-            S.nextToken();
+            nextToken();
             JCExpression bound = parseType();
             return F.at(pos).Wildcard(t, bound);
-        } else if (S.token() == IDENTIFIER) {
+        } else if (token.kind == IDENTIFIER) {
             //error recovery
             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()));
+            JCIdent id = toP(F.at(token.pos).Ident(ident()));
             JCErroneous err = F.at(pos).Erroneous(List.<JCTree>of(wc, id));
             reportSyntaxError(err, "expected3", GT, EXTENDS, SUPER);
             return err;
@@ -1336,7 +1321,7 @@
     }
 
     JCTypeApply typeArguments(JCExpression t, boolean diamondAllowed) {
-        int pos = S.pos();
+        int pos = token.pos;
         List<JCExpression> args = typeArguments(diamondAllowed);
         return toP(F.at(pos).TypeApply(t, args));
     }
@@ -1344,9 +1329,9 @@
     /** BracketsOpt = {"[" "]"}
      */
     private JCExpression bracketsOpt(JCExpression t) {
-        if (S.token() == LBRACKET) {
-            int pos = S.pos();
-            S.nextToken();
+        if (token.kind == LBRACKET) {
+            int pos = token.pos;
+            nextToken();
             t = bracketsOptCont(t, pos);
             F.at(pos);
         }
@@ -1363,17 +1348,17 @@
      *  BracketsSuffixType =
      */
     JCExpression bracketsSuffix(JCExpression t) {
-        if ((mode & EXPR) != 0 && S.token() == DOT) {
+        if ((mode & EXPR) != 0 && token.kind == DOT) {
             mode = EXPR;
-            int pos = S.pos();
-            S.nextToken();
+            int pos = token.pos;
+            nextToken();
             accept(CLASS);
-            if (S.pos() == errorEndPos) {
+            if (token.pos == errorEndPos) {
                 // error recovery
                 Name name = null;
-                if (S.token() == IDENTIFIER) {
-                    name = S.name();
-                    S.nextToken();
+                if (token.kind == IDENTIFIER) {
+                    name = token.name();
+                    nextToken();
                 } else {
                     name = names.error;
                 }
@@ -1384,7 +1369,7 @@
         } else if ((mode & TYPE) != 0) {
             mode = TYPE;
         } else {
-            syntaxError(S.pos(), "dot.class.expected");
+            syntaxError(token.pos, "dot.class.expected");
         }
         return t;
     }
@@ -1392,7 +1377,7 @@
     /** Creator = Qualident [TypeArguments] ( ArrayCreatorRest | ClassCreatorRest )
      */
     JCExpression creator(int newpos, List<JCExpression> typeArgs) {
-        switch (S.token()) {
+        switch (token.kind) {
         case BYTE: case SHORT: case CHAR: case INT: case LONG: case FLOAT:
         case DOUBLE: case BOOLEAN:
             if (typeArgs == null)
@@ -1405,29 +1390,29 @@
         mode = TYPE;
         boolean diamondFound = false;
         int lastTypeargsPos = -1;
-        if (S.token() == LT) {
+        if (token.kind == LT) {
             checkGenerics();
-            lastTypeargsPos = S.pos();
+            lastTypeargsPos = token.pos;
             t = typeArguments(t, true);
             diamondFound = (mode & DIAMOND) != 0;
         }
-        while (S.token() == DOT) {
+        while (token.kind == DOT) {
             if (diamondFound) {
                 //cannot select after a diamond
                 illegal();
             }
-            int pos = S.pos();
-            S.nextToken();
+            int pos = token.pos;
+            nextToken();
             t = toP(F.at(pos).Select(t, ident()));
-            if (S.token() == LT) {
-                lastTypeargsPos = S.pos();
+            if (token.kind == LT) {
+                lastTypeargsPos = token.pos;
                 checkGenerics();
                 t = typeArguments(t, true);
                 diamondFound = (mode & DIAMOND) != 0;
             }
         }
         mode = oldmode;
-        if (S.token() == LBRACKET) {
+        if (token.kind == LBRACKET) {
             JCExpression e = arrayCreatorRest(newpos, t);
             if (diamondFound) {
                 reportSyntaxError(lastTypeargsPos, "cannot.create.array.with.diamond");
@@ -1441,17 +1426,17 @@
                     // modified to improve error recovery.
                     pos = typeArgs.head.pos;
                 }
-                setErrorEndPos(S.prevEndPos());
+                setErrorEndPos(S.prevToken().endPos);
                 JCErroneous err = F.at(pos).Erroneous(typeArgs.prepend(e));
                 reportSyntaxError(err, "cannot.create.array.with.type.arguments");
                 return toP(err);
             }
             return e;
-        } else if (S.token() == LPAREN) {
+        } else if (token.kind == LPAREN) {
             return classCreatorRest(newpos, null, typeArgs, t);
         } else {
-            setErrorEndPos(S.pos());
-            reportSyntaxError(S.pos(), "expected2", LPAREN, LBRACKET);
+            setErrorEndPos(token.pos);
+            reportSyntaxError(token.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)));
         }
@@ -1460,8 +1445,8 @@
     /** 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) {
+        JCExpression t = toP(F.at(token.pos).Ident(ident()));
+        if (token.kind == LT) {
             int oldmode = mode;
             checkGenerics();
             t = typeArguments(t, true);
@@ -1475,23 +1460,23 @@
      */
     JCExpression arrayCreatorRest(int newpos, JCExpression elemtype) {
         accept(LBRACKET);
-        if (S.token() == RBRACKET) {
+        if (token.kind == RBRACKET) {
             accept(RBRACKET);
             elemtype = bracketsOpt(elemtype);
-            if (S.token() == LBRACE) {
+            if (token.kind == LBRACE) {
                 return arrayInitializer(newpos, elemtype);
             } else {
                 JCExpression t = toP(F.at(newpos).NewArray(elemtype, List.<JCExpression>nil(), null));
-                return syntaxError(S.pos(), List.<JCTree>of(t), "array.dimension.missing");
+                return syntaxError(token.pos, List.<JCTree>of(t), "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) {
+            while (token.kind == LBRACKET) {
+                int pos = token.pos;
+                nextToken();
+                if (token.kind == RBRACKET) {
                     elemtype = bracketsOptCont(elemtype, pos);
                 } else {
                     dims.append(parseExpression());
@@ -1511,8 +1496,8 @@
     {
         List<JCExpression> args = arguments();
         JCClassDecl body = null;
-        if (S.token() == LBRACE) {
-            int pos = S.pos();
+        if (token.kind == LBRACE) {
+            int pos = token.pos;
             List<JCTree> defs = classOrInterfaceBody(names.empty, false);
             JCModifiers mods = F.at(Position.NOPOS).Modifiers(0);
             body = toP(F.at(pos).AnonymousClassDef(mods, defs));
@@ -1525,13 +1510,13 @@
     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) {
+        if (token.kind == COMMA) {
+            nextToken();
+        } else if (token.kind != RBRACE) {
             elems.append(variableInitializer());
-            while (S.token() == COMMA) {
-                S.nextToken();
-                if (S.token() == RBRACE) break;
+            while (token.kind == COMMA) {
+                nextToken();
+                if (token.kind == RBRACE) break;
                 elems.append(variableInitializer());
             }
         }
@@ -1542,7 +1527,7 @@
     /** VariableInitializer = ArrayInitializer | Expression
      */
     public JCExpression variableInitializer() {
-        return S.token() == LBRACE ? arrayInitializer(S.pos(), null) : parseExpression();
+        return token.kind == LBRACE ? arrayInitializer(token.pos, null) : parseExpression();
     }
 
     /** ParExpression = "(" Expression ")"
@@ -1560,19 +1545,19 @@
         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());
+        while (token.kind == CASE || token.kind == DEFAULT) {
+            syntaxError("orphaned", token.kind);
             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();
+        t.endpos = token.pos;
         accept(RBRACE);
         return toP(t);
     }
 
     public JCBlock block() {
-        return block(S.pos(), 0);
+        return block(token.pos, 0);
     }
 
     /** BlockStatements = { BlockStatement }
@@ -1588,8 +1573,8 @@
         int lastErrPos = -1;
         ListBuffer<JCStatement> stats = new ListBuffer<JCStatement>();
         while (true) {
-            int pos = S.pos();
-            switch (S.token()) {
+            int pos = token.pos;
+            switch (token.kind) {
             case RBRACE: case CASE: case DEFAULT: case EOF:
                 return stats.toList();
             case LBRACE: case IF: case FOR: case WHILE: case DO: case TRY:
@@ -1599,64 +1584,63 @@
                 break;
             case MONKEYS_AT:
             case FINAL: {
-                String dc = S.docComment();
+                String dc = token.docComment;
                 JCModifiers mods = modifiersOpt();
-                if (S.token() == INTERFACE ||
-                    S.token() == CLASS ||
-                    allowEnums && S.token() == ENUM) {
+                if (token.kind == INTERFACE ||
+                    token.kind == CLASS ||
+                    allowEnums && token.kind == 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());
+                    storeEnd(stats.elems.last(), token.endPos);
                     accept(SEMI);
                 }
                 break;
             }
             case ABSTRACT: case STRICTFP: {
-                String dc = S.docComment();
+                String dc = token.docComment;
                 JCModifiers mods = modifiersOpt();
                 stats.append(classOrInterfaceOrEnumDeclaration(mods, dc));
                 break;
             }
             case INTERFACE:
             case CLASS:
-                stats.append(classOrInterfaceOrEnumDeclaration(modifiersOpt(),
-                                                               S.docComment()));
+                String dc = token.docComment;
+                stats.append(classOrInterfaceOrEnumDeclaration(modifiersOpt(), dc));
                 break;
             case ENUM:
             case ASSERT:
-                if (allowEnums && S.token() == ENUM) {
-                    error(S.pos(), "local.enum");
-                    stats.
-                        append(classOrInterfaceOrEnumDeclaration(modifiersOpt(),
-                                                                 S.docComment()));
+                if (allowEnums && token.kind == ENUM) {
+                    error(token.pos, "local.enum");
+                    dc = token.docComment;
+                    stats.append(classOrInterfaceOrEnumDeclaration(modifiersOpt(), dc));
                     break;
-                } else if (allowAsserts && S.token() == ASSERT) {
+                } else if (allowAsserts && token.kind == ASSERT) {
                     stats.append(parseStatement());
                     break;
                 }
                 /* fall through to default */
             default:
-                Name name = S.name();
+                Token prevToken = token;
                 JCExpression t = term(EXPR | TYPE);
-                if (S.token() == COLON && t.getTag() == JCTree.IDENT) {
-                    S.nextToken();
+                if (token.kind == COLON && t.getTag() == JCTree.IDENT) {
+                    nextToken();
                     JCStatement stat = parseStatement();
-                    stats.append(F.at(pos).Labelled(name, stat));
+                    stats.append(F.at(pos).Labelled(prevToken.name(), stat));
                 } else if ((lastmode & TYPE) != 0 &&
-                           (S.token() == IDENTIFIER ||
-                            S.token() == ASSERT ||
-                            S.token() == ENUM)) {
-                    pos = S.pos();
+                           (token.kind == IDENTIFIER ||
+                            token.kind == ASSERT ||
+                            token.kind == ENUM)) {
+                    pos = token.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());
+                    storeEnd(stats.elems.last(), token.endPos);
                     accept(SEMI);
                 } else {
                     // This Exec is an "ExpressionStatement"; it subsumes the terminating semicolon
@@ -1666,15 +1650,12 @@
             }
 
             // error recovery
-            if (S.pos() == lastErrPos)
+            if (token.pos == lastErrPos)
                 return stats.toList();
-            if (S.pos() <= errorEndPos) {
+            if (token.pos <= errorEndPos) {
                 skip(false, true, true, true);
-                lastErrPos = S.pos();
+                lastErrPos = token.pos;
             }
-
-            // ensure no dangling /** @deprecated */ active
-            S.resetDeprecatedFlag();
         }
     }
 
@@ -1700,29 +1681,29 @@
      */
     @SuppressWarnings("fallthrough")
     public JCStatement parseStatement() {
-        int pos = S.pos();
-        switch (S.token()) {
+        int pos = token.pos;
+        switch (token.kind) {
         case LBRACE:
             return block();
         case IF: {
-            S.nextToken();
+            nextToken();
             JCExpression cond = parExpression();
             JCStatement thenpart = parseStatement();
             JCStatement elsepart = null;
-            if (S.token() == ELSE) {
-                S.nextToken();
+            if (token.kind == ELSE) {
+                nextToken();
                 elsepart = parseStatement();
             }
             return F.at(pos).If(cond, thenpart, elsepart);
         }
         case FOR: {
-            S.nextToken();
+            nextToken();
             accept(LPAREN);
-            List<JCStatement> inits = S.token() == SEMI ? List.<JCStatement>nil() : forInit();
+            List<JCStatement> inits = token.kind == SEMI ? List.<JCStatement>nil() : forInit();
             if (inits.length() == 1 &&
                 inits.head.getTag() == JCTree.VARDEF &&
                 ((JCVariableDecl) inits.head).init == null &&
-                S.token() == COLON) {
+                token.kind == COLON) {
                 checkForeach();
                 JCVariableDecl var = (JCVariableDecl)inits.head;
                 accept(COLON);
@@ -1732,22 +1713,22 @@
                 return F.at(pos).ForeachLoop(var, expr, body);
             } else {
                 accept(SEMI);
-                JCExpression cond = S.token() == SEMI ? null : parseExpression();
+                JCExpression cond = token.kind == SEMI ? null : parseExpression();
                 accept(SEMI);
-                List<JCExpressionStatement> steps = S.token() == RPAREN ? List.<JCExpressionStatement>nil() : forUpdate();
+                List<JCExpressionStatement> steps = token.kind == RPAREN ? List.<JCExpressionStatement>nil() : forUpdate();
                 accept(RPAREN);
                 JCStatement body = parseStatement();
                 return F.at(pos).ForLoop(inits, cond, steps, body);
             }
         }
         case WHILE: {
-            S.nextToken();
+            nextToken();
             JCExpression cond = parExpression();
             JCStatement body = parseStatement();
             return F.at(pos).WhileLoop(cond, body);
         }
         case DO: {
-            S.nextToken();
+            nextToken();
             JCStatement body = parseStatement();
             accept(WHILE);
             JCExpression cond = parExpression();
@@ -1756,21 +1737,21 @@
             return t;
         }
         case TRY: {
-            S.nextToken();
+            nextToken();
             List<JCTree> resources = List.<JCTree>nil();
-            if (S.token() == LPAREN) {
+            if (token.kind == LPAREN) {
                 checkTryWithResources();
-                S.nextToken();
+                nextToken();
                 resources = resources();
                 accept(RPAREN);
             }
             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();
+            if (token.kind == CATCH || token.kind == FINALLY) {
+                while (token.kind == CATCH) catchers.append(catchClause());
+                if (token.kind == FINALLY) {
+                    nextToken();
                     finalizer = block();
                 }
             } else {
@@ -1783,7 +1764,7 @@
             return F.at(pos).Try(resources, body, catchers.toList(), finalizer);
         }
         case SWITCH: {
-            S.nextToken();
+            nextToken();
             JCExpression selector = parExpression();
             accept(LBRACE);
             List<JCCase> cases = switchBlockStatementGroups();
@@ -1792,41 +1773,41 @@
             return t;
         }
         case SYNCHRONIZED: {
-            S.nextToken();
+            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();
+            nextToken();
+            JCExpression result = token.kind == SEMI ? null : parseExpression();
             JCReturn t = to(F.at(pos).Return(result));
             accept(SEMI);
             return t;
         }
         case THROW: {
-            S.nextToken();
+            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;
+            nextToken();
+            Name label = (token.kind == IDENTIFIER || token.kind == ASSERT || token.kind == 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;
+            nextToken();
+            Name label = (token.kind == IDENTIFIER || token.kind == ASSERT || token.kind == ENUM) ? ident() : null;
             JCContinue t =  to(F.at(pos).Continue(label));
             accept(SEMI);
             return t;
         }
         case SEMI:
-            S.nextToken();
+            nextToken();
             return toP(F.at(pos).Skip());
         case ELSE:
             return toP(F.Exec(syntaxError("else.without.if")));
@@ -1835,12 +1816,12 @@
         case CATCH:
             return toP(F.Exec(syntaxError("catch.without.try")));
         case ASSERT: {
-            if (allowAsserts && S.token() == ASSERT) {
-                S.nextToken();
+            if (allowAsserts && token.kind == ASSERT) {
+                nextToken();
                 JCExpression assertion = parseExpression();
                 JCExpression message = null;
-                if (S.token() == COLON) {
-                    S.nextToken();
+                if (token.kind == COLON) {
+                    nextToken();
                     message = parseExpression();
                 }
                 JCAssert t = to(F.at(pos).Assert(assertion, message));
@@ -1851,12 +1832,12 @@
         }
         case ENUM:
         default:
-            Name name = S.name();
+            Token prevToken = token;
             JCExpression expr = parseExpression();
-            if (S.token() == COLON && expr.getTag() == JCTree.IDENT) {
-                S.nextToken();
+            if (token.kind == COLON && expr.getTag() == JCTree.IDENT) {
+                nextToken();
                 JCStatement stat = parseStatement();
-                return F.at(pos).Labelled(name, stat);
+                return F.at(pos).Labelled(prevToken.name(), stat);
             } else {
                 // This Exec is an "ExpressionStatement"; it subsumes the terminating semicolon
                 JCExpressionStatement stat = to(F.at(pos).Exec(checkExprStat(expr)));
@@ -1869,7 +1850,7 @@
     /** CatchClause     = CATCH "(" FormalParameter ")" Block
      */
     protected JCCatch catchClause() {
-        int pos = S.pos();
+        int pos = token.pos;
         accept(CATCH);
         accept(LPAREN);
         JCModifiers mods = optFinal(Flags.PARAMETER);
@@ -1886,9 +1867,9 @@
     List<JCExpression> catchTypes() {
         ListBuffer<JCExpression> catchTypes = ListBuffer.lb();
         catchTypes.add(parseType());
-        while (S.token() == BAR) {
+        while (token.kind == BAR) {
             checkMulticatch();
-            S.nextToken();
+            nextToken();
             catchTypes.add(qualident());
         }
         return catchTypes.toList();
@@ -1901,33 +1882,33 @@
     List<JCCase> switchBlockStatementGroups() {
         ListBuffer<JCCase> cases = new ListBuffer<JCCase>();
         while (true) {
-            int pos = S.pos();
-            switch (S.token()) {
+            int pos = token.pos;
+            switch (token.kind) {
             case CASE: {
-                S.nextToken();
+                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());
+                    storeEnd(c, S.prevToken().endPos);
                 cases.append(c);
                 break;
             }
             case DEFAULT: {
-                S.nextToken();
+                nextToken();
                 accept(COLON);
                 List<JCStatement> stats = blockStatements();
                 JCCase c = F.at(pos).Case(null, stats);
                 if (stats.isEmpty())
-                    storeEnd(c, S.prevEndPos());
+                    storeEnd(c, S.prevToken().endPos);
                 cases.append(c);
                 break;
             }
             case RBRACE: case EOF:
                 return cases.toList();
             default:
-                S.nextToken(); // to ensure progress
+                nextToken(); // to ensure progress
                 syntaxError(pos, "expected3",
                     CASE, DEFAULT, RBRACE);
             }
@@ -1941,9 +1922,9 @@
                                                                     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();
+        while (token.kind == COMMA) {
+            nextToken();
+            pos = token.pos;
             JCExpression t = parseExpression();
             // This Exec is a "StatementExpression"; it subsumes no terminating token
             stats.append(toP(F.at(pos).Exec(checkExprStat(t))));
@@ -1956,13 +1937,13 @@
      */
     List<JCStatement> forInit() {
         ListBuffer<JCStatement> stats = lb();
-        int pos = S.pos();
-        if (S.token() == FINAL || S.token() == MONKEYS_AT) {
+        int pos = token.pos;
+        if (token.kind == FINAL || token.kind == 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))
+                (token.kind == IDENTIFIER || token.kind == ASSERT || token.kind == ENUM))
                 return variableDeclarators(modifiersOpt(), t, stats).toList();
             else
                 return moreStatementExpressions(pos, t, stats).toList();
@@ -1972,7 +1953,7 @@
     /** ForUpdate = StatementExpression MoreStatementExpressions
      */
     List<JCExpressionStatement> forUpdate() {
-        return moreStatementExpressions(S.pos(),
+        return moreStatementExpressions(token.pos,
                                         parseExpression(),
                                         new ListBuffer<JCExpressionStatement>()).toList();
     }
@@ -1980,11 +1961,11 @@
     /** AnnotationsOpt = { '@' Annotation }
      */
     List<JCAnnotation> annotationsOpt() {
-        if (S.token() != MONKEYS_AT) return List.nil(); // optimization
+        if (token.kind != MONKEYS_AT) return List.nil(); // optimization
         ListBuffer<JCAnnotation> buf = new ListBuffer<JCAnnotation>();
-        while (S.token() == MONKEYS_AT) {
-            int pos = S.pos();
-            S.nextToken();
+        while (token.kind == MONKEYS_AT) {
+            int pos = token.pos;
+            nextToken();
             buf.append(annotation(pos));
         }
         return buf.toList();
@@ -2004,21 +1985,20 @@
         int pos;
         if (partial == null) {
             flags = 0;
-            pos = S.pos();
+            pos = token.pos;
         } else {
             flags = partial.flags;
             annotations.appendList(partial.annotations);
             pos = partial.pos;
         }
-        if (S.deprecatedFlag()) {
+        if (token.deprecatedFlag) {
             flags |= Flags.DEPRECATED;
-            S.resetDeprecatedFlag();
         }
         int lastPos = Position.NOPOS;
     loop:
         while (true) {
             long flag;
-            switch (S.token()) {
+            switch (token.kind) {
             case PRIVATE     : flag = Flags.PRIVATE; break;
             case PROTECTED   : flag = Flags.PROTECTED; break;
             case PUBLIC      : flag = Flags.PUBLIC; break;
@@ -2031,15 +2011,15 @@
             case SYNCHRONIZED: flag = Flags.SYNCHRONIZED; break;
             case STRICTFP    : flag = Flags.STRICTFP; break;
             case MONKEYS_AT  : flag = Flags.ANNOTATION; break;
-            case ERROR       : flag = 0; S.nextToken(); break;
+            case ERROR       : flag = 0; nextToken(); break;
             default: break loop;
             }
-            if ((flags & flag) != 0) error(S.pos(), "repeated.modifier");
-            lastPos = S.pos();
-            S.nextToken();
+            if ((flags & flag) != 0) error(token.pos, "repeated.modifier");
+            lastPos = token.pos;
+            nextToken();
             if (flag == Flags.ANNOTATION) {
                 checkAnnotations();
-                if (S.token() != INTERFACE) {
+                if (token.kind != INTERFACE) {
                     JCAnnotation ann = annotation(lastPos);
                     // if first modifier is an annotation, set pos to annotation's.
                     if (flags == 0 && annotations.isEmpty())
@@ -2051,7 +2031,7 @@
             }
             flags |= flag;
         }
-        switch (S.token()) {
+        switch (token.kind) {
         case ENUM: flags |= Flags.ENUM; break;
         case INTERFACE: flags |= Flags.INTERFACE; break;
         default: break;
@@ -2064,7 +2044,7 @@
 
         JCModifiers mods = F.at(pos).Modifiers(flags, annotations.toList());
         if (pos != Position.NOPOS)
-            storeEnd(mods, S.prevEndPos());
+            storeEnd(mods, S.prevToken().endPos);
         return mods;
     }
 
@@ -2077,22 +2057,22 @@
         JCTree ident = qualident();
         List<JCExpression> fieldValues = annotationFieldValuesOpt();
         JCAnnotation ann = F.at(pos).Annotation(ident, fieldValues);
-        storeEnd(ann, S.prevEndPos());
+        storeEnd(ann, S.prevToken().endPos);
         return ann;
     }
 
     List<JCExpression> annotationFieldValuesOpt() {
-        return (S.token() == LPAREN) ? annotationFieldValues() : List.<JCExpression>nil();
+        return (token.kind == LPAREN) ? annotationFieldValues() : List.<JCExpression>nil();
     }
 
     /** AnnotationFieldValues   = "(" [ AnnotationFieldValue { "," AnnotationFieldValue } ] ")" */
     List<JCExpression> annotationFieldValues() {
         accept(LPAREN);
         ListBuffer<JCExpression> buf = new ListBuffer<JCExpression>();
-        if (S.token() != RPAREN) {
+        if (token.kind != RPAREN) {
             buf.append(annotationFieldValue());
-            while (S.token() == COMMA) {
-                S.nextToken();
+            while (token.kind == COMMA) {
+                nextToken();
                 buf.append(annotationFieldValue());
             }
         }
@@ -2104,11 +2084,11 @@
      *                          | Identifier "=" AnnotationValue
      */
     JCExpression annotationFieldValue() {
-        if (S.token() == IDENTIFIER) {
+        if (token.kind == IDENTIFIER) {
             mode = EXPR;
             JCExpression t1 = term1();
-            if (t1.getTag() == JCTree.IDENT && S.token() == EQ) {
-                int pos = S.pos();
+            if (t1.getTag() == JCTree.IDENT && token.kind == EQ) {
+                int pos = token.pos;
                 accept(EQ);
                 JCExpression v = annotationValue();
                 return toP(F.at(pos).Assign(t1, v));
@@ -2125,20 +2105,20 @@
      */
     JCExpression annotationValue() {
         int pos;
-        switch (S.token()) {
+        switch (token.kind) {
         case MONKEYS_AT:
-            pos = S.pos();
-            S.nextToken();
+            pos = token.pos;
+            nextToken();
             return annotation(pos);
         case LBRACE:
-            pos = S.pos();
+            pos = token.pos;
             accept(LBRACE);
             ListBuffer<JCExpression> buf = new ListBuffer<JCExpression>();
-            if (S.token() != RBRACE) {
+            if (token.kind != RBRACE) {
                 buf.append(annotationValue());
-                while (S.token() == COMMA) {
-                    S.nextToken();
-                    if (S.token() == RBRACE) break;
+                while (token.kind == COMMA) {
+                    nextToken();
+                    if (token.kind == RBRACE) break;
                     buf.append(annotationValue());
                 }
             }
@@ -2156,7 +2136,7 @@
                                                                          JCExpression type,
                                                                          T vdefs)
     {
-        return variableDeclaratorsRest(S.pos(), mods, type, ident(), false, null, vdefs);
+        return variableDeclaratorsRest(token.pos, mods, type, ident(), false, null, vdefs);
     }
 
     /** VariableDeclaratorsRest = VariableDeclaratorRest { "," VariableDeclarator }
@@ -2174,10 +2154,10 @@
                                                                      T vdefs)
     {
         vdefs.append(variableDeclaratorRest(pos, mods, type, name, reqInit, dc));
-        while (S.token() == COMMA) {
+        while (token.kind == COMMA) {
             // All but last of multiple declarators subsume a comma
-            storeEnd((JCTree)vdefs.elems.last(), S.endPos());
-            S.nextToken();
+            storeEnd((JCTree)vdefs.elems.last(), token.endPos);
+            nextToken();
             vdefs.append(variableDeclarator(mods, type, reqInit, dc));
         }
         return vdefs;
@@ -2187,7 +2167,7 @@
      *  ConstantDeclarator = Ident ConstantDeclaratorRest
      */
     JCVariableDecl variableDeclarator(JCModifiers mods, JCExpression type, boolean reqInit, String dc) {
-        return variableDeclaratorRest(S.pos(), mods, type, ident(), reqInit, dc);
+        return variableDeclaratorRest(token.pos, mods, type, ident(), reqInit, dc);
     }
 
     /** VariableDeclaratorRest = BracketsOpt ["=" VariableInitializer]
@@ -2200,11 +2180,11 @@
                                   boolean reqInit, String dc) {
         type = bracketsOpt(type);
         JCExpression init = null;
-        if (S.token() == EQ) {
-            S.nextToken();
+        if (token.kind == EQ) {
+            nextToken();
             init = variableInitializer();
         }
-        else if (reqInit) syntaxError(S.pos(), "expected", EQ);
+        else if (reqInit) syntaxError(token.pos, "expected", EQ);
         JCVariableDecl result =
             toP(F.at(pos).VarDef(mods, name, type, init));
         attach(result, dc);
@@ -2214,11 +2194,11 @@
     /** VariableDeclaratorId = Ident BracketsOpt
      */
     JCVariableDecl variableDeclaratorId(JCModifiers mods, JCExpression type) {
-        int pos = S.pos();
+        int pos = token.pos;
         Name name = ident();
         if ((mods.flags & Flags.VARARGS) != 0 &&
-                S.token() == LBRACKET) {
-            log.error(S.pos(), "varargs.and.old.array.syntax");
+                token.kind == LBRACKET) {
+            log.error(token.pos, "varargs.and.old.array.syntax");
         }
         type = bracketsOpt(type);
         return toP(F.at(pos).VarDef(mods, name, type, null));
@@ -2229,12 +2209,12 @@
     List<JCTree> resources() {
         ListBuffer<JCTree> defs = new ListBuffer<JCTree>();
         defs.append(resource());
-        while (S.token() == SEMI) {
+        while (token.kind == SEMI) {
             // All but last of multiple declarators must subsume a semicolon
-            storeEnd(defs.elems.last(), S.endPos());
-            int semiColonPos = S.pos();
-            S.nextToken();
-            if (S.token() == RPAREN) { // Optional trailing semicolon
+            storeEnd(defs.elems.last(), token.endPos);
+            int semiColonPos = token.pos;
+            nextToken();
+            if (token.kind == RPAREN) { // Optional trailing semicolon
                                        // after last resource
                 break;
             }
@@ -2248,7 +2228,7 @@
     protected JCTree resource() {
         JCModifiers optFinal = optFinal(Flags.FINAL);
         JCExpression type = parseType();
-        int pos = S.pos();
+        int pos = token.pos;
         Name ident = ident();
         return variableDeclaratorRest(pos, optFinal, type, ident, true, null);
     }
@@ -2256,54 +2236,61 @@
     /** CompilationUnit = [ { "@" Annotation } PACKAGE Qualident ";"] {ImportDeclaration} {TypeDeclaration}
      */
     public JCTree.JCCompilationUnit parseCompilationUnit() {
-        int pos = S.pos();
+        Token firstToken = token;
         JCExpression pid = null;
-        String dc = S.docComment();
         JCModifiers mods = null;
+        boolean consumedToplevelDoc = false;
+        boolean seenImport = false;
+        boolean seenPackage = false;
         List<JCAnnotation> packageAnnotations = List.nil();
-        if (S.token() == MONKEYS_AT)
+        if (token.kind == MONKEYS_AT)
             mods = modifiersOpt();
 
-        if (S.token() == PACKAGE) {
+        if (token.kind == PACKAGE) {
+            seenPackage = true;
             if (mods != null) {
                 checkNoMods(mods.flags);
                 packageAnnotations = mods.annotations;
                 mods = null;
             }
-            S.nextToken();
+            nextToken();
             pid = qualident();
             accept(SEMI);
         }
         ListBuffer<JCTree> defs = new ListBuffer<JCTree>();
         boolean checkForImports = true;
-        while (S.token() != EOF) {
-            if (S.pos() <= errorEndPos) {
+        boolean firstTypeDecl = true;
+        while (token.kind != EOF) {
+            if (token.pos <= errorEndPos) {
                 // error recovery
                 skip(checkForImports, false, false, false);
-                if (S.token() == EOF)
+                if (token.kind == EOF)
                     break;
             }
-            if (checkForImports && mods == null && S.token() == IMPORT) {
+            if (checkForImports && mods == null && token.kind == IMPORT) {
+                seenImport = true;
                 defs.append(importDeclaration());
             } else {
-                JCTree def = typeDeclaration(mods);
-                if (keepDocComments && dc != null && docComments.get(def) == dc) {
-                    // If the first type declaration has consumed the first doc
-                    // comment, then don't use it for the top level comment as well.
-                    dc = null;
+                String docComment = token.docComment;
+                if (firstTypeDecl && !seenImport && !seenPackage) {
+                    docComment = firstToken.docComment;
+                    consumedToplevelDoc = true;
                 }
+                JCTree def = typeDeclaration(mods, docComment);
                 if (def instanceof JCExpressionStatement)
                     def = ((JCExpressionStatement)def).expr;
                 defs.append(def);
                 if (def instanceof JCClassDecl)
                     checkForImports = false;
                 mods = null;
+                firstTypeDecl = false;
             }
         }
-        JCTree.JCCompilationUnit toplevel = F.at(pos).TopLevel(packageAnnotations, pid, defs.toList());
-        attach(toplevel, dc);
+        JCTree.JCCompilationUnit toplevel = F.at(firstToken.pos).TopLevel(packageAnnotations, pid, defs.toList());
+        if (!consumedToplevelDoc)
+            attach(toplevel, firstToken.docComment);
         if (defs.elems.isEmpty())
-            storeEnd(toplevel, S.prevEndPos());
+            storeEnd(toplevel, S.prevToken().endPos);
         if (keepDocComments)
             toplevel.docComments = docComments;
         if (keepLineMap)
@@ -2314,26 +2301,26 @@
     /** ImportDeclaration = IMPORT [ STATIC ] Ident { "." Ident } [ "." "*" ] ";"
      */
     JCTree importDeclaration() {
-        int pos = S.pos();
-        S.nextToken();
+        int pos = token.pos;
+        nextToken();
         boolean importStatic = false;
-        if (S.token() == STATIC) {
+        if (token.kind == STATIC) {
             checkStaticImports();
             importStatic = true;
-            S.nextToken();
+            nextToken();
         }
-        JCExpression pid = toP(F.at(S.pos()).Ident(ident()));
+        JCExpression pid = toP(F.at(token.pos).Ident(ident()));
         do {
-            int pos1 = S.pos();
+            int pos1 = token.pos;
             accept(DOT);
-            if (S.token() == STAR) {
+            if (token.kind == STAR) {
                 pid = to(F.at(pos1).Select(pid, names.asterisk));
-                S.nextToken();
+                nextToken();
                 break;
             } else {
                 pid = toP(F.at(pos1).Select(pid, ident()));
             }
-        } while (S.token() == DOT);
+        } while (token.kind == DOT);
         accept(SEMI);
         return toP(F.at(pos).Import(pid, importStatic));
     }
@@ -2341,14 +2328,13 @@
     /** TypeDeclaration = ClassOrInterfaceOrEnumDeclaration
      *                  | ";"
      */
-    JCTree typeDeclaration(JCModifiers mods) {
-        int pos = S.pos();
-        if (mods == null && S.token() == SEMI) {
-            S.nextToken();
+    JCTree typeDeclaration(JCModifiers mods, String docComment) {
+        int pos = token.pos;
+        if (mods == null && token.kind == SEMI) {
+            nextToken();
             return toP(F.at(pos).Skip());
         } else {
-            String dc = S.docComment();
-            return classOrInterfaceOrEnumDeclaration(modifiersOpt(mods), dc);
+            return classOrInterfaceOrEnumDeclaration(modifiersOpt(mods), docComment);
         }
     }
 
@@ -2358,19 +2344,19 @@
      *  @param dc       The documentation comment for the class, or null.
      */
     JCStatement classOrInterfaceOrEnumDeclaration(JCModifiers mods, String dc) {
-        if (S.token() == CLASS) {
+        if (token.kind == CLASS) {
             return classDeclaration(mods, dc);
-        } else if (S.token() == INTERFACE) {
+        } else if (token.kind == INTERFACE) {
             return interfaceDeclaration(mods, dc);
         } else if (allowEnums) {
-            if (S.token() == ENUM) {
+            if (token.kind == ENUM) {
                 return enumDeclaration(mods, dc);
             } else {
-                int pos = S.pos();
+                int pos = token.pos;
                 List<JCTree> errs;
-                if (S.token() == IDENTIFIER) {
+                if (token.kind == IDENTIFIER) {
                     errs = List.<JCTree>of(mods, toP(F.at(pos).Ident(ident())));
-                    setErrorEndPos(S.pos());
+                    setErrorEndPos(token.pos);
                 } else {
                     errs = List.<JCTree>of(mods);
                 }
@@ -2378,16 +2364,16 @@
                                               CLASS, INTERFACE, ENUM)));
             }
         } else {
-            if (S.token() == ENUM) {
-                error(S.pos(), "enums.not.supported.in.source", source.name);
+            if (token.kind == ENUM) {
+                error(token.pos, "enums.not.supported.in.source", source.name);
                 allowEnums = true;
                 return enumDeclaration(mods, dc);
             }
-            int pos = S.pos();
+            int pos = token.pos;
             List<JCTree> errs;
-            if (S.token() == IDENTIFIER) {
+            if (token.kind == IDENTIFIER) {
                 errs = List.<JCTree>of(mods, toP(F.at(pos).Ident(ident())));
-                setErrorEndPos(S.pos());
+                setErrorEndPos(token.pos);
             } else {
                 errs = List.<JCTree>of(mods);
             }
@@ -2402,20 +2388,20 @@
      *  @param dc       The documentation comment for the class, or null.
      */
     JCClassDecl classDeclaration(JCModifiers mods, String dc) {
-        int pos = S.pos();
+        int pos = token.pos;
         accept(CLASS);
         Name name = ident();
 
         List<JCTypeParameter> typarams = typeParametersOpt();
 
         JCExpression extending = null;
-        if (S.token() == EXTENDS) {
-            S.nextToken();
+        if (token.kind == EXTENDS) {
+            nextToken();
             extending = parseType();
         }
         List<JCExpression> implementing = List.nil();
-        if (S.token() == IMPLEMENTS) {
-            S.nextToken();
+        if (token.kind == IMPLEMENTS) {
+            nextToken();
             implementing = typeList();
         }
         List<JCTree> defs = classOrInterfaceBody(name, false);
@@ -2431,15 +2417,15 @@
      *  @param dc       The documentation comment for the interface, or null.
      */
     JCClassDecl interfaceDeclaration(JCModifiers mods, String dc) {
-        int pos = S.pos();
+        int pos = token.pos;
         accept(INTERFACE);
         Name name = ident();
 
         List<JCTypeParameter> typarams = typeParametersOpt();
 
         List<JCExpression> extending = List.nil();
-        if (S.token() == EXTENDS) {
-            S.nextToken();
+        if (token.kind == EXTENDS) {
+            nextToken();
             extending = typeList();
         }
         List<JCTree> defs = classOrInterfaceBody(name, true);
@@ -2454,13 +2440,13 @@
      *  @param dc       The documentation comment for the enum, or null.
      */
     JCClassDecl enumDeclaration(JCModifiers mods, String dc) {
-        int pos = S.pos();
+        int pos = token.pos;
         accept(ENUM);
         Name name = ident();
 
         List<JCExpression> implementing = List.nil();
-        if (S.token() == IMPLEMENTS) {
-            S.nextToken();
+        if (token.kind == IMPLEMENTS) {
+            nextToken();
             implementing = typeList();
         }
 
@@ -2479,27 +2465,27 @@
     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) {
+        if (token.kind == COMMA) {
+            nextToken();
+        } else if (token.kind != RBRACE && token.kind != SEMI) {
             defs.append(enumeratorDeclaration(enumName));
-            while (S.token() == COMMA) {
-                S.nextToken();
-                if (S.token() == RBRACE || S.token() == SEMI) break;
+            while (token.kind == COMMA) {
+                nextToken();
+                if (token.kind == RBRACE || token.kind == SEMI) break;
                 defs.append(enumeratorDeclaration(enumName));
             }
-            if (S.token() != SEMI && S.token() != RBRACE) {
-                defs.append(syntaxError(S.pos(), "expected3",
+            if (token.kind != SEMI && token.kind != RBRACE) {
+                defs.append(syntaxError(token.pos, "expected3",
                                 COMMA, RBRACE, SEMI));
-                S.nextToken();
+                nextToken();
             }
         }
-        if (S.token() == SEMI) {
-            S.nextToken();
-            while (S.token() != RBRACE && S.token() != EOF) {
+        if (token.kind == SEMI) {
+            nextToken();
+            while (token.kind != RBRACE && token.kind != EOF) {
                 defs.appendList(classOrInterfaceBodyDeclaration(enumName,
                                                                 false));
-                if (S.pos() <= errorEndPos) {
+                if (token.pos <= errorEndPos) {
                     // error recovery
                    skip(false, true, true, false);
                 }
@@ -2512,23 +2498,22 @@
     /** EnumeratorDeclaration = AnnotationsOpt [TypeArguments] IDENTIFIER [ Arguments ] [ "{" ClassBody "}" ]
      */
     JCTree enumeratorDeclaration(Name enumName) {
-        String dc = S.docComment();
+        String dc = token.docComment;
         int flags = Flags.PUBLIC|Flags.STATIC|Flags.FINAL|Flags.ENUM;
-        if (S.deprecatedFlag()) {
+        if (token.deprecatedFlag) {
             flags |= Flags.DEPRECATED;
-            S.resetDeprecatedFlag();
         }
-        int pos = S.pos();
+        int pos = token.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();
+        int identPos = token.pos;
         Name name = ident();
-        int createPos = S.pos();
-        List<JCExpression> args = (S.token() == LPAREN)
+        int createPos = token.pos;
+        List<JCExpression> args = (token.kind == LPAREN)
             ? arguments() : List.<JCExpression>nil();
         JCClassDecl body = null;
-        if (S.token() == LBRACE) {
+        if (token.kind == 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));
@@ -2538,7 +2523,7 @@
         JCIdent ident = F.at(identPos).Ident(enumName);
         JCNewClass create = F.at(createPos).NewClass(null, typeArgs, ident, args, body);
         if (createPos != identPos)
-            storeEnd(create, S.prevEndPos());
+            storeEnd(create, S.prevToken().endPos);
         ident = F.at(identPos).Ident(enumName);
         JCTree result = toP(F.at(pos).VarDef(mods, name, ident, create));
         attach(result, dc);
@@ -2550,8 +2535,8 @@
     List<JCExpression> typeList() {
         ListBuffer<JCExpression> ts = new ListBuffer<JCExpression>();
         ts.append(parseType());
-        while (S.token() == COMMA) {
-            S.nextToken();
+        while (token.kind == COMMA) {
+            nextToken();
             ts.append(parseType());
         }
         return ts.toList();
@@ -2562,16 +2547,16 @@
      */
     List<JCTree> classOrInterfaceBody(Name className, boolean isInterface) {
         accept(LBRACE);
-        if (S.pos() <= errorEndPos) {
+        if (token.pos <= errorEndPos) {
             // error recovery
             skip(false, true, false, false);
-            if (S.token() == LBRACE)
-                S.nextToken();
+            if (token.kind == LBRACE)
+                nextToken();
         }
         ListBuffer<JCTree> defs = new ListBuffer<JCTree>();
-        while (S.token() != RBRACE && S.token() != EOF) {
+        while (token.kind != RBRACE && token.kind != EOF) {
             defs.appendList(classOrInterfaceBodyDeclaration(className, isInterface));
-            if (S.pos() <= errorEndPos) {
+            if (token.pos <= errorEndPos) {
                // error recovery
                skip(false, true, true, false);
            }
@@ -2598,23 +2583,23 @@
      *      ( ConstantDeclaratorsRest | InterfaceMethodDeclaratorRest ";" )
      */
     protected List<JCTree> classOrInterfaceBodyDeclaration(Name className, boolean isInterface) {
-        if (S.token() == SEMI) {
-            S.nextToken();
+        if (token.kind == SEMI) {
+            nextToken();
             return List.<JCTree>nil();
         } else {
-            String dc = S.docComment();
-            int pos = S.pos();
+            String dc = token.docComment;
+            int pos = token.pos;
             JCModifiers mods = modifiersOpt();
-            if (S.token() == CLASS ||
-                S.token() == INTERFACE ||
-                allowEnums && S.token() == ENUM) {
+            if (token.kind == CLASS ||
+                token.kind == INTERFACE ||
+                allowEnums && token.kind == ENUM) {
                 return List.<JCTree>of(classOrInterfaceOrEnumDeclaration(mods, dc));
-            } else if (S.token() == LBRACE && !isInterface &&
+            } else if (token.kind == LBRACE && !isInterface &&
                        (mods.flags & Flags.StandardFlags & ~Flags.STATIC) == 0 &&
                        mods.annotations.isEmpty()) {
                 return List.<JCTree>of(block(pos, mods.flags));
             } else {
-                pos = S.pos();
+                pos = token.pos;
                 List<JCTypeParameter> typarams = typeParametersOpt();
                 // if there are type parameters but no modifiers, save the start
                 // position of the method in the modifiers.
@@ -2622,26 +2607,26 @@
                     mods.pos = pos;
                     storeEnd(mods, pos);
                 }
-                Name name = S.name();
-                pos = S.pos();
+                Token tk = token;
+                pos = token.pos;
                 JCExpression type;
-                boolean isVoid = S.token() == VOID;
+                boolean isVoid = token.kind == VOID;
                 if (isVoid) {
                     type = to(F.at(pos).TypeIdent(TypeTags.VOID));
-                    S.nextToken();
+                    nextToken();
                 } else {
                     type = parseType();
                 }
-                if (S.token() == LPAREN && !isInterface && type.getTag() == JCTree.IDENT) {
-                    if (isInterface || name != className)
+                if (token.kind == LPAREN && !isInterface && type.getTag() == JCTree.IDENT) {
+                    if (isInterface || tk.name() != className)
                         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) {
+                    pos = token.pos;
+                    Name name = ident();
+                    if (token.kind == LPAREN) {
                         return List.of(methodDeclaratorRest(
                             pos, mods, type, name, typarams,
                             isInterface, isVoid, dc));
@@ -2649,16 +2634,16 @@
                         List<JCTree> defs =
                             variableDeclaratorsRest(pos, mods, type, name, isInterface, dc,
                                                     new ListBuffer<JCTree>()).toList();
-                        storeEnd(defs.last(), S.endPos());
+                        storeEnd(defs.last(), token.endPos);
                         accept(SEMI);
                         return defs;
                     } else {
-                        pos = S.pos();
+                        pos = token.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));
+                        return List.<JCTree>of(syntaxError(token.pos, err, "expected", LPAREN));
                     }
                 }
             }
@@ -2686,27 +2671,27 @@
         List<JCVariableDecl> params = formalParameters();
         if (!isVoid) type = bracketsOpt(type);
         List<JCExpression> thrown = List.nil();
-        if (S.token() == THROWS) {
-            S.nextToken();
+        if (token.kind == THROWS) {
+            nextToken();
             thrown = qualidentList();
         }
         JCBlock body = null;
         JCExpression defaultValue;
-        if (S.token() == LBRACE) {
+        if (token.kind == LBRACE) {
             body = block();
             defaultValue = null;
         } else {
-            if (S.token() == DEFAULT) {
+            if (token.kind == DEFAULT) {
                 accept(DEFAULT);
                 defaultValue = annotationValue();
             } else {
                 defaultValue = null;
             }
             accept(SEMI);
-            if (S.pos() <= errorEndPos) {
+            if (token.pos <= errorEndPos) {
                 // error recovery
                 skip(false, true, false, false);
-                if (S.token() == LBRACE) {
+                if (token.kind == LBRACE) {
                     body = block();
                 }
             }
@@ -2725,8 +2710,8 @@
     List<JCExpression> qualidentList() {
         ListBuffer<JCExpression> ts = new ListBuffer<JCExpression>();
         ts.append(qualident());
-        while (S.token() == COMMA) {
-            S.nextToken();
+        while (token.kind == COMMA) {
+            nextToken();
             ts.append(qualident());
         }
         return ts.toList();
@@ -2735,13 +2720,13 @@
     /** TypeParametersOpt = ["<" TypeParameter {"," TypeParameter} ">"]
      */
     List<JCTypeParameter> typeParametersOpt() {
-        if (S.token() == LT) {
+        if (token.kind == LT) {
             checkGenerics();
             ListBuffer<JCTypeParameter> typarams = new ListBuffer<JCTypeParameter>();
-            S.nextToken();
+            nextToken();
             typarams.append(typeParameter());
-            while (S.token() == COMMA) {
-                S.nextToken();
+            while (token.kind == COMMA) {
+                nextToken();
                 typarams.append(typeParameter());
             }
             accept(GT);
@@ -2756,14 +2741,14 @@
      *  TypeVariable = Ident
      */
     JCTypeParameter typeParameter() {
-        int pos = S.pos();
+        int pos = token.pos;
         Name name = ident();
         ListBuffer<JCExpression> bounds = new ListBuffer<JCExpression>();
-        if (S.token() == EXTENDS) {
-            S.nextToken();
+        if (token.kind == EXTENDS) {
+            nextToken();
             bounds.append(parseType());
-            while (S.token() == AMP) {
-                S.nextToken();
+            while (token.kind == AMP) {
+                nextToken();
                 bounds.append(parseType());
             }
         }
@@ -2778,10 +2763,10 @@
         ListBuffer<JCVariableDecl> params = new ListBuffer<JCVariableDecl>();
         JCVariableDecl lastParam = null;
         accept(LPAREN);
-        if (S.token() != RPAREN) {
+        if (token.kind != RPAREN) {
             params.append(lastParam = formalParameter());
-            while ((lastParam.mods.flags & Flags.VARARGS) == 0 && S.token() == COMMA) {
-                S.nextToken();
+            while ((lastParam.mods.flags & Flags.VARARGS) == 0 && token.kind == COMMA) {
+                nextToken();
                 params.append(lastParam = formalParameter());
             }
         }
@@ -2802,11 +2787,11 @@
     protected JCVariableDecl formalParameter() {
         JCModifiers mods = optFinal(Flags.PARAMETER);
         JCExpression type = parseType();
-        if (S.token() == ELLIPSIS) {
+        if (token.kind == ELLIPSIS) {
             checkVarargs();
             mods.flags |= Flags.VARARGS;
-            type = to(F.at(S.pos()).TypeArray(type));
-            S.nextToken();
+            type = to(F.at(token.pos).TypeArray(type));
+            nextToken();
         }
         return variableDeclaratorId(mods, type);
     }
@@ -2849,7 +2834,7 @@
     /** Return precedence of operator represented by token,
      *  -1 if token is not a binary operator. @see TreeInfo.opPrec
      */
-    static int prec(Token token) {
+    static int prec(TokenKind token) {
         int oc = optag(token);
         return (oc >= 0) ? TreeInfo.opPrec(oc) : -1;
     }
@@ -2869,7 +2854,7 @@
     /** Return operation tag of binary operator represented by token,
      *  -1 if token is not a binary operator.
      */
-    static int optag(Token token) {
+    static int optag(TokenKind token) {
         switch (token) {
         case BARBAR:
             return JCTree.OR;
@@ -2941,7 +2926,7 @@
     /** Return operation tag of unary operator represented by token,
      *  -1 if token is not a binary operator.
      */
-    static int unoptag(Token token) {
+    static int unoptag(TokenKind token) {
         switch (token) {
         case PLUS:
             return JCTree.POS;
@@ -2963,7 +2948,7 @@
     /** Return type tag of basic type represented by token,
      *  -1 if token is not a basic type identifier.
      */
-    static int typetag(Token token) {
+    static int typetag(TokenKind token) {
         switch (token) {
         case BYTE:
             return TypeTags.BYTE;
@@ -2988,49 +2973,49 @@
 
     void checkGenerics() {
         if (!allowGenerics) {
-            error(S.pos(), "generics.not.supported.in.source", source.name);
+            error(token.pos, "generics.not.supported.in.source", source.name);
             allowGenerics = true;
         }
     }
     void checkVarargs() {
         if (!allowVarargs) {
-            error(S.pos(), "varargs.not.supported.in.source", source.name);
+            error(token.pos, "varargs.not.supported.in.source", source.name);
             allowVarargs = true;
         }
     }
     void checkForeach() {
         if (!allowForeach) {
-            error(S.pos(), "foreach.not.supported.in.source", source.name);
+            error(token.pos, "foreach.not.supported.in.source", source.name);
             allowForeach = true;
         }
     }
     void checkStaticImports() {
         if (!allowStaticImport) {
-            error(S.pos(), "static.import.not.supported.in.source", source.name);
+            error(token.pos, "static.import.not.supported.in.source", source.name);
             allowStaticImport = true;
         }
     }
     void checkAnnotations() {
         if (!allowAnnotations) {
-            error(S.pos(), "annotations.not.supported.in.source", source.name);
+            error(token.pos, "annotations.not.supported.in.source", source.name);
             allowAnnotations = true;
         }
     }
     void checkDiamond() {
         if (!allowDiamond) {
-            error(S.pos(), "diamond.not.supported.in.source", source.name);
+            error(token.pos, "diamond.not.supported.in.source", source.name);
             allowDiamond = true;
         }
     }
     void checkMulticatch() {
         if (!allowMulticatch) {
-            error(S.pos(), "multicatch.not.supported.in.source", source.name);
+            error(token.pos, "multicatch.not.supported.in.source", source.name);
             allowMulticatch = true;
         }
     }
     void checkTryWithResources() {
         if (!allowTWR) {
-            error(S.pos(), "try.with.resources.not.supported.in.source", source.name);
+            error(token.pos, "try.with.resources.not.supported.in.source", source.name);
             allowTWR = true;
         }
     }