jdk/src/share/classes/sun/tools/java/Parser.java
changeset 2 90ce3da70b43
child 5506 202f599c92aa
equal deleted inserted replaced
0:fd16c54261b3 2:90ce3da70b43
       
     1 /*
       
     2  * Copyright 1994-2004 Sun Microsystems, Inc.  All Rights Reserved.
       
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
       
     4  *
       
     5  * This code is free software; you can redistribute it and/or modify it
       
     6  * under the terms of the GNU General Public License version 2 only, as
       
     7  * published by the Free Software Foundation.  Sun designates this
       
     8  * particular file as subject to the "Classpath" exception as provided
       
     9  * by Sun in the LICENSE file that accompanied this code.
       
    10  *
       
    11  * This code is distributed in the hope that it will be useful, but WITHOUT
       
    12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
       
    13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
       
    14  * version 2 for more details (a copy is included in the LICENSE file that
       
    15  * accompanied this code).
       
    16  *
       
    17  * You should have received a copy of the GNU General Public License version
       
    18  * 2 along with this work; if not, write to the Free Software Foundation,
       
    19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
       
    20  *
       
    21  * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
       
    22  * CA 95054 USA or visit www.sun.com if you need additional information or
       
    23  * have any questions.
       
    24  */
       
    25 
       
    26 package sun.tools.java;
       
    27 
       
    28 import sun.tools.tree.*;
       
    29 import java.io.IOException;
       
    30 import java.io.InputStream;
       
    31 import java.util.Enumeration;
       
    32 import java.util.Vector;
       
    33 
       
    34 /**
       
    35  * This class is used to parse Java statements and expressions.
       
    36  * The result is a parse tree.<p>
       
    37  *
       
    38  * This class implements an operator precedence parser. Errors are
       
    39  * reported to the Environment object, if the error can't be
       
    40  * resolved immediately, a SyntaxError exception is thrown.<p>
       
    41  *
       
    42  * Error recovery is implemented by catching SyntaxError exceptions
       
    43  * and discarding input tokens until an input token is reached that
       
    44  * is possibly a legal continuation.<p>
       
    45  *
       
    46  * The parse tree that is constructed represents the input
       
    47  * exactly (no rewrites to simpler forms). This is important
       
    48  * if the resulting tree is to be used for code formatting in
       
    49  * a programming environment. Currently only documentation comments
       
    50  * are retained.<p>
       
    51  *
       
    52  * The parsing algorithm does NOT use any type information. Changes
       
    53  * in the type system do not affect the structure of the parse tree.
       
    54  * This restriction does introduce an ambiguity an expression of the
       
    55  * form: (e1) e2 is assumed to be a cast if e2 does not start with
       
    56  * an operator. That means that (a) - b is interpreted as subtract
       
    57  * b from a and not cast negative b to type a. However, if a is a
       
    58  * simple type (byte, int, ...) then it is assumed to be a cast.<p>
       
    59  *
       
    60  * WARNING: The contents of this source file are not part of any
       
    61  * supported API.  Code that depends on them does so at its own risk:
       
    62  * they are subject to change or removal without notice.
       
    63  *
       
    64  * @author      Arthur van Hoff
       
    65  */
       
    66 
       
    67 public
       
    68 class Parser extends Scanner implements ParserActions, Constants {
       
    69     /**
       
    70      * Create a parser
       
    71      */
       
    72     protected Parser(Environment env, InputStream in) throws IOException {
       
    73         super(env, in);
       
    74         this.scanner = this;
       
    75         this.actions = this;
       
    76     }
       
    77 
       
    78     /**
       
    79      * Create a parser, given a scanner.
       
    80      */
       
    81     protected Parser(Scanner scanner) throws IOException {
       
    82         super(scanner.env);
       
    83         this.scanner = scanner;
       
    84         ((Scanner)this).env = scanner.env;
       
    85         ((Scanner)this).token = scanner.token;
       
    86         ((Scanner)this).pos = scanner.pos;
       
    87         this.actions = this;
       
    88     }
       
    89 
       
    90     /**
       
    91      * Create a parser, given a scanner and the semantic callback.
       
    92      */
       
    93     public Parser(Scanner scanner, ParserActions actions) throws IOException {
       
    94         this(scanner);
       
    95         this.actions = actions;
       
    96     }
       
    97 
       
    98     /**
       
    99      * Usually <code>this.actions == (ParserActions)this</code>.
       
   100      * However, a delegate scanner can produce tokens for this parser,
       
   101      * in which case <code>(Scanner)this</code> is unused,
       
   102      * except for <code>this.token</code> and <code>this.pos</code>
       
   103      * instance variables which are filled from the real scanner
       
   104      * by <code>this.scan()</code> and the constructor.
       
   105      */
       
   106     ParserActions actions;
       
   107 
       
   108     // Note:  The duplication of methods allows pre-1.1 classes to
       
   109     // be binary compatible with the new version of the parser,
       
   110     // which now passes IdentifierTokens to the semantics phase,
       
   111     // rather than just Identifiers.  This change is necessary,
       
   112     // since the parser is no longer responsible for managing the
       
   113     // resolution of type names.  (That caused the "Vector" bug.)
       
   114     //
       
   115     // In a future release, the old "plain-Identifier" methods will
       
   116     // go away, and the corresponding "IdentifierToken" methods
       
   117     // may become abstract.
       
   118 
       
   119     /**
       
   120      * package declaration
       
   121      * @deprecated
       
   122      */
       
   123     @Deprecated
       
   124     public void packageDeclaration(long off, IdentifierToken nm) {
       
   125         // By default, call the deprecated version.
       
   126         // Any application must override one of the packageDeclaration methods.
       
   127         packageDeclaration(off, nm.id);
       
   128     }
       
   129     /**
       
   130      * @deprecated
       
   131      */
       
   132     @Deprecated
       
   133     protected void packageDeclaration(long off, Identifier nm) {
       
   134         throw new RuntimeException("beginClass method is abstract");
       
   135     }
       
   136 
       
   137     /**
       
   138      * import class
       
   139      * @deprecated
       
   140      */
       
   141     @Deprecated
       
   142     public void importClass(long off, IdentifierToken nm) {
       
   143         // By default, call the deprecated version.
       
   144         // Any application must override one of the packageDeclaration methods.
       
   145         importClass(off, nm.id);
       
   146     }
       
   147     /**
       
   148      * @deprecated Use the version with the IdentifierToken arguments.
       
   149      */
       
   150     @Deprecated
       
   151     protected void importClass(long off, Identifier nm) {
       
   152         throw new RuntimeException("importClass method is abstract");
       
   153     }
       
   154 
       
   155     /**
       
   156      * import package
       
   157      * @deprecated
       
   158      */
       
   159     @Deprecated
       
   160     public void importPackage(long off, IdentifierToken nm) {
       
   161         // By default, call the deprecated version.
       
   162         // Any application must override one of the importPackage methods.
       
   163         importPackage(off, nm.id);
       
   164     }
       
   165     /**
       
   166      * @deprecated Use the version with the IdentifierToken arguments.
       
   167      */
       
   168     @Deprecated
       
   169     protected void importPackage(long off, Identifier nm) {
       
   170         throw new RuntimeException("importPackage method is abstract");
       
   171     }
       
   172 
       
   173     /**
       
   174      * Define class
       
   175      * @deprecated
       
   176      */
       
   177     @Deprecated
       
   178     public ClassDefinition beginClass(long off, String doc,
       
   179                                       int mod, IdentifierToken nm,
       
   180                                       IdentifierToken sup,
       
   181                                       IdentifierToken impl[]) {
       
   182         // By default, call the deprecated version.
       
   183         // Any application must override one of the beginClass methods.
       
   184         Identifier supId = (sup == null) ? null : sup.id;
       
   185         Identifier implIds[] = null;
       
   186         if (impl != null) {
       
   187             implIds = new Identifier[impl.length];
       
   188             for (int i = 0; i < impl.length; i++) {
       
   189                 implIds[i] = impl[i].id;
       
   190             }
       
   191         }
       
   192         beginClass(off, doc, mod, nm.id, supId, implIds);
       
   193         return getCurrentClass();
       
   194     }
       
   195     /**
       
   196      * @deprecated Use the version with the IdentifierToken arguments.
       
   197      */
       
   198     @Deprecated
       
   199     protected void beginClass(long off, String doc, int mod, Identifier nm,
       
   200                               Identifier sup, Identifier impl[]) {
       
   201         throw new RuntimeException("beginClass method is abstract");
       
   202     }
       
   203 
       
   204     /**
       
   205      * Report the current class under construction.
       
   206      * By default, it's a no-op which returns null.
       
   207      * It may only be called before the corresponding endClass().
       
   208      */
       
   209     protected ClassDefinition getCurrentClass() {
       
   210         return null;
       
   211     }
       
   212 
       
   213     /**
       
   214      * End class
       
   215      * @deprecated
       
   216      */
       
   217     @Deprecated
       
   218     public void endClass(long off, ClassDefinition c) {
       
   219         // By default, call the deprecated version.
       
   220         // Any application must override one of the beginClass methods.
       
   221         endClass(off, c.getName().getFlatName().getName());
       
   222     }
       
   223     /**
       
   224      * @deprecated Use the version with the IdentifierToken arguments.
       
   225      */
       
   226     @Deprecated
       
   227     protected void endClass(long off, Identifier nm) {
       
   228         throw new RuntimeException("endClass method is abstract");
       
   229     }
       
   230 
       
   231     /**
       
   232      * Define a field
       
   233      * @deprecated
       
   234      */
       
   235     @Deprecated
       
   236     public void defineField(long where, ClassDefinition c,
       
   237                             String doc, int mod, Type t,
       
   238                             IdentifierToken nm, IdentifierToken args[],
       
   239                             IdentifierToken exp[], Node val) {
       
   240         // By default, call the deprecated version.
       
   241         // Any application must override one of the defineField methods.
       
   242         Identifier argIds[] = null;
       
   243         Identifier expIds[] = null;
       
   244         if (args != null) {
       
   245             argIds = new Identifier[args.length];
       
   246             for (int i = 0; i < args.length; i++) {
       
   247                 argIds[i] = args[i].id;
       
   248             }
       
   249         }
       
   250         if (exp != null) {
       
   251             expIds = new Identifier[exp.length];
       
   252             for (int i = 0; i < exp.length; i++) {
       
   253                 expIds[i] = exp[i].id;
       
   254             }
       
   255         }
       
   256         defineField(where, doc, mod, t, nm.id, argIds, expIds, val);
       
   257     }
       
   258 
       
   259     /**
       
   260      * @deprecated Use the version with the IdentifierToken arguments.
       
   261      */
       
   262     @Deprecated
       
   263     protected void defineField(long where, String doc, int mod, Type t,
       
   264                                Identifier nm, Identifier args[],
       
   265                                Identifier exp[], Node val) {
       
   266         throw new RuntimeException("defineField method is abstract");
       
   267     }
       
   268 
       
   269     /*
       
   270      * A growable array of nodes. It is used as a growable
       
   271      * buffer to hold argument lists and expression lists.
       
   272      * I'm not using Vector to make it more efficient.
       
   273      */
       
   274     private Node args[] = new Node[32];
       
   275     protected int argIndex = 0;
       
   276 
       
   277     protected final void addArgument(Node n) {
       
   278         if (argIndex == args.length) {
       
   279             Node newArgs[] = new Node[args.length * 2];
       
   280             System.arraycopy(args, 0, newArgs, 0, args.length);
       
   281             args = newArgs;
       
   282         }
       
   283         args[argIndex++] = n;
       
   284     }
       
   285     protected final Expression exprArgs(int index)[] {
       
   286         Expression e[] = new Expression[argIndex - index];
       
   287         System.arraycopy(args, index, e, 0, argIndex - index);
       
   288         argIndex = index;
       
   289         return e;
       
   290     }
       
   291     protected final Statement statArgs(int index)[] {
       
   292         Statement s[] = new Statement[argIndex - index];
       
   293         System.arraycopy(args, index, s, 0, argIndex - index);
       
   294         argIndex = index;
       
   295         return s;
       
   296     }
       
   297 
       
   298     /**
       
   299      * Expect a token, return its value, scan the next token or
       
   300      * throw an exception.
       
   301      */
       
   302     protected void expect(int t) throws SyntaxError, IOException {
       
   303         if (token != t) {
       
   304             switch (t) {
       
   305               case IDENT:
       
   306                 env.error(scanner.prevPos, "identifier.expected");
       
   307                 break;
       
   308               default:
       
   309                 env.error(scanner.prevPos, "token.expected", opNames[t]);
       
   310                 break;
       
   311             }
       
   312                 throw new SyntaxError();
       
   313         }
       
   314         scan();
       
   315     }
       
   316 
       
   317     /**
       
   318      * Parse a type expression. Does not parse the []'s.
       
   319      */
       
   320     protected Expression parseTypeExpression() throws SyntaxError, IOException {
       
   321         switch (token) {
       
   322           case VOID:
       
   323             return new TypeExpression(scan(), Type.tVoid);
       
   324           case BOOLEAN:
       
   325             return new TypeExpression(scan(), Type.tBoolean);
       
   326           case BYTE:
       
   327             return new TypeExpression(scan(), Type.tByte);
       
   328           case CHAR:
       
   329             return new TypeExpression(scan(), Type.tChar);
       
   330           case SHORT:
       
   331             return new TypeExpression(scan(), Type.tShort);
       
   332           case INT:
       
   333             return new TypeExpression(scan(), Type.tInt);
       
   334           case LONG:
       
   335             return new TypeExpression(scan(), Type.tLong);
       
   336           case FLOAT:
       
   337             return new TypeExpression(scan(), Type.tFloat);
       
   338           case DOUBLE:
       
   339             return new TypeExpression(scan(), Type.tDouble);
       
   340           case IDENT:
       
   341             Expression e = new IdentifierExpression(pos, scanner.idValue);
       
   342             scan();
       
   343             while (token == FIELD) {
       
   344                 e = new FieldExpression(scan(), e, scanner.idValue);
       
   345                 expect(IDENT);
       
   346             }
       
   347             return e;
       
   348         }
       
   349 
       
   350         env.error(pos, "type.expected");
       
   351         throw new SyntaxError();
       
   352     }
       
   353 
       
   354     /**
       
   355      * Parse a method invocation. Should be called when the current
       
   356      * then is the '(' of the argument list.
       
   357      */
       
   358     protected Expression parseMethodExpression(Expression e, Identifier id) throws SyntaxError, IOException {
       
   359        long p = scan();
       
   360        int i = argIndex;
       
   361        if (token != RPAREN) {
       
   362            addArgument(parseExpression());
       
   363            while (token == COMMA) {
       
   364                scan();
       
   365                addArgument(parseExpression());
       
   366            }
       
   367        }
       
   368        expect(RPAREN);
       
   369        return new MethodExpression(p, e, id, exprArgs(i));
       
   370     }
       
   371 
       
   372     /**
       
   373      * Parse a new instance expression.  Should be called when the current
       
   374      * token is the '(' of the argument list.
       
   375      */
       
   376     protected Expression parseNewInstanceExpression(long p, Expression outerArg, Expression type) throws SyntaxError, IOException {
       
   377         int i = argIndex;
       
   378         expect(LPAREN);
       
   379         if (token != RPAREN) {
       
   380             addArgument(parseExpression());
       
   381             while (token == COMMA) {
       
   382                 scan();
       
   383                 addArgument(parseExpression());
       
   384             }
       
   385         }
       
   386         expect(RPAREN);
       
   387         ClassDefinition body = null;
       
   388         if (token == LBRACE && !(type instanceof TypeExpression)) {
       
   389             long tp = pos;
       
   390             // x = new Type(arg) { subclass body ... }
       
   391             Identifier superName = FieldExpression.toIdentifier(type);
       
   392             if (superName == null) {
       
   393                 env.error(type.getWhere(), "type.expected");
       
   394             }
       
   395             Vector ext = new Vector(1);
       
   396             Vector impl = new Vector(0);
       
   397             ext.addElement(new IdentifierToken(idNull));
       
   398             if (token == IMPLEMENTS || token == EXTENDS) {
       
   399                 env.error(pos, "anonymous.extends");
       
   400                 parseInheritance(ext, impl); // error recovery
       
   401             }
       
   402             body = parseClassBody(new IdentifierToken(tp, idNull),
       
   403                                   M_ANONYMOUS | M_LOCAL, EXPR, null,
       
   404                                   ext, impl, type.getWhere());
       
   405         }
       
   406         if (outerArg == null && body == null) {
       
   407             return new NewInstanceExpression(p, type, exprArgs(i));
       
   408         }
       
   409         return new NewInstanceExpression(p, type, exprArgs(i), outerArg, body);
       
   410     }
       
   411 
       
   412     /**
       
   413      * Parse a primary expression.
       
   414      */
       
   415     protected Expression parseTerm() throws SyntaxError, IOException {
       
   416         switch (token) {
       
   417           case CHARVAL: {
       
   418             char v = scanner.charValue;
       
   419             return new CharExpression(scan(), v);
       
   420           }
       
   421           case INTVAL: {
       
   422             int v = scanner.intValue;
       
   423             long q = scan();
       
   424             if (v < 0 && radix == 10) env.error(q, "overflow.int.dec");
       
   425             return new IntExpression(q, v);
       
   426           }
       
   427           case LONGVAL: {
       
   428             long v = scanner.longValue;
       
   429             long q = scan();
       
   430             if (v < 0 && radix == 10) env.error(q, "overflow.long.dec");
       
   431             return new LongExpression(q, v);
       
   432           }
       
   433           case FLOATVAL: {
       
   434             float v = scanner.floatValue;
       
   435             return new FloatExpression(scan(), v);
       
   436           }
       
   437           case DOUBLEVAL: {
       
   438             double v = scanner.doubleValue;
       
   439             return new DoubleExpression(scan(), v);
       
   440           }
       
   441           case STRINGVAL: {
       
   442             String v = scanner.stringValue;
       
   443             return new StringExpression(scan(), v);
       
   444           }
       
   445           case IDENT: {
       
   446             Identifier v = scanner.idValue;
       
   447             long p = scan();
       
   448             return (token == LPAREN) ?
       
   449                         parseMethodExpression(null, v) : new IdentifierExpression(p, v);
       
   450           }
       
   451 
       
   452           case TRUE:
       
   453             return new BooleanExpression(scan(), true);
       
   454           case FALSE:
       
   455             return new BooleanExpression(scan(), false);
       
   456           case NULL:
       
   457             return new NullExpression(scan());
       
   458 
       
   459           case THIS: {
       
   460             Expression e = new ThisExpression(scan());
       
   461             return (token == LPAREN) ? parseMethodExpression(e, idInit) : e;
       
   462           }
       
   463           case SUPER: {
       
   464             Expression e = new SuperExpression(scan());
       
   465             return (token == LPAREN) ? parseMethodExpression(e, idInit) : e;
       
   466           }
       
   467 
       
   468           case VOID:
       
   469           case BOOLEAN:
       
   470           case BYTE:
       
   471           case CHAR:
       
   472           case SHORT:
       
   473           case INT:
       
   474           case LONG:
       
   475           case FLOAT:
       
   476           case DOUBLE:
       
   477             return parseTypeExpression();
       
   478 
       
   479           case ADD: {
       
   480             long p = scan();
       
   481             switch (token) {
       
   482               case INTVAL: {
       
   483                 int v = scanner.intValue;
       
   484                 long q = scan();
       
   485                 if (v < 0 && radix == 10) env.error(q, "overflow.int.dec");
       
   486                 return new IntExpression(q, v);
       
   487               }
       
   488               case LONGVAL: {
       
   489                 long v = scanner.longValue;
       
   490                 long q = scan();
       
   491                 if (v < 0 && radix == 10) env.error(q, "overflow.long.dec");
       
   492                 return new LongExpression(q, v);
       
   493               }
       
   494               case FLOATVAL: {
       
   495                 float v = scanner.floatValue;
       
   496                 return new FloatExpression(scan(), v);
       
   497               }
       
   498               case DOUBLEVAL: {
       
   499                 double v = scanner.doubleValue;
       
   500                 return new DoubleExpression(scan(), v);
       
   501               }
       
   502             }
       
   503             return new PositiveExpression(p, parseTerm());
       
   504           }
       
   505           case SUB: {
       
   506             long p = scan();
       
   507             switch (token) {
       
   508               case INTVAL: {
       
   509                 int v = -scanner.intValue;
       
   510                 return new IntExpression(scan(), v);
       
   511               }
       
   512               case LONGVAL: {
       
   513                 long v = -scanner.longValue;
       
   514                 return new LongExpression(scan(), v);
       
   515               }
       
   516               case FLOATVAL: {
       
   517                 float v = -scanner.floatValue;
       
   518                 return new FloatExpression(scan(), v);
       
   519               }
       
   520               case DOUBLEVAL: {
       
   521                 double v = -scanner.doubleValue;
       
   522                 return new DoubleExpression(scan(), v);
       
   523               }
       
   524             }
       
   525             return new NegativeExpression(p, parseTerm());
       
   526           }
       
   527           case NOT:
       
   528             return new NotExpression(scan(), parseTerm());
       
   529           case BITNOT:
       
   530             return new BitNotExpression(scan(), parseTerm());
       
   531           case INC:
       
   532             return new PreIncExpression(scan(), parseTerm());
       
   533           case DEC:
       
   534             return new PreDecExpression(scan(), parseTerm());
       
   535 
       
   536           case LPAREN: {
       
   537             // bracketed-expr: (expr)
       
   538             long p = scan();
       
   539             Expression e = parseExpression();
       
   540             expect(RPAREN);
       
   541 
       
   542             if (e.getOp() == TYPE) {
       
   543                 // cast-expr: (simple-type) expr
       
   544                 return new CastExpression(p, e, parseTerm());
       
   545             }
       
   546 
       
   547             switch (token) {
       
   548 
       
   549                 // We handle INC and DEC specially.
       
   550                 // See the discussion in JLS section 15.14.1.
       
   551                 // (Part of fix for 4044502.)
       
   552 
       
   553               case INC:
       
   554                   // We know this must be a postfix increment.
       
   555                   return new PostIncExpression(scan(), e);
       
   556 
       
   557               case DEC:
       
   558                   // We know this must be a postfix decrement.
       
   559                   return new PostDecExpression(scan(), e);
       
   560 
       
   561               case LPAREN:
       
   562               case CHARVAL:
       
   563               case INTVAL:
       
   564               case LONGVAL:
       
   565               case FLOATVAL:
       
   566               case DOUBLEVAL:
       
   567               case STRINGVAL:
       
   568               case IDENT:
       
   569               case TRUE:
       
   570               case FALSE:
       
   571               case NOT:
       
   572               case BITNOT:
       
   573               case THIS:
       
   574               case SUPER:
       
   575               case NULL:
       
   576               case NEW:
       
   577                 // cast-expr: (expr) expr
       
   578                 return new CastExpression(p, e, parseTerm());
       
   579             }
       
   580             return new ExprExpression(p, e);
       
   581           }
       
   582 
       
   583           case LBRACE: {
       
   584             // array initializer: {expr1, expr2, ... exprn}
       
   585             long p = scan();
       
   586             int i = argIndex;
       
   587             if (token != RBRACE) {
       
   588                 addArgument(parseExpression());
       
   589                 while (token == COMMA) {
       
   590                     scan();
       
   591                     if (token == RBRACE) {
       
   592                         break;
       
   593                     }
       
   594                     addArgument(parseExpression());
       
   595                 }
       
   596             }
       
   597             expect(RBRACE);
       
   598             return new ArrayExpression(p, exprArgs(i));
       
   599           }
       
   600 
       
   601           case NEW: {
       
   602             long p = scan();
       
   603             int i = argIndex;
       
   604 
       
   605             if (token == LPAREN) {
       
   606                 scan();
       
   607                 Expression e = parseExpression();
       
   608                 expect(RPAREN);
       
   609                 env.error(p, "not.supported", "new(...)");
       
   610                 return new NullExpression(p);
       
   611             }
       
   612 
       
   613             Expression e = parseTypeExpression();
       
   614 
       
   615             if (token == LSQBRACKET) {
       
   616                 while (token == LSQBRACKET) {
       
   617                     scan();
       
   618                     addArgument((token != RSQBRACKET) ? parseExpression() : null);
       
   619                     expect(RSQBRACKET);
       
   620                 }
       
   621                 Expression[] dims = exprArgs(i);
       
   622                 if (token == LBRACE) {
       
   623                     return new NewArrayExpression(p, e, dims, parseTerm());
       
   624                 }
       
   625                 return new NewArrayExpression(p, e, dims);
       
   626             } else {
       
   627                 return parseNewInstanceExpression(p, null, e);
       
   628             }
       
   629           }
       
   630         }
       
   631 
       
   632         // System.err.println("NEAR: " + opNames[token]);
       
   633         env.error(scanner.prevPos, "missing.term");
       
   634         return new IntExpression(pos, 0);
       
   635     }
       
   636 
       
   637     /**
       
   638      * Parse an expression.
       
   639      */
       
   640     protected Expression parseExpression() throws SyntaxError, IOException {
       
   641         for (Expression e = parseTerm() ; e != null ; e = e.order()) {
       
   642             Expression more = parseBinaryExpression(e);
       
   643             if (more == null)
       
   644                 return e;
       
   645             e = more;
       
   646         }
       
   647         // this return is bogus
       
   648         return null;
       
   649     }
       
   650 
       
   651     /**
       
   652      * Given a left-hand term, parse an operator and right-hand term.
       
   653      */
       
   654     protected Expression parseBinaryExpression(Expression e) throws SyntaxError, IOException {
       
   655         if (e != null) {
       
   656             switch (token) {
       
   657               case LSQBRACKET: {
       
   658                 // index: expr1[expr2]
       
   659                 long p = scan();
       
   660                 Expression index = (token != RSQBRACKET) ? parseExpression() : null;
       
   661                 expect(RSQBRACKET);
       
   662                 e = new ArrayAccessExpression(p, e, index);
       
   663                 break;
       
   664               }
       
   665 
       
   666               case INC:
       
   667                 e = new PostIncExpression(scan(), e);
       
   668                 break;
       
   669               case DEC:
       
   670                 e = new PostDecExpression(scan(), e);
       
   671                 break;
       
   672               case FIELD: {
       
   673                 long p = scan();
       
   674                 if (token == THIS) {
       
   675                     // class C { class N { ... C.this ... } }
       
   676                     // class C { class N { N(C c){ ... c.this() ... } } }
       
   677                     long q = scan();
       
   678                     if (token == LPAREN) {
       
   679                         e = new ThisExpression(q, e);
       
   680                         e = parseMethodExpression(e, idInit);
       
   681                     } else {
       
   682                         e = new FieldExpression(p, e, idThis);
       
   683                     }
       
   684                     break;
       
   685                 }
       
   686                 if (token == SUPER) {
       
   687                     // class D extends C.N { D(C.N n) { n.super(); } }
       
   688                     // Also, 'C.super', as in:
       
   689                     // class C extends CS { class N { ... C.super.foo ... } }
       
   690                     // class C extends CS { class N { ... C.super.foo() ... } }
       
   691                     long q = scan();
       
   692                     if (token == LPAREN) {
       
   693                         e = new SuperExpression(q, e);
       
   694                         e = parseMethodExpression(e, idInit);
       
   695                     } else {
       
   696                         // We must check elsewhere that this expression
       
   697                         // does not stand alone, but qualifies a member name.
       
   698                         e = new FieldExpression(p, e, idSuper);
       
   699                     }
       
   700                     break;
       
   701                 }
       
   702                 if (token == NEW) {
       
   703                     // new C().new N()
       
   704                     scan();
       
   705                     if (token != IDENT)
       
   706                         expect(IDENT);
       
   707                     e = parseNewInstanceExpression(p, e, parseTypeExpression());
       
   708                     break;
       
   709                 }
       
   710                 if (token == CLASS) {
       
   711                     // just class literals, really
       
   712                     // Class c = C.class;
       
   713                     scan();
       
   714                     e = new FieldExpression(p, e, idClass);
       
   715                     break;
       
   716                 }
       
   717                 Identifier id = scanner.idValue;
       
   718                 expect(IDENT);
       
   719                 if (token == LPAREN) {
       
   720                     e = parseMethodExpression(e, id);
       
   721                 } else {
       
   722                     e = new FieldExpression(p, e, id);
       
   723                 }
       
   724                 break;
       
   725               }
       
   726               case INSTANCEOF:
       
   727                 e = new InstanceOfExpression(scan(), e, parseTerm());
       
   728                 break;
       
   729               case ADD:
       
   730                 e = new AddExpression(scan(), e, parseTerm());
       
   731                 break;
       
   732               case SUB:
       
   733                 e = new SubtractExpression(scan(), e, parseTerm());
       
   734                 break;
       
   735               case MUL:
       
   736                 e = new MultiplyExpression(scan(), e, parseTerm());
       
   737                 break;
       
   738               case DIV:
       
   739                 e = new DivideExpression(scan(), e, parseTerm());
       
   740                 break;
       
   741               case REM:
       
   742                 e = new RemainderExpression(scan(), e, parseTerm());
       
   743                 break;
       
   744               case LSHIFT:
       
   745                 e = new ShiftLeftExpression(scan(), e, parseTerm());
       
   746                 break;
       
   747               case RSHIFT:
       
   748                 e = new ShiftRightExpression(scan(), e, parseTerm());
       
   749                 break;
       
   750               case URSHIFT:
       
   751                 e = new UnsignedShiftRightExpression(scan(), e, parseTerm());
       
   752                 break;
       
   753               case LT:
       
   754                 e = new LessExpression(scan(), e, parseTerm());
       
   755                 break;
       
   756               case LE:
       
   757                 e = new LessOrEqualExpression(scan(), e, parseTerm());
       
   758                 break;
       
   759               case GT:
       
   760                 e = new GreaterExpression(scan(), e, parseTerm());
       
   761                 break;
       
   762               case GE:
       
   763                 e = new GreaterOrEqualExpression(scan(), e, parseTerm());
       
   764                 break;
       
   765               case EQ:
       
   766                 e = new EqualExpression(scan(), e, parseTerm());
       
   767                 break;
       
   768               case NE:
       
   769                 e = new NotEqualExpression(scan(), e, parseTerm());
       
   770                 break;
       
   771               case BITAND:
       
   772                 e = new BitAndExpression(scan(), e, parseTerm());
       
   773                 break;
       
   774               case BITXOR:
       
   775                 e = new BitXorExpression(scan(), e, parseTerm());
       
   776                 break;
       
   777               case BITOR:
       
   778                 e = new BitOrExpression(scan(), e, parseTerm());
       
   779                 break;
       
   780               case AND:
       
   781                 e = new AndExpression(scan(), e, parseTerm());
       
   782                 break;
       
   783               case OR:
       
   784                 e = new OrExpression(scan(), e, parseTerm());
       
   785                 break;
       
   786               case ASSIGN:
       
   787                 e = new AssignExpression(scan(), e, parseTerm());
       
   788                 break;
       
   789               case ASGMUL:
       
   790                 e = new AssignMultiplyExpression(scan(), e, parseTerm());
       
   791                 break;
       
   792               case ASGDIV:
       
   793                 e = new AssignDivideExpression(scan(), e, parseTerm());
       
   794                 break;
       
   795               case ASGREM:
       
   796                 e = new AssignRemainderExpression(scan(), e, parseTerm());
       
   797                 break;
       
   798               case ASGADD:
       
   799                 e = new AssignAddExpression(scan(), e, parseTerm());
       
   800                 break;
       
   801               case ASGSUB:
       
   802                 e = new AssignSubtractExpression(scan(), e, parseTerm());
       
   803                 break;
       
   804               case ASGLSHIFT:
       
   805                 e = new AssignShiftLeftExpression(scan(), e, parseTerm());
       
   806                 break;
       
   807               case ASGRSHIFT:
       
   808                 e = new AssignShiftRightExpression(scan(), e, parseTerm());
       
   809                 break;
       
   810               case ASGURSHIFT:
       
   811                 e = new AssignUnsignedShiftRightExpression(scan(), e, parseTerm());
       
   812                 break;
       
   813               case ASGBITAND:
       
   814                 e = new AssignBitAndExpression(scan(), e, parseTerm());
       
   815                 break;
       
   816               case ASGBITOR:
       
   817                 e = new AssignBitOrExpression(scan(), e, parseTerm());
       
   818                 break;
       
   819               case ASGBITXOR:
       
   820                 e = new AssignBitXorExpression(scan(), e, parseTerm());
       
   821                 break;
       
   822               case QUESTIONMARK: {
       
   823                 long p = scan();
       
   824                 Expression second = parseExpression();
       
   825                 expect(COLON);
       
   826                 Expression third = parseExpression();
       
   827 
       
   828                 // The grammar in the JLS does not allow assignment
       
   829                 // expressions as the third part of a ?: expression.
       
   830                 // Even though javac has no trouble parsing this,
       
   831                 // check for this case and signal an error.
       
   832                 // (fix for bug 4092958)
       
   833                 if (third instanceof AssignExpression
       
   834                     || third instanceof AssignOpExpression) {
       
   835                     env.error(third.getWhere(), "assign.in.conditionalexpr");
       
   836                 }
       
   837 
       
   838                 e = new ConditionalExpression(p, e, second, third);
       
   839                 break;
       
   840               }
       
   841 
       
   842               default:
       
   843                 return null; // mark end of binary expressions
       
   844             }
       
   845         }
       
   846         return e;           // return more binary expression stuff
       
   847     }
       
   848 
       
   849     /**
       
   850      * Recover after a syntax error in a statement. This involves
       
   851      * discarding tokens until EOF or a possible continuation is
       
   852      * encountered.
       
   853      */
       
   854     protected boolean recoverStatement() throws SyntaxError, IOException {
       
   855         while (true) {
       
   856             switch (token) {
       
   857               case EOF:
       
   858               case RBRACE:
       
   859               case LBRACE:
       
   860               case IF:
       
   861               case FOR:
       
   862               case WHILE:
       
   863               case DO:
       
   864               case TRY:
       
   865               case CATCH:
       
   866               case FINALLY:
       
   867               case BREAK:
       
   868               case CONTINUE:
       
   869               case RETURN:
       
   870                 // begin of a statement, return
       
   871                 return true;
       
   872 
       
   873               case VOID:
       
   874               case STATIC:
       
   875               case PUBLIC:
       
   876               case PRIVATE:
       
   877               case SYNCHRONIZED:
       
   878               case INTERFACE:
       
   879               case CLASS:
       
   880               case TRANSIENT:
       
   881                 // begin of something outside a statement, panic some more
       
   882                 expect(RBRACE);
       
   883                 return false;
       
   884 
       
   885               case LPAREN:
       
   886                 match(LPAREN, RPAREN);
       
   887                 scan();
       
   888                 break;
       
   889 
       
   890               case LSQBRACKET:
       
   891                 match(LSQBRACKET, RSQBRACKET);
       
   892                 scan();
       
   893                 break;
       
   894 
       
   895               default:
       
   896                 // don't know what to do, skip
       
   897                 scan();
       
   898                 break;
       
   899             }
       
   900         }
       
   901     }
       
   902 
       
   903     /**
       
   904      * Parse declaration, called after the type expression
       
   905      * has been parsed and the current token is IDENT.
       
   906      */
       
   907     protected Statement parseDeclaration(long p, int mod, Expression type) throws SyntaxError, IOException {
       
   908         int i = argIndex;
       
   909         if (token == IDENT) {
       
   910             addArgument(new VarDeclarationStatement(pos, parseExpression()));
       
   911             while (token == COMMA) {
       
   912                 scan();
       
   913                 addArgument(new VarDeclarationStatement(pos, parseExpression()));
       
   914             }
       
   915         }
       
   916         return new DeclarationStatement(p, mod, type, statArgs(i));
       
   917     }
       
   918 
       
   919     /**
       
   920      * Check if an expression is a legal toplevel expression.
       
   921      * Only method, inc, dec, and new expression are allowed.
       
   922      */
       
   923     protected void topLevelExpression(Expression e) {
       
   924         switch (e.getOp()) {
       
   925           case ASSIGN:
       
   926           case ASGMUL:
       
   927           case ASGDIV:
       
   928           case ASGREM:
       
   929           case ASGADD:
       
   930           case ASGSUB:
       
   931           case ASGLSHIFT:
       
   932           case ASGRSHIFT:
       
   933           case ASGURSHIFT:
       
   934           case ASGBITAND:
       
   935           case ASGBITOR:
       
   936           case ASGBITXOR:
       
   937           case PREINC:
       
   938           case PREDEC:
       
   939           case POSTINC:
       
   940           case POSTDEC:
       
   941           case METHOD:
       
   942           case NEWINSTANCE:
       
   943             return;
       
   944         }
       
   945         env.error(e.getWhere(), "invalid.expr");
       
   946     }
       
   947 
       
   948     /**
       
   949      * Parse a statement.
       
   950      */
       
   951     protected Statement parseStatement() throws SyntaxError, IOException {
       
   952         switch (token) {
       
   953           case SEMICOLON:
       
   954             return new CompoundStatement(scan(), new Statement[0]);
       
   955 
       
   956           case LBRACE:
       
   957               return parseBlockStatement();
       
   958 
       
   959           case IF: {
       
   960             // if-statement: if (expr) stat
       
   961             // if-statement: if (expr) stat else stat
       
   962             long p = scan();
       
   963 
       
   964             expect(LPAREN);
       
   965             Expression c = parseExpression();
       
   966             expect(RPAREN);
       
   967             Statement t = parseStatement();
       
   968             if (token == ELSE) {
       
   969                 scan();
       
   970                 return new IfStatement(p, c, t, parseStatement());
       
   971             } else {
       
   972                 return new IfStatement(p, c, t, null);
       
   973             }
       
   974           }
       
   975 
       
   976           case ELSE: {
       
   977             // else-statement: else stat
       
   978             env.error(scan(), "else.without.if");
       
   979             return parseStatement();
       
   980           }
       
   981 
       
   982           case FOR: {
       
   983             // for-statement: for (decl-expr? ; expr? ; expr?) stat
       
   984             long p = scan();
       
   985             Statement init = null;
       
   986             Expression cond = null, inc = null;
       
   987 
       
   988             expect(LPAREN);
       
   989             if (token != SEMICOLON) {
       
   990                 long p2 = pos;
       
   991                 int mod = parseModifiers(M_FINAL);
       
   992                 Expression e = parseExpression();
       
   993 
       
   994                 if (token == IDENT) {
       
   995                     init = parseDeclaration(p2, mod, e);
       
   996                 } else {
       
   997                     if (mod != 0) {
       
   998                         expect(IDENT); // should have been a declaration
       
   999                     }
       
  1000                     topLevelExpression(e);
       
  1001                     while (token == COMMA) {
       
  1002                         long p3 = scan();
       
  1003                         Expression e2 = parseExpression();
       
  1004                         topLevelExpression(e2);
       
  1005                         e = new CommaExpression(p3, e, e2);
       
  1006                     }
       
  1007                     init = new ExpressionStatement(p2, e);
       
  1008                 }
       
  1009             }
       
  1010             expect(SEMICOLON);
       
  1011             if (token != SEMICOLON) {
       
  1012                 cond = parseExpression();
       
  1013             }
       
  1014             expect(SEMICOLON);
       
  1015             if (token != RPAREN) {
       
  1016                 inc = parseExpression();
       
  1017                 topLevelExpression(inc);
       
  1018                 while (token == COMMA) {
       
  1019                     long p2 = scan();
       
  1020                     Expression e2 = parseExpression();
       
  1021                     topLevelExpression(e2);
       
  1022                     inc = new CommaExpression(p2, inc, e2);
       
  1023                 }
       
  1024             }
       
  1025             expect(RPAREN);
       
  1026             return new ForStatement(p, init, cond, inc, parseStatement());
       
  1027           }
       
  1028 
       
  1029           case WHILE: {
       
  1030             // while-statement: while (expr) stat
       
  1031             long p = scan();
       
  1032 
       
  1033             expect(LPAREN);
       
  1034             Expression cond = parseExpression();
       
  1035             expect(RPAREN);
       
  1036             return new WhileStatement(p, cond, parseStatement());
       
  1037           }
       
  1038 
       
  1039           case DO: {
       
  1040             // do-statement: do stat while (expr)
       
  1041             long p = scan();
       
  1042 
       
  1043             Statement body = parseStatement();
       
  1044             expect(WHILE);
       
  1045             expect(LPAREN);
       
  1046             Expression cond = parseExpression();
       
  1047             expect(RPAREN);
       
  1048             expect(SEMICOLON);
       
  1049             return new DoStatement(p, body, cond);
       
  1050           }
       
  1051 
       
  1052           case BREAK: {
       
  1053             // break-statement: break ;
       
  1054             long p = scan();
       
  1055             Identifier label = null;
       
  1056 
       
  1057             if (token == IDENT) {
       
  1058                 label = scanner.idValue;
       
  1059                 scan();
       
  1060             }
       
  1061             expect(SEMICOLON);
       
  1062             return new BreakStatement(p, label);
       
  1063           }
       
  1064 
       
  1065           case CONTINUE: {
       
  1066             // continue-statement: continue ;
       
  1067             long p = scan();
       
  1068             Identifier label = null;
       
  1069 
       
  1070             if (token == IDENT) {
       
  1071                 label = scanner.idValue;
       
  1072                 scan();
       
  1073             }
       
  1074             expect(SEMICOLON);
       
  1075             return new ContinueStatement(p, label);
       
  1076           }
       
  1077 
       
  1078           case RETURN: {
       
  1079             // return-statement: return ;
       
  1080             // return-statement: return expr ;
       
  1081             long p = scan();
       
  1082             Expression e = null;
       
  1083 
       
  1084             if (token != SEMICOLON) {
       
  1085                 e = parseExpression();
       
  1086             }
       
  1087             expect(SEMICOLON);
       
  1088             return new ReturnStatement(p, e);
       
  1089           }
       
  1090 
       
  1091           case SWITCH: {
       
  1092             // switch statement: switch ( expr ) stat
       
  1093             long p = scan();
       
  1094             int i = argIndex;
       
  1095 
       
  1096             expect(LPAREN);
       
  1097             Expression e = parseExpression();
       
  1098             expect(RPAREN);
       
  1099             expect(LBRACE);
       
  1100 
       
  1101             while ((token != EOF) && (token != RBRACE)) {
       
  1102                 int j = argIndex;
       
  1103                 try {
       
  1104                     switch (token) {
       
  1105                       case CASE:
       
  1106                         // case-statement: case expr:
       
  1107                         addArgument(new CaseStatement(scan(), parseExpression()));
       
  1108                         expect(COLON);
       
  1109                         break;
       
  1110 
       
  1111                       case DEFAULT:
       
  1112                         // default-statement: default:
       
  1113                         addArgument(new CaseStatement(scan(), null));
       
  1114                         expect(COLON);
       
  1115                         break;
       
  1116 
       
  1117                       default:
       
  1118                         addArgument(parseStatement());
       
  1119                         break;
       
  1120                     }
       
  1121                 } catch (SyntaxError ee) {
       
  1122                     argIndex = j;
       
  1123                     if (!recoverStatement()) {
       
  1124                         throw ee;
       
  1125                     }
       
  1126                 }
       
  1127             }
       
  1128             expect(RBRACE);
       
  1129             return new SwitchStatement(p, e, statArgs(i));
       
  1130           }
       
  1131 
       
  1132           case CASE: {
       
  1133             // case-statement: case expr : stat
       
  1134             env.error(pos, "case.without.switch");
       
  1135             while (token == CASE) {
       
  1136                 scan();
       
  1137                 parseExpression();
       
  1138                 expect(COLON);
       
  1139             }
       
  1140             return parseStatement();
       
  1141           }
       
  1142 
       
  1143           case DEFAULT: {
       
  1144             // default-statement: default : stat
       
  1145             env.error(pos, "default.without.switch");
       
  1146             scan();
       
  1147             expect(COLON);
       
  1148             return parseStatement();
       
  1149           }
       
  1150 
       
  1151           case TRY: {
       
  1152             // try-statement: try stat catch (type-expr ident) stat finally stat
       
  1153             long p = scan();
       
  1154             Statement init = null;              // try-object specification
       
  1155             int i = argIndex;
       
  1156             boolean catches = false;
       
  1157 
       
  1158             if (false && token == LPAREN) {
       
  1159                 expect(LPAREN);
       
  1160                 long p2 = pos;
       
  1161                 int mod = parseModifiers(M_FINAL);
       
  1162                 Expression e = parseExpression();
       
  1163 
       
  1164                 if (token == IDENT) {
       
  1165                     init = parseDeclaration(p2, mod, e);
       
  1166                     // leave check for try (T x, y) for semantic phase
       
  1167                 } else {
       
  1168                     if (mod != 0) {
       
  1169                         expect(IDENT); // should have been a declaration
       
  1170                     }
       
  1171                     init = new ExpressionStatement(p2, e);
       
  1172                 }
       
  1173                 expect(RPAREN);
       
  1174             }
       
  1175 
       
  1176             Statement s = parseBlockStatement();
       
  1177 
       
  1178             if (init != null) {
       
  1179                 // s = new FinallyStatement(p, init, s, 0);
       
  1180             }
       
  1181 
       
  1182             while (token == CATCH) {
       
  1183                 long pp = pos;
       
  1184                 expect(CATCH);
       
  1185                 expect(LPAREN);
       
  1186                 int mod = parseModifiers(M_FINAL);
       
  1187                 Expression t = parseExpression();
       
  1188                 IdentifierToken id = scanner.getIdToken();
       
  1189                 expect(IDENT);
       
  1190                 id.modifiers = mod;
       
  1191                 // We only catch Throwable's, so this is no longer required
       
  1192                 // while (token == LSQBRACKET) {
       
  1193                 //    t = new ArrayAccessExpression(scan(), t, null);
       
  1194                 //    expect(RSQBRACKET);
       
  1195                 // }
       
  1196                 expect(RPAREN);
       
  1197                 addArgument(new CatchStatement(pp, t, id, parseBlockStatement()));
       
  1198                 catches = true;
       
  1199             }
       
  1200 
       
  1201             if (catches)
       
  1202                 s = new TryStatement(p, s, statArgs(i));
       
  1203 
       
  1204             if (token == FINALLY) {
       
  1205                 scan();
       
  1206                 return new FinallyStatement(p, s, parseBlockStatement());
       
  1207             } else if (catches || init != null) {
       
  1208                 return s;
       
  1209             } else {
       
  1210                 env.error(pos, "try.without.catch.finally");
       
  1211                 return new TryStatement(p, s, null);
       
  1212             }
       
  1213           }
       
  1214 
       
  1215           case CATCH: {
       
  1216             // catch-statement: catch (expr ident) stat finally stat
       
  1217             env.error(pos, "catch.without.try");
       
  1218 
       
  1219             Statement s;
       
  1220             do {
       
  1221                 scan();
       
  1222                 expect(LPAREN);
       
  1223                 parseModifiers(M_FINAL);
       
  1224                 parseExpression();
       
  1225                 expect(IDENT);
       
  1226                 expect(RPAREN);
       
  1227                 s = parseBlockStatement();
       
  1228             } while (token == CATCH);
       
  1229 
       
  1230             if (token == FINALLY) {
       
  1231                 scan();
       
  1232                 s = parseBlockStatement();
       
  1233             }
       
  1234             return s;
       
  1235           }
       
  1236 
       
  1237           case FINALLY: {
       
  1238             // finally-statement: finally stat
       
  1239             env.error(pos, "finally.without.try");
       
  1240             scan();
       
  1241             return parseBlockStatement();
       
  1242           }
       
  1243 
       
  1244           case THROW: {
       
  1245             // throw-statement: throw expr;
       
  1246             long p = scan();
       
  1247             Expression e = parseExpression();
       
  1248             expect(SEMICOLON);
       
  1249             return new ThrowStatement(p, e);
       
  1250           }
       
  1251 
       
  1252           case GOTO: {
       
  1253             long p = scan();
       
  1254             expect(IDENT);
       
  1255             expect(SEMICOLON);
       
  1256             env.error(p, "not.supported", "goto");
       
  1257             return new CompoundStatement(p, new Statement[0]);
       
  1258           }
       
  1259 
       
  1260           case SYNCHRONIZED: {
       
  1261             // synchronized-statement: synchronized (expr) stat
       
  1262             long p = scan();
       
  1263             expect(LPAREN);
       
  1264             Expression e = parseExpression();
       
  1265             expect(RPAREN);
       
  1266             return new SynchronizedStatement(p, e, parseBlockStatement());
       
  1267           }
       
  1268 
       
  1269           case INTERFACE:
       
  1270           case CLASS:
       
  1271             // Inner class.
       
  1272             return parseLocalClass(0);
       
  1273 
       
  1274           case CONST:
       
  1275           case ABSTRACT:
       
  1276           case FINAL:
       
  1277           case STRICTFP: {
       
  1278             // a declaration of some sort
       
  1279             long p = pos;
       
  1280 
       
  1281             // A class which is local to a block is not a member, and so
       
  1282             // cannot be public, private, protected, or static. It is in
       
  1283             // effect private to the block, since it cannot be used outside
       
  1284             // its scope.
       
  1285             //
       
  1286             // However, any class (if it has a name) can be declared final,
       
  1287             // abstract, or strictfp.
       
  1288             int mod = parseModifiers(M_FINAL | M_ABSTRACT
       
  1289                                              | M_STRICTFP );
       
  1290 
       
  1291             switch (token) {
       
  1292               case INTERFACE:
       
  1293               case CLASS:
       
  1294                 return parseLocalClass(mod);
       
  1295 
       
  1296               case BOOLEAN:
       
  1297               case BYTE:
       
  1298               case CHAR:
       
  1299               case SHORT:
       
  1300               case INT:
       
  1301               case LONG:
       
  1302               case FLOAT:
       
  1303               case DOUBLE:
       
  1304               case IDENT: {
       
  1305                 if ((mod & (M_ABSTRACT | M_STRICTFP )) != 0) {
       
  1306                     mod &= ~ (M_ABSTRACT | M_STRICTFP );
       
  1307                     expect(CLASS);
       
  1308                 }
       
  1309                 Expression e = parseExpression();
       
  1310                 if (token != IDENT) {
       
  1311                     expect(IDENT);
       
  1312                 }
       
  1313                 // declaration: final expr expr
       
  1314                 Statement s = parseDeclaration(p, mod, e);
       
  1315                 expect(SEMICOLON);
       
  1316                 return s;
       
  1317               }
       
  1318 
       
  1319               default:
       
  1320                 env.error(pos, "type.expected");
       
  1321                 throw new SyntaxError();
       
  1322             }
       
  1323           }
       
  1324 
       
  1325           case VOID:
       
  1326           case STATIC:
       
  1327           case PUBLIC:
       
  1328           case PRIVATE:
       
  1329           case TRANSIENT:
       
  1330             // This is the start of something outside a statement
       
  1331             env.error(pos, "statement.expected");
       
  1332             throw new SyntaxError();
       
  1333         }
       
  1334 
       
  1335         long p = pos;
       
  1336         Expression e = parseExpression();
       
  1337 
       
  1338         if (token == IDENT) {
       
  1339             // declaration: expr expr
       
  1340             Statement s = parseDeclaration(p, 0, e);
       
  1341             expect(SEMICOLON);
       
  1342             return s;
       
  1343         }
       
  1344         if (token == COLON) {
       
  1345             // label: id: stat
       
  1346             scan();
       
  1347             Statement s = parseStatement();
       
  1348             s.setLabel(env, e);
       
  1349             return s;
       
  1350         }
       
  1351 
       
  1352         // it was just an expression...
       
  1353         topLevelExpression(e);
       
  1354         expect(SEMICOLON);
       
  1355         return new ExpressionStatement(p, e);
       
  1356     }
       
  1357 
       
  1358     protected Statement parseBlockStatement() throws SyntaxError, IOException {
       
  1359         // compound statement: { stat1 stat2 ... statn }
       
  1360         if (token != LBRACE) {
       
  1361             // We're expecting a block statement.  But we'll probably do the
       
  1362             // least damage if we try to parse a normal statement instead.
       
  1363             env.error(scanner.prevPos, "token.expected", opNames[LBRACE]);
       
  1364             return parseStatement();
       
  1365         }
       
  1366         long p = scan();
       
  1367         int i = argIndex;
       
  1368         while ((token != EOF) && (token != RBRACE)) {
       
  1369             int j = argIndex;
       
  1370             try {
       
  1371                 addArgument(parseStatement());
       
  1372             } catch (SyntaxError e) {
       
  1373                 argIndex = j;
       
  1374                 if (!recoverStatement()) {
       
  1375                     throw e;
       
  1376                 }
       
  1377             }
       
  1378         }
       
  1379 
       
  1380         expect(RBRACE);
       
  1381         return new CompoundStatement(p, statArgs(i));
       
  1382     }
       
  1383 
       
  1384 
       
  1385     /**
       
  1386      * Parse an identifier. ie: a.b.c returns "a.b.c"
       
  1387      * If star is true then "a.b.*" is allowed.
       
  1388      * The return value encodes both the identifier and its location.
       
  1389      */
       
  1390     protected IdentifierToken parseName(boolean star) throws SyntaxError, IOException {
       
  1391         IdentifierToken res = scanner.getIdToken();
       
  1392         expect(IDENT);
       
  1393 
       
  1394         if (token != FIELD) {
       
  1395             return res;
       
  1396         }
       
  1397 
       
  1398         StringBuffer buf = new StringBuffer(res.id.toString());
       
  1399 
       
  1400         while (token == FIELD) {
       
  1401             scan();
       
  1402             if ((token == MUL) && star) {
       
  1403                 scan();
       
  1404                 buf.append(".*");
       
  1405                 break;
       
  1406             }
       
  1407 
       
  1408             buf.append('.');
       
  1409             if (token == IDENT) {
       
  1410                 buf.append(scanner.idValue);
       
  1411             }
       
  1412             expect(IDENT);
       
  1413         }
       
  1414 
       
  1415         res.id = Identifier.lookup(buf.toString());
       
  1416         return res;
       
  1417     }
       
  1418     /**
       
  1419      * @deprecated
       
  1420      * @see #parseName
       
  1421      */
       
  1422     @Deprecated
       
  1423     protected Identifier parseIdentifier(boolean star) throws SyntaxError, IOException {
       
  1424         return parseName(star).id;
       
  1425     }
       
  1426 
       
  1427     /**
       
  1428      * Parse a type expression, this results in a Type.
       
  1429      * The parse includes trailing array brackets.
       
  1430      */
       
  1431     protected Type parseType() throws SyntaxError, IOException {
       
  1432         Type t;
       
  1433 
       
  1434         switch (token) {
       
  1435           case IDENT:
       
  1436             t = Type.tClass(parseName(false).id);
       
  1437             break;
       
  1438           case VOID:
       
  1439             scan();
       
  1440             t = Type.tVoid;
       
  1441             break;
       
  1442           case BOOLEAN:
       
  1443             scan();
       
  1444             t = Type.tBoolean;
       
  1445             break;
       
  1446           case BYTE:
       
  1447             scan();
       
  1448             t = Type.tByte;
       
  1449             break;
       
  1450           case CHAR:
       
  1451             scan();
       
  1452             t = Type.tChar;
       
  1453             break;
       
  1454           case SHORT:
       
  1455             scan();
       
  1456             t = Type.tShort;
       
  1457             break;
       
  1458           case INT:
       
  1459             scan();
       
  1460             t = Type.tInt;
       
  1461             break;
       
  1462           case FLOAT:
       
  1463             scan();
       
  1464             t = Type.tFloat;
       
  1465             break;
       
  1466           case LONG:
       
  1467             scan();
       
  1468             t = Type.tLong;
       
  1469             break;
       
  1470           case DOUBLE:
       
  1471             scan();
       
  1472             t = Type.tDouble;
       
  1473             break;
       
  1474           default:
       
  1475             env.error(pos, "type.expected");
       
  1476             throw new SyntaxError();
       
  1477         }
       
  1478         return parseArrayBrackets(t);
       
  1479     }
       
  1480 
       
  1481     /**
       
  1482      * Parse the tail of a type expression, which might be array brackets.
       
  1483      * Return the given type, as possibly modified by the suffix.
       
  1484      */
       
  1485     protected Type parseArrayBrackets(Type t) throws SyntaxError, IOException {
       
  1486 
       
  1487         // Parse []'s
       
  1488         while (token == LSQBRACKET) {
       
  1489             scan();
       
  1490             if (token != RSQBRACKET) {
       
  1491                 env.error(pos, "array.dim.in.decl");
       
  1492                 parseExpression();
       
  1493             }
       
  1494             expect(RSQBRACKET);
       
  1495             t = Type.tArray(t);
       
  1496         }
       
  1497         return t;
       
  1498     }
       
  1499 
       
  1500     /*
       
  1501      * Dealing with argument lists, I'm not using
       
  1502      * Vector for efficiency.
       
  1503      */
       
  1504 
       
  1505     private int aCount = 0;
       
  1506     private Type aTypes[] = new Type[8];
       
  1507     private IdentifierToken aNames[] = new IdentifierToken[aTypes.length];
       
  1508 
       
  1509     private void addArgument(int mod, Type t, IdentifierToken nm) {
       
  1510         nm.modifiers = mod;
       
  1511         if (aCount >= aTypes.length) {
       
  1512             Type newATypes[] = new Type[aCount * 2];
       
  1513             System.arraycopy(aTypes, 0, newATypes, 0, aCount);
       
  1514             aTypes = newATypes;
       
  1515             IdentifierToken newANames[] = new IdentifierToken[aCount * 2];
       
  1516             System.arraycopy(aNames, 0, newANames, 0, aCount);
       
  1517             aNames = newANames;
       
  1518         }
       
  1519         aTypes[aCount] = t;
       
  1520         aNames[aCount++] = nm;
       
  1521     }
       
  1522 
       
  1523     /**
       
  1524      * Parse a possibly-empty sequence of modifier keywords.
       
  1525      * Return the resulting bitmask.
       
  1526      * Diagnose repeated modifiers, but make no other checks.
       
  1527      * Only modifiers mentioned in the given bitmask are scanned;
       
  1528      * an unmatched modifier must be handled by the caller.
       
  1529      */
       
  1530     protected int parseModifiers(int mask) throws IOException {
       
  1531         int mod = 0;
       
  1532         while (true) {
       
  1533             if (token==CONST) {
       
  1534                 // const isn't in java, but handle a common C++ usage gently
       
  1535                 env.error(pos, "not.supported", "const");
       
  1536                 scan();
       
  1537             }
       
  1538             int nextmod = 0;
       
  1539             switch (token) {
       
  1540                case PRIVATE:            nextmod = M_PRIVATE;      break;
       
  1541                case PUBLIC:             nextmod = M_PUBLIC;       break;
       
  1542                case PROTECTED:          nextmod = M_PROTECTED;    break;
       
  1543                case STATIC:             nextmod = M_STATIC;       break;
       
  1544                case TRANSIENT:          nextmod = M_TRANSIENT;    break;
       
  1545                case FINAL:              nextmod = M_FINAL;        break;
       
  1546                case ABSTRACT:           nextmod = M_ABSTRACT;     break;
       
  1547                case NATIVE:             nextmod = M_NATIVE;       break;
       
  1548                case VOLATILE:           nextmod = M_VOLATILE;     break;
       
  1549                case SYNCHRONIZED:       nextmod = M_SYNCHRONIZED; break;
       
  1550                case STRICTFP:           nextmod = M_STRICTFP;     break;
       
  1551             }
       
  1552             if ((nextmod & mask) == 0) {
       
  1553                 break;
       
  1554             }
       
  1555             if ((nextmod & mod) != 0) {
       
  1556                 env.error(pos, "repeated.modifier");
       
  1557             }
       
  1558             mod |= nextmod;
       
  1559             scan();
       
  1560         }
       
  1561         return mod;
       
  1562     }
       
  1563 
       
  1564     private ClassDefinition curClass;
       
  1565 
       
  1566     /**
       
  1567      * Parse a field.
       
  1568      */
       
  1569     protected void parseField() throws SyntaxError, IOException {
       
  1570 
       
  1571         // Empty fields are not allowed by the JLS but are accepted by
       
  1572         // the compiler, and much code has come to rely on this.  It has
       
  1573         // been decided that the language will be extended to legitimize them.
       
  1574         if (token == SEMICOLON) {
       
  1575             // empty field
       
  1576             scan();
       
  1577             return;
       
  1578         }
       
  1579 
       
  1580         // Optional doc comment
       
  1581         String doc = scanner.docComment;
       
  1582 
       
  1583         // The start of the field
       
  1584         long p = pos;
       
  1585 
       
  1586         // Parse the modifiers
       
  1587         int mod = parseModifiers(MM_FIELD | MM_METHOD);
       
  1588 
       
  1589         // Check for static initializer
       
  1590         // ie: static { ... }
       
  1591         // or an instance initializer (w/o the static).
       
  1592         if ((mod == (mod & M_STATIC)) && (token == LBRACE)) {
       
  1593             // static initializer
       
  1594             actions.defineField(p, curClass, doc, mod,
       
  1595                                 Type.tMethod(Type.tVoid),
       
  1596                                 new IdentifierToken(idClassInit), null, null,
       
  1597                                 parseStatement());
       
  1598             return;
       
  1599         }
       
  1600 
       
  1601         // Check for inner class
       
  1602         if (token == CLASS || token == INTERFACE) {
       
  1603             parseNamedClass(mod, CLASS, doc);
       
  1604             return;
       
  1605         }
       
  1606 
       
  1607         // Parse the type
       
  1608         p = pos;
       
  1609         Type t = parseType();
       
  1610         IdentifierToken id = null;
       
  1611 
       
  1612         // Check that the type is followed by an Identifier
       
  1613         // (the name of the method or the first variable),
       
  1614         // otherwise it is a constructor.
       
  1615         switch (token) {
       
  1616           case IDENT:
       
  1617             id = scanner.getIdToken();
       
  1618             p = scan();
       
  1619             break;
       
  1620 
       
  1621           case LPAREN:
       
  1622             // It is a constructor
       
  1623             id = new IdentifierToken(idInit);
       
  1624             if ((mod & M_STRICTFP) != 0)
       
  1625                 env.error(pos, "bad.constructor.modifier");
       
  1626             break;
       
  1627 
       
  1628           default:
       
  1629             expect(IDENT);
       
  1630         }
       
  1631 
       
  1632         // If the next token is a left-bracket then we
       
  1633         // are dealing with a method or constructor, otherwise it is
       
  1634         // a list of variables
       
  1635         if (token == LPAREN) {
       
  1636             // It is a method or constructor declaration
       
  1637             scan();
       
  1638             aCount = 0;
       
  1639 
       
  1640             if (token != RPAREN) {
       
  1641                 // Parse argument type and identifier
       
  1642                 // (arguments (like locals) are allowed to be final)
       
  1643                 int am = parseModifiers(M_FINAL);
       
  1644                 Type at = parseType();
       
  1645                 IdentifierToken an = scanner.getIdToken();
       
  1646                 expect(IDENT);
       
  1647 
       
  1648                 // Parse optional array specifier, ie: a[][]
       
  1649                 at = parseArrayBrackets(at);
       
  1650                 addArgument(am, at, an);
       
  1651 
       
  1652                 // If the next token is a comma then there are
       
  1653                 // more arguments
       
  1654                 while (token == COMMA) {
       
  1655                     // Parse argument type and identifier
       
  1656                     scan();
       
  1657                     am = parseModifiers(M_FINAL);
       
  1658                     at = parseType();
       
  1659                     an = scanner.getIdToken();
       
  1660                     expect(IDENT);
       
  1661 
       
  1662                     // Parse optional array specifier, ie: a[][]
       
  1663                     at = parseArrayBrackets(at);
       
  1664                     addArgument(am, at, an);
       
  1665                 }
       
  1666             }
       
  1667             expect(RPAREN);
       
  1668 
       
  1669             // Parse optional array sepecifier, ie: foo()[][]
       
  1670             t = parseArrayBrackets(t);
       
  1671 
       
  1672             // copy arguments
       
  1673             Type atypes[] = new Type[aCount];
       
  1674             System.arraycopy(aTypes, 0, atypes, 0, aCount);
       
  1675 
       
  1676             IdentifierToken anames[] = new IdentifierToken[aCount];
       
  1677             System.arraycopy(aNames, 0, anames, 0, aCount);
       
  1678 
       
  1679             // Construct the type signature
       
  1680             t = Type.tMethod(t, atypes);
       
  1681 
       
  1682             // Parse and ignore throws clause
       
  1683             IdentifierToken exp[] = null;
       
  1684             if (token == THROWS) {
       
  1685                 Vector v = new Vector();
       
  1686                 scan();
       
  1687                 v.addElement(parseName(false));
       
  1688                 while (token == COMMA) {
       
  1689                     scan();
       
  1690                     v.addElement(parseName(false));
       
  1691                 }
       
  1692 
       
  1693                 exp = new IdentifierToken[v.size()];
       
  1694                 v.copyInto(exp);
       
  1695             }
       
  1696 
       
  1697             // Check if it is a method definition or a method declaration
       
  1698             // ie: foo() {...} or foo();
       
  1699             switch (token) {
       
  1700               case LBRACE:      // It's a method definition
       
  1701 
       
  1702                 // Set the state of FP strictness for the body of the method
       
  1703                 int oldFPstate = FPstate;
       
  1704                 if ((mod & M_STRICTFP)!=0) {
       
  1705                     FPstate = M_STRICTFP;
       
  1706                 } else {
       
  1707                     mod |= FPstate & M_STRICTFP;
       
  1708                 }
       
  1709 
       
  1710                 actions.defineField(p, curClass, doc, mod, t, id,
       
  1711                                     anames, exp, parseStatement());
       
  1712 
       
  1713                 FPstate = oldFPstate;
       
  1714 
       
  1715                 break;
       
  1716 
       
  1717               case SEMICOLON:
       
  1718                 scan();
       
  1719                 actions.defineField(p, curClass, doc, mod, t, id,
       
  1720                                     anames, exp, null);
       
  1721                 break;
       
  1722 
       
  1723               default:
       
  1724                 // really expected a statement body here
       
  1725                 if ((mod & (M_NATIVE | M_ABSTRACT)) == 0) {
       
  1726                     expect(LBRACE);
       
  1727                 } else {
       
  1728                     expect(SEMICOLON);
       
  1729                 }
       
  1730             }
       
  1731             return;
       
  1732         }
       
  1733 
       
  1734         // It is a list of instance variables
       
  1735         while (true) {
       
  1736             p = pos;            // get the current position
       
  1737             // parse the array brackets (if any)
       
  1738             // ie: var[][][]
       
  1739             Type vt = parseArrayBrackets(t);
       
  1740 
       
  1741             // Parse the optional initializer
       
  1742             Node init = null;
       
  1743             if (token == ASSIGN) {
       
  1744                 scan();
       
  1745                 init = parseExpression();
       
  1746             }
       
  1747 
       
  1748             // Define the variable
       
  1749             actions.defineField(p, curClass, doc, mod, vt, id,
       
  1750                                 null, null, init);
       
  1751 
       
  1752             // If the next token is a comma, then there is more
       
  1753             if (token != COMMA) {
       
  1754                 expect(SEMICOLON);
       
  1755                 return;
       
  1756             }
       
  1757             scan();
       
  1758 
       
  1759             // The next token must be an identifier
       
  1760             id = scanner.getIdToken();
       
  1761             expect(IDENT);
       
  1762         }
       
  1763     }
       
  1764 
       
  1765     /**
       
  1766      * Recover after a syntax error in a field. This involves
       
  1767      * discarding tokens until an EOF or a possible legal
       
  1768      * continuation is encountered.
       
  1769      */
       
  1770     protected void recoverField(ClassDefinition newClass) throws SyntaxError, IOException {
       
  1771         while (true) {
       
  1772             switch (token) {
       
  1773               case EOF:
       
  1774               case STATIC:
       
  1775               case FINAL:
       
  1776               case PUBLIC:
       
  1777               case PRIVATE:
       
  1778               case SYNCHRONIZED:
       
  1779               case TRANSIENT:
       
  1780 
       
  1781               case VOID:
       
  1782               case BOOLEAN:
       
  1783               case BYTE:
       
  1784               case CHAR:
       
  1785               case SHORT:
       
  1786               case INT:
       
  1787               case FLOAT:
       
  1788               case LONG:
       
  1789               case DOUBLE:
       
  1790                 // possible begin of a field, continue
       
  1791                 return;
       
  1792 
       
  1793               case LBRACE:
       
  1794                 match(LBRACE, RBRACE);
       
  1795                 scan();
       
  1796                 break;
       
  1797 
       
  1798               case LPAREN:
       
  1799                 match(LPAREN, RPAREN);
       
  1800                 scan();
       
  1801                 break;
       
  1802 
       
  1803               case LSQBRACKET:
       
  1804                 match(LSQBRACKET, RSQBRACKET);
       
  1805                 scan();
       
  1806                 break;
       
  1807 
       
  1808               case RBRACE:
       
  1809               case INTERFACE:
       
  1810               case CLASS:
       
  1811               case IMPORT:
       
  1812               case PACKAGE:
       
  1813                 // begin of something outside a class, panic more
       
  1814                 actions.endClass(pos, newClass);
       
  1815                 throw new SyntaxError();
       
  1816 
       
  1817               default:
       
  1818                 // don't know what to do, skip
       
  1819                 scan();
       
  1820                 break;
       
  1821             }
       
  1822         }
       
  1823     }
       
  1824 
       
  1825     /**
       
  1826      * Parse a top-level class or interface declaration.
       
  1827      */
       
  1828     protected void parseClass() throws SyntaxError, IOException {
       
  1829         String doc = scanner.docComment;
       
  1830 
       
  1831         // Parse the modifiers.
       
  1832         int mod = parseModifiers(MM_CLASS | MM_MEMBER);
       
  1833 
       
  1834         parseNamedClass(mod, PACKAGE, doc);
       
  1835     }
       
  1836 
       
  1837     // Current strict/default state of floating point.  This is
       
  1838     // set and reset with a stack discipline around methods and named
       
  1839     // classes.  Only M_STRICTFP may be set in this word.  try...
       
  1840     // finally is not needed to protect setting and resetting because
       
  1841     // there are no error messages based on FPstate.
       
  1842     private int FPstate = 0;
       
  1843 
       
  1844     /**
       
  1845      * Parse a block-local class or interface declaration.
       
  1846      */
       
  1847     protected Statement parseLocalClass(int mod) throws SyntaxError, IOException {
       
  1848         long p = pos;
       
  1849         ClassDefinition body = parseNamedClass(M_LOCAL | mod, STAT, null);
       
  1850         Statement ds[] = {
       
  1851             new VarDeclarationStatement(p, new LocalMember(body), null)
       
  1852         };
       
  1853         Expression type = new TypeExpression(p, body.getType());
       
  1854         return new DeclarationStatement(p, 0, type, ds);
       
  1855     }
       
  1856 
       
  1857     /**
       
  1858      * Parse a named class or interface declaration,
       
  1859      * starting at "class" or "interface".
       
  1860      * @arg ctx Syntactic context of the class, one of {PACKAGE CLASS STAT EXPR}.
       
  1861      */
       
  1862     protected ClassDefinition parseNamedClass(int mod, int ctx, String doc) throws SyntaxError, IOException {
       
  1863         // Parse class/interface
       
  1864         switch (token) {
       
  1865           case INTERFACE:
       
  1866             scan();
       
  1867             mod |= M_INTERFACE;
       
  1868             break;
       
  1869 
       
  1870           case CLASS:
       
  1871             scan();
       
  1872             break;
       
  1873 
       
  1874           default:
       
  1875             env.error(pos, "class.expected");
       
  1876             break;
       
  1877         }
       
  1878 
       
  1879         int oldFPstate = FPstate;
       
  1880         if ((mod & M_STRICTFP)!=0) {
       
  1881             FPstate = M_STRICTFP;
       
  1882         } else {
       
  1883             // The & (...) isn't really necessary here because we do maintain
       
  1884             // the invariant that FPstate has no extra bits set.
       
  1885             mod |= FPstate & M_STRICTFP;
       
  1886         }
       
  1887 
       
  1888         // Parse the class name
       
  1889         IdentifierToken nm = scanner.getIdToken();
       
  1890         long p = pos;
       
  1891         expect(IDENT);
       
  1892 
       
  1893         Vector ext = new Vector();
       
  1894         Vector impl = new Vector();
       
  1895         parseInheritance(ext, impl);
       
  1896 
       
  1897         ClassDefinition tmp = parseClassBody(nm, mod, ctx, doc, ext, impl, p);
       
  1898 
       
  1899         FPstate = oldFPstate;
       
  1900 
       
  1901         return tmp;
       
  1902     }
       
  1903 
       
  1904     protected void parseInheritance(Vector ext, Vector impl) throws SyntaxError, IOException {
       
  1905         // Parse extends clause
       
  1906         if (token == EXTENDS) {
       
  1907             scan();
       
  1908             ext.addElement(parseName(false));
       
  1909             while (token == COMMA) {
       
  1910                 scan();
       
  1911                 ext.addElement(parseName(false));
       
  1912             }
       
  1913         }
       
  1914 
       
  1915         // Parse implements clause
       
  1916         if (token == IMPLEMENTS) {
       
  1917             scan();
       
  1918             impl.addElement(parseName(false));
       
  1919             while (token == COMMA) {
       
  1920                 scan();
       
  1921                 impl.addElement(parseName(false));
       
  1922             }
       
  1923         }
       
  1924     }
       
  1925 
       
  1926     /**
       
  1927      * Parse the body of a class or interface declaration,
       
  1928      * starting at the left brace.
       
  1929      */
       
  1930     protected ClassDefinition parseClassBody(IdentifierToken nm, int mod,
       
  1931                                              int ctx, String doc,
       
  1932                                              Vector ext, Vector impl, long p
       
  1933                                              ) throws SyntaxError, IOException {
       
  1934         // Decide which is the super class
       
  1935         IdentifierToken sup = null;
       
  1936         if ((mod & M_INTERFACE) != 0) {
       
  1937             if (impl.size() > 0) {
       
  1938                 env.error(((IdentifierToken)impl.elementAt(0)).getWhere(),
       
  1939                           "intf.impl.intf");
       
  1940             }
       
  1941             impl = ext;
       
  1942         } else {
       
  1943             if (ext.size() > 0) {
       
  1944                 if (ext.size() > 1) {
       
  1945                     env.error(((IdentifierToken)ext.elementAt(1)).getWhere(),
       
  1946                               "multiple.inherit");
       
  1947                 }
       
  1948                 sup = (IdentifierToken)ext.elementAt(0);
       
  1949             }
       
  1950         }
       
  1951 
       
  1952         ClassDefinition oldClass = curClass;
       
  1953 
       
  1954         // Begin a new class
       
  1955         IdentifierToken implids[] = new IdentifierToken[impl.size()];
       
  1956         impl.copyInto(implids);
       
  1957         ClassDefinition newClass =
       
  1958             actions.beginClass(p, doc, mod, nm, sup, implids);
       
  1959 
       
  1960         // Parse fields
       
  1961         expect(LBRACE);
       
  1962         while ((token != EOF) && (token != RBRACE)) {
       
  1963             try {
       
  1964                 curClass = newClass;
       
  1965                 parseField();
       
  1966             } catch (SyntaxError e) {
       
  1967                 recoverField(newClass);
       
  1968             } finally {
       
  1969                 curClass = oldClass;
       
  1970             }
       
  1971         }
       
  1972         expect(RBRACE);
       
  1973 
       
  1974         // End the class
       
  1975         actions.endClass(scanner.prevPos, newClass);
       
  1976         return newClass;
       
  1977     }
       
  1978 
       
  1979     /**
       
  1980      * Recover after a syntax error in the file.
       
  1981      * This involves discarding tokens until an EOF
       
  1982      * or a possible legal continuation is encountered.
       
  1983      */
       
  1984     protected void recoverFile() throws IOException {
       
  1985         while (true) {
       
  1986             switch (token) {
       
  1987               case CLASS:
       
  1988               case INTERFACE:
       
  1989                 // Start of a new source file statement, continue
       
  1990                 return;
       
  1991 
       
  1992               case LBRACE:
       
  1993                 match(LBRACE, RBRACE);
       
  1994                 scan();
       
  1995                 break;
       
  1996 
       
  1997               case LPAREN:
       
  1998                 match(LPAREN, RPAREN);
       
  1999                 scan();
       
  2000                 break;
       
  2001 
       
  2002               case LSQBRACKET:
       
  2003                 match(LSQBRACKET, RSQBRACKET);
       
  2004                 scan();
       
  2005                 break;
       
  2006 
       
  2007               case EOF:
       
  2008                 return;
       
  2009 
       
  2010               default:
       
  2011                 // Don't know what to do, skip
       
  2012                 scan();
       
  2013                 break;
       
  2014             }
       
  2015         }
       
  2016     }
       
  2017 
       
  2018     /**
       
  2019      * Parse an Java file.
       
  2020      */
       
  2021     public void parseFile() {
       
  2022         try {
       
  2023             try {
       
  2024                 if (token == PACKAGE) {
       
  2025                     // Package statement
       
  2026                     long p = scan();
       
  2027                     IdentifierToken id = parseName(false);
       
  2028                     expect(SEMICOLON);
       
  2029                     actions.packageDeclaration(p, id);
       
  2030                 }
       
  2031             } catch (SyntaxError e) {
       
  2032                 recoverFile();
       
  2033             }
       
  2034             while (token == IMPORT) {
       
  2035                 try{
       
  2036                     // Import statement
       
  2037                     long p = scan();
       
  2038                     IdentifierToken id = parseName(true);
       
  2039                     expect(SEMICOLON);
       
  2040                     if (id.id.getName().equals(idStar)) {
       
  2041                         id.id = id.id.getQualifier();
       
  2042                         actions.importPackage(p, id);
       
  2043                     } else {
       
  2044                         actions.importClass(p, id);
       
  2045                     }
       
  2046                 } catch (SyntaxError e) {
       
  2047                     recoverFile();
       
  2048                 }
       
  2049             }
       
  2050 
       
  2051             while (token != EOF) {
       
  2052                 try {
       
  2053                     switch (token) {
       
  2054                       case FINAL:
       
  2055                       case PUBLIC:
       
  2056                       case PRIVATE:
       
  2057                       case ABSTRACT:
       
  2058                       case CLASS:
       
  2059                       case INTERFACE:
       
  2060                       case STRICTFP:
       
  2061                         // Start of a class
       
  2062                         parseClass();
       
  2063                         break;
       
  2064 
       
  2065                       case SEMICOLON:
       
  2066                         // Bogus semicolon.
       
  2067                         // According to the JLS (7.6,19.6), a TypeDeclaration
       
  2068                         // may consist of a single semicolon, however, this
       
  2069                         // usage is discouraged (JLS 7.6).  In contrast,
       
  2070                         // a FieldDeclaration may not be empty, and is flagged
       
  2071                         // as an error.  See parseField above.
       
  2072                         scan();
       
  2073                         break;
       
  2074 
       
  2075                       case EOF:
       
  2076                         // The end
       
  2077                         return;
       
  2078 
       
  2079                       default:
       
  2080                         // Oops
       
  2081                         env.error(pos, "toplevel.expected");
       
  2082                         throw new SyntaxError();
       
  2083                     }
       
  2084                 } catch (SyntaxError e) {
       
  2085                     recoverFile();
       
  2086                 }
       
  2087             }
       
  2088         } catch (IOException e) {
       
  2089             env.error(pos, "io.exception", env.getSource());
       
  2090             return;
       
  2091         }
       
  2092     }
       
  2093 
       
  2094     /**
       
  2095      * Usually <code>this.scanner == (Scanner)this</code>.
       
  2096      * However, a delegate scanner can produce tokens for this parser,
       
  2097      * in which case <code>(Scanner)this</code> is unused,
       
  2098      * except for <code>this.token</code> and <code>this.pos</code>
       
  2099      * instance variables which are filled from the real scanner
       
  2100      * by <code>this.scan()</code> and the constructor.
       
  2101      */
       
  2102     protected Scanner scanner;
       
  2103 
       
  2104     // Design Note: We ought to disinherit Parser from Scanner.
       
  2105     // We also should split out the interface ParserActions from
       
  2106     // Parser, and make BatchParser implement ParserActions,
       
  2107     // not extend Parser.  This would split scanning, parsing,
       
  2108     // and class building into distinct responsibility areas.
       
  2109     // (Perhaps tree building could be virtualized too.)
       
  2110 
       
  2111     public long scan() throws IOException {
       
  2112         if (scanner != this && scanner != null) {
       
  2113             long result = scanner.scan();
       
  2114             ((Scanner)this).token = scanner.token;
       
  2115             ((Scanner)this).pos = scanner.pos;
       
  2116             return result;
       
  2117         }
       
  2118         return super.scan();
       
  2119     }
       
  2120 
       
  2121     public void match(int open, int close) throws IOException {
       
  2122         if (scanner != this) {
       
  2123             scanner.match(open, close);
       
  2124             ((Scanner)this).token = scanner.token;
       
  2125             ((Scanner)this).pos = scanner.pos;
       
  2126             return;
       
  2127         }
       
  2128         super.match(open, close);
       
  2129     }
       
  2130 }