Source Code Cross Referenced for Parser.java in  » Scripting » janino-2.5.11 » org » codehaus » janino » 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 » Scripting » janino 2.5.11 » org.codehaus.janino 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        /*
0002:         * Janino - An embedded Java[TM] compiler
0003:         *
0004:         * Copyright (c) 2001-2007, Arno Unkrig
0005:         * All rights reserved.
0006:         *
0007:         * Redistribution and use in source and binary forms, with or without
0008:         * modification, are permitted provided that the following conditions
0009:         * are met:
0010:         *
0011:         *    1. Redistributions of source code must retain the above copyright
0012:         *       notice, this list of conditions and the following disclaimer.
0013:         *    2. Redistributions in binary form must reproduce the above
0014:         *       copyright notice, this list of conditions and the following
0015:         *       disclaimer in the documentation and/or other materials
0016:         *       provided with the distribution.
0017:         *    3. The name of the author may not be used to endorse or promote
0018:         *       products derived from this software without specific prior
0019:         *       written permission.
0020:         *
0021:         * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
0022:         * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
0023:         * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
0024:         * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
0025:         * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
0026:         * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
0027:         * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
0028:         * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
0029:         * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
0030:         * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
0031:         * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
0032:         */
0033:
0034:        package org.codehaus.janino;
0035:
0036:        import java.io.*;
0037:        import java.util.*;
0038:
0039:        import org.codehaus.janino.Java.CompilationUnit.ImportDeclaration;
0040:        import org.codehaus.janino.util.LocatedException;
0041:        import org.codehaus.janino.util.enumerator.Enumerator;
0042:
0043:        /**
0044:         * A parser for the Java<sup>TM</sup> programming language.
0045:         */
0046:        public class Parser {
0047:            private final Scanner scanner;
0048:
0049:            public Parser(Scanner scanner) {
0050:                this .scanner = scanner;
0051:            }
0052:
0053:            public Scanner getScanner() {
0054:                return this .scanner;
0055:            }
0056:
0057:            /**
0058:             * <pre>
0059:             *   CompilationUnit := [ PackageDeclaration ]
0060:             *                      { ImportDeclaration }
0061:             *                      { TypeDeclaration }
0062:             * </pre>
0063:             */
0064:            public Java.CompilationUnit parseCompilationUnit()
0065:                    throws ParseException, Scanner.ScanException, IOException {
0066:                Java.CompilationUnit compilationUnit = new Java.CompilationUnit(
0067:                        this .location().getFileName());
0068:
0069:                if (this .peekKeyword("package")) {
0070:                    compilationUnit.setPackageDeclaration(this 
0071:                            .parsePackageDeclaration());
0072:                }
0073:
0074:                while (this .peekKeyword("import")) {
0075:                    compilationUnit.addImportDeclaration(this 
0076:                            .parseImportDeclaration());
0077:                }
0078:
0079:                while (!this .scanner.peek().isEOF()) {
0080:                    if (this .peekOperator(";")) {
0081:                        this .eatToken();
0082:                    } else {
0083:                        compilationUnit.addPackageMemberTypeDeclaration(this 
0084:                                .parsePackageMemberTypeDeclaration());
0085:                    }
0086:                }
0087:
0088:                return compilationUnit;
0089:            }
0090:
0091:            /**
0092:             * <pre>
0093:             *   PackageDeclaration := 'package' QualifiedIdentifier ';'
0094:             * </pre>
0095:             */
0096:            public Java.PackageDeclaration parsePackageDeclaration()
0097:                    throws Parser.ParseException, Scanner.ScanException,
0098:                    IOException {
0099:                this .readKeyword("package");
0100:                Location loc = this .location();
0101:                String packageName = Parser.join(this 
0102:                        .parseQualifiedIdentifier(), ".");
0103:                this .readOperator(";");
0104:                this .verifyStringIsConventionalPackageName(packageName, loc);
0105:                return new Java.PackageDeclaration(loc, packageName);
0106:            }
0107:
0108:            /**
0109:             * <pre>
0110:             *   ImportDeclaration := 'import' ImportDeclarationBody ';'
0111:             * </pre>
0112:             */
0113:            public Java.CompilationUnit.ImportDeclaration parseImportDeclaration()
0114:                    throws ParseException, Scanner.ScanException, IOException {
0115:                this .readKeyword("import");
0116:                Java.CompilationUnit.ImportDeclaration importDeclaration = this 
0117:                        .parseImportDeclarationBody();
0118:                this .readOperator(";");
0119:                return importDeclaration;
0120:            }
0121:
0122:            /**
0123:             * <pre>
0124:             *   ImportDeclarationBody := [ 'static' ] Identifier { '.' Identifier } [ '.' '*' ]
0125:             * </pre>
0126:             */
0127:            public Java.CompilationUnit.ImportDeclaration parseImportDeclarationBody()
0128:                    throws ParseException, Scanner.ScanException, IOException {
0129:                Location loc = this .location();
0130:                boolean isStatic;
0131:                if (this .peekKeyword("static")) {
0132:                    isStatic = true;
0133:                    this .eatToken();
0134:                } else {
0135:                    isStatic = false;
0136:                }
0137:                List l = new ArrayList();
0138:                l.add(this .readIdentifier());
0139:                for (;;) {
0140:                    if (!this .peekOperator(".")) {
0141:                        String[] identifiers = (String[]) l
0142:                                .toArray(new String[l.size()]);
0143:                        return (isStatic ? (ImportDeclaration) new Java.CompilationUnit.SingleStaticImportDeclaration(
0144:                                loc, identifiers)
0145:                                : (ImportDeclaration) new Java.CompilationUnit.SingleTypeImportDeclaration(
0146:                                        loc, identifiers));
0147:                    }
0148:                    this .readOperator(".");
0149:                    if (this .peekOperator("*")) {
0150:                        this .eatToken();
0151:                        String[] identifiers = (String[]) l
0152:                                .toArray(new String[l.size()]);
0153:                        return (isStatic ? (ImportDeclaration) new Java.CompilationUnit.StaticImportOnDemandDeclaration(
0154:                                loc, identifiers)
0155:                                : (ImportDeclaration) new Java.CompilationUnit.TypeImportOnDemandDeclaration(
0156:                                        loc, identifiers));
0157:                    }
0158:                    l.add(this .readIdentifier());
0159:                }
0160:            }
0161:
0162:            /**
0163:             * QualifiedIdentifier := Identifier { '.' Identifier }
0164:             */
0165:            public String[] parseQualifiedIdentifier() throws ParseException,
0166:                    Scanner.ScanException, IOException {
0167:                if (!this .scanner.peek().isIdentifier())
0168:                    this .throwParseException("Identifier expected");
0169:                List l = new ArrayList();
0170:                l.add(this .readIdentifier());
0171:                while (this .peekOperator(".")
0172:                        && this .scanner.peekNextButOne().isIdentifier()) {
0173:                    this .eatToken();
0174:                    l.add(this .readIdentifier());
0175:                }
0176:                return (String[]) l.toArray(new String[l.size()]);
0177:            }
0178:
0179:            /**
0180:             * <pre>
0181:             *   PackageMemberTypeDeclaration :=
0182:             *             ModifiersOpt 'class' ClassDeclarationRest |
0183:             *             ModifiersOpt 'interface' InterfaceDeclarationRest
0184:             * </pre>
0185:             */
0186:            public Java.PackageMemberTypeDeclaration parsePackageMemberTypeDeclaration()
0187:                    throws ParseException, Scanner.ScanException, IOException {
0188:                String optionalDocComment = this .scanner.doc();
0189:
0190:                short modifiers = this .parseModifiersOpt();
0191:
0192:                Java.PackageMemberTypeDeclaration res;
0193:                if (this .peekKeyword("class")) {
0194:                    if (optionalDocComment == null)
0195:                        this .warning("CDCM", "Class doc comment missing", this 
0196:                                .location());
0197:                    this .eatToken();
0198:                    res = (Java.PackageMemberClassDeclaration) this 
0199:                            .parseClassDeclarationRest(optionalDocComment, // optionalDocComment
0200:                                    modifiers, // modifiers
0201:                                    ClassDeclarationContext.COMPILATION_UNIT // context
0202:                            );
0203:                } else if (this .peekKeyword("interface")) {
0204:                    if (optionalDocComment == null)
0205:                        this .warning("IDCM", "Interface doc comment missing",
0206:                                this .location());
0207:                    this .eatToken();
0208:                    res = (Java.PackageMemberInterfaceDeclaration) this 
0209:                            .parseInterfaceDeclarationRest(
0210:                                    optionalDocComment, // optionalDocComment
0211:                                    modifiers, // modifiers
0212:                                    InterfaceDeclarationContext.COMPILATION_UNIT // context
0213:                            );
0214:                } else {
0215:                    this .throwParseException("Unexpected token \""
0216:                            + this .scanner.peek()
0217:                            + "\" in class or interface declaration");
0218:                    /* NEVER REACHED */return null;
0219:                }
0220:                return res;
0221:            }
0222:
0223:            /**
0224:             * <pre>
0225:             *   ModifiersOpt := { 'public' | 'protected' | 'private' | 'static' |
0226:             *           'abstract' | 'final' | 'native' | 'synchronized' |
0227:             *           'transient' | 'volatile' | 'strictfp'
0228:             * </pre>
0229:             */
0230:            public short parseModifiersOpt() throws ParseException,
0231:                    Scanner.ScanException, IOException {
0232:                short mod = 0;
0233:                while (this .peekKeyword()) {
0234:                    String kw = this .scanner.peek().getKeyword();
0235:                    short x = (short) (kw == "public" ? Mod.PUBLIC
0236:                            : kw == "protected" ? Mod.PROTECTED
0237:                                    : kw == "private" ? Mod.PRIVATE
0238:                                            : kw == "static" ? Mod.STATIC
0239:                                                    : kw == "abstract" ? Mod.ABSTRACT
0240:                                                            : kw == "final" ? Mod.FINAL
0241:                                                                    : kw == "native" ? Mod.NATIVE
0242:                                                                            : kw == "synchronized" ? Mod.SYNCHRONIZED
0243:                                                                                    : kw == "transient" ? Mod.TRANSIENT
0244:                                                                                            : kw == "volatile" ? Mod.VOLATILE
0245:                                                                                                    : kw == "strictfp" ? Mod.STRICTFP
0246:                                                                                                            : -1);
0247:                    if (x == -1)
0248:                        break;
0249:
0250:                    this .eatToken();
0251:                    if ((mod & x) != 0)
0252:                        this .throwParseException("Duplicate modifier \"" + kw
0253:                                + "\"");
0254:                    for (int i = 0; i < Parser.MUTUALS.length; ++i) {
0255:                        short m = Parser.MUTUALS[i];
0256:                        if ((x & m) != 0 && (mod & m) != 0) {
0257:                            this .throwParseException("Only one of \""
0258:                                    + Mod.shortToString(m) + "\" allowed");
0259:                        }
0260:                    }
0261:                    mod |= x;
0262:                }
0263:                return mod;
0264:            }
0265:
0266:            private static final short[] MUTUALS = { Mod.PUBLIC | Mod.PROTECTED
0267:                    | Mod.PRIVATE, };
0268:
0269:            /**
0270:             * <pre>
0271:             *   ClassDeclarationRest :=
0272:             *        Identifier
0273:             *        [ 'extends' ReferenceType ]
0274:             *        [ 'implements' ReferenceTypeList ]
0275:             *        ClassBody
0276:             * </pre>
0277:             */
0278:            public Java.NamedClassDeclaration parseClassDeclarationRest(
0279:                    String optionalDocComment, short modifiers,
0280:                    ClassDeclarationContext context) throws ParseException,
0281:                    Scanner.ScanException, IOException {
0282:                Location location = this .location();
0283:                String className = this .readIdentifier();
0284:                this .verifyIdentifierIsConventionalClassOrInterfaceName(
0285:                        className, location);
0286:
0287:                Java.ReferenceType optionalExtendedType = null;
0288:                if (this .peekKeyword("extends")) {
0289:                    this .eatToken();
0290:                    optionalExtendedType = this .parseReferenceType();
0291:                }
0292:
0293:                Java.ReferenceType[] implementedTypes = new Java.ReferenceType[0];
0294:                if (this .peekKeyword("implements")) {
0295:                    this .eatToken();
0296:                    implementedTypes = this .parseReferenceTypeList();
0297:                }
0298:
0299:                Java.NamedClassDeclaration namedClassDeclaration;
0300:                if (context == ClassDeclarationContext.COMPILATION_UNIT) {
0301:                    namedClassDeclaration = new Java.PackageMemberClassDeclaration(
0302:                            location, // location
0303:                            optionalDocComment, // optionalDocComment
0304:                            modifiers, // modifiers
0305:                            className, // name
0306:                            optionalExtendedType, // optinalExtendedType
0307:                            implementedTypes // implementedTypes
0308:                    );
0309:                } else if (context == ClassDeclarationContext.TYPE_DECLARATION) {
0310:                    namedClassDeclaration = new Java.MemberClassDeclaration(
0311:                            location, // location
0312:                            optionalDocComment, // optionalDocComment
0313:                            modifiers, // modifiers
0314:                            className, // name
0315:                            optionalExtendedType, // optionalExtendedType
0316:                            implementedTypes // implementedTypes
0317:                    );
0318:                } else if (context == ClassDeclarationContext.BLOCK) {
0319:                    namedClassDeclaration = new Java.LocalClassDeclaration(
0320:                            location, // location
0321:                            optionalDocComment, // optionalDocComment
0322:                            modifiers, // modifiers
0323:                            className, // name
0324:                            optionalExtendedType, // optionalExtendedType
0325:                            implementedTypes // implementedTypes
0326:                    );
0327:                } else {
0328:                    throw new RuntimeException(
0329:                            "SNO: Class declaration in unexpected context "
0330:                                    + context);
0331:                }
0332:
0333:                this .parseClassBody(namedClassDeclaration);
0334:                return namedClassDeclaration;
0335:            }
0336:
0337:            public static class ClassDeclarationContext extends Enumerator {
0338:                public static final ClassDeclarationContext BLOCK = new ClassDeclarationContext(
0339:                        "block");
0340:                public static final ClassDeclarationContext TYPE_DECLARATION = new ClassDeclarationContext(
0341:                        "type_declaration");
0342:                public static final ClassDeclarationContext COMPILATION_UNIT = new ClassDeclarationContext(
0343:                        "compilation_unit");
0344:
0345:                private ClassDeclarationContext(String name) {
0346:                    super (name);
0347:                }
0348:            }
0349:
0350:            /**
0351:             * <pre>
0352:             *   ClassBody := '{' { ClassBodyDeclaration } '}'
0353:             * </pre>
0354:             */
0355:            public void parseClassBody(Java.ClassDeclaration classDeclaration)
0356:                    throws ParseException, Scanner.ScanException, IOException {
0357:                if (!this .peekOperator("{"))
0358:                    this 
0359:                            .throwParseException("\"{\" expected at start of class body");
0360:                this .eatToken();
0361:
0362:                for (;;) {
0363:                    if (this .peekOperator("}")) {
0364:                        this .eatToken();
0365:                        return;
0366:                    }
0367:
0368:                    this .parseClassBodyDeclaration(classDeclaration);
0369:                }
0370:            }
0371:
0372:            /**
0373:             * <pre>
0374:             *   ClassBodyDeclaration :=
0375:             *     ';' |
0376:             *     ModifiersOpt (
0377:             *       Block |                                    // Instance (JLS2 8.6) or static initializer (JLS2 8.7)
0378:             *       'void' Identifier MethodDeclarationRest |
0379:             *       'class' ClassDeclarationRest |
0380:             *       'interface' InterfaceDeclarationRest |
0381:             *       ConstructorDeclarator |
0382:             *       Type Identifier (
0383:             *         MethodDeclarationRest |
0384:             *         FieldDeclarationRest ';'
0385:             *       )
0386:             *     )
0387:             *
0388:             * </pre>
0389:             */
0390:            public void parseClassBodyDeclaration(
0391:                    Java.ClassDeclaration classDeclaration)
0392:                    throws ParseException, Scanner.ScanException, IOException {
0393:                if (this .peekOperator(";")) {
0394:                    this .eatToken();
0395:                    return;
0396:                }
0397:
0398:                String optionalDocComment = this .scanner.doc();
0399:                short modifiers = this .parseModifiersOpt();
0400:
0401:                // Initializer?
0402:                if (this .peekOperator("{")) {
0403:                    if ((modifiers & ~Mod.STATIC) != 0)
0404:                        this 
0405:                                .throwParseException("Only modifier \"static\" allowed on initializer");
0406:
0407:                    Java.Initializer initializer = new Java.Initializer(this 
0408:                            .location(), // location
0409:                            (modifiers & Mod.STATIC) != 0, // statiC
0410:                            this .parseBlock() // block
0411:                    );
0412:
0413:                    classDeclaration
0414:                            .addVariableDeclaratorOrInitializer(initializer);
0415:                    return;
0416:                }
0417:
0418:                // "void" method declaration.
0419:                if (this .peekKeyword("void")) {
0420:                    Location location = this .location();
0421:                    this .eatToken();
0422:                    if (optionalDocComment == null)
0423:                        this .warning("MDCM", "Method doc comment missing",
0424:                                location);
0425:                    String name = this .readIdentifier();
0426:                    classDeclaration.addDeclaredMethod(this 
0427:                            .parseMethodDeclarationRest(optionalDocComment, // declaringType
0428:                                    modifiers, // optionalDocComment
0429:                                    new Java.BasicType(location,
0430:                                            Java.BasicType.VOID), // modifiers
0431:                                    name // name
0432:                            ));
0433:                    return;
0434:                }
0435:
0436:                // Member class.
0437:                if (this .peekKeyword("class")) {
0438:                    if (optionalDocComment == null)
0439:                        this .warning("MCDCM",
0440:                                "Member class doc comment missing", this 
0441:                                        .location());
0442:                    this .eatToken();
0443:                    classDeclaration
0444:                            .addMemberTypeDeclaration((Java.MemberTypeDeclaration) this 
0445:                                    .parseClassDeclarationRest(
0446:                                            optionalDocComment, // optionalDocComment
0447:                                            modifiers, // modifiers
0448:                                            ClassDeclarationContext.TYPE_DECLARATION // context
0449:                                    ));
0450:                    return;
0451:                }
0452:
0453:                // Member interface.
0454:                if (this .peekKeyword("interface")) {
0455:                    if (optionalDocComment == null)
0456:                        this .warning("MIDCM",
0457:                                "Member interface doc comment missing", this 
0458:                                        .location());
0459:                    this .eatToken();
0460:                    classDeclaration
0461:                            .addMemberTypeDeclaration((Java.MemberTypeDeclaration) this 
0462:                                    .parseInterfaceDeclarationRest(
0463:                                            optionalDocComment, // optionalDocComment
0464:                                            (short) (modifiers | Mod.STATIC), // modifiers
0465:                                            InterfaceDeclarationContext.NAMED_TYPE_DECLARATION // context
0466:                                    ));
0467:                    return;
0468:                }
0469:
0470:                // Constructor.
0471:                if (classDeclaration instanceof  Java.NamedClassDeclaration
0472:                        && this .scanner.peek().isIdentifier(
0473:                                ((Java.NamedClassDeclaration) classDeclaration)
0474:                                        .getName())
0475:                        && this .scanner.peekNextButOne().isOperator("(")) {
0476:                    if (optionalDocComment == null)
0477:                        this .warning("CDCM", "Constructor doc comment missing",
0478:                                this .location());
0479:                    classDeclaration.addConstructor(this 
0480:                            .parseConstructorDeclarator(optionalDocComment, // declaringClass
0481:                                    modifiers // modifiers
0482:                            ));
0483:                    return;
0484:                }
0485:
0486:                // Member method or field.
0487:                Java.Type memberType = this .parseType();
0488:                Location location = this .location();
0489:                String memberName = this .readIdentifier();
0490:
0491:                // Method declarator.
0492:                if (this .peekOperator("(")) {
0493:                    if (optionalDocComment == null)
0494:                        this .warning("MDCM", "Method doc comment missing", this 
0495:                                .location());
0496:                    classDeclaration.addDeclaredMethod(this 
0497:                            .parseMethodDeclarationRest(optionalDocComment, // declaringType
0498:                                    modifiers, // optionalDocComment
0499:                                    memberType, // modifiers
0500:                                    memberName // name
0501:                            ));
0502:                    return;
0503:                }
0504:
0505:                // Field declarator.
0506:                if (optionalDocComment == null)
0507:                    this .warning("FDCM", "Field doc comment missing", this 
0508:                            .location());
0509:                Java.FieldDeclaration fd = new Java.FieldDeclaration(location, // location
0510:                        optionalDocComment, // optionalDocComment
0511:                        modifiers, // modifiers
0512:                        memberType, // type
0513:                        this .parseFieldDeclarationRest(memberName) // variableDeclarators
0514:                );
0515:                this .readOperator(";");
0516:                classDeclaration.addVariableDeclaratorOrInitializer(fd);
0517:            }
0518:
0519:            /**
0520:             * <pre>
0521:             *   InterfaceDeclarationRest :=
0522:             *     Identifier
0523:             *     [ 'extends' ReferenceTypeList ]
0524:             *     InterfaceBody
0525:             * </pre>
0526:             */
0527:            public Java.InterfaceDeclaration parseInterfaceDeclarationRest(
0528:                    String optionalDocComment, short modifiers,
0529:                    InterfaceDeclarationContext context) throws ParseException,
0530:                    Scanner.ScanException, IOException {
0531:                Location location = this .location();
0532:                String interfaceName = this .readIdentifier();
0533:                this .verifyIdentifierIsConventionalClassOrInterfaceName(
0534:                        interfaceName, location);
0535:
0536:                Java.ReferenceType[] extendedTypes = new Java.ReferenceType[0];
0537:                if (this .peekKeyword("extends")) {
0538:                    this .eatToken();
0539:                    extendedTypes = this .parseReferenceTypeList();
0540:                }
0541:
0542:                Java.InterfaceDeclaration interfaceDeclaration;
0543:                if (context == InterfaceDeclarationContext.COMPILATION_UNIT) {
0544:                    interfaceDeclaration = new Java.PackageMemberInterfaceDeclaration(
0545:                            location, // location
0546:                            optionalDocComment, // optionalDocComment
0547:                            modifiers, // modifiers
0548:                            interfaceName, // name
0549:                            extendedTypes // extendedTypes
0550:                    );
0551:                } else if (context == InterfaceDeclarationContext.NAMED_TYPE_DECLARATION) {
0552:                    interfaceDeclaration = new Java.MemberInterfaceDeclaration(
0553:                            location, // location
0554:                            optionalDocComment, // optionalDocComment
0555:                            modifiers, // modifiers
0556:                            interfaceName, // name
0557:                            extendedTypes // extendedTypes
0558:                    );
0559:                } else {
0560:                    throw new RuntimeException(
0561:                            "SNO: Interface declaration in unexpected context "
0562:                                    + context);
0563:                }
0564:
0565:                this .parseInterfaceBody(interfaceDeclaration);
0566:                return interfaceDeclaration;
0567:            }
0568:
0569:            public static class InterfaceDeclarationContext extends Enumerator {
0570:                public static final InterfaceDeclarationContext NAMED_TYPE_DECLARATION = new InterfaceDeclarationContext(
0571:                        "named_type_declaration");
0572:                public static final InterfaceDeclarationContext COMPILATION_UNIT = new InterfaceDeclarationContext(
0573:                        "compilation_unit");
0574:
0575:                private InterfaceDeclarationContext(String name) {
0576:                    super (name);
0577:                }
0578:            }
0579:
0580:            /**
0581:             * <pre>
0582:             *   InterfaceBody := '{' {
0583:             *     ';' |
0584:             *     ModifiersOpt (
0585:             *       'void' Identifier MethodDeclarationRest |
0586:             *       'class' ClassDeclarationRest |
0587:             *       'interface' InterfaceDeclarationRest |
0588:             *       Type Identifier (
0589:             *         MethodDeclarationRest |
0590:             *         FieldDeclarationRest
0591:             *       )
0592:             *     )
0593:             *   } '}'
0594:             * </pre>
0595:             */
0596:            public void parseInterfaceBody(
0597:                    Java.InterfaceDeclaration interfaceDeclaration)
0598:                    throws ParseException, Scanner.ScanException, IOException {
0599:                this .readOperator("{");
0600:
0601:                for (;;) {
0602:                    if (this .peekOperator("}")) {
0603:                        this .eatToken();
0604:                        break;
0605:                    }
0606:
0607:                    if (this .peekOperator(";")) {
0608:                        this .eatToken();
0609:                        continue;
0610:                    }
0611:
0612:                    String optionalDocComment = this .scanner.doc();
0613:                    short modifiers = this .parseModifiersOpt();
0614:
0615:                    // "void" method declaration.
0616:                    if (this .peekKeyword("void")) {
0617:                        if (optionalDocComment == null)
0618:                            this .warning("MDCM", "Method doc comment missing",
0619:                                    this .location());
0620:                        Location location = this .location();
0621:                        this .eatToken();
0622:                        String name = this .readIdentifier();
0623:                        interfaceDeclaration
0624:                                .addDeclaredMethod(this 
0625:                                        .parseMethodDeclarationRest(
0626:                                                optionalDocComment, // declaringType
0627:                                                (short) (modifiers
0628:                                                        | Mod.ABSTRACT | Mod.PUBLIC), // optionalDocComment
0629:                                                new Java.BasicType(location,
0630:                                                        Java.BasicType.VOID), // modifiers
0631:                                                name // name
0632:                                        ));
0633:                    } else
0634:
0635:                    // Member class.
0636:                    if (this .peekKeyword("class")) {
0637:                        if (optionalDocComment == null)
0638:                            this .warning("MCDCM",
0639:                                    "Member class doc comment missing", this 
0640:                                            .location());
0641:                        this .eatToken();
0642:                        interfaceDeclaration
0643:                                .addMemberTypeDeclaration((Java.MemberTypeDeclaration) this 
0644:                                        .parseClassDeclarationRest(
0645:                                                optionalDocComment, // optionalDocComment
0646:                                                (short) (modifiers | Mod.STATIC | Mod.PUBLIC), // modifiers
0647:                                                ClassDeclarationContext.TYPE_DECLARATION // context
0648:                                        ));
0649:                    } else
0650:
0651:                    // Member interface.
0652:                    if (this .peekKeyword("interface")) {
0653:                        if (optionalDocComment == null)
0654:                            this .warning("MIDCM",
0655:                                    "Member interface doc comment missing",
0656:                                    this .location());
0657:                        this .eatToken();
0658:                        interfaceDeclaration
0659:                                .addMemberTypeDeclaration((Java.MemberTypeDeclaration) this 
0660:                                        .parseInterfaceDeclarationRest(
0661:                                                optionalDocComment, // optionalDocComment
0662:                                                (short) (modifiers | Mod.STATIC | Mod.PUBLIC), // modifiers
0663:                                                InterfaceDeclarationContext.NAMED_TYPE_DECLARATION // context
0664:                                        ));
0665:                    } else
0666:
0667:                    // Member method or field.
0668:                    {
0669:                        Java.Type memberType = this .parseType();
0670:                        if (!this .scanner.peek().isIdentifier())
0671:                            this 
0672:                                    .throwParseException("Identifier expected in member declaration");
0673:                        Location location = this .location();
0674:                        String memberName = this .readIdentifier();
0675:
0676:                        // Method declarator.
0677:                        if (this .peekOperator("(")) {
0678:                            if (optionalDocComment == null)
0679:                                this .warning("MDCM",
0680:                                        "Method doc comment missing", this 
0681:                                                .location());
0682:                            interfaceDeclaration
0683:                                    .addDeclaredMethod(this 
0684:                                            .parseMethodDeclarationRest(
0685:                                                    optionalDocComment, // declaringType
0686:                                                    (short) (modifiers
0687:                                                            | Mod.ABSTRACT | Mod.PUBLIC), // optionalDocComment
0688:                                                    memberType, // modifiers
0689:                                                    memberName // name
0690:                                            ));
0691:                        } else
0692:
0693:                        // Field declarator.
0694:                        {
0695:                            if (optionalDocComment == null)
0696:                                this .warning("FDCM",
0697:                                        "Field doc comment missing", this 
0698:                                                .location());
0699:                            Java.FieldDeclaration fd = new Java.FieldDeclaration(
0700:                                    location, // location
0701:                                    optionalDocComment, // optionalDocComment
0702:                                    (short) ( // modifiers
0703:                                    modifiers | Mod.PUBLIC | Mod.STATIC | Mod.FINAL),
0704:                                    memberType, // type
0705:                                    this .parseFieldDeclarationRest(memberName) // variableDeclarators
0706:                            );
0707:                            interfaceDeclaration.addConstantDeclaration(fd);
0708:                        }
0709:                    }
0710:                }
0711:            }
0712:
0713:            /**
0714:             * <pre>
0715:             *   ConstructorDeclarator :=
0716:             *     Identifier
0717:             *     FormalParameters
0718:             *     [ 'throws' ReferenceTypeList ]
0719:             *     '{'
0720:             *       [ 'this' Arguments ';' | 'super' Arguments ';' | Primary '.' 'super' Arguments ';' ]
0721:             *       BlockStatements
0722:             *     '}'
0723:             * </pre>
0724:             */
0725:            public Java.ConstructorDeclarator parseConstructorDeclarator(
0726:                    String optionalDocComment, short modifiers)
0727:                    throws ParseException, Scanner.ScanException, IOException {
0728:                Location location = this .location();
0729:                this .readIdentifier(); // Class name
0730:
0731:                // Parse formal parameters.
0732:                Java.FunctionDeclarator.FormalParameter[] formalParameters = this 
0733:                        .parseFormalParameters();
0734:
0735:                // Parse "throws" clause.
0736:                Java.ReferenceType[] thrownExceptions;
0737:                if (this .peekKeyword("throws")) {
0738:                    this .eatToken();
0739:                    thrownExceptions = this .parseReferenceTypeList();
0740:                } else {
0741:                    thrownExceptions = new Java.ReferenceType[0];
0742:                }
0743:
0744:                // Parse constructor body.
0745:                location = this .location();
0746:                this .readOperator("{");
0747:
0748:                // Special treatment for the first statement of the constructor body: If this is surely an
0749:                // expression statement, and if it could be a "ConstructorInvocation", then parse the
0750:                // expression and check if it IS a ConstructorInvocation.
0751:                Java.ConstructorInvocation optionalConstructorInvocation = null;
0752:                Java.Block body = new Java.Block(location);
0753:                if (this .peekKeyword(new String[] { "this", "super", "new",
0754:                        "void", "byte", "char", "short", "int", "long",
0755:                        "float", "double", "boolean", })
0756:                        || this .scanner.peek().isLiteral()
0757:                        || this .scanner.peek().isIdentifier()) {
0758:                    Java.Atom a = this .parseExpression();
0759:                    if (a instanceof  Java.ConstructorInvocation) {
0760:                        this .readOperator(";");
0761:                        optionalConstructorInvocation = (Java.ConstructorInvocation) a;
0762:                    } else {
0763:                        Java.Statement s;
0764:                        if (this .scanner.peek().isIdentifier()) {
0765:                            Java.Type variableType = a.toTypeOrPE();
0766:                            s = new Java.LocalVariableDeclarationStatement(a
0767:                                    .getLocation(), // location
0768:                                    (short) 0, // modifiers
0769:                                    variableType, // type
0770:                                    this .parseLocalVariableDeclarators() // variableDeclarators
0771:                            );
0772:                            this .readOperator(";");
0773:                        } else {
0774:                            s = new Java.ExpressionStatement(a.toRvalueOrPE());
0775:                            this .readOperator(";");
0776:                        }
0777:                        body.addStatement(s);
0778:                    }
0779:                }
0780:                body.addStatements(this .parseBlockStatements());
0781:
0782:                this .readOperator("}");
0783:
0784:                return new Java.ConstructorDeclarator(location, // location
0785:                        optionalDocComment, // optionalDocComment
0786:                        modifiers, // modifiers
0787:                        formalParameters, // formalParameters
0788:                        thrownExceptions, // thrownExceptions
0789:                        optionalConstructorInvocation, // optionalConstructorInvocationStatement
0790:                        body // body
0791:                );
0792:            }
0793:
0794:            /**
0795:             * <pre>
0796:             *   MethodDeclarationRest :=
0797:             *     FormalParameters
0798:             *     { '[' ']' }
0799:             *     [ 'throws' ReferenceTypeList ]
0800:             *     ( ';' | MethodBody )
0801:             * </pre>
0802:             */
0803:            public Java.MethodDeclarator parseMethodDeclarationRest(
0804:                    String optionalDocComment, short modifiers, Java.Type type,
0805:                    String name) throws ParseException, Scanner.ScanException,
0806:                    IOException {
0807:                Location location = this .location();
0808:
0809:                this .verifyIdentifierIsConventionalMethodName(name, location);
0810:
0811:                Java.FunctionDeclarator.FormalParameter[] formalParameters = this 
0812:                        .parseFormalParameters();
0813:
0814:                for (int i = this .parseBracketsOpt(); i > 0; --i)
0815:                    type = new Java.ArrayType(type);
0816:
0817:                Java.ReferenceType[] thrownExceptions;
0818:                if (this .peekKeyword("throws")) {
0819:                    this .eatToken();
0820:                    thrownExceptions = this .parseReferenceTypeList();
0821:                } else {
0822:                    thrownExceptions = new Java.ReferenceType[0];
0823:                }
0824:
0825:                Java.Block optionalBody;
0826:                if (this .peekOperator(";")) {
0827:                    if ((modifiers & (Mod.ABSTRACT | Mod.NATIVE)) == 0)
0828:                        this 
0829:                                .throwParseException("Non-abstract, non-native method must have a body");
0830:                    this .eatToken();
0831:                    optionalBody = null;
0832:                } else {
0833:                    if ((modifiers & (Mod.ABSTRACT | Mod.NATIVE)) != 0)
0834:                        this 
0835:                                .throwParseException("Abstract or native method must not have a body");
0836:                    optionalBody = this .parseMethodBody();
0837:                }
0838:                return new Java.MethodDeclarator(location, // location
0839:                        optionalDocComment, // optionalDocComment
0840:                        modifiers, // modifiers
0841:                        type, // type
0842:                        name, // name
0843:                        formalParameters, // formalParameters
0844:                        thrownExceptions, // thrownExceptions
0845:                        optionalBody // optionalBody
0846:                );
0847:            }
0848:
0849:            /**
0850:             * <pre>
0851:             *   VariableInitializer :=
0852:             *     ArrayInitializer |
0853:             *     Expression
0854:             * </pre>
0855:             */
0856:            public Java.ArrayInitializerOrRvalue parseVariableInitializer()
0857:                    throws ParseException, Scanner.ScanException, IOException {
0858:                if (this .peekOperator("{")) {
0859:                    return this .parseArrayInitializer();
0860:                } else {
0861:                    return this .parseExpression().toRvalueOrPE();
0862:                }
0863:            }
0864:
0865:            /**
0866:             * <pre>
0867:             *   ArrayInitializer :=
0868:             *     '{' [ VariableInitializer { ',' VariableInitializer } [ ',' ] '}'
0869:             * </pre>
0870:             */
0871:            public Java.ArrayInitializer parseArrayInitializer()
0872:                    throws ParseException, Scanner.ScanException, IOException {
0873:                Location location = this .location();
0874:                this .readOperator("{");
0875:                List l = new ArrayList(); // ArrayInitializerOrRvalue
0876:                while (!this .peekOperator("}")) {
0877:                    l.add(this .parseVariableInitializer());
0878:                    if (this .peekOperator("}"))
0879:                        break;
0880:                    if (!this .peekOperator(","))
0881:                        this .throwParseException("\",\" or \"}\" expected");
0882:                    this .eatToken();
0883:                }
0884:                this .eatToken();
0885:                return new Java.ArrayInitializer(location,
0886:                        (Java.ArrayInitializerOrRvalue[]) l
0887:                                .toArray(new Java.ArrayInitializerOrRvalue[l
0888:                                        .size()]));
0889:            }
0890:
0891:            /**
0892:             * <pre>
0893:             *   FormalParameters := '(' [ FormalParameter { ',' FormalParameter } ] ')'
0894:             * </pre>
0895:             */
0896:            public Java.FunctionDeclarator.FormalParameter[] parseFormalParameters()
0897:                    throws ParseException, Scanner.ScanException, IOException {
0898:                this .readOperator("(");
0899:                if (this .peekOperator(")")) {
0900:                    this .eatToken();
0901:                    return new Java.FunctionDeclarator.FormalParameter[0];
0902:                }
0903:
0904:                List l = new ArrayList(); // Java.FormalParameter
0905:                for (;;) {
0906:                    l.add(this .parseFormalParameter());
0907:                    if (!this .peekOperator(","))
0908:                        break;
0909:                    this .eatToken();
0910:                }
0911:                this .readOperator(")");
0912:                return (Java.FunctionDeclarator.FormalParameter[]) l
0913:                        .toArray(new Java.FunctionDeclarator.FormalParameter[l
0914:                                .size()]);
0915:            }
0916:
0917:            /**
0918:             * <pre>
0919:             *   FormalParameter := [ 'final' ] Type Identifier BracketsOpt
0920:             * </pre>
0921:             */
0922:            public Java.FunctionDeclarator.FormalParameter parseFormalParameter()
0923:                    throws ParseException, Scanner.ScanException, IOException {
0924:                boolean finaL = this .peekKeyword("final");
0925:                if (finaL)
0926:                    this .eatToken();
0927:
0928:                Java.Type type = this .parseType();
0929:
0930:                Location location = this .location();
0931:                String name = this .readIdentifier();
0932:                this 
0933:                        .verifyIdentifierIsConventionalLocalVariableOrParameterName(
0934:                                name, location);
0935:
0936:                for (int i = this .parseBracketsOpt(); i > 0; --i)
0937:                    type = new Java.ArrayType(type);
0938:                return new Java.FunctionDeclarator.FormalParameter(location,
0939:                        finaL, type, name);
0940:            }
0941:
0942:            /**
0943:             * <pre>
0944:             *   BracketsOpt := { '[' ']' }
0945:             * </pre>
0946:             */
0947:            int parseBracketsOpt() throws Scanner.ScanException, IOException {
0948:                int res = 0;
0949:                while (this .scanner.peek().isOperator("[")
0950:                        && this .scanner.peekNextButOne().isOperator("]")) {
0951:                    this .eatToken();
0952:                    this .eatToken();
0953:                    ++res;
0954:                }
0955:                return res;
0956:            }
0957:
0958:            /**
0959:             * <pre>
0960:             *   MethodBody := Block
0961:             * </pre>
0962:             */
0963:            public Java.Block parseMethodBody() throws ParseException,
0964:                    Scanner.ScanException, IOException {
0965:                return this .parseBlock();
0966:            }
0967:
0968:            /**
0969:             * <pre>
0970:             *   '{' BlockStatements '}'
0971:             * </pre>
0972:             */
0973:            public Java.Block parseBlock() throws ParseException,
0974:                    Scanner.ScanException, IOException {
0975:                Java.Block block = new Java.Block(this .location());
0976:                this .readOperator("{");
0977:                block.addStatements(this .parseBlockStatements());
0978:                this .readOperator("}");
0979:                return block;
0980:            }
0981:
0982:            /**
0983:             * <pre>
0984:             *   BlockStatements := { BlockStatement }
0985:             * </pre>
0986:             */
0987:            public List parseBlockStatements() throws ParseException,
0988:                    Scanner.ScanException, IOException {
0989:                List l = new ArrayList();
0990:                while (!this .peekOperator("}") && !this .peekKeyword("case")
0991:                        && !this .peekKeyword("default"))
0992:                    l.add(this .parseBlockStatement());
0993:                return l;
0994:            }
0995:
0996:            /**
0997:             * <pre>
0998:             *   BlockStatement := { Identifier ':' } (
0999:             *     ( Modifiers Type | ModifiersOpt BasicType ) LocalVariableDeclarators ';' |
1000:             *     'class' ... |
1001:             *     Statement |
1002:             *     'final' Type LocalVariableDeclarators ';' |
1003:             *     Expression ';' |
1004:             *     Expression LocalVariableDeclarators ';'   (1)
1005:             *   )
1006:             * </pre>
1007:             *
1008:             * (1) "Expression" must pose a type, and has optional trailing brackets.
1009:             */
1010:            public Java.BlockStatement parseBlockStatement()
1011:                    throws ParseException, Scanner.ScanException, IOException {
1012:
1013:                // Statement?
1014:                if ((this .scanner.peek().isIdentifier() && this .scanner
1015:                        .peekNextButOne().isOperator(":"))
1016:                        || this .peekKeyword(new String[] { "if", "for",
1017:                                "while", "do", "try", "switch", "synchronized",
1018:                                "return", "throw", "break", "continue" })
1019:                        || this .peekOperator(new String[] { "{", ";" }))
1020:                    return this .parseStatement();
1021:
1022:                // Local class declaration?
1023:                if (this .peekKeyword("class")) {
1024:                    // JAVADOC[TM] ignores doc comments for local classes, but we
1025:                    // don't...
1026:                    String optionalDocComment = this .scanner.doc();
1027:                    if (optionalDocComment == null)
1028:                        this .warning("LCDCM",
1029:                                "Local class doc comment missing", this 
1030:                                        .location());
1031:
1032:                    this .eatToken();
1033:                    final Java.LocalClassDeclaration lcd = (Java.LocalClassDeclaration) this 
1034:                            .parseClassDeclarationRest(optionalDocComment, // optionalDocComment
1035:                                    (short) (Mod.FINAL | Mod.PRIVATE), // modifiers
1036:                                    ClassDeclarationContext.BLOCK // context
1037:                            );
1038:                    return new Java.LocalClassDeclarationStatement(lcd);
1039:                }
1040:
1041:                // 'final' Type LocalVariableDeclarators ';'
1042:                if (this .peekKeyword("final")) {
1043:                    Location location = this .location();
1044:                    this .eatToken();
1045:                    Java.Type variableType = this .parseType();
1046:                    Java.LocalVariableDeclarationStatement lvds = new Java.LocalVariableDeclarationStatement(
1047:                            location, // location
1048:                            Mod.FINAL, // modifiers
1049:                            variableType, // type
1050:                            this .parseLocalVariableDeclarators() // variableDeclarators
1051:                    );
1052:                    this .readOperator(";");
1053:                    return lvds;
1054:                }
1055:
1056:                // It's either a non-final local variable declaration or an expression statement. We can
1057:                // only tell after parsing an expression.
1058:                Java.Atom a = this .parseExpression();
1059:
1060:                // Expression ';'
1061:                if (this .peekOperator(";")) {
1062:                    this .eatToken();
1063:                    return new Java.ExpressionStatement(a.toRvalueOrPE());
1064:                }
1065:
1066:                // Expression LocalVariableDeclarators ';'
1067:                Java.Type variableType = a.toTypeOrPE();
1068:                Java.LocalVariableDeclarationStatement lvds = new Java.LocalVariableDeclarationStatement(
1069:                        a.getLocation(), // location
1070:                        Mod.NONE, // modifiers
1071:                        variableType, // type
1072:                        this .parseLocalVariableDeclarators() // variableDeclarators
1073:                );
1074:                this .readOperator(";");
1075:                return lvds;
1076:            }
1077:
1078:            /**
1079:             * <pre>
1080:             *   LocalVariableDeclarators := VariableDeclarator { ',' VariableDeclarator }
1081:             * </pre>
1082:             */
1083:            public Java.VariableDeclarator[] parseLocalVariableDeclarators()
1084:                    throws ParseException, Scanner.ScanException, IOException {
1085:                List l = new ArrayList();
1086:                for (;;) {
1087:                    Java.VariableDeclarator vd = this .parseVariableDeclarator();
1088:                    this 
1089:                            .verifyIdentifierIsConventionalLocalVariableOrParameterName(
1090:                                    vd.name, vd.getLocation());
1091:                    l.add(vd);
1092:                    if (!this .peekOperator(","))
1093:                        break;
1094:                    this .eatToken();
1095:                }
1096:                return (Java.VariableDeclarator[]) l
1097:                        .toArray(new Java.VariableDeclarator[l.size()]);
1098:            }
1099:
1100:            /**
1101:             * <pre>
1102:             *   FieldDeclarationRest :=
1103:             *     VariableDeclaratorRest
1104:             *     { ',' VariableDeclarator }
1105:             * </pre>
1106:             */
1107:            public Java.VariableDeclarator[] parseFieldDeclarationRest(
1108:                    String name) throws ParseException, Scanner.ScanException,
1109:                    IOException {
1110:                List l = new ArrayList();
1111:
1112:                Java.VariableDeclarator vd = this 
1113:                        .parseVariableDeclaratorRest(name);
1114:                this .verifyIdentifierIsConventionalFieldName(vd.name, vd
1115:                        .getLocation());
1116:                l.add(vd);
1117:
1118:                while (this .peekOperator(",")) {
1119:                    this .eatToken();
1120:
1121:                    vd = this .parseVariableDeclarator();
1122:                    this .verifyIdentifierIsConventionalFieldName(vd.name, vd
1123:                            .getLocation());
1124:                    l.add(vd);
1125:                }
1126:                return (Java.VariableDeclarator[]) l
1127:                        .toArray(new Java.VariableDeclarator[l.size()]);
1128:            }
1129:
1130:            /**
1131:             * <pre>
1132:             *   VariableDeclarator := Identifier VariableDeclaratorRest
1133:             * </pre>
1134:             */
1135:            public Java.VariableDeclarator parseVariableDeclarator()
1136:                    throws ParseException, Scanner.ScanException, IOException {
1137:                return this .parseVariableDeclaratorRest(this .readIdentifier());
1138:            }
1139:
1140:            /**
1141:             * <pre>
1142:             *   VariableDeclaratorRest := { '[' ']' } [ '=' VariableInitializer ]
1143:             * </pre>
1144:             * Used by field declarations and local variable declarations.
1145:             */
1146:            public Java.VariableDeclarator parseVariableDeclaratorRest(
1147:                    String name) throws ParseException, Scanner.ScanException,
1148:                    IOException {
1149:                Location loc = this .location();
1150:                int brackets = this .parseBracketsOpt();
1151:                Java.ArrayInitializerOrRvalue initializer = null;
1152:                if (this .peekOperator("=")) {
1153:                    this .eatToken();
1154:                    initializer = this .parseVariableInitializer();
1155:                }
1156:                return new Java.VariableDeclarator(loc, name, brackets,
1157:                        initializer);
1158:            }
1159:
1160:            /**
1161:             * <pre>
1162:             *   Statement :=
1163:             *     LabeledStatement |
1164:             *     Block |
1165:             *     IfStatement |
1166:             *     ForStatement |
1167:             *     WhileStatement |
1168:             *     DoStatement |
1169:             *     TryStatement |
1170:             *     'switch' ... |
1171:             *     'synchronized' ... |
1172:             *     ReturnStatement |
1173:             *     ThrowStatement |
1174:             *     BreakStatement |
1175:             *     ContinueStatement |
1176:             *     EmptyStatement |
1177:             *     ExpressionStatement
1178:             * </pre>
1179:             */
1180:            public Java.Statement parseStatement() throws ParseException,
1181:                    Scanner.ScanException, IOException {
1182:                if (this .scanner.peek().isIdentifier()
1183:                        && this .scanner.peekNextButOne().isOperator(":")) {
1184:                    return this .parseLabeledStatement();
1185:                }
1186:
1187:                Scanner.Token t = this .scanner.peek();
1188:                Java.Statement stmt = (t.isOperator("{") ? this .parseBlock()
1189:                        : t.isKeyword("if") ? this .parseIfStatement() : t
1190:                                .isKeyword("for") ? this .parseForStatement()
1191:                                : t.isKeyword("while") ? this 
1192:                                        .parseWhileStatement() : t
1193:                                        .isKeyword("do") ? this 
1194:                                        .parseDoStatement() : t
1195:                                        .isKeyword("try") ? this 
1196:                                        .parseTryStatement() : t
1197:                                        .isKeyword("switch") ? this 
1198:                                        .parseSwitchStatement() : t
1199:                                        .isKeyword("synchronized") ? this 
1200:                                        .parseSynchronizedStatement() : t
1201:                                        .isKeyword("return") ? this 
1202:                                        .parseReturnStatement() : t
1203:                                        .isKeyword("throw") ? this 
1204:                                        .parseThrowStatement() : t
1205:                                        .isKeyword("break") ? this 
1206:                                        .parseBreakStatement() : t
1207:                                        .isKeyword("continue") ? this 
1208:                                        .parseContinueStatement() : t
1209:                                        .isOperator(";") ? this 
1210:                                        .parseEmptyStatement() : this 
1211:                                        .parseExpressionStatement());
1212:                if (stmt == null)
1213:                    this .throwParseException("\"" + t.getKeyword() + "\" NYI");
1214:
1215:                return stmt;
1216:            }
1217:
1218:            /**
1219:             * <pre>
1220:             *   LabeledStatement := Identifier ':' Statement
1221:             * </pre>
1222:             */
1223:            public Java.Statement parseLabeledStatement()
1224:                    throws ParseException, Scanner.ScanException, IOException {
1225:                String label = this .readIdentifier();
1226:                this .readOperator(":");
1227:                return new Java.LabeledStatement(this .location(), // location
1228:                        label, // label
1229:                        this .parseStatement() // body
1230:                );
1231:            }
1232:
1233:            /**
1234:             * <pre>
1235:             *   IfStatement := 'if' '(' Expression ')' Statement [ 'else' Statement ]
1236:             * </pre>
1237:             */
1238:            public Java.Statement parseIfStatement() throws ParseException,
1239:                    Scanner.ScanException, IOException {
1240:                Location location = this .location();
1241:                this .readKeyword("if");
1242:                this .readOperator("(");
1243:                final Java.Rvalue condition = this .parseExpression()
1244:                        .toRvalueOrPE();
1245:                this .readOperator(")");
1246:
1247:                Java.Statement thenStatement = this .parseStatement();
1248:
1249:                Java.Statement optionalElseStatement = null;
1250:                if (this .peekKeyword("else")) {
1251:                    this .eatToken();
1252:                    optionalElseStatement = this .parseStatement();
1253:                }
1254:
1255:                return new Java.IfStatement(location, // location
1256:                        condition, // condition
1257:                        thenStatement, // thenStatement
1258:                        optionalElseStatement // optionalElseStatement
1259:                );
1260:            }
1261:
1262:            /**
1263:             * <pre>
1264:             *   ForStatement :=
1265:             *     'for' '('
1266:             *       [ ForInit ] ';'
1267:             *       [ Expression ] ';'
1268:             *       [ ExpressionList ]
1269:             *     ')' Statement
1270:             * </pre>
1271:             */
1272:            public Java.Statement parseForStatement() throws ParseException,
1273:                    Scanner.ScanException, IOException {
1274:                Location location = this .location();
1275:                this .readKeyword("for");
1276:
1277:                this .readOperator("(");
1278:
1279:                Java.BlockStatement optionalInit = null;
1280:                if (!this .peekOperator(";"))
1281:                    optionalInit = this .parseForInit();
1282:
1283:                this .readOperator(";");
1284:
1285:                Java.Rvalue optionalCondition = null;
1286:                if (!this .peekOperator(";"))
1287:                    optionalCondition = this .parseExpression().toRvalueOrPE();
1288:
1289:                this .readOperator(";");
1290:
1291:                Java.Rvalue[] optionalUpdate = null;
1292:                if (!this .peekOperator(")"))
1293:                    optionalUpdate = this .parseExpressionList();
1294:
1295:                this .readOperator(")");
1296:
1297:                // KLUDGE: Insert an implicit Block here.
1298:                //        Java.Block implicitBlock = new Java.Block(location);
1299:                return /*Java.ForStatement forStatement =*/new Java.ForStatement(
1300:                        location, // location
1301:                        optionalInit, // optionalInit
1302:                        optionalCondition, // optionalCondition
1303:                        optionalUpdate, // optionalUpdate
1304:                        this .parseStatement() // body
1305:                );
1306:                //        implicitBlock.addStatement(forStatement);
1307:
1308:                //        return implicitBlock;
1309:            }
1310:
1311:            /**
1312:             * <pre>
1313:             *   ForInit :=
1314:             *     Modifiers Type LocalVariableDeclarators |
1315:             *     ModifiersOpt BasicType LocalVariableDeclarators |
1316:             *     Expression (
1317:             *       LocalVariableDeclarators |       (1)
1318:             *       { ',' Expression }
1319:             *     )
1320:             * </pre>
1321:             *
1322:             * (1) "Expression" must pose a type.
1323:             */
1324:            private Java.BlockStatement parseForInit() throws ParseException,
1325:                    Scanner.ScanException, IOException {
1326:
1327:                // Modifiers Type LocalVariableDeclarators
1328:                // ModifiersOpt BasicType LocalVariableDeclarators
1329:                if (this .peekKeyword(new String[] { "final", "byte", "short",
1330:                        "char", "int", "long", "float", "double", "boolean" })) {
1331:                    short modifiers = this .parseModifiersOpt();
1332:                    Java.Type variableType = this .parseType();
1333:                    return new Java.LocalVariableDeclarationStatement(this 
1334:                            .location(), // location
1335:                            modifiers, // modifiers
1336:                            variableType, // type
1337:                            this .parseLocalVariableDeclarators() // variableDeclarators
1338:                    );
1339:                }
1340:
1341:                Java.Atom a = this .parseExpression();
1342:
1343:                // Expression LocalVariableDeclarators
1344:                if (this .scanner.peek().isIdentifier()) {
1345:                    Java.Type variableType = a.toTypeOrPE();
1346:                    return new Java.LocalVariableDeclarationStatement(a
1347:                            .getLocation(), // location
1348:                            Mod.NONE, // modifiers
1349:                            variableType, // type
1350:                            this .parseLocalVariableDeclarators() // variableDeclarators
1351:                    );
1352:                }
1353:
1354:                // Expression { ',' Expression }
1355:                if (!this .peekOperator(",")) {
1356:                    return new Java.ExpressionStatement(a.toRvalueOrPE());
1357:                }
1358:                this .eatToken();
1359:                List l = new ArrayList();
1360:                l.add(new Java.ExpressionStatement(a.toRvalueOrPE()));
1361:                for (;;) {
1362:                    l.add(new Java.ExpressionStatement(this .parseExpression()
1363:                            .toRvalueOrPE()));
1364:                    if (!this .peekOperator(","))
1365:                        break;
1366:                    this .eatToken();
1367:                }
1368:
1369:                Java.Block b = new Java.Block(a.getLocation());
1370:                b.addStatements(l);
1371:                return b;
1372:            }
1373:
1374:            /**
1375:             * <pre>
1376:             *   WhileStatement := 'while' '(' Expression ')' Statement
1377:             * </pre>
1378:             */
1379:            public Java.Statement parseWhileStatement() throws ParseException,
1380:                    Scanner.ScanException, IOException {
1381:                Location location = this .location();
1382:                this .readKeyword("while");
1383:
1384:                this .readOperator("(");
1385:                Java.Rvalue condition = this .parseExpression().toRvalueOrPE();
1386:                this .readOperator(")");
1387:
1388:                return new Java.WhileStatement(location, // location
1389:                        condition, // condition
1390:                        this .parseStatement() // body
1391:                );
1392:            }
1393:
1394:            /**
1395:             * <pre>
1396:             *   DoStatement := 'do' Statement 'while' '(' Expression ')' ';'
1397:             * </pre>
1398:             */
1399:            public Java.Statement parseDoStatement() throws ParseException,
1400:                    Scanner.ScanException, IOException {
1401:                Location location = this .location();
1402:                this .readKeyword("do");
1403:
1404:                Java.Statement body = this .parseStatement();
1405:
1406:                this .readKeyword("while");
1407:                this .readOperator("(");
1408:                Java.Rvalue condition = this .parseExpression().toRvalueOrPE();
1409:                this .readOperator(")");
1410:                this .readOperator(";");
1411:
1412:                return new Java.DoStatement(location, // location
1413:                        body, // body
1414:                        condition // condition
1415:                );
1416:            }
1417:
1418:            /**
1419:             * <pre>
1420:             *   TryStatement :=
1421:             *     'try' Block Catches [ Finally ] |
1422:             *     'try' Block Finally
1423:             *
1424:             *   Catches := CatchClause { CatchClause }
1425:             *
1426:             *   CatchClause := 'catch' '(' FormalParameter ')' Block
1427:             *
1428:             *   Finally := 'finally' Block
1429:             * </pre>
1430:             */
1431:            public Java.Statement parseTryStatement() throws ParseException,
1432:                    Scanner.ScanException, IOException {
1433:                Location location = this .location();
1434:                this .readKeyword("try");
1435:
1436:                Java.Block body = this .parseBlock();
1437:
1438:                // { CatchClause }
1439:                List ccs = new ArrayList();
1440:                while (this .peekKeyword("catch")) {
1441:                    Location loc = this .location();
1442:                    this .eatToken();
1443:                    this .readOperator("(");
1444:                    Java.FunctionDeclarator.FormalParameter caughtException = this 
1445:                            .parseFormalParameter();
1446:                    this .readOperator(")");
1447:                    ccs.add(new Java.CatchClause(loc, // location
1448:                            caughtException, // caughtException
1449:                            this .parseBlock() // body
1450:                            ));
1451:                }
1452:                Java.Block optionalFinally = null;
1453:                if (this .peekKeyword("finally")) {
1454:                    this .eatToken();
1455:                    optionalFinally = this .parseBlock();
1456:                }
1457:                if (ccs.size() == 0 && optionalFinally == null)
1458:                    this 
1459:                            .throwParseException("\"try\" statement must have at least one \"catch\" clause or a \"finally\" clause");
1460:
1461:                return new Java.TryStatement(location, // location
1462:                        body, // body
1463:                        ccs, // catchClauses
1464:                        optionalFinally // optionalFinally
1465:                );
1466:            }
1467:
1468:            /**
1469:             * <pre>
1470:             *   SwitchStatement :=
1471:             *     'switch' '(' Expression ')' '{' { SwitchLabels BlockStatements } '}'
1472:             *
1473:             *   SwitchLabels := SwitchLabels { SwitchLabels }
1474:             *
1475:             *   SwitchLabel := 'case' Expression ':' | 'default' ':'
1476:             * </pre>
1477:             */
1478:            public Java.Statement parseSwitchStatement() throws ParseException,
1479:                    Scanner.ScanException, IOException {
1480:                Location location = this .location();
1481:                this .readKeyword("switch");
1482:
1483:                this .readOperator("(");
1484:                Java.Rvalue condition = this .parseExpression().toRvalueOrPE();
1485:                this .readOperator(")");
1486:
1487:                this .readOperator("{");
1488:                List sbsgs = new ArrayList();
1489:                while (!this .peekOperator("}")) {
1490:                    Location location2 = this .location();
1491:                    boolean hasDefaultLabel = false;
1492:                    List caseLabels = new ArrayList();
1493:                    do {
1494:                        if (this .peekKeyword("case")) {
1495:                            this .eatToken();
1496:                            caseLabels.add(this .parseExpression()
1497:                                    .toRvalueOrPE());
1498:                        } else if (this .peekKeyword("default")) {
1499:                            this .eatToken();
1500:                            if (hasDefaultLabel)
1501:                                this 
1502:                                        .throwParseException("Duplicate \"default\" label");
1503:                            hasDefaultLabel = true;
1504:                        } else {
1505:                            this 
1506:                                    .throwParseException("\"case\" or \"default\" expected");
1507:                        }
1508:                        this .readOperator(":");
1509:                    } while (this 
1510:                            .peekKeyword(new String[] { "case", "default" }));
1511:
1512:                    Java.SwitchStatement.SwitchBlockStatementGroup sbsg = new Java.SwitchStatement.SwitchBlockStatementGroup(
1513:                            location2, // location
1514:                            caseLabels, // caseLabels
1515:                            hasDefaultLabel, // hasDefaultLabel
1516:                            this .parseBlockStatements() // blockStatements
1517:                    );
1518:                    sbsgs.add(sbsg);
1519:                }
1520:                this .eatToken();
1521:                return new Java.SwitchStatement(location, // location
1522:                        condition, // condition
1523:                        sbsgs // sbsgs
1524:                );
1525:            }
1526:
1527:            /**
1528:             * <pre>
1529:             *   SynchronizedStatement :=
1530:             *     'synchronized' '(' expression ')' Block
1531:             * </pre>
1532:             */
1533:            public Java.Statement parseSynchronizedStatement()
1534:                    throws ParseException, Scanner.ScanException, IOException {
1535:                Location location = this .location();
1536:                this .readKeyword("synchronized");
1537:                this .readOperator("(");
1538:                Java.Rvalue expression = this .parseExpression().toRvalueOrPE();
1539:                this .readOperator(")");
1540:                return new Java.SynchronizedStatement(location, // location
1541:                        expression, // expression
1542:                        this .parseBlock() // body
1543:                );
1544:            }
1545:
1546:            /**
1547:             * <pre>
1548:             *   ReturnStatement := 'return' [ Expression ] ';'
1549:             * </pre>
1550:             */
1551:            public Java.Statement parseReturnStatement() throws ParseException,
1552:                    Scanner.ScanException, IOException {
1553:                Location location = this .location();
1554:                this .readKeyword("return");
1555:                Java.Rvalue returnValue = this .peekOperator(";") ? null : this 
1556:                        .parseExpression().toRvalueOrPE();
1557:                this .readOperator(";");
1558:                return new Java.ReturnStatement(location, returnValue);
1559:            }
1560:
1561:            /**
1562:             * <pre>
1563:             *   ThrowStatement := 'throw' Expression ';'
1564:             * </pre>
1565:             */
1566:            public Java.Statement parseThrowStatement() throws ParseException,
1567:                    Scanner.ScanException, IOException {
1568:                Location location = this .location();
1569:                this .readKeyword("throw");
1570:                final Java.Rvalue expression = this .parseExpression()
1571:                        .toRvalueOrPE();
1572:                this .readOperator(";");
1573:
1574:                return new Java.ThrowStatement(location, expression);
1575:            }
1576:
1577:            /**
1578:             * <pre>
1579:             *   BreakStatement := 'break' [ Identifier ] ';'
1580:             * </pre>
1581:             */
1582:            public Java.Statement parseBreakStatement() throws ParseException,
1583:                    Scanner.ScanException, IOException {
1584:                Location location = this .location();
1585:                this .readKeyword("break");
1586:                String optionalLabel = null;
1587:                if (this .scanner.peek().isIdentifier())
1588:                    optionalLabel = this .readIdentifier();
1589:                this .readOperator(";");
1590:                return new Java.BreakStatement(location, optionalLabel);
1591:            }
1592:
1593:            /**
1594:             * <pre>
1595:             *   ContinueStatement := 'continue' [ Identifier ] ';'
1596:             * </pre>
1597:             */
1598:            public Java.Statement parseContinueStatement()
1599:                    throws ParseException, Scanner.ScanException, IOException {
1600:                Location location = this .location();
1601:                this .readKeyword("continue");
1602:                String optionalLabel = null;
1603:                if (this .scanner.peek().isIdentifier())
1604:                    optionalLabel = this .readIdentifier();
1605:                this .readOperator(";");
1606:                return new Java.ContinueStatement(location, optionalLabel);
1607:            }
1608:
1609:            /**
1610:             * <pre>
1611:             *   EmptyStatement := ';'
1612:             * </pre>
1613:             */
1614:            public Java.Statement parseEmptyStatement() throws ParseException,
1615:                    Scanner.ScanException, IOException {
1616:                Location location = this .location();
1617:                this .readOperator(";");
1618:                return new Java.EmptyStatement(location);
1619:            }
1620:
1621:            /**
1622:             * <pre>
1623:             *   ExpressionList := Expression { ',' Expression }
1624:             * </pre>
1625:             */
1626:            public Java.Rvalue[] parseExpressionList() throws ParseException,
1627:                    Scanner.ScanException, IOException {
1628:                List l = new ArrayList();
1629:                for (;;) {
1630:                    l.add(this .parseExpression().toRvalueOrPE());
1631:                    if (!this .peekOperator(","))
1632:                        break;
1633:                    this .eatToken();
1634:                }
1635:                return (Java.Rvalue[]) l.toArray(new Java.Rvalue[l.size()]);
1636:            }
1637:
1638:            /**
1639:             * <pre>
1640:             *   Type := (
1641:             *     'byte' | 'short' | 'char' | 'int' | 'long' |
1642:             *     'float' | 'double' | 'boolean' |
1643:             *     ReferenceType
1644:             *   ) { '[' ']' }
1645:             * </pre>
1646:             */
1647:            public Java.Type parseType() throws ParseException,
1648:                    Scanner.ScanException, IOException {
1649:                Scanner.Token t = this .scanner.peek();
1650:                int bt = -1;
1651:                if (t.isKeyword("byte")) {
1652:                    bt = Java.BasicType.BYTE;
1653:                } else if (t.isKeyword("short")) {
1654:                    bt = Java.BasicType.SHORT;
1655:                } else if (t.isKeyword("char")) {
1656:                    bt = Java.BasicType.CHAR;
1657:                } else if (t.isKeyword("int")) {
1658:                    bt = Java.BasicType.INT;
1659:                } else if (t.isKeyword("long")) {
1660:                    bt = Java.BasicType.LONG;
1661:                } else if (t.isKeyword("float")) {
1662:                    bt = Java.BasicType.FLOAT;
1663:                } else if (t.isKeyword("double")) {
1664:                    bt = Java.BasicType.DOUBLE;
1665:                } else if (t.isKeyword("boolean")) {
1666:                    bt = Java.BasicType.BOOLEAN;
1667:                }
1668:                Java.Type res;
1669:                if (bt != -1) {
1670:                    res = new Java.BasicType(t.getLocation(), bt);
1671:                    this .eatToken();
1672:                } else {
1673:                    res = this .parseReferenceType();
1674:                }
1675:                for (int i = this .parseBracketsOpt(); i > 0; --i)
1676:                    res = new Java.ArrayType(res);
1677:                return res;
1678:            }
1679:
1680:            /**
1681:             * <pre>
1682:             *   ReferenceType := QualifiedIdentifier
1683:             * </pre>
1684:             */
1685:            public Java.ReferenceType parseReferenceType()
1686:                    throws ParseException, Scanner.ScanException, IOException {
1687:                return new Java.ReferenceType(this .location(), // location
1688:                        this .parseQualifiedIdentifier() // identifiers
1689:                );
1690:            }
1691:
1692:            /**
1693:             * <pre>
1694:             *   ReferenceTypeList := ReferenceType { ',' ReferenceType }
1695:             * </pre>
1696:             */
1697:            public Java.ReferenceType[] parseReferenceTypeList()
1698:                    throws ParseException, Scanner.ScanException, IOException {
1699:                List l = new ArrayList();
1700:                l.add(this .parseReferenceType());
1701:                while (this .peekOperator(",")) {
1702:                    this .eatToken();
1703:                    l.add(this .parseReferenceType());
1704:                }
1705:                return (Java.ReferenceType[]) l
1706:                        .toArray(new Java.ReferenceType[l.size()]);
1707:            }
1708:
1709:            /**
1710:             * <pre>
1711:             *   Expression := AssignmentExpression
1712:             * </pre>
1713:             */
1714:            public Java.Atom parseExpression() throws ParseException,
1715:                    Scanner.ScanException, IOException {
1716:                return this .parseAssignmentExpression();
1717:            }
1718:
1719:            /**
1720:             * <pre>
1721:             *   AssignmentExpression :=
1722:             *     ConditionalExpression [ AssignmentOperator AssignmentExpression ]
1723:             *
1724:             *   AssignmentOperator :=
1725:             *     '=' | '*=' | '/=' | '%=' | '+=' | '-=' | '<<=' |
1726:             *     '>>=' | '>>>=' | '&=' | '^=' | '|='
1727:             * </pre>
1728:             */
1729:            public Java.Atom parseAssignmentExpression() throws ParseException,
1730:                    Scanner.ScanException, IOException {
1731:                Java.Atom a = this .parseConditionalExpression();
1732:                if (this .peekOperator(new String[] { "=", "+=", "-=", "*=",
1733:                        "/=", "&=", "|=", "^=", "%=", "<<=", ">>=", ">>>=" })) {
1734:                    Location location = this .location();
1735:                    String operator = this .readOperator();
1736:                    final Java.Lvalue lhs = a.toLvalueOrPE();
1737:                    final Java.Rvalue rhs = this .parseAssignmentExpression()
1738:                            .toRvalueOrPE();
1739:                    return new Java.Assignment(location, lhs, operator, rhs);
1740:                }
1741:                return a;
1742:            }
1743:
1744:            /**
1745:             * <pre>
1746:             *   ConditionalExpression :=
1747:             *     ConditionalOrExpression [ '?' Expression ':' ConditionalExpression ]
1748:             * </pre>
1749:             */
1750:            public Java.Atom parseConditionalExpression()
1751:                    throws ParseException, Scanner.ScanException, IOException {
1752:                Java.Atom a = this .parseConditionalOrExpression();
1753:                if (!this .peekOperator("?"))
1754:                    return a;
1755:                Location location = this .location();
1756:                this .eatToken();
1757:
1758:                Java.Rvalue lhs = a.toRvalueOrPE();
1759:                Java.Rvalue mhs = this .parseExpression().toRvalueOrPE();
1760:                this .readOperator(":");
1761:                Java.Rvalue rhs = this .parseConditionalExpression()
1762:                        .toRvalueOrPE();
1763:                return new Java.ConditionalExpression(location, lhs, mhs, rhs);
1764:            }
1765:
1766:            /**
1767:             * <pre>
1768:             *   ConditionalOrExpression :=
1769:             *     ConditionalAndExpression { '||' ConditionalAndExpression ]
1770:             * </pre>
1771:             */
1772:            public Java.Atom parseConditionalOrExpression()
1773:                    throws ParseException, Scanner.ScanException, IOException {
1774:                Java.Atom a = this .parseConditionalAndExpression();
1775:                while (this .peekOperator("||")) {
1776:                    Location location = this .location();
1777:                    this .eatToken();
1778:                    a = new Java.BinaryOperation(location, a.toRvalueOrPE(),
1779:                            "||", this .parseConditionalAndExpression()
1780:                                    .toRvalueOrPE());
1781:                }
1782:                return a;
1783:            }
1784:
1785:            /**
1786:             * <pre>
1787:             *   ConditionalAndExpression :=
1788:             *     InclusiveOrExpression { '&&' InclusiveOrExpression }
1789:             * </pre>
1790:             */
1791:            public Java.Atom parseConditionalAndExpression()
1792:                    throws ParseException, Scanner.ScanException, IOException {
1793:                Java.Atom a = this .parseInclusiveOrExpression();
1794:                while (this .peekOperator("&&")) {
1795:                    Location location = this .location();
1796:                    this .eatToken();
1797:                    a = new Java.BinaryOperation(location, a.toRvalueOrPE(),
1798:                            "&&", this .parseInclusiveOrExpression()
1799:                                    .toRvalueOrPE());
1800:                }
1801:                return a;
1802:            }
1803:
1804:            /**
1805:             * <pre>
1806:             *   InclusiveOrExpression :=
1807:             *     ExclusiveOrExpression { '|' ExclusiveOrExpression }
1808:             * </pre>
1809:             */
1810:            public Java.Atom parseInclusiveOrExpression()
1811:                    throws ParseException, Scanner.ScanException, IOException {
1812:                Java.Atom a = this .parseExclusiveOrExpression();
1813:                while (this .peekOperator("|")) {
1814:                    Location location = this .location();
1815:                    this .eatToken();
1816:                    a = new Java.BinaryOperation(location, a.toRvalueOrPE(),
1817:                            "|", this .parseExclusiveOrExpression()
1818:                                    .toRvalueOrPE());
1819:                }
1820:                return a;
1821:            }
1822:
1823:            /**
1824:             * <pre>
1825:             *   ExclusiveOrExpression :=
1826:             *     AndExpression { '^' AndExpression }
1827:             * </pre>
1828:             */
1829:            public Java.Atom parseExclusiveOrExpression()
1830:                    throws ParseException, Scanner.ScanException, IOException {
1831:                Java.Atom a = this .parseAndExpression();
1832:                while (this .peekOperator("^")) {
1833:                    Location location = this .location();
1834:                    this .eatToken();
1835:                    a = new Java.BinaryOperation(location, a.toRvalueOrPE(),
1836:                            "^", this .parseAndExpression().toRvalueOrPE());
1837:                }
1838:                return a;
1839:            }
1840:
1841:            /**
1842:             * <pre>
1843:             *   AndExpression :=
1844:             *     EqualityExpression { '&' EqualityExpression }
1845:             * </pre>
1846:             */
1847:            public Java.Atom parseAndExpression() throws ParseException,
1848:                    Scanner.ScanException, IOException {
1849:                Java.Atom a = this .parseEqualityExpression();
1850:                while (this .peekOperator("&")) {
1851:                    Location location = this .location();
1852:                    this .eatToken();
1853:                    a = new Java.BinaryOperation(location, a.toRvalueOrPE(),
1854:                            "&", this .parseEqualityExpression().toRvalueOrPE());
1855:                }
1856:                return a;
1857:            }
1858:
1859:            /**
1860:             * <pre>
1861:             *   EqualityExpression :=
1862:             *     RelationalExpression { ( '==' | '!=' ) RelationalExpression }
1863:             * </pre>
1864:             */
1865:            public Java.Atom parseEqualityExpression() throws ParseException,
1866:                    Scanner.ScanException, IOException {
1867:                Java.Atom a = this .parseRelationalExpression();
1868:
1869:                while (this .peekOperator(new String[] { "==", "!=" })) {
1870:                    a = new Java.BinaryOperation(this .location(), // location
1871:                            a.toRvalueOrPE(), // lhs
1872:                            this .readOperator(), // op
1873:                            this .parseRelationalExpression().toRvalueOrPE() // rhs
1874:                    );
1875:                }
1876:                return a;
1877:            }
1878:
1879:            /**
1880:             * <pre>
1881:             *   RelationalExpression :=
1882:             *     ShiftExpression {
1883:             *       ( ( '<' | '>' | '<=' | '>=' ) ShiftExpression ) |
1884:             *       ( 'instanceof' ReferenceType )
1885:             *     }
1886:             * </pre>
1887:             */
1888:            public Java.Atom parseRelationalExpression() throws ParseException,
1889:                    Scanner.ScanException, IOException {
1890:                Java.Atom a = this .parseShiftExpression();
1891:
1892:                for (;;) {
1893:                    if (this .peekKeyword("instanceof")) {
1894:                        Location location = this .location();
1895:                        this .eatToken();
1896:                        a = new Java.Instanceof(location, a.toRvalueOrPE(),
1897:                                this .parseType());
1898:                    } else if (this .peekOperator(new String[] { "<", ">", "<=",
1899:                            ">=" })) {
1900:                        a = new Java.BinaryOperation(this .location(), // location
1901:                                a.toRvalueOrPE(), // lhs
1902:                                this .readOperator(), // op
1903:                                this .parseShiftExpression().toRvalueOrPE() // rhs
1904:                        );
1905:                    } else {
1906:                        return a;
1907:                    }
1908:                }
1909:            }
1910:
1911:            /**
1912:             * <pre>
1913:             *   ShiftExpression :=
1914:             *     AdditiveExpression { ( '<<' | '>>' | '>>>' ) AdditiveExpression }
1915:             * </pre>
1916:             */
1917:            public Java.Atom parseShiftExpression() throws ParseException,
1918:                    Scanner.ScanException, IOException {
1919:                Java.Atom a = this .parseAdditiveExpression();
1920:
1921:                while (this .peekOperator(new String[] { "<<", ">>", ">>>" })) {
1922:                    a = new Java.BinaryOperation(this .location(), // location
1923:                            a.toRvalueOrPE(), // lhs
1924:                            this .readOperator(), // op
1925:                            this .parseAdditiveExpression().toRvalueOrPE() // rhs
1926:                    );
1927:                }
1928:                return a;
1929:            }
1930:
1931:            /**
1932:             * <pre>
1933:             *   AdditiveExpression :=
1934:             *     MultiplicativeExpression { ( '+' | '-' ) MultiplicativeExpression }
1935:             * </pre>
1936:             */
1937:            public Java.Atom parseAdditiveExpression() throws ParseException,
1938:                    Scanner.ScanException, IOException {
1939:                Java.Atom a = this .parseMultiplicativeExpression();
1940:
1941:                while (this .peekOperator(new String[] { "+", "-" })) {
1942:                    a = new Java.BinaryOperation(this .location(), // location
1943:                            a.toRvalueOrPE(), // lhs
1944:                            this .readOperator(), // op
1945:                            this .parseMultiplicativeExpression().toRvalueOrPE() // rhs
1946:                    );
1947:                }
1948:                return a;
1949:            }
1950:
1951:            /**
1952:             * <pre>
1953:             *   MultiplicativeExpression :=
1954:             *     UnaryExpression { ( '*' | '/' | '%' ) UnaryExpression }
1955:             * </pre>
1956:             */
1957:            public Java.Atom parseMultiplicativeExpression()
1958:                    throws ParseException, Scanner.ScanException, IOException {
1959:                Java.Atom a = this .parseUnaryExpression();
1960:
1961:                while (this .peekOperator(new String[] { "*", "/", "%" })) {
1962:                    a = new Java.BinaryOperation(this .location(), // location
1963:                            a.toRvalueOrPE(), // lhs
1964:                            this .readOperator(), // op
1965:                            this .parseUnaryExpression().toRvalueOrPE() // rhs
1966:                    );
1967:                }
1968:                return a;
1969:            }
1970:
1971:            /**
1972:             * <pre>
1973:             *   UnaryExpression :=
1974:             *     { PrefixOperator } Primary { Selector } { PostfixOperator }
1975:             *
1976:             *   PrefixOperator := '++' | '--' | '+' | '-' | '~' | '!'
1977:             *
1978:             *   PostfixOperator := '++' | '--'
1979:             * </pre>
1980:             */
1981:            public Java.Atom parseUnaryExpression() throws ParseException,
1982:                    Scanner.ScanException, IOException {
1983:                if (this .peekOperator(new String[] { "++", "--" })) {
1984:                    return new Java.Crement(this .location(), // location
1985:                            this .readOperator(), // operator
1986:                            this .parseUnaryExpression().toLvalueOrPE() // operand
1987:                    );
1988:                }
1989:
1990:                if (this .peekOperator(new String[] { "+", "-", "~", "!" })) {
1991:                    return new Java.UnaryOperation(this .location(), // location
1992:                            this .readOperator(), // operator
1993:                            this .parseUnaryExpression().toRvalueOrPE() // operand
1994:                    );
1995:                }
1996:
1997:                Java.Atom a = this .parsePrimary();
1998:
1999:                while (this .peekOperator(new String[] { ".", "[" })) {
2000:                    a = this .parseSelector(a);
2001:                }
2002:
2003:                while (this .peekOperator(new String[] { "++", "--" })) {
2004:                    a = new Java.Crement(this .location(), // location
2005:                            a.toLvalueOrPE(), // operand
2006:                            this .readOperator() // operator
2007:                    );
2008:                }
2009:
2010:                return a;
2011:            }
2012:
2013:            /**
2014:             * <pre>
2015:             *   Primary :=
2016:             *     CastExpression |                        // CastExpression 15.16
2017:             *     '(' Expression ')' |                    // ParenthesizedExpression 15.8.5
2018:             *     Literal |                               // Literal 15.8.1
2019:             *     Name |                                  // AmbiguousName
2020:             *     Name Arguments |                        // MethodInvocation
2021:             *     Name '[]' { '[]' } |                    // ArrayType 10.1
2022:             *     Name '[]' { '[]' } '.' 'class' |        // ClassLiteral 15.8.2
2023:             *     'this' |                                // This 15.8.3
2024:             *     'this' Arguments |                      // Alternate constructor invocation 8.8.5.1
2025:             *     'super' Arguments |                     // Unqualified superclass constructor invocation 8.8.5.1
2026:             *     'super' '.' Identifier |                // SuperclassFieldAccess 15.11.2
2027:             *     'super' '.' Identifier Arguments |      // SuperclassMethodInvocation 15.12.4.9
2028:             *     NewClassInstance |
2029:             *     NewAnonymousClassInstance |             // ClassInstanceCreationExpression 15.9
2030:             *     NewArray |                              // ArrayCreationExpression 15.10
2031:             *     NewInitializedArray |                   // ArrayInitializer 10.6
2032:             *     BasicType { '[]' } |                    // Type
2033:             *     BasicType { '[]' } '.' 'class' |        // ClassLiteral 15.8.2
2034:             *     'void' '.' 'class'                      // ClassLiteral 15.8.2
2035:             *
2036:             *   CastExpression :=
2037:             *     '(' PrimitiveType { '[]' } ')' UnaryExpression |
2038:             *     '(' Expression ')' UnaryExpression
2039:             * 
2040:             *   NewClassInstance := 'new' ReferenceType Arguments
2041:             * 
2042:             *   NewAnonymousClassInstance := 'new' ReferenceType Arguments [ ClassBody ]
2043:             * 
2044:             *   NewArray := 'new' Type DimExprs { '[]' }
2045:             * 
2046:             *   NewInitializedArray := 'new' ArrayType ArrayInitializer
2047:             * </pre>
2048:             */
2049:            public Java.Atom parsePrimary() throws ParseException,
2050:                    Scanner.ScanException, IOException {
2051:                if (this .peekOperator("(")) {
2052:                    this .eatToken();
2053:                    if (this 
2054:                            .peekKeyword(new String[] { "boolean", "char",
2055:                                    "byte", "short", "int", "long", "float",
2056:                                    "double", })) {
2057:                        // '(' PrimitiveType { '[]' } ')' UnaryExpression
2058:                        Java.Type type = this .parseType();
2059:                        int brackets = this .parseBracketsOpt();
2060:                        this .readOperator(")");
2061:                        for (int i = 0; i < brackets; ++i)
2062:                            type = new Java.ArrayType(type);
2063:                        return new Java.Cast(this .location(), // location
2064:                                type, // targetType
2065:                                this .parseUnaryExpression().toRvalueOrPE() // value
2066:                        );
2067:                    }
2068:                    Java.Atom a = this .parseExpression();
2069:                    this .readOperator(")");
2070:
2071:                    if (this .scanner.peek().isLiteral()
2072:                            || this .scanner.peek().isIdentifier()
2073:                            || this 
2074:                                    .peekOperator(new String[] { "(", "~", "!", })
2075:                            || this .peekKeyword(new String[] { "this", "super",
2076:                                    "new", })) {
2077:                        // '(' Expression ')' UnaryExpression
2078:                        return new Java.Cast(this .location(), // location
2079:                                a.toTypeOrPE(), // targetType
2080:                                this .parseUnaryExpression().toRvalueOrPE() // value
2081:                        );
2082:                    }
2083:
2084:                    // '(' Expression ')'
2085:                    return new Java.ParenthesizedExpression(a.getLocation(), a
2086:                            .toRvalueOrPE());
2087:                }
2088:
2089:                if (this .scanner.peek().isLiteral()) {
2090:                    // Literal
2091:                    return this .parseLiteral();
2092:                }
2093:
2094:                if (this .scanner.peek().isIdentifier()) {
2095:                    Location location = this .location();
2096:                    String[] qi = this .parseQualifiedIdentifier();
2097:                    if (this .peekOperator("(")) {
2098:                        // Name Arguments
2099:                        return new Java.MethodInvocation(this .location(), // location
2100:                                qi.length == 1 ? null : new Java.AmbiguousName( // optionalTarget
2101:                                        location, // location
2102:                                        qi, // identifiers
2103:                                        qi.length - 1 // n
2104:                                        ), qi[qi.length - 1], // methodName
2105:                                this .parseArguments() // arguments
2106:                        );
2107:                    }
2108:                    if (this .peekOperator("[")
2109:                            && this .scanner.peekNextButOne().isOperator("]")) {
2110:                        // Name '[]' { '[]' }
2111:                        // Name '[]' { '[]' } '.' 'class'
2112:                        Java.Type res = new Java.ReferenceType(location, // location
2113:                                qi // identifiers
2114:                        );
2115:                        int brackets = this .parseBracketsOpt();
2116:                        for (int i = 0; i < brackets; ++i)
2117:                            res = new Java.ArrayType(res);
2118:                        if (this .peekOperator(".")
2119:                                && this .scanner.peekNextButOne().isKeyword(
2120:                                        "class")) {
2121:                            this .eatToken();
2122:                            Location location2 = this .location();
2123:                            this .eatToken();
2124:                            return new Java.ClassLiteral(location2, res);
2125:                        } else {
2126:                            return res;
2127:                        }
2128:                    }
2129:                    // Name
2130:                    return new Java.AmbiguousName(this .location(), // location
2131:                            qi // identifiers
2132:                    );
2133:                }
2134:
2135:                if (this .peekKeyword("this")) {
2136:                    Location location = this .location();
2137:                    this .eatToken();
2138:                    if (this .peekOperator("(")) {
2139:
2140:                        // 'this' Arguments
2141:                        // Alternate constructor invocation (JLS 8.8.5.1)
2142:                        return new Java.AlternateConstructorInvocation(
2143:                                location, // location
2144:                                this .parseArguments() // arguments
2145:                        );
2146:                    } else {
2147:
2148:                        // 'this'
2149:                        return new Java.ThisReference(location);
2150:                    }
2151:                }
2152:
2153:                if (this .peekKeyword("super")) {
2154:                    this .eatToken();
2155:                    if (this .peekOperator("(")) {
2156:
2157:                        // 'super' Arguments
2158:                        // Unqualified superclass constructor invocation (JLS 8.8.5.1)
2159:                        return new Java.SuperConstructorInvocation(this 
2160:                                .location(), // location
2161:                                (Java.Rvalue) null, // optionalQualification
2162:                                this .parseArguments() // arguments
2163:                        );
2164:                    }
2165:                    this .readOperator(".");
2166:                    String name = this .readIdentifier();
2167:                    if (this .peekOperator("(")) {
2168:
2169:                        // 'super' '.' Identifier Arguments
2170:                        return new Java.SuperclassMethodInvocation(this 
2171:                                .location(), // location
2172:                                name, // methodName
2173:                                this .parseArguments() // arguments
2174:                        );
2175:                    } else {
2176:
2177:                        // 'super' '.' Identifier
2178:                        return new Java.SuperclassFieldAccessExpression(this 
2179:                                .location(), // location
2180:                                (Java.Type) null, // optionalQualification
2181:                                name // fieldName
2182:                        );
2183:                    }
2184:                }
2185:
2186:                // 'new'
2187:                if (this .peekKeyword("new")) {
2188:                    Location location = this .location();
2189:                    this .eatToken();
2190:                    Java.Type type = this .parseType();
2191:                    if (type instanceof  Java.ArrayType) {
2192:                        // 'new' ArrayType ArrayInitializer
2193:                        return new Java.NewInitializedArray(location,
2194:                                (Java.ArrayType) type, this 
2195:                                        .parseArrayInitializer());
2196:                    }
2197:                    if (type instanceof  Java.ReferenceType
2198:                            && this .peekOperator("(")) {
2199:                        // 'new' ReferenceType Arguments [ ClassBody ]
2200:                        Java.Rvalue[] arguments = this .parseArguments();
2201:                        if (this .peekOperator("{")) {
2202:                            // 'new' ReferenceType Arguments ClassBody
2203:                            final Java.AnonymousClassDeclaration anonymousClassDeclaration = new Java.AnonymousClassDeclaration(
2204:                                    this .location(), // location
2205:                                    type // baseType
2206:                            );
2207:                            this .parseClassBody(anonymousClassDeclaration);
2208:                            return new Java.NewAnonymousClassInstance(location, // location
2209:                                    (Java.Rvalue) null, // optionalQualification
2210:                                    anonymousClassDeclaration, // anonymousClassDeclaration
2211:                                    arguments // arguments
2212:                            );
2213:                        } else {
2214:                            // 'new' ReferenceType Arguments
2215:                            return new Java.NewClassInstance(location, // location
2216:                                    (Java.Rvalue) null, // optionalQualification
2217:                                    type, // type
2218:                                    arguments // arguments
2219:                            );
2220:                        }
2221:                    }
2222:                    // 'new' Type DimExprs { '[]' }
2223:                    return new Java.NewArray(location, // location
2224:                            type, // type
2225:                            this .parseDimExprs(), // dimExprs
2226:                            this .parseBracketsOpt() // dims
2227:                    );
2228:                }
2229:
2230:                // BasicType
2231:                if (this .peekKeyword(new String[] { "boolean", "char", "byte",
2232:                        "short", "int", "long", "float", "double", })) {
2233:                    Java.Type res = this .parseType();
2234:                    int brackets = this .parseBracketsOpt();
2235:                    for (int i = 0; i < brackets; ++i)
2236:                        res = new Java.ArrayType(res);
2237:                    if (this .peekOperator(".")
2238:                            && this .scanner.peekNextButOne().isKeyword("class")) {
2239:                        // BasicType { '[]' } '.' 'class'
2240:                        this .eatToken();
2241:                        Location location = this .location();
2242:                        this .eatToken();
2243:                        return new Java.ClassLiteral(location, res);
2244:                    }
2245:                    // BasicType { '[]' }
2246:                    return res;
2247:                }
2248:
2249:                // 'void'
2250:                if (this .peekKeyword("void")) {
2251:                    this .eatToken();
2252:                    if (this .peekOperator(".")
2253:                            && this .scanner.peekNextButOne().isKeyword("class")) {
2254:                        // 'void' '.' 'class'
2255:                        this .eatToken();
2256:                        Location location = this .location();
2257:                        this .eatToken();
2258:                        return new Java.ClassLiteral(location,
2259:                                new Java.BasicType(location,
2260:                                        Java.BasicType.VOID));
2261:                    }
2262:                    this 
2263:                            .throwParseException("\"void\" encountered in wrong context");
2264:                }
2265:
2266:                this .throwParseException("Unexpected token \""
2267:                        + this .scanner.peek() + "\" in primary");
2268:                /* NEVER REACHED */return null;
2269:            }
2270:
2271:            /**
2272:             * <pre>
2273:             *   Selector :=
2274:             *     '.' Identifier |                       // FieldAccess 15.11.1
2275:             *     '.' Identifier Arguments |             // MethodInvocation
2276:             *     '.' 'this'                             // QualifiedThis 15.8.4
2277:             *     '.' 'super' Arguments                  // Qualified superclass constructor invocation (JLS 8.8.5.1)
2278:             *     '.' 'super' '.' Identifier |           // SuperclassFieldReference (JLS 15.11.2)
2279:             *     '.' 'super' '.' Identifier Arguments | // SuperclassMethodInvocation (JLS 15.12.4.9)
2280:             *     '.' 'new' Identifier Arguments [ ClassBody ] | // QualifiedClassInstanceCreationExpression  15.9
2281:             *     '.' 'class'
2282:             *     '[' Expression ']'                     // ArrayAccessExpression 15.13
2283:             * </pre>
2284:             */
2285:            public Java.Atom parseSelector(Java.Atom atom)
2286:                    throws ParseException, Scanner.ScanException, IOException {
2287:                if (this .peekOperator(".")) {
2288:                    this .eatToken();
2289:                    if (this .scanner.peek().isIdentifier()) {
2290:                        String identifier = this .readIdentifier();
2291:                        if (this .peekOperator("(")) {
2292:                            // '.' Identifier Arguments
2293:                            return new Java.MethodInvocation(this .location(), // location
2294:                                    atom.toRvalueOrPE(), // optionalTarget
2295:                                    identifier, // methodName
2296:                                    this .parseArguments() // arguments
2297:                            );
2298:                        }
2299:                        // '.' Identifier
2300:                        return new Java.FieldAccessExpression(this .location(), // location
2301:                                atom.toRvalueOrPE(), // lhs
2302:                                identifier // fieldName
2303:                        );
2304:                    }
2305:                    if (this .peekKeyword("this")) {
2306:                        // '.' 'this'
2307:                        Location location = this .location();
2308:                        this .eatToken();
2309:                        return new Java.QualifiedThisReference(location, // location
2310:                                atom.toTypeOrPE() // qualification
2311:                        );
2312:                    }
2313:                    if (this .peekKeyword("super")) {
2314:                        Location location = this .location();
2315:                        this .eatToken();
2316:                        if (this .peekOperator("(")) {
2317:
2318:                            // '.' 'super' Arguments
2319:                            // Qualified superclass constructor invocation (JLS 8.8.5.1) (LHS is an Rvalue)
2320:                            return new Java.SuperConstructorInvocation(
2321:                                    location, // location
2322:                                    atom.toRvalueOrPE(), // optionalQualification
2323:                                    this .parseArguments() // arguments
2324:                            );
2325:                        }
2326:                        this .readOperator(".");
2327:                        String identifier = this .readIdentifier();
2328:
2329:                        if (this .peekOperator("(")) {
2330:
2331:                            // '.' 'super' '.' Identifier Arguments
2332:                            // Qualified superclass method invocation (JLS 15.12) (LHS is a ClassName)
2333:                            // TODO: Qualified superclass method invocation
2334:                            this 
2335:                                    .throwParseException("Qualified superclass method invocation NYI");
2336:                        } else {
2337:
2338:                            // '.' 'super' '.' Identifier
2339:                            // Qualified superclass field access (JLS 15.11.2) (LHS is an Rvalue)
2340:                            return new Java.SuperclassFieldAccessExpression(
2341:                                    location, // location
2342:                                    atom.toTypeOrPE(), // optionalQualification
2343:                                    identifier // fieldName
2344:                            );
2345:                        }
2346:                    }
2347:                    if (this .peekKeyword("new")) {
2348:                        // '.' 'new' Identifier Arguments [ ClassBody ]
2349:                        Java.Rvalue lhs = atom.toRvalue();
2350:                        Location location = this .location();
2351:                        this .eatToken();
2352:                        String identifier = this .readIdentifier();
2353:                        Java.Type type = new Java.RvalueMemberType(location, // location
2354:                                lhs, // rValue
2355:                                identifier // identifier
2356:                        );
2357:                        Java.Rvalue[] arguments = this .parseArguments();
2358:                        if (this .peekOperator("{")) {
2359:                            // '.' 'new' Identifier Arguments ClassBody (LHS is an Rvalue)
2360:                            final Java.AnonymousClassDeclaration anonymousClassDeclaration = new Java.AnonymousClassDeclaration(
2361:                                    this .location(), // location
2362:                                    type // baseType
2363:                            );
2364:                            this .parseClassBody(anonymousClassDeclaration);
2365:                            return new Java.NewAnonymousClassInstance(location, // location
2366:                                    lhs, // optionalQualification
2367:                                    anonymousClassDeclaration, // anonymousClassDeclaration
2368:                                    arguments // arguments
2369:                            );
2370:                        } else {
2371:                            // '.' 'new' Identifier Arguments (LHS is an Rvalue)
2372:                            return new Java.NewClassInstance(location, // location
2373:                                    lhs, // optionalQualification
2374:                                    type, // referenceType
2375:                                    arguments // arguments
2376:                            );
2377:                        }
2378:                    }
2379:                    if (this .peekKeyword("class")) {
2380:                        // '.' 'class'
2381:                        Location location = this .location();
2382:                        this .eatToken();
2383:                        return new Java.ClassLiteral(location, atom
2384:                                .toTypeOrPE());
2385:                    }
2386:                    this .throwParseException("Unexpected selector \""
2387:                            + this .scanner.peek() + "\" after \".\"");
2388:                }
2389:                if (this .peekOperator("[")) {
2390:                    // '[' Expression ']'
2391:                    Location location = this .location();
2392:                    this .eatToken();
2393:                    Java.Rvalue index = this .parseExpression().toRvalueOrPE();
2394:                    this .readOperator("]");
2395:                    return new Java.ArrayAccessExpression(location, // location
2396:                            atom.toRvalueOrPE(), // lhs
2397:                            index // index
2398:                    );
2399:                }
2400:                this .throwParseException("Unexpected token \""
2401:                        + this .scanner.peek() + "\" in selector");
2402:                /* NEVER REACHED */return null;
2403:            }
2404:
2405:            /**
2406:             * <pre>
2407:             *   DimExprs := DimExpr { DimExpr }
2408:             * </pre>
2409:             */
2410:            public Java.Rvalue[] parseDimExprs() throws ParseException,
2411:                    Scanner.ScanException, IOException {
2412:                List l = new ArrayList();
2413:                l.add(this .parseDimExpr());
2414:                while (this .peekOperator("[")
2415:                        && !this .scanner.peekNextButOne().isOperator("]"))
2416:                    l.add(this .parseDimExpr());
2417:                return (Java.Rvalue[]) l.toArray(new Java.Rvalue[l.size()]);
2418:            }
2419:
2420:            /**
2421:             * <pre>
2422:             *   DimExpr := '[' Expression ']'
2423:             * </pre>
2424:             */
2425:            public Java.Rvalue parseDimExpr() throws Scanner.ScanException,
2426:                    ParseException, IOException {
2427:                this .readOperator("[");
2428:                Java.Rvalue res = this .parseExpression().toRvalueOrPE();
2429:                this .readOperator("]");
2430:                return res;
2431:            }
2432:
2433:            /**
2434:             * <pre>
2435:             *   Arguments := '(' [ ArgumentList ] ')'
2436:             * </pre>
2437:             */
2438:            public Java.Rvalue[] parseArguments() throws ParseException,
2439:                    Scanner.ScanException, IOException {
2440:                this .readOperator("(");
2441:                if (this .peekOperator(")")) {
2442:                    this .eatToken();
2443:                    return new Java.Rvalue[0];
2444:                }
2445:                Java.Rvalue[] arguments = this .parseArgumentList();
2446:                this .readOperator(")");
2447:                return arguments;
2448:            }
2449:
2450:            /**
2451:             * <pre>
2452:             *   ArgumentList := Expression { ',' Expression }
2453:             * </pre>
2454:             */
2455:            public Java.Rvalue[] parseArgumentList() throws ParseException,
2456:                    Scanner.ScanException, IOException {
2457:                List l = new ArrayList();
2458:                for (;;) {
2459:                    l.add(this .parseExpression().toRvalueOrPE());
2460:                    if (!this .peekOperator(","))
2461:                        break;
2462:                    this .eatToken();
2463:                }
2464:                return (Java.Rvalue[]) l.toArray(new Java.Rvalue[l.size()]);
2465:            }
2466:
2467:            public Java.Atom parseLiteral() throws ParseException,
2468:                    Scanner.ScanException, IOException {
2469:                Scanner.Token t = this .scanner.read();
2470:                if (!t.isLiteral())
2471:                    this .throwParseException("Literal expected");
2472:                return new Java.Literal(t.getLocation(), t.getLiteralValue());
2473:            }
2474:
2475:            // Simplified access to the scanner.
2476:
2477:            public Location location() {
2478:                return this .scanner.location();
2479:            }
2480:
2481:            public void eatToken() throws Scanner.ScanException, IOException {
2482:                this .scanner.read();
2483:            }
2484:
2485:            // Keyword-related.
2486:            public boolean peekKeyword() {
2487:                return this .scanner.peek().isKeyword();
2488:            }
2489:
2490:            public boolean peekKeyword(String keyword) {
2491:                return this .scanner.peek().isKeyword(keyword);
2492:            }
2493:
2494:            public boolean peekKeyword(String[] keywords) {
2495:                return this .scanner.peek().isKeyword(keywords);
2496:            }
2497:
2498:            public void readKeyword(String keyword) throws ParseException,
2499:                    Scanner.ScanException, IOException {
2500:                if (!this .scanner.read().isKeyword(keyword))
2501:                    this .throwParseException("\"" + keyword + "\" expected"); // We want a ParseException, not a ScanException
2502:            }
2503:
2504:            // Operator-related.
2505:            public boolean peekOperator(String operator) {
2506:                return this .scanner.peek().isOperator(operator);
2507:            }
2508:
2509:            public boolean peekOperator(String[] operators) {
2510:                return this .scanner.peek().isOperator(operators);
2511:            }
2512:
2513:            public String readOperator() throws ParseException,
2514:                    Scanner.ScanException, IOException {
2515:                Scanner.Token t = this .scanner.read();
2516:                if (!t.isOperator())
2517:                    this .throwParseException("Operator expected"); // We want a ParseException, not a ScanException
2518:                return t.getOperator();
2519:            }
2520:
2521:            public void readOperator(String operator) throws ParseException,
2522:                    Scanner.ScanException, IOException {
2523:                if (!this .scanner.read().isOperator(operator))
2524:                    this .throwParseException("Operator \"" + operator
2525:                            + "\" expected"); // We want a ParseException, not a ScanException
2526:            }
2527:
2528:            // Identifier-related.
2529:            public boolean peekIdentifier() {
2530:                return this .scanner.peek().isIdentifier();
2531:            }
2532:
2533:            public String readIdentifier() throws ParseException,
2534:                    Scanner.ScanException, IOException {
2535:                Scanner.Token t = this .scanner.read();
2536:                if (!t.isIdentifier())
2537:                    this .throwParseException("Identifier expected"); // We want a ParseException, not a ScanException
2538:                return t.getIdentifier();
2539:            }
2540:
2541:            /**
2542:             * <pre>
2543:             *   ExpressionStatement := Expression ';'
2544:             * </pre>
2545:             */
2546:            public Java.Statement parseExpressionStatement()
2547:                    throws ParseException, Scanner.ScanException, IOException {
2548:                Java.Rvalue rv = this .parseExpression().toRvalueOrPE();
2549:                this .readOperator(";");
2550:
2551:                return new Java.ExpressionStatement(rv);
2552:            }
2553:
2554:            /**
2555:             * Issue a warning if the given string does not comply with the package naming conventions
2556:             * (JLS2 6.8.1).
2557:             */
2558:            private void verifyStringIsConventionalPackageName(String s,
2559:                    Location loc) {
2560:                if (!Character.isLowerCase(s.charAt(0))) {
2561:                    this 
2562:                            .warning(
2563:                                    "UPN",
2564:                                    "Package name \""
2565:                                            + s
2566:                                            + "\" does not begin with a lower-case letter (see JLS2 6.8.1)",
2567:                                    loc);
2568:                    return;
2569:                }
2570:
2571:                for (int i = 0; i < s.length(); ++i) {
2572:                    char c = s.charAt(i);
2573:                    if (!Character.isLowerCase(c) && c != '_' && c != '.') {
2574:                        this .warning("PPN", "Poorly chosen package name \"" + s
2575:                                + "\" contains bad character '" + c + "'", loc);
2576:                        return;
2577:                    }
2578:                }
2579:            }
2580:
2581:            /**
2582:             * Issue a warning if the given identifier does not comply with the class and interface type
2583:             * naming conventions (JLS2 6.8.2).
2584:             */
2585:            private void verifyIdentifierIsConventionalClassOrInterfaceName(
2586:                    String id, Location loc) {
2587:                if (!Character.isUpperCase(id.charAt(0))) {
2588:                    this 
2589:                            .warning(
2590:                                    "UCOIN1",
2591:                                    "Class or interface name \""
2592:                                            + id
2593:                                            + "\" does not begin with an upper-case letter (see JLS2 6.8.2)",
2594:                                    loc);
2595:                    return;
2596:                }
2597:                for (int i = 0; i < id.length(); ++i) {
2598:                    char c = id.charAt(i);
2599:                    if (!Character.isLetter(c) && !Character.isDigit(c)) {
2600:                        this .warning("UCOIN", "Class or interface name \"" + id
2601:                                + "\" contains unconventional character \"" + c
2602:                                + "\" (see JLS2 6.8.2)", loc);
2603:                        return;
2604:                    }
2605:                }
2606:            }
2607:
2608:            /**
2609:             * Issue a warning if the given identifier does not comply with the method naming conventions
2610:             * (JLS2 6.8.3).
2611:             */
2612:            private void verifyIdentifierIsConventionalMethodName(String id,
2613:                    Location loc) {
2614:                if (!Character.isLowerCase(id.charAt(0))) {
2615:                    this 
2616:                            .warning(
2617:                                    "UMN1",
2618:                                    "Method name \""
2619:                                            + id
2620:                                            + "\" does not begin with a lower-case letter (see JLS2 6.8.3)",
2621:                                    loc);
2622:                    return;
2623:                }
2624:                for (int i = 0; i < id.length(); ++i) {
2625:                    char c = id.charAt(i);
2626:                    if (!Character.isLetter(c) && !Character.isDigit(c)) {
2627:                        this .warning("UMN", "Method name \"" + id
2628:                                + "\" contains unconventional character \"" + c
2629:                                + "\" (see JLS2 6.8.3)", loc);
2630:                        return;
2631:                    }
2632:                }
2633:            }
2634:
2635:            /**
2636:             * Issue a warning if the given identifier does not comply with the field naming conventions
2637:             * (JLS2 6.8.4) and constant naming conventions (JLS2 6.8.5).
2638:             */
2639:            private void verifyIdentifierIsConventionalFieldName(String id,
2640:                    Location loc) {
2641:
2642:                // In practice, a field is not always a constant iff it is static-final. So let's
2643:                // always tolerate both field and constant names.
2644:
2645:                if (Character.isUpperCase(id.charAt(0))) {
2646:                    for (int i = 0; i < id.length(); ++i) {
2647:                        char c = id.charAt(i);
2648:                        if (!Character.isUpperCase(c) && !Character.isDigit(c)
2649:                                && c != '_') {
2650:                            this .warning("UCN", "Constant name \"" + id
2651:                                    + "\" contains unconventional character \""
2652:                                    + c + "\" (see JLS2 6.8.5)", loc);
2653:                            return;
2654:                        }
2655:                    }
2656:                } else if (Character.isLowerCase(id.charAt(0))) {
2657:                    for (int i = 0; i < id.length(); ++i) {
2658:                        char c = id.charAt(i);
2659:                        if (!Character.isLetter(c) && !Character.isDigit(c)) {
2660:                            this .warning("UFN", "Field name \"" + id
2661:                                    + "\" contains unconventional character \""
2662:                                    + c + "\" (see JLS2 6.8.4)", loc);
2663:                            return;
2664:                        }
2665:                    }
2666:                } else {
2667:                    this 
2668:                            .warning(
2669:                                    "UFN1",
2670:                                    "\""
2671:                                            + id
2672:                                            + "\" is neither a conventional field name (JLS2 6.8.4) nor a conventional constant name (JLS2 6.8.5)",
2673:                                    loc);
2674:                }
2675:            }
2676:
2677:            /**
2678:             * Issue a warning if the given identifier does not comply with the local variable and
2679:             * parameter naming conventions (JLS2 6.8.6).
2680:             */
2681:            private void verifyIdentifierIsConventionalLocalVariableOrParameterName(
2682:                    String id, Location loc) {
2683:                if (!Character.isLowerCase(id.charAt(0))) {
2684:                    this 
2685:                            .warning(
2686:                                    "ULVN1",
2687:                                    "Local variable name \""
2688:                                            + id
2689:                                            + "\" does not begin with a lower-case letter (see JLS2 6.8.6)",
2690:                                    loc);
2691:                    return;
2692:                }
2693:                for (int i = 0; i < id.length(); ++i) {
2694:                    char c = id.charAt(i);
2695:                    if (!Character.isLetter(c) && !Character.isDigit(c)) {
2696:                        this .warning("ULVN", "Local variable name \"" + id
2697:                                + "\" contains unconventional character \"" + c
2698:                                + "\" (see JLS2 6.8.6)", loc);
2699:                        return;
2700:                    }
2701:                }
2702:            }
2703:
2704:            /**
2705:             * By default, warnings are discarded, but an application my install a
2706:             * {@link WarningHandler}.
2707:             * <p>
2708:             * Notice that there is no <code>Parser.setErrorHandler()</code> method, but parse errors
2709:             * always throw a {@link ParseException}. The reason being is that there is no reasonable
2710:             * way to recover from parse errors and continue parsing, so there is no need to install
2711:             * a custom parse error handler.
2712:             *
2713:             * @param optionalWarningHandler <code>null</code> to indicate that no warnings be issued
2714:             */
2715:            public void setWarningHandler(WarningHandler optionalWarningHandler) {
2716:                this .optionalWarningHandler = optionalWarningHandler;
2717:            }
2718:
2719:            // Used for elaborate warning handling.
2720:            private WarningHandler optionalWarningHandler = null;
2721:
2722:            /**
2723:             * Issues a warning with the given message and location and returns. This is done through
2724:             * a {@link WarningHandler} that was installed through
2725:             * {@link #setWarningHandler(WarningHandler)}.
2726:             * <p>
2727:             * The <code>handle</code> argument qulifies the warning and is typically used by
2728:             * the {@link WarningHandler} to suppress individual warnings.
2729:             */
2730:            private void warning(String handle, String message,
2731:                    Location optionalLocation) {
2732:                if (this .optionalWarningHandler != null)
2733:                    this .optionalWarningHandler.handleWarning(handle, message,
2734:                            optionalLocation);
2735:            }
2736:
2737:            /**
2738:             * An exception that reflects an error during parsing.
2739:             *
2740:             * This exception is associated with a particular {@link Location
2741:             * Location} in the source code.
2742:             */
2743:            public static class ParseException extends LocatedException {
2744:                public ParseException(String message, Location location) {
2745:                    super (message, location);
2746:                }
2747:            }
2748:
2749:            /**
2750:             * Convenience method for throwing a ParseException.
2751:             */
2752:            protected final void throwParseException(String message)
2753:                    throws ParseException {
2754:                throw new ParseException(message, this .location());
2755:            }
2756:
2757:            private static String join(String[] sa, String separator) {
2758:                if (sa == null)
2759:                    return ("(null)");
2760:                if (sa.length == 0)
2761:                    return ("(zero length array)");
2762:                StringBuffer sb = new StringBuffer(sa[0]);
2763:                for (int i = 1; i < sa.length; ++i) {
2764:                    sb.append(separator).append(sa[i]);
2765:                }
2766:                return sb.toString();
2767:            }
2768:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.