Source Code Cross Referenced for Parser.java in  » 6.0-JDK-Modules-sun » tools » sun » tools » java » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » 6.0 JDK Modules sun » tools » sun.tools.java 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        /*
0002:         * Copyright 1994-2004 Sun Microsystems, Inc.  All Rights Reserved.
0003:         * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
0004:         *
0005:         * This code is free software; you can redistribute it and/or modify it
0006:         * under the terms of the GNU General Public License version 2 only, as
0007:         * published by the Free Software Foundation.  Sun designates this
0008:         * particular file as subject to the "Classpath" exception as provided
0009:         * by Sun in the LICENSE file that accompanied this code.
0010:         *
0011:         * This code is distributed in the hope that it will be useful, but WITHOUT
0012:         * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
0013:         * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
0014:         * version 2 for more details (a copy is included in the LICENSE file that
0015:         * accompanied this code).
0016:         *
0017:         * You should have received a copy of the GNU General Public License version
0018:         * 2 along with this work; if not, write to the Free Software Foundation,
0019:         * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
0020:         *
0021:         * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
0022:         * CA 95054 USA or visit www.sun.com if you need additional information or
0023:         * have any questions.
0024:         */
0025:
0026:        package sun.tools.java;
0027:
0028:        import sun.tools.tree.*;
0029:        import java.io.IOException;
0030:        import java.io.InputStream;
0031:        import java.util.Enumeration;
0032:        import java.util.Vector;
0033:
0034:        /**
0035:         * This class is used to parse Java statements and expressions.
0036:         * The result is a parse tree.<p>
0037:         *
0038:         * This class implements an operator precedence parser. Errors are
0039:         * reported to the Environment object, if the error can't be
0040:         * resolved immediately, a SyntaxError exception is thrown.<p>
0041:         *
0042:         * Error recovery is implemented by catching SyntaxError exceptions
0043:         * and discarding input tokens until an input token is reached that
0044:         * is possibly a legal continuation.<p>
0045:         *
0046:         * The parse tree that is constructed represents the input
0047:         * exactly (no rewrites to simpler forms). This is important
0048:         * if the resulting tree is to be used for code formatting in
0049:         * a programming environment. Currently only documentation comments
0050:         * are retained.<p>
0051:         *
0052:         * The parsing algorithm does NOT use any type information. Changes
0053:         * in the type system do not affect the structure of the parse tree.
0054:         * This restriction does introduce an ambiguity an expression of the
0055:         * form: (e1) e2 is assumed to be a cast if e2 does not start with
0056:         * an operator. That means that (a) - b is interpreted as subtract
0057:         * b from a and not cast negative b to type a. However, if a is a
0058:         * simple type (byte, int, ...) then it is assumed to be a cast.<p>
0059:         *
0060:         * WARNING: The contents of this source file are not part of any
0061:         * supported API.  Code that depends on them does so at its own risk:
0062:         * they are subject to change or removal without notice.
0063:         *
0064:         * @author 	Arthur van Hoff
0065:         * @version 1.97, 05/05/07
0066:         */
0067:
0068:        public class Parser extends Scanner implements  ParserActions, Constants {
0069:            /**
0070:             * Create a parser
0071:             */
0072:            protected Parser(Environment env, InputStream in)
0073:                    throws IOException {
0074:                super (env, in);
0075:                this .scanner = this ;
0076:                this .actions = this ;
0077:            }
0078:
0079:            /**
0080:             * Create a parser, given a scanner.
0081:             */
0082:            protected Parser(Scanner scanner) throws IOException {
0083:                super (scanner.env);
0084:                this .scanner = scanner;
0085:                ((Scanner) this ).env = scanner.env;
0086:                ((Scanner) this ).token = scanner.token;
0087:                ((Scanner) this ).pos = scanner.pos;
0088:                this .actions = this ;
0089:            }
0090:
0091:            /**
0092:             * Create a parser, given a scanner and the semantic callback.
0093:             */
0094:            public Parser(Scanner scanner, ParserActions actions)
0095:                    throws IOException {
0096:                this (scanner);
0097:                this .actions = actions;
0098:            }
0099:
0100:            /**
0101:             * Usually <code>this.actions == (ParserActions)this</code>.
0102:             * However, a delegate scanner can produce tokens for this parser,
0103:             * in which case <code>(Scanner)this</code> is unused,
0104:             * except for <code>this.token</code> and <code>this.pos</code>
0105:             * instance variables which are filled from the real scanner
0106:             * by <code>this.scan()</code> and the constructor.
0107:             */
0108:            ParserActions actions;
0109:
0110:            // Note:  The duplication of methods allows pre-1.1 classes to
0111:            // be binary compatible with the new version of the parser,
0112:            // which now passes IdentifierTokens to the semantics phase,
0113:            // rather than just Identifiers.  This change is necessary,
0114:            // since the parser is no longer responsible for managing the
0115:            // resolution of type names.  (That caused the "Vector" bug.)
0116:            //
0117:            // In a future release, the old "plain-Identifier" methods will
0118:            // go away, and the corresponding "IdentifierToken" methods
0119:            // may become abstract.
0120:
0121:            /**
0122:             * package declaration
0123:             * @deprecated
0124:             */
0125:            @Deprecated
0126:            public void packageDeclaration(long off, IdentifierToken nm) {
0127:                // By default, call the deprecated version.
0128:                // Any application must override one of the packageDeclaration methods.
0129:                packageDeclaration(off, nm.id);
0130:            }
0131:
0132:            /**
0133:             * @deprecated
0134:             */
0135:            @Deprecated
0136:            protected void packageDeclaration(long off, Identifier nm) {
0137:                throw new RuntimeException("beginClass method is abstract");
0138:            }
0139:
0140:            /**
0141:             * import class
0142:             * @deprecated
0143:             */
0144:            @Deprecated
0145:            public void importClass(long off, IdentifierToken nm) {
0146:                // By default, call the deprecated version.
0147:                // Any application must override one of the packageDeclaration methods.
0148:                importClass(off, nm.id);
0149:            }
0150:
0151:            /**
0152:             * @deprecated Use the version with the IdentifierToken arguments.
0153:             */
0154:            @Deprecated
0155:            protected void importClass(long off, Identifier nm) {
0156:                throw new RuntimeException("importClass method is abstract");
0157:            }
0158:
0159:            /**
0160:             * import package
0161:             * @deprecated
0162:             */
0163:            @Deprecated
0164:            public void importPackage(long off, IdentifierToken nm) {
0165:                // By default, call the deprecated version.
0166:                // Any application must override one of the importPackage methods.
0167:                importPackage(off, nm.id);
0168:            }
0169:
0170:            /**
0171:             * @deprecated Use the version with the IdentifierToken arguments.
0172:             */
0173:            @Deprecated
0174:            protected void importPackage(long off, Identifier nm) {
0175:                throw new RuntimeException("importPackage method is abstract");
0176:            }
0177:
0178:            /**
0179:             * Define class
0180:             * @deprecated
0181:             */
0182:            @Deprecated
0183:            public ClassDefinition beginClass(long off, String doc, int mod,
0184:                    IdentifierToken nm, IdentifierToken sup,
0185:                    IdentifierToken impl[]) {
0186:                // By default, call the deprecated version.
0187:                // Any application must override one of the beginClass methods.
0188:                Identifier supId = (sup == null) ? null : sup.id;
0189:                Identifier implIds[] = null;
0190:                if (impl != null) {
0191:                    implIds = new Identifier[impl.length];
0192:                    for (int i = 0; i < impl.length; i++) {
0193:                        implIds[i] = impl[i].id;
0194:                    }
0195:                }
0196:                beginClass(off, doc, mod, nm.id, supId, implIds);
0197:                return getCurrentClass();
0198:            }
0199:
0200:            /**
0201:             * @deprecated Use the version with the IdentifierToken arguments.
0202:             */
0203:            @Deprecated
0204:            protected void beginClass(long off, String doc, int mod,
0205:                    Identifier nm, Identifier sup, Identifier impl[]) {
0206:                throw new RuntimeException("beginClass method is abstract");
0207:            }
0208:
0209:            /**
0210:             * Report the current class under construction.
0211:             * By default, it's a no-op which returns null.
0212:             * It may only be called before the corresponding endClass().
0213:             */
0214:            protected ClassDefinition getCurrentClass() {
0215:                return null;
0216:            }
0217:
0218:            /**
0219:             * End class
0220:             * @deprecated
0221:             */
0222:            @Deprecated
0223:            public void endClass(long off, ClassDefinition c) {
0224:                // By default, call the deprecated version.
0225:                // Any application must override one of the beginClass methods.
0226:                endClass(off, c.getName().getFlatName().getName());
0227:            }
0228:
0229:            /**
0230:             * @deprecated Use the version with the IdentifierToken arguments.
0231:             */
0232:            @Deprecated
0233:            protected void endClass(long off, Identifier nm) {
0234:                throw new RuntimeException("endClass method is abstract");
0235:            }
0236:
0237:            /**
0238:             * Define a field
0239:             * @deprecated
0240:             */
0241:            @Deprecated
0242:            public void defineField(long where, ClassDefinition c, String doc,
0243:                    int mod, Type t, IdentifierToken nm,
0244:                    IdentifierToken args[], IdentifierToken exp[], Node val) {
0245:                // By default, call the deprecated version.
0246:                // Any application must override one of the defineField methods.
0247:                Identifier argIds[] = null;
0248:                Identifier expIds[] = null;
0249:                if (args != null) {
0250:                    argIds = new Identifier[args.length];
0251:                    for (int i = 0; i < args.length; i++) {
0252:                        argIds[i] = args[i].id;
0253:                    }
0254:                }
0255:                if (exp != null) {
0256:                    expIds = new Identifier[exp.length];
0257:                    for (int i = 0; i < exp.length; i++) {
0258:                        expIds[i] = exp[i].id;
0259:                    }
0260:                }
0261:                defineField(where, doc, mod, t, nm.id, argIds, expIds, val);
0262:            }
0263:
0264:            /**
0265:             * @deprecated Use the version with the IdentifierToken arguments.
0266:             */
0267:            @Deprecated
0268:            protected void defineField(long where, String doc, int mod, Type t,
0269:                    Identifier nm, Identifier args[], Identifier exp[], Node val) {
0270:                throw new RuntimeException("defineField method is abstract");
0271:            }
0272:
0273:            /*
0274:             * A growable array of nodes. It is used as a growable
0275:             * buffer to hold argument lists and expression lists.
0276:             * I'm not using Vector to make it more efficient.
0277:             */
0278:            private Node args[] = new Node[32];
0279:            protected int argIndex = 0;
0280:
0281:            protected final void addArgument(Node n) {
0282:                if (argIndex == args.length) {
0283:                    Node newArgs[] = new Node[args.length * 2];
0284:                    System.arraycopy(args, 0, newArgs, 0, args.length);
0285:                    args = newArgs;
0286:                }
0287:                args[argIndex++] = n;
0288:            }
0289:
0290:            protected final Expression exprArgs(int index)[] {
0291:                Expression e[] = new Expression[argIndex - index];
0292:                System.arraycopy(args, index, e, 0, argIndex - index);
0293:                argIndex = index;
0294:                return e;
0295:            }
0296:
0297:            protected final Statement statArgs(int index)[] {
0298:                Statement s[] = new Statement[argIndex - index];
0299:                System.arraycopy(args, index, s, 0, argIndex - index);
0300:                argIndex = index;
0301:                return s;
0302:            }
0303:
0304:            /**
0305:             * Expect a token, return its value, scan the next token or
0306:             * throw an exception.
0307:             */
0308:            protected void expect(int t) throws SyntaxError, IOException {
0309:                if (token != t) {
0310:                    switch (t) {
0311:                    case IDENT:
0312:                        env.error(scanner.prevPos, "identifier.expected");
0313:                        break;
0314:                    default:
0315:                        env
0316:                                .error(scanner.prevPos, "token.expected",
0317:                                        opNames[t]);
0318:                        break;
0319:                    }
0320:                    throw new SyntaxError();
0321:                }
0322:                scan();
0323:            }
0324:
0325:            /**
0326:             * Parse a type expression. Does not parse the []'s.
0327:             */
0328:            protected Expression parseTypeExpression() throws SyntaxError,
0329:                    IOException {
0330:                switch (token) {
0331:                case VOID:
0332:                    return new TypeExpression(scan(), Type.tVoid);
0333:                case BOOLEAN:
0334:                    return new TypeExpression(scan(), Type.tBoolean);
0335:                case BYTE:
0336:                    return new TypeExpression(scan(), Type.tByte);
0337:                case CHAR:
0338:                    return new TypeExpression(scan(), Type.tChar);
0339:                case SHORT:
0340:                    return new TypeExpression(scan(), Type.tShort);
0341:                case INT:
0342:                    return new TypeExpression(scan(), Type.tInt);
0343:                case LONG:
0344:                    return new TypeExpression(scan(), Type.tLong);
0345:                case FLOAT:
0346:                    return new TypeExpression(scan(), Type.tFloat);
0347:                case DOUBLE:
0348:                    return new TypeExpression(scan(), Type.tDouble);
0349:                case IDENT:
0350:                    Expression e = new IdentifierExpression(pos,
0351:                            scanner.idValue);
0352:                    scan();
0353:                    while (token == FIELD) {
0354:                        e = new FieldExpression(scan(), e, scanner.idValue);
0355:                        expect(IDENT);
0356:                    }
0357:                    return e;
0358:                }
0359:
0360:                env.error(pos, "type.expected");
0361:                throw new SyntaxError();
0362:            }
0363:
0364:            /**
0365:             * Parse a method invocation. Should be called when the current
0366:             * then is the '(' of the argument list.
0367:             */
0368:            protected Expression parseMethodExpression(Expression e,
0369:                    Identifier id) throws SyntaxError, IOException {
0370:                long p = scan();
0371:                int i = argIndex;
0372:                if (token != RPAREN) {
0373:                    addArgument(parseExpression());
0374:                    while (token == COMMA) {
0375:                        scan();
0376:                        addArgument(parseExpression());
0377:                    }
0378:                }
0379:                expect(RPAREN);
0380:                return new MethodExpression(p, e, id, exprArgs(i));
0381:            }
0382:
0383:            /**
0384:             * Parse a new instance expression.  Should be called when the current
0385:             * token is the '(' of the argument list.
0386:             */
0387:            protected Expression parseNewInstanceExpression(long p,
0388:                    Expression outerArg, Expression type) throws SyntaxError,
0389:                    IOException {
0390:                int i = argIndex;
0391:                expect(LPAREN);
0392:                if (token != RPAREN) {
0393:                    addArgument(parseExpression());
0394:                    while (token == COMMA) {
0395:                        scan();
0396:                        addArgument(parseExpression());
0397:                    }
0398:                }
0399:                expect(RPAREN);
0400:                ClassDefinition body = null;
0401:                if (token == LBRACE && !(type instanceof  TypeExpression)) {
0402:                    long tp = pos;
0403:                    // x = new Type(arg) { subclass body ... }
0404:                    Identifier super Name = FieldExpression.toIdentifier(type);
0405:                    if (super Name == null) {
0406:                        env.error(type.getWhere(), "type.expected");
0407:                    }
0408:                    Vector ext = new Vector(1);
0409:                    Vector impl = new Vector(0);
0410:                    ext.addElement(new IdentifierToken(idNull));
0411:                    if (token == IMPLEMENTS || token == EXTENDS) {
0412:                        env.error(pos, "anonymous.extends");
0413:                        parseInheritance(ext, impl); // error recovery
0414:                    }
0415:                    body = parseClassBody(new IdentifierToken(tp, idNull),
0416:                            M_ANONYMOUS | M_LOCAL, EXPR, null, ext, impl, type
0417:                                    .getWhere());
0418:                }
0419:                if (outerArg == null && body == null) {
0420:                    return new NewInstanceExpression(p, type, exprArgs(i));
0421:                }
0422:                return new NewInstanceExpression(p, type, exprArgs(i),
0423:                        outerArg, body);
0424:            }
0425:
0426:            /**
0427:             * Parse a primary expression.
0428:             */
0429:            protected Expression parseTerm() throws SyntaxError, IOException {
0430:                switch (token) {
0431:                case CHARVAL: {
0432:                    char v = scanner.charValue;
0433:                    return new CharExpression(scan(), v);
0434:                }
0435:                case INTVAL: {
0436:                    int v = scanner.intValue;
0437:                    long q = scan();
0438:                    if (v < 0 && radix == 10)
0439:                        env.error(q, "overflow.int.dec");
0440:                    return new IntExpression(q, v);
0441:                }
0442:                case LONGVAL: {
0443:                    long v = scanner.longValue;
0444:                    long q = scan();
0445:                    if (v < 0 && radix == 10)
0446:                        env.error(q, "overflow.long.dec");
0447:                    return new LongExpression(q, v);
0448:                }
0449:                case FLOATVAL: {
0450:                    float v = scanner.floatValue;
0451:                    return new FloatExpression(scan(), v);
0452:                }
0453:                case DOUBLEVAL: {
0454:                    double v = scanner.doubleValue;
0455:                    return new DoubleExpression(scan(), v);
0456:                }
0457:                case STRINGVAL: {
0458:                    String v = scanner.stringValue;
0459:                    return new StringExpression(scan(), v);
0460:                }
0461:                case IDENT: {
0462:                    Identifier v = scanner.idValue;
0463:                    long p = scan();
0464:                    return (token == LPAREN) ? parseMethodExpression(null, v)
0465:                            : new IdentifierExpression(p, v);
0466:                }
0467:
0468:                case TRUE:
0469:                    return new BooleanExpression(scan(), true);
0470:                case FALSE:
0471:                    return new BooleanExpression(scan(), false);
0472:                case NULL:
0473:                    return new NullExpression(scan());
0474:
0475:                case THIS: {
0476:                    Expression e = new ThisExpression(scan());
0477:                    return (token == LPAREN) ? parseMethodExpression(e, idInit)
0478:                            : e;
0479:                }
0480:                case SUPER: {
0481:                    Expression e = new SuperExpression(scan());
0482:                    return (token == LPAREN) ? parseMethodExpression(e, idInit)
0483:                            : e;
0484:                }
0485:
0486:                case VOID:
0487:                case BOOLEAN:
0488:                case BYTE:
0489:                case CHAR:
0490:                case SHORT:
0491:                case INT:
0492:                case LONG:
0493:                case FLOAT:
0494:                case DOUBLE:
0495:                    return parseTypeExpression();
0496:
0497:                case ADD: {
0498:                    long p = scan();
0499:                    switch (token) {
0500:                    case INTVAL: {
0501:                        int v = scanner.intValue;
0502:                        long q = scan();
0503:                        if (v < 0 && radix == 10)
0504:                            env.error(q, "overflow.int.dec");
0505:                        return new IntExpression(q, v);
0506:                    }
0507:                    case LONGVAL: {
0508:                        long v = scanner.longValue;
0509:                        long q = scan();
0510:                        if (v < 0 && radix == 10)
0511:                            env.error(q, "overflow.long.dec");
0512:                        return new LongExpression(q, v);
0513:                    }
0514:                    case FLOATVAL: {
0515:                        float v = scanner.floatValue;
0516:                        return new FloatExpression(scan(), v);
0517:                    }
0518:                    case DOUBLEVAL: {
0519:                        double v = scanner.doubleValue;
0520:                        return new DoubleExpression(scan(), v);
0521:                    }
0522:                    }
0523:                    return new PositiveExpression(p, parseTerm());
0524:                }
0525:                case SUB: {
0526:                    long p = scan();
0527:                    switch (token) {
0528:                    case INTVAL: {
0529:                        int v = -scanner.intValue;
0530:                        return new IntExpression(scan(), v);
0531:                    }
0532:                    case LONGVAL: {
0533:                        long v = -scanner.longValue;
0534:                        return new LongExpression(scan(), v);
0535:                    }
0536:                    case FLOATVAL: {
0537:                        float v = -scanner.floatValue;
0538:                        return new FloatExpression(scan(), v);
0539:                    }
0540:                    case DOUBLEVAL: {
0541:                        double v = -scanner.doubleValue;
0542:                        return new DoubleExpression(scan(), v);
0543:                    }
0544:                    }
0545:                    return new NegativeExpression(p, parseTerm());
0546:                }
0547:                case NOT:
0548:                    return new NotExpression(scan(), parseTerm());
0549:                case BITNOT:
0550:                    return new BitNotExpression(scan(), parseTerm());
0551:                case INC:
0552:                    return new PreIncExpression(scan(), parseTerm());
0553:                case DEC:
0554:                    return new PreDecExpression(scan(), parseTerm());
0555:
0556:                case LPAREN: {
0557:                    // bracketed-expr: (expr)
0558:                    long p = scan();
0559:                    Expression e = parseExpression();
0560:                    expect(RPAREN);
0561:
0562:                    if (e.getOp() == TYPE) {
0563:                        // cast-expr: (simple-type) expr
0564:                        return new CastExpression(p, e, parseTerm());
0565:                    }
0566:
0567:                    switch (token) {
0568:
0569:                    // We handle INC and DEC specially.
0570:                    // See the discussion in JLS section 15.14.1.
0571:                    // (Part of fix for 4044502.)
0572:
0573:                    case INC:
0574:                        // We know this must be a postfix increment.
0575:                        return new PostIncExpression(scan(), e);
0576:
0577:                    case DEC:
0578:                        // We know this must be a postfix decrement.
0579:                        return new PostDecExpression(scan(), e);
0580:
0581:                    case LPAREN:
0582:                    case CHARVAL:
0583:                    case INTVAL:
0584:                    case LONGVAL:
0585:                    case FLOATVAL:
0586:                    case DOUBLEVAL:
0587:                    case STRINGVAL:
0588:                    case IDENT:
0589:                    case TRUE:
0590:                    case FALSE:
0591:                    case NOT:
0592:                    case BITNOT:
0593:                    case THIS:
0594:                    case SUPER:
0595:                    case NULL:
0596:                    case NEW:
0597:                        // cast-expr: (expr) expr
0598:                        return new CastExpression(p, e, parseTerm());
0599:                    }
0600:                    return new ExprExpression(p, e);
0601:                }
0602:
0603:                case LBRACE: {
0604:                    // array initializer: {expr1, expr2, ... exprn}
0605:                    long p = scan();
0606:                    int i = argIndex;
0607:                    if (token != RBRACE) {
0608:                        addArgument(parseExpression());
0609:                        while (token == COMMA) {
0610:                            scan();
0611:                            if (token == RBRACE) {
0612:                                break;
0613:                            }
0614:                            addArgument(parseExpression());
0615:                        }
0616:                    }
0617:                    expect(RBRACE);
0618:                    return new ArrayExpression(p, exprArgs(i));
0619:                }
0620:
0621:                case NEW: {
0622:                    long p = scan();
0623:                    int i = argIndex;
0624:
0625:                    if (token == LPAREN) {
0626:                        scan();
0627:                        Expression e = parseExpression();
0628:                        expect(RPAREN);
0629:                        env.error(p, "not.supported", "new(...)");
0630:                        return new NullExpression(p);
0631:                    }
0632:
0633:                    Expression e = parseTypeExpression();
0634:
0635:                    if (token == LSQBRACKET) {
0636:                        while (token == LSQBRACKET) {
0637:                            scan();
0638:                            addArgument((token != RSQBRACKET) ? parseExpression()
0639:                                    : null);
0640:                            expect(RSQBRACKET);
0641:                        }
0642:                        Expression[] dims = exprArgs(i);
0643:                        if (token == LBRACE) {
0644:                            return new NewArrayExpression(p, e, dims,
0645:                                    parseTerm());
0646:                        }
0647:                        return new NewArrayExpression(p, e, dims);
0648:                    } else {
0649:                        return parseNewInstanceExpression(p, null, e);
0650:                    }
0651:                }
0652:                }
0653:
0654:                // System.err.println("NEAR: " + opNames[token]);
0655:                env.error(scanner.prevPos, "missing.term");
0656:                return new IntExpression(pos, 0);
0657:            }
0658:
0659:            /**
0660:             * Parse an expression.
0661:             */
0662:            protected Expression parseExpression() throws SyntaxError,
0663:                    IOException {
0664:                for (Expression e = parseTerm(); e != null; e = e.order()) {
0665:                    Expression more = parseBinaryExpression(e);
0666:                    if (more == null)
0667:                        return e;
0668:                    e = more;
0669:                }
0670:                // this return is bogus
0671:                return null;
0672:            }
0673:
0674:            /**
0675:             * Given a left-hand term, parse an operator and right-hand term.
0676:             */
0677:            protected Expression parseBinaryExpression(Expression e)
0678:                    throws SyntaxError, IOException {
0679:                if (e != null) {
0680:                    switch (token) {
0681:                    case LSQBRACKET: {
0682:                        // index: expr1[expr2]
0683:                        long p = scan();
0684:                        Expression index = (token != RSQBRACKET) ? parseExpression()
0685:                                : null;
0686:                        expect(RSQBRACKET);
0687:                        e = new ArrayAccessExpression(p, e, index);
0688:                        break;
0689:                    }
0690:
0691:                    case INC:
0692:                        e = new PostIncExpression(scan(), e);
0693:                        break;
0694:                    case DEC:
0695:                        e = new PostDecExpression(scan(), e);
0696:                        break;
0697:                    case FIELD: {
0698:                        long p = scan();
0699:                        if (token == THIS) {
0700:                            // class C { class N { ... C.this ... } }
0701:                            // class C { class N { N(C c){ ... c.this() ... } } }
0702:                            long q = scan();
0703:                            if (token == LPAREN) {
0704:                                e = new ThisExpression(q, e);
0705:                                e = parseMethodExpression(e, idInit);
0706:                            } else {
0707:                                e = new FieldExpression(p, e, idThis);
0708:                            }
0709:                            break;
0710:                        }
0711:                        if (token == SUPER) {
0712:                            // class D extends C.N { D(C.N n) { n.super(); } }
0713:                            // Also, 'C.super', as in:
0714:                            // class C extends CS { class N { ... C.super.foo ... } }
0715:                            // class C extends CS { class N { ... C.super.foo() ... } }
0716:                            long q = scan();
0717:                            if (token == LPAREN) {
0718:                                e = new SuperExpression(q, e);
0719:                                e = parseMethodExpression(e, idInit);
0720:                            } else {
0721:                                // We must check elsewhere that this expression
0722:                                // does not stand alone, but qualifies a member name.
0723:                                e = new FieldExpression(p, e, idSuper);
0724:                            }
0725:                            break;
0726:                        }
0727:                        if (token == NEW) {
0728:                            // new C().new N()
0729:                            scan();
0730:                            if (token != IDENT)
0731:                                expect(IDENT);
0732:                            e = parseNewInstanceExpression(p, e,
0733:                                    parseTypeExpression());
0734:                            break;
0735:                        }
0736:                        if (token == CLASS) {
0737:                            // just class literals, really
0738:                            // Class c = C.class;
0739:                            scan();
0740:                            e = new FieldExpression(p, e, idClass);
0741:                            break;
0742:                        }
0743:                        Identifier id = scanner.idValue;
0744:                        expect(IDENT);
0745:                        if (token == LPAREN) {
0746:                            e = parseMethodExpression(e, id);
0747:                        } else {
0748:                            e = new FieldExpression(p, e, id);
0749:                        }
0750:                        break;
0751:                    }
0752:                    case INSTANCEOF:
0753:                        e = new InstanceOfExpression(scan(), e, parseTerm());
0754:                        break;
0755:                    case ADD:
0756:                        e = new AddExpression(scan(), e, parseTerm());
0757:                        break;
0758:                    case SUB:
0759:                        e = new SubtractExpression(scan(), e, parseTerm());
0760:                        break;
0761:                    case MUL:
0762:                        e = new MultiplyExpression(scan(), e, parseTerm());
0763:                        break;
0764:                    case DIV:
0765:                        e = new DivideExpression(scan(), e, parseTerm());
0766:                        break;
0767:                    case REM:
0768:                        e = new RemainderExpression(scan(), e, parseTerm());
0769:                        break;
0770:                    case LSHIFT:
0771:                        e = new ShiftLeftExpression(scan(), e, parseTerm());
0772:                        break;
0773:                    case RSHIFT:
0774:                        e = new ShiftRightExpression(scan(), e, parseTerm());
0775:                        break;
0776:                    case URSHIFT:
0777:                        e = new UnsignedShiftRightExpression(scan(), e,
0778:                                parseTerm());
0779:                        break;
0780:                    case LT:
0781:                        e = new LessExpression(scan(), e, parseTerm());
0782:                        break;
0783:                    case LE:
0784:                        e = new LessOrEqualExpression(scan(), e, parseTerm());
0785:                        break;
0786:                    case GT:
0787:                        e = new GreaterExpression(scan(), e, parseTerm());
0788:                        break;
0789:                    case GE:
0790:                        e = new GreaterOrEqualExpression(scan(), e, parseTerm());
0791:                        break;
0792:                    case EQ:
0793:                        e = new EqualExpression(scan(), e, parseTerm());
0794:                        break;
0795:                    case NE:
0796:                        e = new NotEqualExpression(scan(), e, parseTerm());
0797:                        break;
0798:                    case BITAND:
0799:                        e = new BitAndExpression(scan(), e, parseTerm());
0800:                        break;
0801:                    case BITXOR:
0802:                        e = new BitXorExpression(scan(), e, parseTerm());
0803:                        break;
0804:                    case BITOR:
0805:                        e = new BitOrExpression(scan(), e, parseTerm());
0806:                        break;
0807:                    case AND:
0808:                        e = new AndExpression(scan(), e, parseTerm());
0809:                        break;
0810:                    case OR:
0811:                        e = new OrExpression(scan(), e, parseTerm());
0812:                        break;
0813:                    case ASSIGN:
0814:                        e = new AssignExpression(scan(), e, parseTerm());
0815:                        break;
0816:                    case ASGMUL:
0817:                        e = new AssignMultiplyExpression(scan(), e, parseTerm());
0818:                        break;
0819:                    case ASGDIV:
0820:                        e = new AssignDivideExpression(scan(), e, parseTerm());
0821:                        break;
0822:                    case ASGREM:
0823:                        e = new AssignRemainderExpression(scan(), e,
0824:                                parseTerm());
0825:                        break;
0826:                    case ASGADD:
0827:                        e = new AssignAddExpression(scan(), e, parseTerm());
0828:                        break;
0829:                    case ASGSUB:
0830:                        e = new AssignSubtractExpression(scan(), e, parseTerm());
0831:                        break;
0832:                    case ASGLSHIFT:
0833:                        e = new AssignShiftLeftExpression(scan(), e,
0834:                                parseTerm());
0835:                        break;
0836:                    case ASGRSHIFT:
0837:                        e = new AssignShiftRightExpression(scan(), e,
0838:                                parseTerm());
0839:                        break;
0840:                    case ASGURSHIFT:
0841:                        e = new AssignUnsignedShiftRightExpression(scan(), e,
0842:                                parseTerm());
0843:                        break;
0844:                    case ASGBITAND:
0845:                        e = new AssignBitAndExpression(scan(), e, parseTerm());
0846:                        break;
0847:                    case ASGBITOR:
0848:                        e = new AssignBitOrExpression(scan(), e, parseTerm());
0849:                        break;
0850:                    case ASGBITXOR:
0851:                        e = new AssignBitXorExpression(scan(), e, parseTerm());
0852:                        break;
0853:                    case QUESTIONMARK: {
0854:                        long p = scan();
0855:                        Expression second = parseExpression();
0856:                        expect(COLON);
0857:                        Expression third = parseExpression();
0858:
0859:                        // The grammar in the JLS does not allow assignment
0860:                        // expressions as the third part of a ?: expression.
0861:                        // Even though javac has no trouble parsing this,
0862:                        // check for this case and signal an error.
0863:                        // (fix for bug 4092958)
0864:                        if (third instanceof  AssignExpression
0865:                                || third instanceof  AssignOpExpression) {
0866:                            env.error(third.getWhere(),
0867:                                    "assign.in.conditionalexpr");
0868:                        }
0869:
0870:                        e = new ConditionalExpression(p, e, second, third);
0871:                        break;
0872:                    }
0873:
0874:                    default:
0875:                        return null; // mark end of binary expressions
0876:                    }
0877:                }
0878:                return e; // return more binary expression stuff
0879:            }
0880:
0881:            /**
0882:             * Recover after a syntax error in a statement. This involves
0883:             * discarding tokens until EOF or a possible continuation is
0884:             * encountered.
0885:             */
0886:            protected boolean recoverStatement() throws SyntaxError,
0887:                    IOException {
0888:                while (true) {
0889:                    switch (token) {
0890:                    case EOF:
0891:                    case RBRACE:
0892:                    case LBRACE:
0893:                    case IF:
0894:                    case FOR:
0895:                    case WHILE:
0896:                    case DO:
0897:                    case TRY:
0898:                    case CATCH:
0899:                    case FINALLY:
0900:                    case BREAK:
0901:                    case CONTINUE:
0902:                    case RETURN:
0903:                        // begin of a statement, return
0904:                        return true;
0905:
0906:                    case VOID:
0907:                    case STATIC:
0908:                    case PUBLIC:
0909:                    case PRIVATE:
0910:                    case SYNCHRONIZED:
0911:                    case INTERFACE:
0912:                    case CLASS:
0913:                    case TRANSIENT:
0914:                        // begin of something outside a statement, panic some more
0915:                        expect(RBRACE);
0916:                        return false;
0917:
0918:                    case LPAREN:
0919:                        match(LPAREN, RPAREN);
0920:                        scan();
0921:                        break;
0922:
0923:                    case LSQBRACKET:
0924:                        match(LSQBRACKET, RSQBRACKET);
0925:                        scan();
0926:                        break;
0927:
0928:                    default:
0929:                        // don't know what to do, skip
0930:                        scan();
0931:                        break;
0932:                    }
0933:                }
0934:            }
0935:
0936:            /**
0937:             * Parse declaration, called after the type expression
0938:             * has been parsed and the current token is IDENT.
0939:             */
0940:            protected Statement parseDeclaration(long p, int mod,
0941:                    Expression type) throws SyntaxError, IOException {
0942:                int i = argIndex;
0943:                if (token == IDENT) {
0944:                    addArgument(new VarDeclarationStatement(pos,
0945:                            parseExpression()));
0946:                    while (token == COMMA) {
0947:                        scan();
0948:                        addArgument(new VarDeclarationStatement(pos,
0949:                                parseExpression()));
0950:                    }
0951:                }
0952:                return new DeclarationStatement(p, mod, type, statArgs(i));
0953:            }
0954:
0955:            /**
0956:             * Check if an expression is a legal toplevel expression.
0957:             * Only method, inc, dec, and new expression are allowed.
0958:             */
0959:            protected void topLevelExpression(Expression e) {
0960:                switch (e.getOp()) {
0961:                case ASSIGN:
0962:                case ASGMUL:
0963:                case ASGDIV:
0964:                case ASGREM:
0965:                case ASGADD:
0966:                case ASGSUB:
0967:                case ASGLSHIFT:
0968:                case ASGRSHIFT:
0969:                case ASGURSHIFT:
0970:                case ASGBITAND:
0971:                case ASGBITOR:
0972:                case ASGBITXOR:
0973:                case PREINC:
0974:                case PREDEC:
0975:                case POSTINC:
0976:                case POSTDEC:
0977:                case METHOD:
0978:                case NEWINSTANCE:
0979:                    return;
0980:                }
0981:                env.error(e.getWhere(), "invalid.expr");
0982:            }
0983:
0984:            /**
0985:             * Parse a statement.
0986:             */
0987:            protected Statement parseStatement() throws SyntaxError,
0988:                    IOException {
0989:                switch (token) {
0990:                case SEMICOLON:
0991:                    return new CompoundStatement(scan(), new Statement[0]);
0992:
0993:                case LBRACE:
0994:                    return parseBlockStatement();
0995:
0996:                case IF: {
0997:                    // if-statement: if (expr) stat
0998:                    // if-statement: if (expr) stat else stat
0999:                    long p = scan();
1000:
1001:                    expect(LPAREN);
1002:                    Expression c = parseExpression();
1003:                    expect(RPAREN);
1004:                    Statement t = parseStatement();
1005:                    if (token == ELSE) {
1006:                        scan();
1007:                        return new IfStatement(p, c, t, parseStatement());
1008:                    } else {
1009:                        return new IfStatement(p, c, t, null);
1010:                    }
1011:                }
1012:
1013:                case ELSE: {
1014:                    // else-statement: else stat
1015:                    env.error(scan(), "else.without.if");
1016:                    return parseStatement();
1017:                }
1018:
1019:                case FOR: {
1020:                    // for-statement: for (decl-expr? ; expr? ; expr?) stat
1021:                    long p = scan();
1022:                    Statement init = null;
1023:                    Expression cond = null, inc = null;
1024:
1025:                    expect(LPAREN);
1026:                    if (token != SEMICOLON) {
1027:                        long p2 = pos;
1028:                        int mod = parseModifiers(M_FINAL);
1029:                        Expression e = parseExpression();
1030:
1031:                        if (token == IDENT) {
1032:                            init = parseDeclaration(p2, mod, e);
1033:                        } else {
1034:                            if (mod != 0) {
1035:                                expect(IDENT); // should have been a declaration
1036:                            }
1037:                            topLevelExpression(e);
1038:                            while (token == COMMA) {
1039:                                long p3 = scan();
1040:                                Expression e2 = parseExpression();
1041:                                topLevelExpression(e2);
1042:                                e = new CommaExpression(p3, e, e2);
1043:                            }
1044:                            init = new ExpressionStatement(p2, e);
1045:                        }
1046:                    }
1047:                    expect(SEMICOLON);
1048:                    if (token != SEMICOLON) {
1049:                        cond = parseExpression();
1050:                    }
1051:                    expect(SEMICOLON);
1052:                    if (token != RPAREN) {
1053:                        inc = parseExpression();
1054:                        topLevelExpression(inc);
1055:                        while (token == COMMA) {
1056:                            long p2 = scan();
1057:                            Expression e2 = parseExpression();
1058:                            topLevelExpression(e2);
1059:                            inc = new CommaExpression(p2, inc, e2);
1060:                        }
1061:                    }
1062:                    expect(RPAREN);
1063:                    return new ForStatement(p, init, cond, inc,
1064:                            parseStatement());
1065:                }
1066:
1067:                case WHILE: {
1068:                    // while-statement: while (expr) stat
1069:                    long p = scan();
1070:
1071:                    expect(LPAREN);
1072:                    Expression cond = parseExpression();
1073:                    expect(RPAREN);
1074:                    return new WhileStatement(p, cond, parseStatement());
1075:                }
1076:
1077:                case DO: {
1078:                    // do-statement: do stat while (expr)
1079:                    long p = scan();
1080:
1081:                    Statement body = parseStatement();
1082:                    expect(WHILE);
1083:                    expect(LPAREN);
1084:                    Expression cond = parseExpression();
1085:                    expect(RPAREN);
1086:                    expect(SEMICOLON);
1087:                    return new DoStatement(p, body, cond);
1088:                }
1089:
1090:                case BREAK: {
1091:                    // break-statement: break ;
1092:                    long p = scan();
1093:                    Identifier label = null;
1094:
1095:                    if (token == IDENT) {
1096:                        label = scanner.idValue;
1097:                        scan();
1098:                    }
1099:                    expect(SEMICOLON);
1100:                    return new BreakStatement(p, label);
1101:                }
1102:
1103:                case CONTINUE: {
1104:                    // continue-statement: continue ;
1105:                    long p = scan();
1106:                    Identifier label = null;
1107:
1108:                    if (token == IDENT) {
1109:                        label = scanner.idValue;
1110:                        scan();
1111:                    }
1112:                    expect(SEMICOLON);
1113:                    return new ContinueStatement(p, label);
1114:                }
1115:
1116:                case RETURN: {
1117:                    // return-statement: return ;
1118:                    // return-statement: return expr ;
1119:                    long p = scan();
1120:                    Expression e = null;
1121:
1122:                    if (token != SEMICOLON) {
1123:                        e = parseExpression();
1124:                    }
1125:                    expect(SEMICOLON);
1126:                    return new ReturnStatement(p, e);
1127:                }
1128:
1129:                case SWITCH: {
1130:                    // switch statement: switch ( expr ) stat
1131:                    long p = scan();
1132:                    int i = argIndex;
1133:
1134:                    expect(LPAREN);
1135:                    Expression e = parseExpression();
1136:                    expect(RPAREN);
1137:                    expect(LBRACE);
1138:
1139:                    while ((token != EOF) && (token != RBRACE)) {
1140:                        int j = argIndex;
1141:                        try {
1142:                            switch (token) {
1143:                            case CASE:
1144:                                // case-statement: case expr:
1145:                                addArgument(new CaseStatement(scan(),
1146:                                        parseExpression()));
1147:                                expect(COLON);
1148:                                break;
1149:
1150:                            case DEFAULT:
1151:                                // default-statement: default:
1152:                                addArgument(new CaseStatement(scan(), null));
1153:                                expect(COLON);
1154:                                break;
1155:
1156:                            default:
1157:                                addArgument(parseStatement());
1158:                                break;
1159:                            }
1160:                        } catch (SyntaxError ee) {
1161:                            argIndex = j;
1162:                            if (!recoverStatement()) {
1163:                                throw ee;
1164:                            }
1165:                        }
1166:                    }
1167:                    expect(RBRACE);
1168:                    return new SwitchStatement(p, e, statArgs(i));
1169:                }
1170:
1171:                case CASE: {
1172:                    // case-statement: case expr : stat
1173:                    env.error(pos, "case.without.switch");
1174:                    while (token == CASE) {
1175:                        scan();
1176:                        parseExpression();
1177:                        expect(COLON);
1178:                    }
1179:                    return parseStatement();
1180:                }
1181:
1182:                case DEFAULT: {
1183:                    // default-statement: default : stat
1184:                    env.error(pos, "default.without.switch");
1185:                    scan();
1186:                    expect(COLON);
1187:                    return parseStatement();
1188:                }
1189:
1190:                case TRY: {
1191:                    // try-statement: try stat catch (type-expr ident) stat finally stat
1192:                    long p = scan();
1193:                    Statement init = null; // try-object specification
1194:                    int i = argIndex;
1195:                    boolean catches = false;
1196:
1197:                    if (false && token == LPAREN) {
1198:                        expect(LPAREN);
1199:                        long p2 = pos;
1200:                        int mod = parseModifiers(M_FINAL);
1201:                        Expression e = parseExpression();
1202:
1203:                        if (token == IDENT) {
1204:                            init = parseDeclaration(p2, mod, e);
1205:                            // leave check for try (T x, y) for semantic phase
1206:                        } else {
1207:                            if (mod != 0) {
1208:                                expect(IDENT); // should have been a declaration
1209:                            }
1210:                            init = new ExpressionStatement(p2, e);
1211:                        }
1212:                        expect(RPAREN);
1213:                    }
1214:
1215:                    Statement s = parseBlockStatement();
1216:
1217:                    if (init != null) {
1218:                        // s = new FinallyStatement(p, init, s, 0);
1219:                    }
1220:
1221:                    while (token == CATCH) {
1222:                        long pp = pos;
1223:                        expect(CATCH);
1224:                        expect(LPAREN);
1225:                        int mod = parseModifiers(M_FINAL);
1226:                        Expression t = parseExpression();
1227:                        IdentifierToken id = scanner.getIdToken();
1228:                        expect(IDENT);
1229:                        id.modifiers = mod;
1230:                        // We only catch Throwable's, so this is no longer required
1231:                        // while (token == LSQBRACKET) {
1232:                        //    t = new ArrayAccessExpression(scan(), t, null);
1233:                        //    expect(RSQBRACKET);
1234:                        // }
1235:                        expect(RPAREN);
1236:                        addArgument(new CatchStatement(pp, t, id,
1237:                                parseBlockStatement()));
1238:                        catches = true;
1239:                    }
1240:
1241:                    if (catches)
1242:                        s = new TryStatement(p, s, statArgs(i));
1243:
1244:                    if (token == FINALLY) {
1245:                        scan();
1246:                        return new FinallyStatement(p, s, parseBlockStatement());
1247:                    } else if (catches || init != null) {
1248:                        return s;
1249:                    } else {
1250:                        env.error(pos, "try.without.catch.finally");
1251:                        return new TryStatement(p, s, null);
1252:                    }
1253:                }
1254:
1255:                case CATCH: {
1256:                    // catch-statement: catch (expr ident) stat finally stat
1257:                    env.error(pos, "catch.without.try");
1258:
1259:                    Statement s;
1260:                    do {
1261:                        scan();
1262:                        expect(LPAREN);
1263:                        parseModifiers(M_FINAL);
1264:                        parseExpression();
1265:                        expect(IDENT);
1266:                        expect(RPAREN);
1267:                        s = parseBlockStatement();
1268:                    } while (token == CATCH);
1269:
1270:                    if (token == FINALLY) {
1271:                        scan();
1272:                        s = parseBlockStatement();
1273:                    }
1274:                    return s;
1275:                }
1276:
1277:                case FINALLY: {
1278:                    // finally-statement: finally stat
1279:                    env.error(pos, "finally.without.try");
1280:                    scan();
1281:                    return parseBlockStatement();
1282:                }
1283:
1284:                case THROW: {
1285:                    // throw-statement: throw expr;
1286:                    long p = scan();
1287:                    Expression e = parseExpression();
1288:                    expect(SEMICOLON);
1289:                    return new ThrowStatement(p, e);
1290:                }
1291:
1292:                case GOTO: {
1293:                    long p = scan();
1294:                    expect(IDENT);
1295:                    expect(SEMICOLON);
1296:                    env.error(p, "not.supported", "goto");
1297:                    return new CompoundStatement(p, new Statement[0]);
1298:                }
1299:
1300:                case SYNCHRONIZED: {
1301:                    // synchronized-statement: synchronized (expr) stat
1302:                    long p = scan();
1303:                    expect(LPAREN);
1304:                    Expression e = parseExpression();
1305:                    expect(RPAREN);
1306:                    return new SynchronizedStatement(p, e,
1307:                            parseBlockStatement());
1308:                }
1309:
1310:                case INTERFACE:
1311:                case CLASS:
1312:                    // Inner class.
1313:                    return parseLocalClass(0);
1314:
1315:                case CONST:
1316:                case ABSTRACT:
1317:                case FINAL:
1318:                case STRICTFP: {
1319:                    // a declaration of some sort
1320:                    long p = pos;
1321:
1322:                    // A class which is local to a block is not a member, and so
1323:                    // cannot be public, private, protected, or static. It is in
1324:                    // effect private to the block, since it cannot be used outside
1325:                    // its scope.
1326:                    //
1327:                    // However, any class (if it has a name) can be declared final,
1328:                    // abstract, or strictfp.
1329:                    int mod = parseModifiers(M_FINAL | M_ABSTRACT | M_STRICTFP);
1330:
1331:                    switch (token) {
1332:                    case INTERFACE:
1333:                    case CLASS:
1334:                        return parseLocalClass(mod);
1335:
1336:                    case BOOLEAN:
1337:                    case BYTE:
1338:                    case CHAR:
1339:                    case SHORT:
1340:                    case INT:
1341:                    case LONG:
1342:                    case FLOAT:
1343:                    case DOUBLE:
1344:                    case IDENT: {
1345:                        if ((mod & (M_ABSTRACT | M_STRICTFP)) != 0) {
1346:                            mod &= ~(M_ABSTRACT | M_STRICTFP);
1347:                            expect(CLASS);
1348:                        }
1349:                        Expression e = parseExpression();
1350:                        if (token != IDENT) {
1351:                            expect(IDENT);
1352:                        }
1353:                        // declaration: final expr expr
1354:                        Statement s = parseDeclaration(p, mod, e);
1355:                        expect(SEMICOLON);
1356:                        return s;
1357:                    }
1358:
1359:                    default:
1360:                        env.error(pos, "type.expected");
1361:                        throw new SyntaxError();
1362:                    }
1363:                }
1364:
1365:                case VOID:
1366:                case STATIC:
1367:                case PUBLIC:
1368:                case PRIVATE:
1369:                case TRANSIENT:
1370:                    // This is the start of something outside a statement
1371:                    env.error(pos, "statement.expected");
1372:                    throw new SyntaxError();
1373:                }
1374:
1375:                long p = pos;
1376:                Expression e = parseExpression();
1377:
1378:                if (token == IDENT) {
1379:                    // declaration: expr expr
1380:                    Statement s = parseDeclaration(p, 0, e);
1381:                    expect(SEMICOLON);
1382:                    return s;
1383:                }
1384:                if (token == COLON) {
1385:                    // label: id: stat
1386:                    scan();
1387:                    Statement s = parseStatement();
1388:                    s.setLabel(env, e);
1389:                    return s;
1390:                }
1391:
1392:                // it was just an expression...
1393:                topLevelExpression(e);
1394:                expect(SEMICOLON);
1395:                return new ExpressionStatement(p, e);
1396:            }
1397:
1398:            protected Statement parseBlockStatement() throws SyntaxError,
1399:                    IOException {
1400:                // compound statement: { stat1 stat2 ... statn }
1401:                if (token != LBRACE) {
1402:                    // We're expecting a block statement.  But we'll probably do the
1403:                    // least damage if we try to parse a normal statement instead.
1404:                    env.error(scanner.prevPos, "token.expected",
1405:                            opNames[LBRACE]);
1406:                    return parseStatement();
1407:                }
1408:                long p = scan();
1409:                int i = argIndex;
1410:                while ((token != EOF) && (token != RBRACE)) {
1411:                    int j = argIndex;
1412:                    try {
1413:                        addArgument(parseStatement());
1414:                    } catch (SyntaxError e) {
1415:                        argIndex = j;
1416:                        if (!recoverStatement()) {
1417:                            throw e;
1418:                        }
1419:                    }
1420:                }
1421:
1422:                expect(RBRACE);
1423:                return new CompoundStatement(p, statArgs(i));
1424:            }
1425:
1426:            /**
1427:             * Parse an identifier. ie: a.b.c returns "a.b.c"
1428:             * If star is true then "a.b.*" is allowed.
1429:             * The return value encodes both the identifier and its location.
1430:             */
1431:            protected IdentifierToken parseName(boolean star)
1432:                    throws SyntaxError, IOException {
1433:                IdentifierToken res = scanner.getIdToken();
1434:                expect(IDENT);
1435:
1436:                if (token != FIELD) {
1437:                    return res;
1438:                }
1439:
1440:                StringBuffer buf = new StringBuffer(res.id.toString());
1441:
1442:                while (token == FIELD) {
1443:                    scan();
1444:                    if ((token == MUL) && star) {
1445:                        scan();
1446:                        buf.append(".*");
1447:                        break;
1448:                    }
1449:
1450:                    buf.append('.');
1451:                    if (token == IDENT) {
1452:                        buf.append(scanner.idValue);
1453:                    }
1454:                    expect(IDENT);
1455:                }
1456:
1457:                res.id = Identifier.lookup(buf.toString());
1458:                return res;
1459:            }
1460:
1461:            /**
1462:             * @deprecated
1463:             * @see #parseName
1464:             */
1465:            @Deprecated
1466:            protected Identifier parseIdentifier(boolean star)
1467:                    throws SyntaxError, IOException {
1468:                return parseName(star).id;
1469:            }
1470:
1471:            /**
1472:             * Parse a type expression, this results in a Type.
1473:             * The parse includes trailing array brackets.
1474:             */
1475:            protected Type parseType() throws SyntaxError, IOException {
1476:                Type t;
1477:
1478:                switch (token) {
1479:                case IDENT:
1480:                    t = Type.tClass(parseName(false).id);
1481:                    break;
1482:                case VOID:
1483:                    scan();
1484:                    t = Type.tVoid;
1485:                    break;
1486:                case BOOLEAN:
1487:                    scan();
1488:                    t = Type.tBoolean;
1489:                    break;
1490:                case BYTE:
1491:                    scan();
1492:                    t = Type.tByte;
1493:                    break;
1494:                case CHAR:
1495:                    scan();
1496:                    t = Type.tChar;
1497:                    break;
1498:                case SHORT:
1499:                    scan();
1500:                    t = Type.tShort;
1501:                    break;
1502:                case INT:
1503:                    scan();
1504:                    t = Type.tInt;
1505:                    break;
1506:                case FLOAT:
1507:                    scan();
1508:                    t = Type.tFloat;
1509:                    break;
1510:                case LONG:
1511:                    scan();
1512:                    t = Type.tLong;
1513:                    break;
1514:                case DOUBLE:
1515:                    scan();
1516:                    t = Type.tDouble;
1517:                    break;
1518:                default:
1519:                    env.error(pos, "type.expected");
1520:                    throw new SyntaxError();
1521:                }
1522:                return parseArrayBrackets(t);
1523:            }
1524:
1525:            /**
1526:             * Parse the tail of a type expression, which might be array brackets.
1527:             * Return the given type, as possibly modified by the suffix.
1528:             */
1529:            protected Type parseArrayBrackets(Type t) throws SyntaxError,
1530:                    IOException {
1531:
1532:                // Parse []'s
1533:                while (token == LSQBRACKET) {
1534:                    scan();
1535:                    if (token != RSQBRACKET) {
1536:                        env.error(pos, "array.dim.in.decl");
1537:                        parseExpression();
1538:                    }
1539:                    expect(RSQBRACKET);
1540:                    t = Type.tArray(t);
1541:                }
1542:                return t;
1543:            }
1544:
1545:            /*
1546:             * Dealing with argument lists, I'm not using
1547:             * Vector for efficiency.
1548:             */
1549:
1550:            private int aCount = 0;
1551:            private Type aTypes[] = new Type[8];
1552:            private IdentifierToken aNames[] = new IdentifierToken[aTypes.length];
1553:
1554:            private void addArgument(int mod, Type t, IdentifierToken nm) {
1555:                nm.modifiers = mod;
1556:                if (aCount >= aTypes.length) {
1557:                    Type newATypes[] = new Type[aCount * 2];
1558:                    System.arraycopy(aTypes, 0, newATypes, 0, aCount);
1559:                    aTypes = newATypes;
1560:                    IdentifierToken newANames[] = new IdentifierToken[aCount * 2];
1561:                    System.arraycopy(aNames, 0, newANames, 0, aCount);
1562:                    aNames = newANames;
1563:                }
1564:                aTypes[aCount] = t;
1565:                aNames[aCount++] = nm;
1566:            }
1567:
1568:            /**
1569:             * Parse a possibly-empty sequence of modifier keywords.
1570:             * Return the resulting bitmask.
1571:             * Diagnose repeated modifiers, but make no other checks.
1572:             * Only modifiers mentioned in the given bitmask are scanned;
1573:             * an unmatched modifier must be handled by the caller.
1574:             */
1575:            protected int parseModifiers(int mask) throws IOException {
1576:                int mod = 0;
1577:                while (true) {
1578:                    if (token == CONST) {
1579:                        // const isn't in java, but handle a common C++ usage gently
1580:                        env.error(pos, "not.supported", "const");
1581:                        scan();
1582:                    }
1583:                    int nextmod = 0;
1584:                    switch (token) {
1585:                    case PRIVATE:
1586:                        nextmod = M_PRIVATE;
1587:                        break;
1588:                    case PUBLIC:
1589:                        nextmod = M_PUBLIC;
1590:                        break;
1591:                    case PROTECTED:
1592:                        nextmod = M_PROTECTED;
1593:                        break;
1594:                    case STATIC:
1595:                        nextmod = M_STATIC;
1596:                        break;
1597:                    case TRANSIENT:
1598:                        nextmod = M_TRANSIENT;
1599:                        break;
1600:                    case FINAL:
1601:                        nextmod = M_FINAL;
1602:                        break;
1603:                    case ABSTRACT:
1604:                        nextmod = M_ABSTRACT;
1605:                        break;
1606:                    case NATIVE:
1607:                        nextmod = M_NATIVE;
1608:                        break;
1609:                    case VOLATILE:
1610:                        nextmod = M_VOLATILE;
1611:                        break;
1612:                    case SYNCHRONIZED:
1613:                        nextmod = M_SYNCHRONIZED;
1614:                        break;
1615:                    case STRICTFP:
1616:                        nextmod = M_STRICTFP;
1617:                        break;
1618:                    }
1619:                    if ((nextmod & mask) == 0) {
1620:                        break;
1621:                    }
1622:                    if ((nextmod & mod) != 0) {
1623:                        env.error(pos, "repeated.modifier");
1624:                    }
1625:                    mod |= nextmod;
1626:                    scan();
1627:                }
1628:                return mod;
1629:            }
1630:
1631:            private ClassDefinition curClass;
1632:
1633:            /**
1634:             * Parse a field.
1635:             */
1636:            protected void parseField() throws SyntaxError, IOException {
1637:
1638:                // Empty fields are not allowed by the JLS but are accepted by
1639:                // the compiler, and much code has come to rely on this.  It has
1640:                // been decided that the language will be extended to legitimize them.
1641:                if (token == SEMICOLON) {
1642:                    // empty field
1643:                    scan();
1644:                    return;
1645:                }
1646:
1647:                // Optional doc comment
1648:                String doc = scanner.docComment;
1649:
1650:                // The start of the field
1651:                long p = pos;
1652:
1653:                // Parse the modifiers
1654:                int mod = parseModifiers(MM_FIELD | MM_METHOD);
1655:
1656:                // Check for static initializer
1657:                // ie: static { ... }
1658:                // or an instance initializer (w/o the static).
1659:                if ((mod == (mod & M_STATIC)) && (token == LBRACE)) {
1660:                    // static initializer
1661:                    actions.defineField(p, curClass, doc, mod, Type
1662:                            .tMethod(Type.tVoid), new IdentifierToken(
1663:                            idClassInit), null, null, parseStatement());
1664:                    return;
1665:                }
1666:
1667:                // Check for inner class
1668:                if (token == CLASS || token == INTERFACE) {
1669:                    parseNamedClass(mod, CLASS, doc);
1670:                    return;
1671:                }
1672:
1673:                // Parse the type
1674:                p = pos;
1675:                Type t = parseType();
1676:                IdentifierToken id = null;
1677:
1678:                // Check that the type is followed by an Identifier
1679:                // (the name of the method or the first variable),
1680:                // otherwise it is a constructor.
1681:                switch (token) {
1682:                case IDENT:
1683:                    id = scanner.getIdToken();
1684:                    p = scan();
1685:                    break;
1686:
1687:                case LPAREN:
1688:                    // It is a constructor
1689:                    id = new IdentifierToken(idInit);
1690:                    if ((mod & M_STRICTFP) != 0)
1691:                        env.error(pos, "bad.constructor.modifier");
1692:                    break;
1693:
1694:                default:
1695:                    expect(IDENT);
1696:                }
1697:
1698:                // If the next token is a left-bracket then we
1699:                // are dealing with a method or constructor, otherwise it is
1700:                // a list of variables
1701:                if (token == LPAREN) {
1702:                    // It is a method or constructor declaration
1703:                    scan();
1704:                    aCount = 0;
1705:
1706:                    if (token != RPAREN) {
1707:                        // Parse argument type and identifier
1708:                        // (arguments (like locals) are allowed to be final)
1709:                        int am = parseModifiers(M_FINAL);
1710:                        Type at = parseType();
1711:                        IdentifierToken an = scanner.getIdToken();
1712:                        expect(IDENT);
1713:
1714:                        // Parse optional array specifier, ie: a[][]
1715:                        at = parseArrayBrackets(at);
1716:                        addArgument(am, at, an);
1717:
1718:                        // If the next token is a comma then there are
1719:                        // more arguments
1720:                        while (token == COMMA) {
1721:                            // Parse argument type and identifier
1722:                            scan();
1723:                            am = parseModifiers(M_FINAL);
1724:                            at = parseType();
1725:                            an = scanner.getIdToken();
1726:                            expect(IDENT);
1727:
1728:                            // Parse optional array specifier, ie: a[][]
1729:                            at = parseArrayBrackets(at);
1730:                            addArgument(am, at, an);
1731:                        }
1732:                    }
1733:                    expect(RPAREN);
1734:
1735:                    // Parse optional array sepecifier, ie: foo()[][]
1736:                    t = parseArrayBrackets(t);
1737:
1738:                    // copy arguments
1739:                    Type atypes[] = new Type[aCount];
1740:                    System.arraycopy(aTypes, 0, atypes, 0, aCount);
1741:
1742:                    IdentifierToken anames[] = new IdentifierToken[aCount];
1743:                    System.arraycopy(aNames, 0, anames, 0, aCount);
1744:
1745:                    // Construct the type signature
1746:                    t = Type.tMethod(t, atypes);
1747:
1748:                    // Parse and ignore throws clause
1749:                    IdentifierToken exp[] = null;
1750:                    if (token == THROWS) {
1751:                        Vector v = new Vector();
1752:                        scan();
1753:                        v.addElement(parseName(false));
1754:                        while (token == COMMA) {
1755:                            scan();
1756:                            v.addElement(parseName(false));
1757:                        }
1758:
1759:                        exp = new IdentifierToken[v.size()];
1760:                        v.copyInto(exp);
1761:                    }
1762:
1763:                    // Check if it is a method definition or a method declaration
1764:                    // ie: foo() {...} or foo();
1765:                    switch (token) {
1766:                    case LBRACE: // It's a method definition
1767:
1768:                        // Set the state of FP strictness for the body of the method
1769:                        int oldFPstate = FPstate;
1770:                        if ((mod & M_STRICTFP) != 0) {
1771:                            FPstate = M_STRICTFP;
1772:                        } else {
1773:                            mod |= FPstate & M_STRICTFP;
1774:                        }
1775:
1776:                        actions.defineField(p, curClass, doc, mod, t, id,
1777:                                anames, exp, parseStatement());
1778:
1779:                        FPstate = oldFPstate;
1780:
1781:                        break;
1782:
1783:                    case SEMICOLON:
1784:                        scan();
1785:                        actions.defineField(p, curClass, doc, mod, t, id,
1786:                                anames, exp, null);
1787:                        break;
1788:
1789:                    default:
1790:                        // really expected a statement body here
1791:                        if ((mod & (M_NATIVE | M_ABSTRACT)) == 0) {
1792:                            expect(LBRACE);
1793:                        } else {
1794:                            expect(SEMICOLON);
1795:                        }
1796:                    }
1797:                    return;
1798:                }
1799:
1800:                // It is a list of instance variables
1801:                while (true) {
1802:                    p = pos; // get the current position
1803:                    // parse the array brackets (if any)
1804:                    // ie: var[][][]
1805:                    Type vt = parseArrayBrackets(t);
1806:
1807:                    // Parse the optional initializer
1808:                    Node init = null;
1809:                    if (token == ASSIGN) {
1810:                        scan();
1811:                        init = parseExpression();
1812:                    }
1813:
1814:                    // Define the variable
1815:                    actions.defineField(p, curClass, doc, mod, vt, id, null,
1816:                            null, init);
1817:
1818:                    // If the next token is a comma, then there is more
1819:                    if (token != COMMA) {
1820:                        expect(SEMICOLON);
1821:                        return;
1822:                    }
1823:                    scan();
1824:
1825:                    // The next token must be an identifier
1826:                    id = scanner.getIdToken();
1827:                    expect(IDENT);
1828:                }
1829:            }
1830:
1831:            /**
1832:             * Recover after a syntax error in a field. This involves
1833:             * discarding tokens until an EOF or a possible legal
1834:             * continuation is encountered.
1835:             */
1836:            protected void recoverField(ClassDefinition newClass)
1837:                    throws SyntaxError, IOException {
1838:                while (true) {
1839:                    switch (token) {
1840:                    case EOF:
1841:                    case STATIC:
1842:                    case FINAL:
1843:                    case PUBLIC:
1844:                    case PRIVATE:
1845:                    case SYNCHRONIZED:
1846:                    case TRANSIENT:
1847:
1848:                    case VOID:
1849:                    case BOOLEAN:
1850:                    case BYTE:
1851:                    case CHAR:
1852:                    case SHORT:
1853:                    case INT:
1854:                    case FLOAT:
1855:                    case LONG:
1856:                    case DOUBLE:
1857:                        // possible begin of a field, continue
1858:                        return;
1859:
1860:                    case LBRACE:
1861:                        match(LBRACE, RBRACE);
1862:                        scan();
1863:                        break;
1864:
1865:                    case LPAREN:
1866:                        match(LPAREN, RPAREN);
1867:                        scan();
1868:                        break;
1869:
1870:                    case LSQBRACKET:
1871:                        match(LSQBRACKET, RSQBRACKET);
1872:                        scan();
1873:                        break;
1874:
1875:                    case RBRACE:
1876:                    case INTERFACE:
1877:                    case CLASS:
1878:                    case IMPORT:
1879:                    case PACKAGE:
1880:                        // begin of something outside a class, panic more
1881:                        actions.endClass(pos, newClass);
1882:                        throw new SyntaxError();
1883:
1884:                    default:
1885:                        // don't know what to do, skip
1886:                        scan();
1887:                        break;
1888:                    }
1889:                }
1890:            }
1891:
1892:            /**
1893:             * Parse a top-level class or interface declaration.
1894:             */
1895:            protected void parseClass() throws SyntaxError, IOException {
1896:                String doc = scanner.docComment;
1897:
1898:                // Parse the modifiers.
1899:                int mod = parseModifiers(MM_CLASS | MM_MEMBER);
1900:
1901:                parseNamedClass(mod, PACKAGE, doc);
1902:            }
1903:
1904:            // Current strict/default state of floating point.  This is
1905:            // set and reset with a stack discipline around methods and named
1906:            // classes.  Only M_STRICTFP may be set in this word.  try...
1907:            // finally is not needed to protect setting and resetting because
1908:            // there are no error messages based on FPstate.
1909:            private int FPstate = 0;
1910:
1911:            /**
1912:             * Parse a block-local class or interface declaration.
1913:             */
1914:            protected Statement parseLocalClass(int mod) throws SyntaxError,
1915:                    IOException {
1916:                long p = pos;
1917:                ClassDefinition body = parseNamedClass(M_LOCAL | mod, STAT,
1918:                        null);
1919:                Statement ds[] = { new VarDeclarationStatement(p,
1920:                        new LocalMember(body), null) };
1921:                Expression type = new TypeExpression(p, body.getType());
1922:                return new DeclarationStatement(p, 0, type, ds);
1923:            }
1924:
1925:            /**
1926:             * Parse a named class or interface declaration,
1927:             * starting at "class" or "interface".
1928:             * @arg ctx Syntactic context of the class, one of {PACKAGE CLASS STAT EXPR}.
1929:             */
1930:            protected ClassDefinition parseNamedClass(int mod, int ctx,
1931:                    String doc) throws SyntaxError, IOException {
1932:                // Parse class/interface
1933:                switch (token) {
1934:                case INTERFACE:
1935:                    scan();
1936:                    mod |= M_INTERFACE;
1937:                    break;
1938:
1939:                case CLASS:
1940:                    scan();
1941:                    break;
1942:
1943:                default:
1944:                    env.error(pos, "class.expected");
1945:                    break;
1946:                }
1947:
1948:                int oldFPstate = FPstate;
1949:                if ((mod & M_STRICTFP) != 0) {
1950:                    FPstate = M_STRICTFP;
1951:                } else {
1952:                    // The & (...) isn't really necessary here because we do maintain
1953:                    // the invariant that FPstate has no extra bits set.
1954:                    mod |= FPstate & M_STRICTFP;
1955:                }
1956:
1957:                // Parse the class name
1958:                IdentifierToken nm = scanner.getIdToken();
1959:                long p = pos;
1960:                expect(IDENT);
1961:
1962:                Vector ext = new Vector();
1963:                Vector impl = new Vector();
1964:                parseInheritance(ext, impl);
1965:
1966:                ClassDefinition tmp = parseClassBody(nm, mod, ctx, doc, ext,
1967:                        impl, p);
1968:
1969:                FPstate = oldFPstate;
1970:
1971:                return tmp;
1972:            }
1973:
1974:            protected void parseInheritance(Vector ext, Vector impl)
1975:                    throws SyntaxError, IOException {
1976:                // Parse extends clause
1977:                if (token == EXTENDS) {
1978:                    scan();
1979:                    ext.addElement(parseName(false));
1980:                    while (token == COMMA) {
1981:                        scan();
1982:                        ext.addElement(parseName(false));
1983:                    }
1984:                }
1985:
1986:                // Parse implements clause
1987:                if (token == IMPLEMENTS) {
1988:                    scan();
1989:                    impl.addElement(parseName(false));
1990:                    while (token == COMMA) {
1991:                        scan();
1992:                        impl.addElement(parseName(false));
1993:                    }
1994:                }
1995:            }
1996:
1997:            /**
1998:             * Parse the body of a class or interface declaration,
1999:             * starting at the left brace.
2000:             */
2001:            protected ClassDefinition parseClassBody(IdentifierToken nm,
2002:                    int mod, int ctx, String doc, Vector ext, Vector impl,
2003:                    long p) throws SyntaxError, IOException {
2004:                // Decide which is the super class
2005:                IdentifierToken sup = null;
2006:                if ((mod & M_INTERFACE) != 0) {
2007:                    if (impl.size() > 0) {
2008:                        env.error(((IdentifierToken) impl.elementAt(0))
2009:                                .getWhere(), "intf.impl.intf");
2010:                    }
2011:                    impl = ext;
2012:                } else {
2013:                    if (ext.size() > 0) {
2014:                        if (ext.size() > 1) {
2015:                            env.error(((IdentifierToken) ext.elementAt(1))
2016:                                    .getWhere(), "multiple.inherit");
2017:                        }
2018:                        sup = (IdentifierToken) ext.elementAt(0);
2019:                    }
2020:                }
2021:
2022:                ClassDefinition oldClass = curClass;
2023:
2024:                // Begin a new class
2025:                IdentifierToken implids[] = new IdentifierToken[impl.size()];
2026:                impl.copyInto(implids);
2027:                ClassDefinition newClass = actions.beginClass(p, doc, mod, nm,
2028:                        sup, implids);
2029:
2030:                // Parse fields
2031:                expect(LBRACE);
2032:                while ((token != EOF) && (token != RBRACE)) {
2033:                    try {
2034:                        curClass = newClass;
2035:                        parseField();
2036:                    } catch (SyntaxError e) {
2037:                        recoverField(newClass);
2038:                    } finally {
2039:                        curClass = oldClass;
2040:                    }
2041:                }
2042:                expect(RBRACE);
2043:
2044:                // End the class
2045:                actions.endClass(scanner.prevPos, newClass);
2046:                return newClass;
2047:            }
2048:
2049:            /**
2050:             * Recover after a syntax error in the file.
2051:             * This involves discarding tokens until an EOF
2052:             * or a possible legal continuation is encountered.
2053:             */
2054:            protected void recoverFile() throws IOException {
2055:                while (true) {
2056:                    switch (token) {
2057:                    case CLASS:
2058:                    case INTERFACE:
2059:                        // Start of a new source file statement, continue
2060:                        return;
2061:
2062:                    case LBRACE:
2063:                        match(LBRACE, RBRACE);
2064:                        scan();
2065:                        break;
2066:
2067:                    case LPAREN:
2068:                        match(LPAREN, RPAREN);
2069:                        scan();
2070:                        break;
2071:
2072:                    case LSQBRACKET:
2073:                        match(LSQBRACKET, RSQBRACKET);
2074:                        scan();
2075:                        break;
2076:
2077:                    case EOF:
2078:                        return;
2079:
2080:                    default:
2081:                        // Don't know what to do, skip
2082:                        scan();
2083:                        break;
2084:                    }
2085:                }
2086:            }
2087:
2088:            /**
2089:             * Parse an Java file.
2090:             */
2091:            public void parseFile() {
2092:                try {
2093:                    try {
2094:                        if (token == PACKAGE) {
2095:                            // Package statement
2096:                            long p = scan();
2097:                            IdentifierToken id = parseName(false);
2098:                            expect(SEMICOLON);
2099:                            actions.packageDeclaration(p, id);
2100:                        }
2101:                    } catch (SyntaxError e) {
2102:                        recoverFile();
2103:                    }
2104:                    while (token == IMPORT) {
2105:                        try {
2106:                            // Import statement
2107:                            long p = scan();
2108:                            IdentifierToken id = parseName(true);
2109:                            expect(SEMICOLON);
2110:                            if (id.id.getName().equals(idStar)) {
2111:                                id.id = id.id.getQualifier();
2112:                                actions.importPackage(p, id);
2113:                            } else {
2114:                                actions.importClass(p, id);
2115:                            }
2116:                        } catch (SyntaxError e) {
2117:                            recoverFile();
2118:                        }
2119:                    }
2120:
2121:                    while (token != EOF) {
2122:                        try {
2123:                            switch (token) {
2124:                            case FINAL:
2125:                            case PUBLIC:
2126:                            case PRIVATE:
2127:                            case ABSTRACT:
2128:                            case CLASS:
2129:                            case INTERFACE:
2130:                            case STRICTFP:
2131:                                // Start of a class
2132:                                parseClass();
2133:                                break;
2134:
2135:                            case SEMICOLON:
2136:                                // Bogus semicolon.
2137:                                // According to the JLS (7.6,19.6), a TypeDeclaration
2138:                                // may consist of a single semicolon, however, this
2139:                                // usage is discouraged (JLS 7.6).  In contrast,
2140:                                // a FieldDeclaration may not be empty, and is flagged
2141:                                // as an error.  See parseField above.
2142:                                scan();
2143:                                break;
2144:
2145:                            case EOF:
2146:                                // The end
2147:                                return;
2148:
2149:                            default:
2150:                                // Oops
2151:                                env.error(pos, "toplevel.expected");
2152:                                throw new SyntaxError();
2153:                            }
2154:                        } catch (SyntaxError e) {
2155:                            recoverFile();
2156:                        }
2157:                    }
2158:                } catch (IOException e) {
2159:                    env.error(pos, "io.exception", env.getSource());
2160:                    return;
2161:                }
2162:            }
2163:
2164:            /**
2165:             * Usually <code>this.scanner == (Scanner)this</code>.
2166:             * However, a delegate scanner can produce tokens for this parser,
2167:             * in which case <code>(Scanner)this</code> is unused,
2168:             * except for <code>this.token</code> and <code>this.pos</code>
2169:             * instance variables which are filled from the real scanner
2170:             * by <code>this.scan()</code> and the constructor.
2171:             */
2172:            protected Scanner scanner;
2173:
2174:            // Design Note: We ought to disinherit Parser from Scanner.
2175:            // We also should split out the interface ParserActions from
2176:            // Parser, and make BatchParser implement ParserActions,
2177:            // not extend Parser.  This would split scanning, parsing,
2178:            // and class building into distinct responsibility areas.
2179:            // (Perhaps tree building could be virtualized too.)
2180:
2181:            public long scan() throws IOException {
2182:                if (scanner != this  && scanner != null) {
2183:                    long result = scanner.scan();
2184:                    ((Scanner) this ).token = scanner.token;
2185:                    ((Scanner) this ).pos = scanner.pos;
2186:                    return result;
2187:                }
2188:                return super .scan();
2189:            }
2190:
2191:            public void match(int open, int close) throws IOException {
2192:                if (scanner != this ) {
2193:                    scanner.match(open, close);
2194:                    ((Scanner) this ).token = scanner.token;
2195:                    ((Scanner) this).pos = scanner.pos;
2196:                    return;
2197:                }
2198:                super.match(open, close);
2199:            }
2200:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.