Source Code Cross Referenced for Parser.java in  » IDE-Netbeans » library » org » mozilla » javascript » 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 » IDE Netbeans » library » org.mozilla.javascript 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        /* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
0002:         *
0003:         * ***** BEGIN LICENSE BLOCK *****
0004:         * Version: MPL 1.1/GPL 2.0
0005:         *
0006:         * The contents of this file are subject to the Mozilla Public License Version
0007:         * 1.1 (the "License"); you may not use this file except in compliance with
0008:         * the License. You may obtain a copy of the License at
0009:         * http://www.mozilla.org/MPL/
0010:         *
0011:         * Software distributed under the License is distributed on an "AS IS" basis,
0012:         * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
0013:         * for the specific language governing rights and limitations under the
0014:         * License.
0015:         *
0016:         * The Original Code is Rhino code, released
0017:         * May 6, 1999.
0018:         *
0019:         * The Initial Developer of the Original Code is
0020:         * Netscape Communications Corporation.
0021:         * Portions created by the Initial Developer are Copyright (C) 1997-1999
0022:         * the Initial Developer. All Rights Reserved.
0023:         *
0024:         * Contributor(s):
0025:         *   Mike Ang
0026:         *   Igor Bukanov
0027:         *   Yuh-Ruey Chen
0028:         *   Ethan Hugg
0029:         *   Bob Jervis
0030:         *   Terry Lucas
0031:         *   Mike McCabe
0032:         *   Milen Nankov
0033:         *
0034:         * Alternatively, the contents of this file may be used under the terms of
0035:         * the GNU General Public License Version 2 or later (the "GPL"), in which
0036:         * case the provisions of the GPL are applicable instead of those above. If
0037:         * you wish to allow use of your version of this file only under the terms of
0038:         * the GPL and not to allow others to use your version of this file under the
0039:         * MPL, indicate your decision by deleting the provisions above and replacing
0040:         * them with the notice and other provisions required by the GPL. If you do
0041:         * not delete the provisions above, a recipient may use your version of this
0042:         * file under either the MPL or the GPL.
0043:         *
0044:         * ***** END LICENSE BLOCK ***** */
0045:
0046:        package org.mozilla.javascript;
0047:
0048:        import java.io.Reader;
0049:        import java.io.IOException;
0050:        import java.util.ArrayList;
0051:        import java.util.Hashtable;
0052:        import java.util.List;
0053:
0054:        /**
0055:         * This class implements the JavaScript parser.
0056:         *
0057:         * It is based on the C source files jsparse.c and jsparse.h
0058:         * in the jsref package.
0059:         *
0060:         * @see TokenStream
0061:         *
0062:         * @author Mike McCabe
0063:         * @author Brendan Eich
0064:         */
0065:
0066:        public class Parser {
0067:            // TokenInformation flags : currentFlaggedToken stores them together
0068:            // with token type
0069:            // <netbeans>
0070:            public// </netbeans>
0071:            final static int CLEAR_TI_MASK = 0xFFFF, // mask to clear token information bits
0072:                    TI_AFTER_EOL = 1 << 16, // first token of the source line
0073:                    TI_CHECK_LABEL = 1 << 17; // indicates to check for label
0074:
0075:            CompilerEnvirons compilerEnv;
0076:            private ErrorReporter errorReporter;
0077:            private String sourceURI;
0078:            boolean calledByCompileFunction;
0079:
0080:            private TokenStream ts;
0081:            // <netbeans>
0082:            private int peekedTokenStart;
0083:            private int peekedTokenEnd;
0084:            private int matchedTokenStart;
0085:            private int matchedTokenEnd;
0086:            private int matchedToken;
0087:            private boolean jsonMode;
0088:
0089:            public void setJsonMode(boolean jsonMode) {
0090:                this .jsonMode = jsonMode;
0091:            }
0092:
0093:            // </netbeans>
0094:            private int currentFlaggedToken;
0095:            private int syntaxErrorCount;
0096:
0097:            private IRFactory nf;
0098:
0099:            private int nestingOfFunction;
0100:
0101:            private Decompiler decompiler;
0102:            private String encodedSource;
0103:
0104:            // The following are per function variables and should be saved/restored
0105:            // during function parsing.
0106:            // XXX Move to separated class?
0107:            ScriptOrFnNode currentScriptOrFn;
0108:            private int nestingOfWith;
0109:            private Hashtable labelSet; // map of label names into nodes
0110:            private ObjArray loopSet;
0111:            private ObjArray loopAndSwitchSet;
0112:            private boolean hasReturnValue;
0113:            private int functionEndFlags;
0114:
0115:            // end of per function variables
0116:
0117:            // Exception to unwind
0118:            private static class ParserException extends RuntimeException {
0119:                static final long serialVersionUID = 5882582646773765630L;
0120:            }
0121:
0122:            public Parser(CompilerEnvirons compilerEnv,
0123:                    ErrorReporter errorReporter) {
0124:                this .compilerEnv = compilerEnv;
0125:                this .errorReporter = errorReporter;
0126:            }
0127:
0128:            protected Decompiler createDecompiler(CompilerEnvirons compilerEnv) {
0129:                return new Decompiler();
0130:            }
0131:
0132:            void addStrictWarning(String messageId, String messageArg
0133:            // <netbeans>
0134:                    // Additional error parameters that can be passed to the error handler
0135:                    , Object params
0136:            // </netbeans>
0137:            ) {
0138:                if (compilerEnv.isStrictMode())
0139:                    addWarning(messageId, messageArg
0140:                    // <netbeans>
0141:                            // Additional error parameters that can be passed to the error handler
0142:                            , params
0143:                    // </netbeans>
0144:                    );
0145:            }
0146:
0147:            void addWarning(String messageId, String messageArg
0148:            // <netbeans>
0149:                    // Additional error parameters that can be passed to the error handler
0150:                    , Object params
0151:            // </netbeans>
0152:            ) {
0153:                String message = ScriptRuntime.getMessage1(messageId,
0154:                        messageArg);
0155:                if (compilerEnv.reportWarningAsError()) {
0156:                    ++syntaxErrorCount;
0157:                    errorReporter.error(message, sourceURI, ts.getLineno(), ts
0158:                            .getLine(), ts.getOffset()
0159:                    // <netbeans>
0160:                            , messageId, params
0161:                    // </netbeans>
0162:                            );
0163:                } else
0164:                    errorReporter.warning(message, sourceURI, ts.getLineno(),
0165:                            ts.getLine(), ts.getOffset()
0166:                            // <netbeans>
0167:                            , messageId, params
0168:                    // </netbeans>
0169:                            );
0170:            }
0171:
0172:            void addError(String messageId) {
0173:                ++syntaxErrorCount;
0174:                String message = ScriptRuntime.getMessage0(messageId);
0175:                errorReporter.error(message, sourceURI, ts.getLineno(), ts
0176:                        .getLine(), ts.getOffset()
0177:                // <netbeans>
0178:                        , messageId, null
0179:                // </netbeans>
0180:                        );
0181:            }
0182:
0183:            void addError(String messageId, String messageArg
0184:            // <netbeans>
0185:                    // Additional error parameters that can be passed to the error handler
0186:                    , Object params
0187:            // </netbeans>
0188:            ) {
0189:                ++syntaxErrorCount;
0190:                String message = ScriptRuntime.getMessage1(messageId,
0191:                        messageArg);
0192:                errorReporter.error(message, sourceURI, ts.getLineno(), ts
0193:                        .getLine(), ts.getOffset()
0194:                // <netbeans>
0195:                        , messageId, params
0196:                // </netbeans>
0197:                        );
0198:            }
0199:
0200:            RuntimeException reportError(String messageId) {
0201:                addError(messageId);
0202:
0203:                // Throw a ParserException exception to unwind the recursive descent
0204:                // parse.
0205:                throw new ParserException();
0206:            }
0207:
0208:            private int peekToken() throws IOException {
0209:                int tt = currentFlaggedToken;
0210:                if (tt == Token.EOF) {
0211:                    // <netbeans>                    
0212:                    peekedTokenStart = ts.getBufferOffset();
0213:                    // </netbeans>                    
0214:                    tt = ts.getToken();
0215:                    if (tt == Token.EOL) {
0216:                        do {
0217:                            // <netbeans>                    
0218:                            peekedTokenStart = ts.getBufferOffset();
0219:                            // </netbeans>                    
0220:                            tt = ts.getToken();
0221:                        } while (tt == Token.EOL);
0222:                        tt |= TI_AFTER_EOL;
0223:                    }
0224:                    currentFlaggedToken = tt;
0225:                    // <netbeans>                    
0226:                    peekedTokenStart += ts.seenSpaces();
0227:                    peekedTokenEnd = ts.getBufferOffset();
0228:                    // </netbeans>                    
0229:                }
0230:                return tt & CLEAR_TI_MASK;
0231:            }
0232:
0233:            private int peekFlaggedToken() throws IOException {
0234:                peekToken();
0235:                return currentFlaggedToken;
0236:            }
0237:
0238:            private void consumeToken() {
0239:                // <netbeans>                    
0240:                // Consume token gets called as part of nextToken() for example so doesn't help us very much
0241:                //currentFlaggedTokenOffset = -1;
0242:                matchedToken = currentFlaggedToken;
0243:                matchedTokenStart = peekedTokenStart;
0244:                matchedTokenEnd = peekedTokenEnd;
0245:                // </netbeans>                    
0246:                currentFlaggedToken = Token.EOF;
0247:            }
0248:
0249:            private int nextToken() throws IOException {
0250:                int tt = peekToken();
0251:                consumeToken();
0252:                return tt;
0253:            }
0254:
0255:            private int nextFlaggedToken() throws IOException {
0256:                peekToken();
0257:                int ttFlagged = currentFlaggedToken;
0258:                consumeToken();
0259:                return ttFlagged;
0260:            }
0261:
0262:            private boolean matchToken(int toMatch) throws IOException {
0263:                int tt = peekToken();
0264:                if (tt != toMatch) {
0265:                    return false;
0266:                }
0267:                consumeToken();
0268:                return true;
0269:            }
0270:
0271:            private int peekTokenOrEOL() throws IOException {
0272:                int tt = peekToken();
0273:                // Check for last peeked token flags
0274:                if ((currentFlaggedToken & TI_AFTER_EOL) != 0) {
0275:                    tt = Token.EOL;
0276:                }
0277:                return tt;
0278:            }
0279:
0280:            private void setCheckForLabel() {
0281:                if ((currentFlaggedToken & CLEAR_TI_MASK) != Token.NAME)
0282:                    throw Kit.codeBug();
0283:                currentFlaggedToken |= TI_CHECK_LABEL;
0284:            }
0285:
0286:            private void mustMatchToken(int toMatch, String messageId)
0287:                    throws IOException, ParserException {
0288:                if (!matchToken(toMatch)) {
0289:                    reportError(messageId);
0290:                }
0291:            }
0292:
0293:            private void mustHaveXML() {
0294:                if (!compilerEnv.isXmlAvailable()) {
0295:                    reportError("msg.XML.not.available");
0296:                }
0297:            }
0298:
0299:            public String getEncodedSource() {
0300:                return encodedSource;
0301:            }
0302:
0303:            public boolean eof() {
0304:                return ts.eof();
0305:            }
0306:
0307:            boolean insideFunction() {
0308:                return nestingOfFunction != 0;
0309:            }
0310:
0311:            private Node enterLoop(Node loopLabel) {
0312:                Node loop = nf.createLoopNode(loopLabel, ts.getLineno());
0313:                // <netbeans>
0314:                int startOffset = getStartOffset();
0315:                // TODO: Compute end position, perhaps in exitLoop?
0316:                loop.setSourceBounds(startOffset, startOffset);
0317:                // </netbeans>
0318:                if (loopSet == null) {
0319:                    loopSet = new ObjArray();
0320:                    if (loopAndSwitchSet == null) {
0321:                        loopAndSwitchSet = new ObjArray();
0322:                    }
0323:                }
0324:                loopSet.push(loop);
0325:                loopAndSwitchSet.push(loop);
0326:                return loop;
0327:            }
0328:
0329:            private void exitLoop() {
0330:                loopSet.pop();
0331:                loopAndSwitchSet.pop();
0332:            }
0333:
0334:            private Node enterSwitch(Node switchSelector, int lineno) {
0335:                Node switchNode = nf.createSwitch(switchSelector, lineno);
0336:                // <netbeans>
0337:                int startOffset = getStartOffset();
0338:                // TODO: Compute end position, perhaps in exitSwitch??
0339:                switchNode.setSourceBounds(startOffset, startOffset);
0340:                // </netbeans>
0341:                if (loopAndSwitchSet == null) {
0342:                    loopAndSwitchSet = new ObjArray();
0343:                }
0344:                loopAndSwitchSet.push(switchNode);
0345:                return switchNode;
0346:            }
0347:
0348:            private void exitSwitch() {
0349:                // <netbeans>
0350:                //loopAndSwitchSet.pop();
0351:                Node switchNode = (Node) loopAndSwitchSet.pop();
0352:                setSourceOffsets(switchNode, switchNode.getSourceStart());
0353:                // </netbeaans>
0354:            }
0355:
0356:            /*
0357:             * Build a parse tree from the given sourceString.
0358:             *
0359:             * @return an Object representing the parsed
0360:             * program.  If the parse fails, null will be returned.  (The
0361:             * parse failure will result in a call to the ErrorReporter from
0362:             * CompilerEnvirons.)
0363:             */
0364:            public ScriptOrFnNode parse(String sourceString, String sourceURI,
0365:                    int lineno) {
0366:                this .sourceURI = sourceURI;
0367:                this .ts = new TokenStream(this , null, sourceString, lineno);
0368:                try {
0369:                    // <netbeans>
0370:                    setJsonMode(false);
0371:                    // </netbeans>
0372:                    return parse();
0373:                } catch (IOException ex) {
0374:                    // Should never happen
0375:                    throw new IllegalStateException();
0376:                }
0377:            }
0378:
0379:            /*
0380:             * Build a parse tree from the given sourceString.
0381:             *
0382:             * @return an Object representing the parsed
0383:             * program.  If the parse fails, null will be returned.  (The
0384:             * parse failure will result in a call to the ErrorReporter from
0385:             * CompilerEnvirons.)
0386:             */
0387:            public ScriptOrFnNode parse(Reader sourceReader, String sourceURI,
0388:                    int lineno) throws IOException {
0389:                this .sourceURI = sourceURI;
0390:                this .ts = new TokenStream(this , sourceReader, null, lineno);
0391:                return parse();
0392:            }
0393:
0394:            private ScriptOrFnNode parse() throws IOException {
0395:                this .decompiler = createDecompiler(compilerEnv);
0396:                this .nf = new IRFactory(this );
0397:                currentScriptOrFn = nf.createScript();
0398:                int sourceStartOffset = decompiler.getCurrentOffset();
0399:                // <netbeans>
0400:                int realSourceStartOffset = ts.getBufferOffset();
0401:                // </netbeans>
0402:                this .encodedSource = null;
0403:                decompiler.addToken(Token.SCRIPT);
0404:
0405:                this .currentFlaggedToken = Token.EOF;
0406:                this .syntaxErrorCount = 0;
0407:
0408:                int baseLineno = ts.getLineno(); // line number where source starts
0409:
0410:                /* so we have something to add nodes to until
0411:                 * we've collected all the source */
0412:                Node pn = nf.createLeaf(Token.BLOCK);
0413:
0414:                try {
0415:                    for (;;) {
0416:                        int tt = peekToken();
0417:
0418:                        if (tt <= Token.EOF) {
0419:                            break;
0420:                        }
0421:
0422:                        Node n;
0423:                        if (tt == Token.FUNCTION) {
0424:                            // <netbeans>
0425:                            int startOffset = peekedTokenStart;
0426:                            // </netbeans>
0427:                            consumeToken();
0428:                            try {
0429:                                n = function(calledByCompileFunction ? FunctionNode.FUNCTION_EXPRESSION
0430:                                        : FunctionNode.FUNCTION_STATEMENT);
0431:                                // <netbeans>
0432:                                setSourceOffsets(n, startOffset);
0433:                                // </netbeans>
0434:                            } catch (ParserException e) {
0435:                                break;
0436:                            }
0437:                        } else {
0438:                            n = statement();
0439:                        }
0440:                        nf.addChildToBack(pn, n);
0441:                    }
0442:                } catch (StackOverflowError ex) {
0443:                    String msg = ScriptRuntime
0444:                            .getMessage0("msg.too.deep.parser.recursion");
0445:                    throw Context.reportRuntimeError(msg, sourceURI, ts
0446:                            .getLineno(), null, 0);
0447:                }
0448:
0449:                if (this .syntaxErrorCount != 0) {
0450:                    String msg = String.valueOf(this .syntaxErrorCount);
0451:                    msg = ScriptRuntime.getMessage1("msg.got.syntax.errors",
0452:                            msg);
0453:                    // <netbeans>
0454:                    //throw errorReporter.runtimeError(msg, sourceURI, baseLineno,
0455:                    //                                 null, 0);
0456:                    // Don't show an error for this at all!
0457:                    //EvaluatorException exc = errorReporter.runtimeError(msg, sourceURI, baseLineno,
0458:                    //                                 null, 0);
0459:                    //if (exc != null) {
0460:                    //    throw exc;
0461:                    //} else {
0462:                    //                currentScriptOrFn.setSourceName(sourceURI);
0463:                    //                currentScriptOrFn.setBaseLineno(baseLineno);
0464:                    //                currentScriptOrFn.setEndLineno(ts.getLineno());
0465:                    //
0466:                    //                return currentScriptOrFn;
0467:                    return null;
0468:                    //}
0469:                    // </netbeans>
0470:                }
0471:
0472:                currentScriptOrFn.setSourceName(sourceURI);
0473:                currentScriptOrFn.setBaseLineno(baseLineno);
0474:                currentScriptOrFn.setEndLineno(ts.getLineno());
0475:
0476:                int sourceEndOffset = decompiler.getCurrentOffset();
0477:                currentScriptOrFn.setEncodedSourceBounds(sourceStartOffset,
0478:                        sourceEndOffset);
0479:                // <netbeans>
0480:                int realSourceEndOffset = getEndOffset();
0481:                currentScriptOrFn.setSourceBounds(realSourceStartOffset,
0482:                        realSourceEndOffset);
0483:                // </netbeans>
0484:
0485:                nf.initScript(currentScriptOrFn, pn);
0486:
0487:                if (compilerEnv.isGeneratingSource()) {
0488:                    encodedSource = decompiler.getEncodedSource();
0489:                }
0490:                this .decompiler = null; // It helps GC
0491:
0492:                return currentScriptOrFn;
0493:            }
0494:
0495:            /*
0496:             * The C version of this function takes an argument list,
0497:             * which doesn't seem to be needed for tree generation...
0498:             * it'd only be useful for checking argument hiding, which
0499:             * I'm not doing anyway...
0500:             */
0501:            private Node parseFunctionBody() throws IOException {
0502:                ++nestingOfFunction;
0503:                // <netbeans>
0504:                int startOffset = getStartOffset();
0505:                // </netbeans>
0506:                Node pn = nf.createBlock(ts.getLineno());
0507:                try {
0508:                    bodyLoop: for (;;) {
0509:                        Node n;
0510:                        int tt = peekToken();
0511:                        switch (tt) {
0512:                        case Token.ERROR:
0513:                        case Token.EOF:
0514:                        case Token.RC:
0515:                            break bodyLoop;
0516:
0517:                        case Token.FUNCTION:
0518:                            consumeToken();
0519:                            n = function(FunctionNode.FUNCTION_STATEMENT);
0520:                            break;
0521:                        default:
0522:                            n = statement();
0523:                            break;
0524:                        }
0525:                        nf.addChildToBack(pn, n);
0526:                    }
0527:                } catch (ParserException e) {
0528:                    // Ignore it
0529:                } finally {
0530:                    --nestingOfFunction;
0531:                }
0532:
0533:                // <netbeans>
0534:                //setSourceOffsets(pn, startOffset);
0535:                pn.setSourceBounds(startOffset, getEndOffset());
0536:                // </netbeans>
0537:                return pn;
0538:            }
0539:
0540:            private Node function(int functionType) throws IOException,
0541:                    ParserException {
0542:                int syntheticType = functionType;
0543:                int baseLineno = ts.getLineno(); // line number where source starts
0544:
0545:                int functionSourceStart = decompiler
0546:                        .markFunctionStart(functionType);
0547:                // <netbeans>
0548:                int realSourceStartOffset = getStartOffset();
0549:                int realSourceEndOffset = realSourceStartOffset;
0550:                Node funcNameNode = null;
0551:                // </netbeans>
0552:                String name;
0553:                Node memberExprNode = null;
0554:                if (matchToken(Token.NAME)) {
0555:                    name = ts.getString();
0556:                    // <netbeans>
0557:                    funcNameNode = Node.newString(Token.FUNCNAME, name);
0558:                    setSourceOffsets(funcNameNode, getStartOffset());
0559:                    // </netbeans>
0560:                    decompiler.addName(name);
0561:                    if (!matchToken(Token.LP)) {
0562:                        if (compilerEnv.isAllowMemberExprAsFunctionName()) {
0563:                            // Extension to ECMA: if 'function <name>' does not follow
0564:                            // by '(', assume <name> starts memberExpr
0565:                            Node memberExprHead = nf.createName(name);
0566:                            name = "";
0567:                            memberExprNode = memberExprTail(false,
0568:                                    memberExprHead);
0569:                        }
0570:                        mustMatchToken(Token.LP, "msg.no.paren.parms");
0571:                    }
0572:                } else if (matchToken(Token.LP)) {
0573:                    // Anonymous function
0574:                    name = "";
0575:                } else {
0576:                    name = "";
0577:                    if (compilerEnv.isAllowMemberExprAsFunctionName()) {
0578:                        // Note that memberExpr can not start with '(' like
0579:                        // in function (1+2).toString(), because 'function (' already
0580:                        // processed as anonymous function
0581:                        memberExprNode = memberExpr(false);
0582:                    }
0583:                    mustMatchToken(Token.LP, "msg.no.paren.parms");
0584:                }
0585:
0586:                if (memberExprNode != null) {
0587:                    syntheticType = FunctionNode.FUNCTION_EXPRESSION;
0588:                }
0589:
0590:                boolean nested = insideFunction();
0591:
0592:                FunctionNode fnNode = nf.createFunction(name);
0593:                // <netbeans>
0594:                // Add a special node for the function name with proper offsets etc.
0595:                // for IDE usage in refactoring, highlighting etc.
0596:                if (funcNameNode != null) {
0597:                    fnNode.addChildToFront(funcNameNode);
0598:                }
0599:                // </netbeans>
0600:
0601:                if (nested || nestingOfWith > 0) {
0602:                    // 1. Nested functions are not affected by the dynamic scope flag
0603:                    // as dynamic scope is already a parent of their scope.
0604:                    // 2. Functions defined under the with statement also immune to
0605:                    // this setup, in which case dynamic scope is ignored in favor
0606:                    // of with object.
0607:                    fnNode.itsIgnoreDynamicScope = true;
0608:                }
0609:
0610:                int functionIndex = currentScriptOrFn.addFunction(fnNode);
0611:
0612:                int functionSourceEnd;
0613:
0614:                ScriptOrFnNode savedScriptOrFn = currentScriptOrFn;
0615:                currentScriptOrFn = fnNode;
0616:                int savedNestingOfWith = nestingOfWith;
0617:                nestingOfWith = 0;
0618:                Hashtable savedLabelSet = labelSet;
0619:                labelSet = null;
0620:                ObjArray savedLoopSet = loopSet;
0621:                loopSet = null;
0622:                ObjArray savedLoopAndSwitchSet = loopAndSwitchSet;
0623:                loopAndSwitchSet = null;
0624:                boolean savedHasReturnValue = hasReturnValue;
0625:                int savedFunctionEndFlags = functionEndFlags;
0626:
0627:                Node body;
0628:                try {
0629:                    decompiler.addToken(Token.LP);
0630:                    if (!matchToken(Token.RP)) {
0631:                        boolean first = true;
0632:                        do {
0633:                            if (!first)
0634:                                decompiler.addToken(Token.COMMA);
0635:                            first = false;
0636:                            mustMatchToken(Token.NAME, "msg.no.parm");
0637:                            String s = ts.getString();
0638:                            // <netbeans>
0639:                            Node paramNode = Node.newString(Token.PARAMETER, s);
0640:                            setSourceOffsets(paramNode, getStartOffset());
0641:                            fnNode.addChildToBack(paramNode);
0642:                            // </netbeans>
0643:                            if (fnNode.hasParamOrVar(s)) {
0644:                                addWarning("msg.dup.parms", s
0645:                                // <netbeans> - pass in additional parameters for the error
0646:                                        , paramNode
0647:                                // </netbeans>
0648:                                );
0649:                            }
0650:                            fnNode.addParam(s);
0651:                            decompiler.addName(s);
0652:                        } while (matchToken(Token.COMMA));
0653:
0654:                        mustMatchToken(Token.RP, "msg.no.paren.after.parms");
0655:                    }
0656:                    decompiler.addToken(Token.RP);
0657:
0658:                    mustMatchToken(Token.LC, "msg.no.brace.body");
0659:                    decompiler.addEOL(Token.LC);
0660:                    body = parseFunctionBody();
0661:                    mustMatchToken(Token.RC, "msg.no.brace.after.body");
0662:
0663:                    if (compilerEnv.isStrictMode()
0664:                            && !body.hasConsistentReturnUsage()) {
0665:                        String msg = name.length() > 0 ? "msg.no.return.value"
0666:                                : "msg.anon.no.return.value";
0667:                        addStrictWarning(msg, name
0668:                        // <netbeans> - pass in additional parameters for the error
0669:                                , fnNode
0670:                        // </netbeans>
0671:                        );
0672:                    }
0673:
0674:                    decompiler.addToken(Token.RC);
0675:                    functionSourceEnd = decompiler
0676:                            .markFunctionEnd(functionSourceStart);
0677:                    // <netbeans>
0678:                    realSourceEndOffset = getEndOffset();
0679:                    // </netbeans>
0680:
0681:                    if (functionType != FunctionNode.FUNCTION_EXPRESSION) {
0682:                        // Add EOL only if function is not part of expression
0683:                        // since it gets SEMI + EOL from Statement in that case
0684:                        decompiler.addToken(Token.EOL);
0685:                    }
0686:                } finally {
0687:                    hasReturnValue = savedHasReturnValue;
0688:                    functionEndFlags = savedFunctionEndFlags;
0689:                    loopAndSwitchSet = savedLoopAndSwitchSet;
0690:                    loopSet = savedLoopSet;
0691:                    labelSet = savedLabelSet;
0692:                    nestingOfWith = savedNestingOfWith;
0693:                    currentScriptOrFn = savedScriptOrFn;
0694:                }
0695:
0696:                fnNode.setEncodedSourceBounds(functionSourceStart,
0697:                        functionSourceEnd);
0698:                fnNode.setSourceName(sourceURI);
0699:                fnNode.setBaseLineno(baseLineno);
0700:                fnNode.setEndLineno(ts.getLineno());
0701:                // <netbeans>
0702:                fnNode.setSourceBounds(realSourceStartOffset,
0703:                        realSourceEndOffset);
0704:                // </netbeans>
0705:
0706:                if (name != null) {
0707:                    int index = currentScriptOrFn.getParamOrVarIndex(name);
0708:                    if (index >= 0 && index < currentScriptOrFn.getParamCount()) {
0709:                        // Find the parameter node of the given index
0710:                        Node n = fnNode.getFirstChild();
0711:                        for (int i = 0; i < index && n != null;) {
0712:                            if (n.getType() == Token.PARAMETER) {
0713:                                i++;
0714:                                if (i == index) {
0715:                                    break;
0716:                                }
0717:                            }
0718:                            n = n.getParentNode();
0719:                        }
0720:                        addStrictWarning("msg.var.hides.arg", name
0721:                        // <netbeans> - pass in additional parameters for the error
0722:                                , n
0723:                        // </netbeans>
0724:                        );
0725:                    }
0726:                }
0727:
0728:                Node pn = nf.initFunction(fnNode, functionIndex, body,
0729:                        syntheticType);
0730:                if (memberExprNode != null) {
0731:                    // <netbeans>
0732:                    // TODO - how should I update the pn offsets based on this?
0733:                    // </netbeans>
0734:                    pn = nf.createAssignment(Token.ASSIGN, memberExprNode, pn);
0735:                    if (functionType != FunctionNode.FUNCTION_EXPRESSION) {
0736:                        // XXX check JScript behavior: should it be createExprStatement?
0737:                        pn = nf.createExprStatementNoReturn(pn, baseLineno);
0738:                    }
0739:                }
0740:
0741:                // <netbeans>
0742:                // TODO - how does memberExprNode deal with this?
0743:                pn.setSourceBounds(fnNode.getSourceStart(), fnNode
0744:                        .getSourceEnd());
0745:                // </netbeans>
0746:                return pn;
0747:            }
0748:
0749:            private Node statements() throws IOException {
0750:                // <netbeans>
0751:                int startOffset = getStartOffset();
0752:                // </netbeans>
0753:                Node pn = nf.createBlock(ts.getLineno());
0754:
0755:                int tt;
0756:                while ((tt = peekToken()) > Token.EOF && tt != Token.RC) {
0757:                    nf.addChildToBack(pn, statement());
0758:                }
0759:
0760:                // <netbeans>
0761:                setSourceOffsets(pn, startOffset);
0762:                // </netbeans>
0763:
0764:                return pn;
0765:            }
0766:
0767:            private Node condition() throws IOException, ParserException {
0768:                mustMatchToken(Token.LP, "msg.no.paren.cond");
0769:
0770:                decompiler.addToken(Token.LP);
0771:                // <netbeans>
0772:                // NOTE - the END offset is AFTER the left parenthesis! We don't 
0773:                // want to include it since we're not creating a node wrapping the
0774:                // parens!
0775:                int startOffset = getEndOffset();
0776:                // </netbeans>
0777:                Node pn = expr(false);
0778:                // <netbeans>
0779:                int endOffset = getEndOffset();
0780:                pn.setSourceBounds(startOffset, endOffset);
0781:                // </netbeans>
0782:                mustMatchToken(Token.RP, "msg.no.paren.after.cond");
0783:                decompiler.addToken(Token.RP);
0784:
0785:                // Report strict warning on code like "if (a = 7) ...". Suppress the
0786:                // warning if the condition is parenthesized, like "if ((a = 7)) ...".
0787:                if (pn.getProp(Node.PARENTHESIZED_PROP) == null
0788:                        && (pn.getType() == Token.SETNAME
0789:                                || pn.getType() == Token.SETPROP || pn
0790:                                .getType() == Token.SETELEM)) {
0791:                    addStrictWarning("msg.equal.as.assign", ""
0792:                    // <netbeans> - pass in additional parameters for the error
0793:                            , pn
0794:                    // </netbeans>
0795:                    );
0796:                }
0797:
0798:                return pn;
0799:            }
0800:
0801:            // match a NAME; return null if no match.
0802:            private Node matchJumpLabelName() throws IOException,
0803:                    ParserException {
0804:                // TODO - handle positions here?        
0805:                Node label = null;
0806:
0807:                int tt = peekTokenOrEOL();
0808:                if (tt == Token.NAME) {
0809:                    consumeToken();
0810:                    String name = ts.getString();
0811:                    decompiler.addName(name);
0812:                    if (labelSet != null) {
0813:                        label = (Node) labelSet.get(name);
0814:                    }
0815:                    if (label == null) {
0816:                        reportError("msg.undef.label");
0817:                    }
0818:                }
0819:
0820:                return label;
0821:            }
0822:
0823:            private Node statement() throws IOException {
0824:                // <netbeans>
0825:                int startOffset = getStartOffset();
0826:                // </netbeans>
0827:                try {
0828:                    Node pn = statementHelper(null);
0829:                    if (pn != null) {
0830:                        if (compilerEnv.isStrictMode() && !pn.hasSideEffects())
0831:                            addStrictWarning("msg.no.side.effects", ""
0832:                            // <netbeans> - pass in additional parameters for the error
0833:                                    , pn
0834:                            // </netbeans>
0835:                            );
0836:                        return pn;
0837:                    }
0838:                } catch (ParserException e) {
0839:                }
0840:
0841:                // skip to end of statement
0842:                int lineno = ts.getLineno();
0843:                guessingStatementEnd: for (;;) {
0844:                    int tt = peekTokenOrEOL();
0845:                    consumeToken();
0846:                    switch (tt) {
0847:                    case Token.ERROR:
0848:                    case Token.EOF:
0849:                    case Token.EOL:
0850:                    case Token.SEMI:
0851:                        break guessingStatementEnd;
0852:                    }
0853:                }
0854:                // <netbeans>
0855:                //return nf.createExprStatement(nf.createName("error"), lineno);
0856:                return setSourceOffsets(nf.createExprStatement(nf
0857:                        .createName("error"), lineno), startOffset);
0858:                // </netbeans>
0859:            }
0860:
0861:            /**
0862:             * Whether the "catch (e: e instanceof Exception) { ... }" syntax
0863:             * is implemented.
0864:             */
0865:
0866:            private Node statementHelper(Node statementLabel)
0867:                    throws IOException, ParserException {
0868:                Node pn = null;
0869:
0870:                int tt;
0871:
0872:                tt = peekToken();
0873:
0874:                // <netbeans>
0875:                int startOffset = peekedTokenStart;
0876:                // </netbeans>
0877:
0878:                switch (tt) {
0879:                case Token.IF: {
0880:                    consumeToken();
0881:
0882:                    decompiler.addToken(Token.IF);
0883:                    int lineno = ts.getLineno();
0884:                    Node cond = condition();
0885:                    decompiler.addEOL(Token.LC);
0886:                    Node ifTrue = statement();
0887:                    Node ifFalse = null;
0888:                    if (matchToken(Token.ELSE)) {
0889:                        decompiler.addToken(Token.RC);
0890:                        decompiler.addToken(Token.ELSE);
0891:                        decompiler.addEOL(Token.LC);
0892:                        ifFalse = statement();
0893:                    }
0894:                    decompiler.addEOL(Token.RC);
0895:                    pn = nf.createIf(cond, ifTrue, ifFalse, lineno);
0896:                    // <netbeans>
0897:                    pn.setSourceBounds(startOffset, getEndOffset());
0898:                    // </netbeans>
0899:                    return pn;
0900:                }
0901:
0902:                case Token.SWITCH: {
0903:                    consumeToken();
0904:
0905:                    decompiler.addToken(Token.SWITCH);
0906:                    int lineno = ts.getLineno();
0907:                    mustMatchToken(Token.LP, "msg.no.paren.switch");
0908:                    decompiler.addToken(Token.LP);
0909:                    pn = enterSwitch(expr(false), lineno);
0910:                    try {
0911:                        mustMatchToken(Token.RP, "msg.no.paren.after.switch");
0912:                        decompiler.addToken(Token.RP);
0913:                        mustMatchToken(Token.LC, "msg.no.brace.switch");
0914:                        decompiler.addEOL(Token.LC);
0915:
0916:                        boolean hasDefault = false;
0917:                        switchLoop: for (;;) {
0918:                            tt = nextToken();
0919:                            Node caseExpression;
0920:                            switch (tt) {
0921:                            case Token.RC:
0922:                                break switchLoop;
0923:
0924:                            case Token.CASE:
0925:                                decompiler.addToken(Token.CASE);
0926:                                caseExpression = expr(false);
0927:                                mustMatchToken(Token.COLON, "msg.no.colon.case");
0928:                                decompiler.addEOL(Token.COLON);
0929:                                break;
0930:
0931:                            case Token.DEFAULT:
0932:                                if (hasDefault) {
0933:                                    reportError("msg.double.switch.default");
0934:                                }
0935:                                decompiler.addToken(Token.DEFAULT);
0936:                                hasDefault = true;
0937:                                caseExpression = null;
0938:                                mustMatchToken(Token.COLON, "msg.no.colon.case");
0939:                                decompiler.addEOL(Token.COLON);
0940:                                break;
0941:
0942:                            default:
0943:                                reportError("msg.bad.switch");
0944:                                break switchLoop;
0945:                            }
0946:
0947:                            Node block = nf.createLeaf(Token.BLOCK);
0948:                            // <netbeans>
0949:                            int blockStart = getStartOffset();
0950:                            pn.setSourceBounds(blockStart, blockStart);
0951:                            // </netbeans>
0952:
0953:                            while ((tt = peekToken()) != Token.RC
0954:                                    && tt != Token.CASE && tt != Token.DEFAULT
0955:                                    && tt != Token.EOF) {
0956:                                nf.addChildToBack(block, statement());
0957:                            }
0958:
0959:                            // caseExpression == null => add default lable
0960:                            nf.addSwitchCase(pn, caseExpression, block);
0961:                        }
0962:                        decompiler.addEOL(Token.RC);
0963:                        nf.closeSwitch(pn);
0964:                    } finally {
0965:                        exitSwitch();
0966:                    }
0967:                    // <netbeans>
0968:                    setSourceOffsets(pn, startOffset);
0969:                    // </netbeans>
0970:                    return pn;
0971:                }
0972:
0973:                case Token.WHILE: {
0974:                    consumeToken();
0975:                    decompiler.addToken(Token.WHILE);
0976:
0977:                    Node loop = enterLoop(statementLabel);
0978:                    try {
0979:                        Node cond = condition();
0980:                        decompiler.addEOL(Token.LC);
0981:                        Node body = statement();
0982:                        decompiler.addEOL(Token.RC);
0983:                        pn = nf.createWhile(loop, cond, body);
0984:                        // <netbeans>
0985:                        setSourceOffsets(pn, startOffset);
0986:                        // </netbeans>
0987:                    } finally {
0988:                        exitLoop();
0989:                    }
0990:                    return pn;
0991:                }
0992:
0993:                case Token.DO: {
0994:                    consumeToken();
0995:                    decompiler.addToken(Token.DO);
0996:                    decompiler.addEOL(Token.LC);
0997:
0998:                    Node loop = enterLoop(statementLabel);
0999:                    try {
1000:                        Node body = statement();
1001:                        decompiler.addToken(Token.RC);
1002:                        mustMatchToken(Token.WHILE, "msg.no.while.do");
1003:                        decompiler.addToken(Token.WHILE);
1004:                        Node cond = condition();
1005:                        pn = nf.createDoWhile(loop, body, cond);
1006:                    } finally {
1007:                        exitLoop();
1008:                    }
1009:                    // Always auto-insert semicon to follow SpiderMonkey:
1010:                    // It is required by EMAScript but is ignored by the rest of
1011:                    // world, see bug 238945
1012:                    matchToken(Token.SEMI);
1013:                    decompiler.addEOL(Token.SEMI);
1014:                    // <netbeans>
1015:                    setSourceOffsets(pn, startOffset);
1016:                    // </netbeans>
1017:                    return pn;
1018:                }
1019:
1020:                case Token.FOR: {
1021:                    consumeToken();
1022:                    boolean isForEach = false;
1023:                    decompiler.addToken(Token.FOR);
1024:
1025:                    Node loop = enterLoop(statementLabel);
1026:                    try {
1027:
1028:                        Node init; // Node init is also foo in 'foo in Object'
1029:                        Node cond; // Node cond is also object in 'foo in Object'
1030:                        Node incr = null; // to kill warning
1031:                        Node body;
1032:
1033:                        // See if this is a for each () instead of just a for ()
1034:                        if (matchToken(Token.NAME)) {
1035:                            decompiler.addName(ts.getString());
1036:                            if (ts.getString().equals("each")) {
1037:                                isForEach = true;
1038:                            } else {
1039:                                reportError("msg.no.paren.for");
1040:                            }
1041:                        }
1042:
1043:                        mustMatchToken(Token.LP, "msg.no.paren.for");
1044:                        decompiler.addToken(Token.LP);
1045:                        // <netbeans>
1046:                        int realSourceStartOffset = getStartOffset();
1047:                        // </netbeans>
1048:                        tt = peekToken();
1049:                        if (tt == Token.SEMI) {
1050:                            init = nf.createLeaf(Token.EMPTY);
1051:                        } else {
1052:                            if (tt == Token.VAR) {
1053:                                // set init to a var list or initial
1054:                                consumeToken(); // consume the 'var' token
1055:                                init = variables(Token.FOR);
1056:                                // <netbeans>
1057:                                // TODO - This isn't right, there could be MULTIPLE variables... they should
1058:                                // all be marked somehow
1059:                                int realSourceEndOffset = getEndOffset();
1060:                                init.setSourceBounds(realSourceStartOffset,
1061:                                        realSourceEndOffset);
1062:                                // </netbeans>
1063:                            } else {
1064:                                init = expr(true);
1065:                            }
1066:                        }
1067:
1068:                        if (matchToken(Token.IN)) {
1069:                            decompiler.addToken(Token.IN);
1070:                            // 'cond' is the object over which we're iterating
1071:                            cond = expr(false);
1072:                        } else { // ordinary for loop
1073:                            mustMatchToken(Token.SEMI, "msg.no.semi.for");
1074:                            decompiler.addToken(Token.SEMI);
1075:                            if (peekToken() == Token.SEMI) {
1076:                                // no loop condition
1077:                                // TODO - position?                        
1078:                                cond = nf.createLeaf(Token.EMPTY);
1079:                            } else {
1080:                                cond = expr(false);
1081:                            }
1082:
1083:                            mustMatchToken(Token.SEMI, "msg.no.semi.for.cond");
1084:                            decompiler.addToken(Token.SEMI);
1085:                            if (peekToken() == Token.RP) {
1086:                                incr = nf.createLeaf(Token.EMPTY);
1087:                                // TODO Position?
1088:                            } else {
1089:                                incr = expr(false);
1090:                            }
1091:                        }
1092:
1093:                        mustMatchToken(Token.RP, "msg.no.paren.for.ctrl");
1094:                        decompiler.addToken(Token.RP);
1095:                        decompiler.addEOL(Token.LC);
1096:                        body = statement();
1097:                        decompiler.addEOL(Token.RC);
1098:
1099:                        if (incr == null) {
1100:                            // cond could be null if 'in obj' got eaten
1101:                            // by the init node.
1102:                            pn = nf.createForIn(loop, init, cond, body,
1103:                                    isForEach);
1104:                        } else {
1105:                            pn = nf.createFor(loop, init, cond, incr, body);
1106:                        }
1107:                    } finally {
1108:                        exitLoop();
1109:                    }
1110:                    // <netbeans>
1111:                    setSourceOffsets(pn, startOffset);
1112:                    // </netbeans>
1113:                    return pn;
1114:                }
1115:
1116:                case Token.TRY: {
1117:                    consumeToken();
1118:                    int lineno = ts.getLineno();
1119:
1120:                    Node tryblock;
1121:                    Node catchblocks = null;
1122:                    Node finallyblock = null;
1123:
1124:                    decompiler.addToken(Token.TRY);
1125:                    decompiler.addEOL(Token.LC);
1126:                    tryblock = statement();
1127:                    decompiler.addEOL(Token.RC);
1128:
1129:                    catchblocks = nf.createLeaf(Token.BLOCK);
1130:
1131:                    boolean sawDefaultCatch = false;
1132:                    int peek = peekToken();
1133:                    if (peek == Token.CATCH) {
1134:                        while (matchToken(Token.CATCH)) {
1135:                            if (sawDefaultCatch) {
1136:                                reportError("msg.catch.unreachable");
1137:                            }
1138:                            decompiler.addToken(Token.CATCH);
1139:                            mustMatchToken(Token.LP, "msg.no.paren.catch");
1140:                            decompiler.addToken(Token.LP);
1141:
1142:                            mustMatchToken(Token.NAME, "msg.bad.catchcond");
1143:                            // <netbeans>
1144:                            int varStart = getStartOffset();
1145:                            int varEnd = matchedTokenEnd;
1146:                            // </netbeans>
1147:                            String varName = ts.getString();
1148:                            decompiler.addName(varName);
1149:
1150:                            Node catchCond = null;
1151:                            if (matchToken(Token.IF)) {
1152:                                decompiler.addToken(Token.IF);
1153:                                catchCond = expr(false);
1154:                            } else {
1155:                                sawDefaultCatch = true;
1156:                            }
1157:
1158:                            mustMatchToken(Token.RP, "msg.bad.catchcond");
1159:                            decompiler.addToken(Token.RP);
1160:                            mustMatchToken(Token.LC, "msg.no.brace.catchblock");
1161:                            decompiler.addEOL(Token.LC);
1162:
1163:                            // <netbeans>
1164:                            catchblocks.setSourceBounds(startOffset,
1165:                                    getEndOffset());
1166:                            // </netbeans>
1167:                            nf.addChildToBack(catchblocks, nf.createCatch(
1168:                                    varName, catchCond, statements(), ts
1169:                                            .getLineno()));
1170:                            // <netbeans>
1171:                            Node varNode = catchblocks.getLastChild()
1172:                                    .getFirstChild();
1173:                            varNode.setSourceBounds(varStart, varEnd);
1174:                            // </netbeans>
1175:
1176:                            mustMatchToken(Token.RC, "msg.no.brace.after.body");
1177:                            decompiler.addEOL(Token.RC);
1178:                        }
1179:                    } else if (peek != Token.FINALLY) {
1180:                        mustMatchToken(Token.FINALLY, "msg.try.no.catchfinally");
1181:                    }
1182:
1183:                    if (matchToken(Token.FINALLY)) {
1184:                        decompiler.addToken(Token.FINALLY);
1185:                        decompiler.addEOL(Token.LC);
1186:                        finallyblock = statement();
1187:                        decompiler.addEOL(Token.RC);
1188:                    }
1189:
1190:                    pn = nf.createTryCatchFinally(tryblock, catchblocks,
1191:                            finallyblock, lineno);
1192:
1193:                    // <netbeans>
1194:                    setSourceOffsets(pn, startOffset);
1195:                    // </netbeans>
1196:                    return pn;
1197:                }
1198:
1199:                case Token.THROW: {
1200:                    consumeToken();
1201:                    if (peekTokenOrEOL() == Token.EOL) {
1202:                        // ECMAScript does not allow new lines before throw expression,
1203:                        // see bug 256617
1204:                        reportError("msg.bad.throw.eol");
1205:                    }
1206:
1207:                    int lineno = ts.getLineno();
1208:                    decompiler.addToken(Token.THROW);
1209:                    pn = nf.createThrow(expr(false), lineno);
1210:                    // <netbeans>
1211:                    pn.setSourceBounds(startOffset, getEndOffset());
1212:                    // </netbeans>
1213:                    break;
1214:                }
1215:
1216:                case Token.BREAK: {
1217:                    consumeToken();
1218:                    int lineno = ts.getLineno();
1219:
1220:                    decompiler.addToken(Token.BREAK);
1221:
1222:                    // matchJumpLabelName only matches if there is one
1223:                    Node breakStatement = matchJumpLabelName();
1224:                    if (breakStatement == null) {
1225:                        if (loopAndSwitchSet == null
1226:                                || loopAndSwitchSet.size() == 0) {
1227:                            reportError("msg.bad.break");
1228:                            return null;
1229:                        }
1230:                        breakStatement = (Node) loopAndSwitchSet.peek();
1231:                    }
1232:                    pn = nf.createBreak(breakStatement, lineno);
1233:                    // <netbeans>
1234:                    setSourceOffsets(pn, startOffset);
1235:                    // </netbeans>
1236:                    break;
1237:                }
1238:
1239:                case Token.CONTINUE: {
1240:                    consumeToken();
1241:                    int lineno = ts.getLineno();
1242:
1243:                    decompiler.addToken(Token.CONTINUE);
1244:
1245:                    Node loop;
1246:                    // matchJumpLabelName only matches if there is one
1247:                    Node label = matchJumpLabelName();
1248:                    if (label == null) {
1249:                        if (loopSet == null || loopSet.size() == 0) {
1250:                            reportError("msg.continue.outside");
1251:                            return null;
1252:                        }
1253:                        loop = (Node) loopSet.peek();
1254:                    } else {
1255:                        loop = nf.getLabelLoop(label);
1256:                        if (loop == null) {
1257:                            reportError("msg.continue.nonloop");
1258:                            return null;
1259:                        }
1260:                    }
1261:                    pn = nf.createContinue(loop, lineno);
1262:                    // <netbeans>
1263:                    setSourceOffsets(pn, startOffset);
1264:                    // </netbeans>
1265:                    break;
1266:                }
1267:
1268:                case Token.WITH: {
1269:                    consumeToken();
1270:
1271:                    decompiler.addToken(Token.WITH);
1272:                    int lineno = ts.getLineno();
1273:                    mustMatchToken(Token.LP, "msg.no.paren.with");
1274:                    decompiler.addToken(Token.LP);
1275:                    Node obj = expr(false);
1276:                    mustMatchToken(Token.RP, "msg.no.paren.after.with");
1277:                    decompiler.addToken(Token.RP);
1278:                    decompiler.addEOL(Token.LC);
1279:
1280:                    ++nestingOfWith;
1281:                    Node body;
1282:                    try {
1283:                        body = statement();
1284:                    } finally {
1285:                        --nestingOfWith;
1286:                    }
1287:
1288:                    decompiler.addEOL(Token.RC);
1289:
1290:                    pn = nf.createWith(obj, body, lineno);
1291:                    // <netbeans>
1292:                    setSourceOffsets(pn, startOffset);
1293:                    // </netbeans>
1294:                    return pn;
1295:                }
1296:
1297:                case Token.CONST:
1298:                case Token.VAR: {
1299:                    consumeToken();
1300:                    pn = variables(tt);
1301:                    // <netbeans>
1302:                    setSourceOffsets(pn, startOffset);
1303:                    // </netbeans>
1304:                    break;
1305:                }
1306:
1307:                case Token.RETURN: {
1308:                    if (!insideFunction()) {
1309:                        reportError("msg.bad.return");
1310:                    }
1311:                    consumeToken();
1312:                    decompiler.addToken(Token.RETURN);
1313:                    int lineno = ts.getLineno();
1314:
1315:                    Node retExpr;
1316:                    /* This is ugly, but we don't want to require a semicolon. */
1317:                    tt = peekTokenOrEOL();
1318:                    switch (tt) {
1319:                    case Token.SEMI:
1320:                    case Token.RC:
1321:                    case Token.EOF:
1322:                    case Token.EOL:
1323:                    case Token.ERROR:
1324:                        retExpr = null;
1325:                        break;
1326:                    default:
1327:                        retExpr = expr(false);
1328:                        hasReturnValue = true;
1329:                    }
1330:                    pn = nf.createReturn(retExpr, lineno);
1331:                    // <netbeans>
1332:                    pn.setSourceBounds(startOffset, getEndOffset());
1333:                    // </netbeans>
1334:
1335:                    // see if we need a strict mode warning
1336:                    if (retExpr == null) {
1337:                        if (functionEndFlags == Node.END_RETURNS_VALUE)
1338:                            addStrictWarning("msg.return.inconsistent", ""
1339:                            // <netbeans> - pass in additional parameters for the error
1340:                                    , pn
1341:                            // </netbeans>
1342:                            );
1343:
1344:                        functionEndFlags |= Node.END_RETURNS;
1345:                    } else {
1346:                        if (functionEndFlags == Node.END_RETURNS)
1347:                            addStrictWarning("msg.return.inconsistent", ""
1348:                            // <netbeans> - pass in additional parameters for the error
1349:                                    , pn
1350:                            // </netbeans>
1351:                            );
1352:
1353:                        functionEndFlags |= Node.END_RETURNS_VALUE;
1354:                    }
1355:
1356:                    break;
1357:                }
1358:
1359:                case Token.LC:
1360:                    consumeToken();
1361:                    if (statementLabel != null) {
1362:                        decompiler.addToken(Token.LC);
1363:                    }
1364:                    pn = statements();
1365:                    mustMatchToken(Token.RC, "msg.no.brace.block");
1366:                    if (statementLabel != null) {
1367:                        decompiler.addEOL(Token.RC);
1368:                    }
1369:                    // <netbeans>
1370:                    pn.setSourceBounds(startOffset, getEndOffset());
1371:                    // </netbeans>
1372:                    return pn;
1373:
1374:                case Token.ERROR:
1375:                    // Fall thru, to have a node for error recovery to work on
1376:                case Token.SEMI:
1377:                    consumeToken();
1378:                    pn = nf.createLeaf(Token.EMPTY);
1379:                    return pn;
1380:
1381:                case Token.FUNCTION: {
1382:                    consumeToken();
1383:                    pn = function(FunctionNode.FUNCTION_EXPRESSION_STATEMENT);
1384:                    // <netbeans>
1385:                    setSourceOffsets(pn, startOffset);
1386:                    // </netbeans>
1387:                    return pn;
1388:                }
1389:
1390:                case Token.DEFAULT:
1391:                    consumeToken();
1392:                    mustHaveXML();
1393:
1394:                    decompiler.addToken(Token.DEFAULT);
1395:                    int nsLine = ts.getLineno();
1396:
1397:                    if (!(matchToken(Token.NAME) && ts.getString()
1398:                            .equals("xml"))) {
1399:                        reportError("msg.bad.namespace");
1400:                    }
1401:                    decompiler.addName(" xml");
1402:
1403:                    if (!(matchToken(Token.NAME) && ts.getString().equals(
1404:                            "namespace"))) {
1405:                        reportError("msg.bad.namespace");
1406:                    }
1407:                    decompiler.addName(" namespace");
1408:
1409:                    if (!matchToken(Token.ASSIGN)) {
1410:                        reportError("msg.bad.namespace");
1411:                    }
1412:                    decompiler.addToken(Token.ASSIGN);
1413:
1414:                    Node expr = expr(false);
1415:                    pn = nf.createDefaultNamespace(expr, nsLine);
1416:                    // <netbeans>
1417:                    setSourceOffsets(pn, startOffset);
1418:                    // </netbeans>
1419:                    break;
1420:
1421:                case Token.NAME: {
1422:                    int lineno = ts.getLineno();
1423:                    String name = ts.getString();
1424:                    setCheckForLabel();
1425:                    pn = expr(false);
1426:                    if (pn.getType() != Token.LABEL) {
1427:                        pn = nf.createExprStatement(pn, lineno);
1428:                    } else {
1429:                        // Parsed the label: push back token should be
1430:                        // colon that primaryExpr left untouched.
1431:                        if (peekToken() != Token.COLON)
1432:                            Kit.codeBug();
1433:                        consumeToken();
1434:                        // depend on decompiling lookahead to guess that that
1435:                        // last name was a label.
1436:                        decompiler.addName(name);
1437:                        decompiler.addEOL(Token.COLON);
1438:
1439:                        if (labelSet == null) {
1440:                            labelSet = new Hashtable();
1441:                        } else if (labelSet.containsKey(name)) {
1442:                            reportError("msg.dup.label");
1443:                        }
1444:
1445:                        boolean firstLabel;
1446:                        if (statementLabel == null) {
1447:                            firstLabel = true;
1448:                            statementLabel = pn;
1449:                        } else {
1450:                            // Discard multiple label nodes and use only
1451:                            // the first: it allows to simplify IRFactory
1452:                            firstLabel = false;
1453:                        }
1454:                        labelSet.put(name, statementLabel);
1455:                        try {
1456:                            pn = statementHelper(statementLabel);
1457:                        } finally {
1458:                            labelSet.remove(name);
1459:                        }
1460:                        if (firstLabel) {
1461:                            pn = nf.createLabeledStatement(statementLabel, pn);
1462:                        }
1463:                        // <netbeans>
1464:                        setSourceOffsets(pn, startOffset);
1465:                        // </netbeans>
1466:                        return pn;
1467:                    }
1468:                    // <netbeans>
1469:                    setSourceOffsets(pn, startOffset);
1470:                    // </netbeans>
1471:                    break;
1472:                }
1473:
1474:                default: {
1475:                    int lineno = ts.getLineno();
1476:                    pn = expr(false);
1477:                    pn = nf.createExprStatement(pn, lineno);
1478:                    // <netbeans>
1479:                    setSourceOffsets(pn, startOffset);
1480:                    // </netbeans>
1481:                    break;
1482:                }
1483:                }
1484:
1485:                int ttFlagged = peekFlaggedToken();
1486:                switch (ttFlagged & CLEAR_TI_MASK) {
1487:                case Token.SEMI:
1488:                    // Consume ';' as a part of expression
1489:                    consumeToken();
1490:                    break;
1491:                case Token.ERROR:
1492:                case Token.EOF:
1493:                case Token.RC:
1494:                    // Autoinsert ;
1495:                    break;
1496:                default:
1497:                    if ((ttFlagged & TI_AFTER_EOL) == 0) {
1498:                        // Report error if no EOL or autoinsert ; otherwise
1499:                        reportError("msg.no.semi.stmt");
1500:                    }
1501:                    break;
1502:                }
1503:                decompiler.addEOL(Token.SEMI);
1504:
1505:                // <netbeans>
1506:                setSourceOffsets(pn, startOffset);
1507:                // </netbeans>
1508:
1509:                return pn;
1510:            }
1511:
1512:            /**
1513:             * Parse a 'var' or 'const' statement, or a 'var' init list in a for
1514:             * statement.
1515:             * @param context A token value: either VAR, CONST or FOR depending on
1516:             * context.
1517:             * @return The parsed statement
1518:             * @throws IOException
1519:             * @throws ParserException
1520:             */
1521:            private Node variables(int context) throws IOException,
1522:                    ParserException {
1523:                // <netbeans>
1524:                int startOffset = getStartOffset();
1525:                // </netbeans>
1526:
1527:                Node pn;
1528:                boolean first = true;
1529:
1530:                if (context == Token.CONST) {
1531:                    pn = nf.createVariables(Token.CONST, ts.getLineno());
1532:                    decompiler.addToken(Token.CONST);
1533:                } else {
1534:                    pn = nf.createVariables(Token.VAR, ts.getLineno());
1535:                    decompiler.addToken(Token.VAR);
1536:                }
1537:
1538:                for (;;) {
1539:                    Node name;
1540:                    Node init;
1541:                    mustMatchToken(Token.NAME, "msg.bad.var");
1542:                    // <netbeans>
1543:                    int nameStartOffset = getStartOffset();
1544:                    // </netbeans>
1545:                    String s = ts.getString();
1546:
1547:                    if (!first)
1548:                        decompiler.addToken(Token.COMMA);
1549:                    first = false;
1550:
1551:                    decompiler.addName(s);
1552:
1553:                    // <netbeans>
1554:                    name = nf.createName(s);
1555:                    // </netbeans>
1556:                    if (context == Token.CONST) {
1557:                        if (!currentScriptOrFn.addConst(s)) {
1558:                            // We know it's already defined, since addConst passes if
1559:                            // it's not defined at all.  The addVar call just confirms
1560:                            // what it is.
1561:                            if (currentScriptOrFn.addVar(s) != ScriptOrFnNode.DUPLICATE_CONST)
1562:                                addError("msg.var.redecl", s
1563:                                // <netbeans>
1564:                                        , name
1565:                                // </netbeans>
1566:                                );
1567:                            else
1568:                                addError("msg.const.redecl", s
1569:                                // <netbeans>
1570:                                        , name
1571:                                // </netbeans>
1572:                                );
1573:                        }
1574:                    } else {
1575:                        int dupState = currentScriptOrFn.addVar(s);
1576:                        if (dupState == ScriptOrFnNode.DUPLICATE_CONST)
1577:                            addError("msg.const.redecl", s
1578:                            // <netbeans>
1579:                                    , name
1580:                            // </netbeans>
1581:                            );
1582:                        else if (dupState == ScriptOrFnNode.DUPLICATE_PARAMETER)
1583:                            addStrictWarning("msg.var.hides.arg", s
1584:                            // <netbeans> - pass in additional parameters for the error
1585:                                    , name
1586:                            // </netbeans>
1587:                            );
1588:                        else if (dupState == ScriptOrFnNode.DUPLICATE_VAR)
1589:                            addStrictWarning("msg.var.redecl", s
1590:                            // <netbeans> - pass in additional parameters for the error
1591:                                    , name
1592:                            // </netbeans>
1593:                            );
1594:                    }
1595:                    // <netbeans>
1596:                    // Moved up before the if so we can pass it to the error handler
1597:                    //name = nf.createName(s);
1598:                    // </netbeans>
1599:
1600:                    // <netbeans>
1601:                    setSourceOffsets(name, nameStartOffset);
1602:                    // </netbeans>
1603:
1604:                    // omitted check for argument hiding
1605:
1606:                    if (matchToken(Token.ASSIGN)) {
1607:                        decompiler.addToken(Token.ASSIGN);
1608:
1609:                        init = assignExpr(context == Token.FOR);
1610:                        nf.addChildToBack(name, init);
1611:                    }
1612:                    nf.addChildToBack(pn, name);
1613:                    if (!matchToken(Token.COMMA))
1614:                        break;
1615:                }
1616:
1617:                // <netbeans>
1618:                pn.setSourceBounds(startOffset, getEndOffset());
1619:                // </netbeans>
1620:
1621:                return pn;
1622:            }
1623:
1624:            private Node expr(boolean inForInit) throws IOException,
1625:                    ParserException {
1626:                // <netbeans>
1627:                int startOffset = getStartOffset();
1628:                // </netbeans>
1629:
1630:                Node pn = assignExpr(inForInit);
1631:                while (matchToken(Token.COMMA)) {
1632:                    decompiler.addToken(Token.COMMA);
1633:                    if (compilerEnv.isStrictMode() && !pn.hasSideEffects())
1634:                        addStrictWarning("msg.no.side.effects", ""
1635:                        // <netbeans>
1636:                                , pn
1637:                        // </netbeans>
1638:                        );
1639:                    pn = nf
1640:                            .createBinary(Token.COMMA, pn,
1641:                                    assignExpr(inForInit));
1642:                }
1643:
1644:                // <netbeans>
1645:                setSourceOffsets(pn, startOffset);
1646:                // </netbeans>
1647:
1648:                return pn;
1649:            }
1650:
1651:            private Node assignExpr(boolean inForInit) throws IOException,
1652:                    ParserException {
1653:                // <netbeans>
1654:                int startOffset = getStartOffset();
1655:                // </netbeans>
1656:
1657:                Node pn = condExpr(inForInit);
1658:
1659:                int tt = peekToken();
1660:                if (Token.FIRST_ASSIGN <= tt && tt <= Token.LAST_ASSIGN) {
1661:                    consumeToken();
1662:                    decompiler.addToken(tt);
1663:                    pn = nf.createAssignment(tt, pn, assignExpr(inForInit));
1664:                }
1665:
1666:                // <netbeans>
1667:                setSourceOffsets(pn, startOffset);
1668:                // </netbeans>
1669:
1670:                return pn;
1671:            }
1672:
1673:            private Node condExpr(boolean inForInit) throws IOException,
1674:                    ParserException {
1675:                // <netbeans>
1676:                int startOffset = getStartOffset();
1677:                // </netbeans>
1678:
1679:                Node pn = orExpr(inForInit);
1680:
1681:                if (matchToken(Token.HOOK)) {
1682:                    decompiler.addToken(Token.HOOK);
1683:                    Node ifTrue = assignExpr(false);
1684:                    mustMatchToken(Token.COLON, "msg.no.colon.cond");
1685:                    decompiler.addToken(Token.COLON);
1686:                    Node ifFalse = assignExpr(inForInit);
1687:                    return nf.createCondExpr(pn, ifTrue, ifFalse);
1688:                }
1689:
1690:                // <netbeans>
1691:                setSourceOffsets(pn, startOffset);
1692:                // </netbeans>
1693:
1694:                return pn;
1695:            }
1696:
1697:            private Node orExpr(boolean inForInit) throws IOException,
1698:                    ParserException {
1699:                // <netbeans>
1700:                int startOffset = getStartOffset();
1701:                // </netbeans>
1702:
1703:                Node pn = andExpr(inForInit);
1704:                if (matchToken(Token.OR)) {
1705:                    decompiler.addToken(Token.OR);
1706:                    pn = nf.createBinary(Token.OR, pn, orExpr(inForInit));
1707:                }
1708:
1709:                // <netbeans>
1710:                setSourceOffsets(pn, startOffset);
1711:                // </netbeans>
1712:
1713:                return pn;
1714:            }
1715:
1716:            private Node andExpr(boolean inForInit) throws IOException,
1717:                    ParserException {
1718:                // <netbeans>
1719:                int startOffset = getStartOffset();
1720:                // </netbeans>
1721:
1722:                Node pn = bitOrExpr(inForInit);
1723:                if (matchToken(Token.AND)) {
1724:                    decompiler.addToken(Token.AND);
1725:                    pn = nf.createBinary(Token.AND, pn, andExpr(inForInit));
1726:                }
1727:
1728:                // <netbeans>
1729:                setSourceOffsets(pn, startOffset);
1730:                // </netbeans>
1731:
1732:                return pn;
1733:            }
1734:
1735:            private Node bitOrExpr(boolean inForInit) throws IOException,
1736:                    ParserException {
1737:                // <netbeans>
1738:                int startOffset = getStartOffset();
1739:                // </netbeans>
1740:
1741:                Node pn = bitXorExpr(inForInit);
1742:                while (matchToken(Token.BITOR)) {
1743:                    decompiler.addToken(Token.BITOR);
1744:                    pn = nf
1745:                            .createBinary(Token.BITOR, pn,
1746:                                    bitXorExpr(inForInit));
1747:                }
1748:
1749:                // <netbeans>
1750:                setSourceOffsets(pn, startOffset);
1751:                // </netbeans>
1752:
1753:                return pn;
1754:            }
1755:
1756:            private Node bitXorExpr(boolean inForInit) throws IOException,
1757:                    ParserException {
1758:                // <netbeans>
1759:                int startOffset = getStartOffset();
1760:                // </netbeans>
1761:
1762:                Node pn = bitAndExpr(inForInit);
1763:                while (matchToken(Token.BITXOR)) {
1764:                    decompiler.addToken(Token.BITXOR);
1765:                    pn = nf.createBinary(Token.BITXOR, pn,
1766:                            bitAndExpr(inForInit));
1767:                }
1768:
1769:                // <netbeans>
1770:                setSourceOffsets(pn, startOffset);
1771:                // </netbeans>
1772:
1773:                return pn;
1774:            }
1775:
1776:            private Node bitAndExpr(boolean inForInit) throws IOException,
1777:                    ParserException {
1778:                // <netbeans>
1779:                int startOffset = getStartOffset();
1780:                // </netbeans>
1781:
1782:                Node pn = eqExpr(inForInit);
1783:                while (matchToken(Token.BITAND)) {
1784:                    decompiler.addToken(Token.BITAND);
1785:                    pn = nf.createBinary(Token.BITAND, pn, eqExpr(inForInit));
1786:                }
1787:
1788:                // <netbeans>
1789:                setSourceOffsets(pn, startOffset);
1790:                // </netbeans>
1791:
1792:                return pn;
1793:            }
1794:
1795:            private Node eqExpr(boolean inForInit) throws IOException,
1796:                    ParserException {
1797:                // <netbeans>
1798:                int startOffset = getStartOffset();
1799:                // </netbeans>
1800:
1801:                Node pn = relExpr(inForInit);
1802:                for (;;) {
1803:                    int tt = peekToken();
1804:                    switch (tt) {
1805:                    case Token.EQ:
1806:                    case Token.NE:
1807:                    case Token.SHEQ:
1808:                    case Token.SHNE:
1809:                        consumeToken();
1810:                        int decompilerToken = tt;
1811:                        int parseToken = tt;
1812:                        if (compilerEnv.getLanguageVersion() == Context.VERSION_1_2) {
1813:                            // JavaScript 1.2 uses shallow equality for == and != .
1814:                            // In addition, convert === and !== for decompiler into
1815:                            // == and != since the decompiler is supposed to show
1816:                            // canonical source and in 1.2 ===, !== are allowed
1817:                            // only as an alias to ==, !=.
1818:                            switch (tt) {
1819:                            case Token.EQ:
1820:                                parseToken = Token.SHEQ;
1821:                                break;
1822:                            case Token.NE:
1823:                                parseToken = Token.SHNE;
1824:                                break;
1825:                            case Token.SHEQ:
1826:                                decompilerToken = Token.EQ;
1827:                                break;
1828:                            case Token.SHNE:
1829:                                decompilerToken = Token.NE;
1830:                                break;
1831:                            }
1832:                        }
1833:                        decompiler.addToken(decompilerToken);
1834:                        pn = nf
1835:                                .createBinary(parseToken, pn,
1836:                                        relExpr(inForInit));
1837:                        continue;
1838:                    }
1839:                    break;
1840:                }
1841:
1842:                // <netbeans>
1843:                setSourceOffsets(pn, startOffset);
1844:                // </netbeans>
1845:
1846:                return pn;
1847:            }
1848:
1849:            private Node relExpr(boolean inForInit) throws IOException,
1850:                    ParserException {
1851:                // <netbeans>
1852:                int startOffset = getStartOffset();
1853:                // </netbeans>
1854:
1855:                Node pn = shiftExpr();
1856:                for (;;) {
1857:                    int tt = peekToken();
1858:                    switch (tt) {
1859:                    case Token.IN:
1860:                        if (inForInit)
1861:                            break;
1862:                        // fall through
1863:                    case Token.INSTANCEOF:
1864:                    case Token.LE:
1865:                    case Token.LT:
1866:                    case Token.GE:
1867:                    case Token.GT:
1868:                        consumeToken();
1869:                        decompiler.addToken(tt);
1870:                        pn = nf.createBinary(tt, pn, shiftExpr());
1871:                        continue;
1872:                    }
1873:                    break;
1874:                }
1875:
1876:                // <netbeans>
1877:                setSourceOffsets(pn, startOffset);
1878:                // </netbeans>
1879:
1880:                return pn;
1881:            }
1882:
1883:            private Node shiftExpr() throws IOException, ParserException {
1884:                // <netbeans>
1885:                int startOffset = getStartOffset();
1886:                // </netbeans>
1887:
1888:                Node pn = addExpr();
1889:                for (;;) {
1890:                    int tt = peekToken();
1891:                    switch (tt) {
1892:                    case Token.LSH:
1893:                    case Token.URSH:
1894:                    case Token.RSH:
1895:                        consumeToken();
1896:                        decompiler.addToken(tt);
1897:                        pn = nf.createBinary(tt, pn, addExpr());
1898:                        continue;
1899:                    }
1900:                    break;
1901:                }
1902:
1903:                // <netbeans>
1904:                setSourceOffsets(pn, startOffset);
1905:                // </netbeans>
1906:
1907:                return pn;
1908:            }
1909:
1910:            private Node addExpr() throws IOException, ParserException {
1911:                // <netbeans>
1912:                int startOffset = getStartOffset();
1913:                // </netbeans>
1914:
1915:                Node pn = mulExpr();
1916:                for (;;) {
1917:                    int tt = peekToken();
1918:                    if (tt == Token.ADD || tt == Token.SUB) {
1919:                        consumeToken();
1920:                        decompiler.addToken(tt);
1921:                        // flushNewLines
1922:                        pn = nf.createBinary(tt, pn, mulExpr());
1923:                        continue;
1924:                    }
1925:                    break;
1926:                }
1927:
1928:                // <netbeans>
1929:                setSourceOffsets(pn, startOffset);
1930:                // </netbeans>
1931:
1932:                return pn;
1933:            }
1934:
1935:            private Node mulExpr() throws IOException, ParserException {
1936:                // <netbeans>
1937:                int startOffset = getStartOffset();
1938:                // </netbeans>
1939:
1940:                Node pn = unaryExpr();
1941:                for (;;) {
1942:                    int tt = peekToken();
1943:                    switch (tt) {
1944:                    case Token.MUL:
1945:                    case Token.DIV:
1946:                    case Token.MOD:
1947:                        consumeToken();
1948:                        decompiler.addToken(tt);
1949:                        pn = nf.createBinary(tt, pn, unaryExpr());
1950:                        continue;
1951:                    }
1952:                    break;
1953:                }
1954:
1955:                // <netbeans>
1956:                setSourceOffsets(pn, startOffset);
1957:                // </netbeans>
1958:
1959:                return pn;
1960:            }
1961:
1962:            private Node unaryExpr() throws IOException, ParserException {
1963:                int tt;
1964:
1965:                tt = peekToken();
1966:
1967:                // <netbeans>
1968:                int startOffset = getStartOffset();
1969:                // </netbeans>
1970:
1971:                switch (tt) {
1972:                case Token.VOID:
1973:                case Token.NOT:
1974:                case Token.BITNOT:
1975:                case Token.TYPEOF:
1976:                    consumeToken();
1977:                    decompiler.addToken(tt);
1978:                    // <netbeans>
1979:                    //return nf.createUnary(tt, unaryExpr());
1980:                    return setSourceOffsets(nf.createUnary(tt, unaryExpr()),
1981:                            startOffset);
1982:                    // </netbeans>
1983:
1984:                case Token.ADD:
1985:                    consumeToken();
1986:                    // Convert to special POS token in decompiler and parse tree
1987:                    decompiler.addToken(Token.POS);
1988:                    // <netbeans>
1989:                    //return nf.createUnary(Token.POS, unaryExpr());
1990:                    return setSourceOffsets(nf.createUnary(Token.POS,
1991:                            unaryExpr()), startOffset);
1992:                    // </netbeans>
1993:
1994:                case Token.SUB:
1995:                    consumeToken();
1996:                    // Convert to special NEG token in decompiler and parse tree
1997:                    decompiler.addToken(Token.NEG);
1998:                    // <netbeans>
1999:                    //return nf.createUnary(Token.NEG, unaryExpr());
2000:                    return setSourceOffsets(nf.createUnary(Token.NEG,
2001:                            unaryExpr()), startOffset);
2002:                    // </netbeans>
2003:
2004:                case Token.INC:
2005:                case Token.DEC:
2006:                    consumeToken();
2007:                    decompiler.addToken(tt);
2008:                    // <netbeans>
2009:                    //return nf.createIncDec(tt, false, memberExpr(true));
2010:                    return setSourceOffsets(nf.createIncDec(tt, false,
2011:                            memberExpr(true)), startOffset);
2012:                    // </netbeans>
2013:
2014:                case Token.DELPROP:
2015:                    consumeToken();
2016:                    decompiler.addToken(Token.DELPROP);
2017:                    // <netbeans>
2018:                    //return nf.createUnary(Token.DELPROP, unaryExpr());
2019:                    return setSourceOffsets(nf.createUnary(Token.DELPROP,
2020:                            unaryExpr()), startOffset);
2021:                    // </netbeans>
2022:
2023:                case Token.ERROR:
2024:                    consumeToken();
2025:                    break;
2026:
2027:                // XML stream encountered in expression.
2028:                case Token.LT:
2029:                    if (compilerEnv.isXmlAvailable()) {
2030:                        consumeToken();
2031:                        Node pn = xmlInitializer();
2032:                        // <netbeans>
2033:                        //return memberExprTail(true, pn);
2034:                        return setSourceOffsets(memberExprTail(true, pn),
2035:                                startOffset);
2036:                        // </netbeans>
2037:                    }
2038:                    // Fall thru to the default handling of RELOP
2039:
2040:                default:
2041:                    Node pn = memberExpr(true);
2042:
2043:                    // Don't look across a newline boundary for a postfix incop.
2044:                    tt = peekTokenOrEOL();
2045:                    if (tt == Token.INC || tt == Token.DEC) {
2046:                        consumeToken();
2047:                        decompiler.addToken(tt);
2048:                        // <netbeans>
2049:                        //return nf.createIncDec(tt, true, pn);
2050:                        return setSourceOffsets(nf.createIncDec(tt, true, pn),
2051:                                startOffset);
2052:                        // </netbeans>
2053:                    }
2054:
2055:                    // <netbeans>
2056:                    setSourceOffsets(pn, startOffset);
2057:                    // </netbeans>
2058:
2059:                    return pn;
2060:                }
2061:                // <netbeans>
2062:                return nf.createName("err"); // Only reached on error.  Try to continue.
2063:                // </netbeans>
2064:
2065:            }
2066:
2067:            // <netbeans>
2068:            // TODO - rename to something like setSourceOffsets
2069:            Node setSourceOffsets(Node n, int startOffset) {
2070:                if (n.getSourceEnd() != 0) {
2071:                    return n;
2072:                }
2073:                int endOffset = matchedTokenEnd;
2074:                n.setSourceBounds(startOffset, endOffset);
2075:                // Return n such that expressions can be chained, e.g
2076:                // return factory.createNumber(42)
2077:                //   can be written as
2078:                // return factory.createNumber(42).setSourceOffsets(n, startOffset)
2079:                return n;
2080:            }
2081:
2082:            int getStartOffset() {
2083:                return matchedTokenStart;
2084:            }
2085:
2086:            int getEndOffset() {
2087:                return matchedTokenEnd;
2088:            }
2089:
2090:            // </netbeans>
2091:
2092:            private Node xmlInitializer() throws IOException {
2093:                // <netbeans>
2094:                int startOffset = getStartOffset();
2095:                // </netbeans>
2096:
2097:                int tt = ts.getFirstXMLToken();
2098:                if (tt != Token.XML && tt != Token.XMLEND) {
2099:                    reportError("msg.syntax");
2100:                    return null;
2101:                }
2102:
2103:                /* Make a NEW node to append to. */
2104:                Node pnXML = nf.createLeaf(Token.NEW);
2105:
2106:                String xml = ts.getString();
2107:                boolean fAnonymous = xml.trim().startsWith("<>");
2108:
2109:                Node pn = nf.createName(fAnonymous ? "XMLList" : "XML");
2110:                nf.addChildToBack(pnXML, pn);
2111:
2112:                pn = null;
2113:                Node expr;
2114:                for (;; tt = ts.getNextXMLToken()) {
2115:                    switch (tt) {
2116:                    case Token.XML:
2117:                        xml = ts.getString();
2118:                        decompiler.addName(xml);
2119:                        mustMatchToken(Token.LC, "msg.syntax");
2120:                        decompiler.addToken(Token.LC);
2121:                        expr = (peekToken() == Token.RC) ? nf.createString("")
2122:                                : expr(false);
2123:                        mustMatchToken(Token.RC, "msg.syntax");
2124:                        decompiler.addToken(Token.RC);
2125:                        if (pn == null) {
2126:                            pn = nf.createString(xml);
2127:                        } else {
2128:                            pn = nf.createBinary(Token.ADD, pn, nf
2129:                                    .createString(xml));
2130:                        }
2131:                        if (ts.isXMLAttribute()) {
2132:                            /* Need to put the result in double quotes */
2133:                            expr = nf.createUnary(Token.ESCXMLATTR, expr);
2134:                            Node prepend = nf.createBinary(Token.ADD, nf
2135:                                    .createString("\""), expr);
2136:                            expr = nf.createBinary(Token.ADD, prepend, nf
2137:                                    .createString("\""));
2138:                        } else {
2139:                            expr = nf.createUnary(Token.ESCXMLTEXT, expr);
2140:                        }
2141:                        pn = nf.createBinary(Token.ADD, pn, expr);
2142:                        break;
2143:                    case Token.XMLEND:
2144:                        xml = ts.getString();
2145:                        decompiler.addName(xml);
2146:                        if (pn == null) {
2147:                            pn = nf.createString(xml);
2148:                        } else {
2149:                            pn = nf.createBinary(Token.ADD, pn, nf
2150:                                    .createString(xml));
2151:                        }
2152:
2153:                        nf.addChildToBack(pnXML, pn);
2154:
2155:                        // <netbeans>
2156:                        setSourceOffsets(pnXML, startOffset);
2157:                        // </netbeans>
2158:
2159:                        return pnXML;
2160:                    default:
2161:                        reportError("msg.syntax");
2162:                        return null;
2163:                    }
2164:                }
2165:            }
2166:
2167:            private void argumentList(Node listNode) throws IOException,
2168:                    ParserException {
2169:                // <netbeans>
2170:                int startOffset = getStartOffset();
2171:                // </netbeans>
2172:
2173:                boolean matched;
2174:                matched = matchToken(Token.RP);
2175:                if (!matched) {
2176:                    boolean first = true;
2177:                    do {
2178:                        if (!first)
2179:                            decompiler.addToken(Token.COMMA);
2180:                        first = false;
2181:                        nf.addChildToBack(listNode, assignExpr(false));
2182:                    } while (matchToken(Token.COMMA));
2183:
2184:                    mustMatchToken(Token.RP, "msg.no.paren.arg");
2185:                }
2186:
2187:                // <netbeans>
2188:                setSourceOffsets(listNode, startOffset);
2189:                // </netbeans>
2190:
2191:                decompiler.addToken(Token.RP);
2192:            }
2193:
2194:            private Node memberExpr(boolean allowCallSyntax)
2195:                    throws IOException, ParserException {
2196:                int tt;
2197:
2198:                Node pn;
2199:
2200:                /* Check for new expressions. */
2201:                tt = peekToken();
2202:
2203:                // <netbeans>
2204:                int startOffset = getStartOffset();
2205:                // </netbeans>
2206:
2207:                if (tt == Token.NEW) {
2208:                    /* Eat the NEW token. */
2209:                    consumeToken();
2210:                    decompiler.addToken(Token.NEW);
2211:
2212:                    /* Make a NEW node to append to. */
2213:                    pn = nf.createCallOrNew(Token.NEW, memberExpr(false));
2214:
2215:                    if (matchToken(Token.LP)) {
2216:                        decompiler.addToken(Token.LP);
2217:                        /* Add the arguments to pn, if any are supplied. */
2218:                        argumentList(pn);
2219:                    }
2220:
2221:                    /* XXX there's a check in the C source against
2222:                     * "too many constructor arguments" - how many
2223:                     * do we claim to support?
2224:                     */
2225:
2226:                    /* Experimental syntax:  allow an object literal to follow a new expression,
2227:                     * which will mean a kind of anonymous class built with the JavaAdapter.
2228:                     * the object literal will be passed as an additional argument to the constructor.
2229:                     */
2230:                    tt = peekToken();
2231:                    if (tt == Token.LC) {
2232:                        nf.addChildToBack(pn, primaryExpr());
2233:                    }
2234:                } else {
2235:                    pn = primaryExpr();
2236:                }
2237:
2238:                // <netbeans>
2239:                setSourceOffsets(pn, startOffset);
2240:                // </netbeans>
2241:
2242:                return memberExprTail(allowCallSyntax, pn);
2243:            }
2244:
2245:            private Node memberExprTail(boolean allowCallSyntax, Node pn)
2246:                    throws IOException, ParserException {
2247:                // <netbeans>
2248:                //int startOffset = getStartOffset();
2249:                assert pn.getSourceStart() <= getStartOffset() : pn
2250:                        .getSourceStart()
2251:                        + "," + getStartOffset();
2252:                int startOffset = pn.getSourceStart();
2253:                // </netbeans>
2254:
2255:                tailLoop: for (;;) {
2256:                    int tt = peekToken();
2257:                    switch (tt) {
2258:
2259:                    case Token.DOT:
2260:                    case Token.DOTDOT: {
2261:                        int memberTypeFlags;
2262:                        String s;
2263:
2264:                        consumeToken();
2265:                        decompiler.addToken(tt);
2266:                        memberTypeFlags = 0;
2267:                        if (tt == Token.DOTDOT) {
2268:                            mustHaveXML();
2269:                            memberTypeFlags = Node.DESCENDANTS_FLAG;
2270:                        }
2271:                        if (!compilerEnv.isXmlAvailable()) {
2272:                            mustMatchToken(Token.NAME, "msg.no.name.after.dot");
2273:                            s = ts.getString();
2274:                            decompiler.addName(s);
2275:                            pn = nf.createPropertyGet(pn, null, s,
2276:                                    memberTypeFlags);
2277:                            break;
2278:                        }
2279:
2280:                        tt = nextToken();
2281:                        switch (tt) {
2282:                        // handles: name, ns::name, ns::*, ns::[expr]
2283:                        case Token.NAME:
2284:                            s = ts.getString();
2285:                            decompiler.addName(s);
2286:                            pn = propertyName(pn, s, memberTypeFlags);
2287:                            // <netbeans>
2288:                            setSourceOffsets(pn.getLastChild(),
2289:                                    getStartOffset());
2290:                            // </netbeans>
2291:                            break;
2292:
2293:                        // handles: *, *::name, *::*, *::[expr]
2294:                        case Token.MUL:
2295:                            decompiler.addName("*");
2296:                            pn = propertyName(pn, "*", memberTypeFlags);
2297:                            break;
2298:
2299:                        // handles: '@attr', '@ns::attr', '@ns::*', '@ns::*',
2300:                        //          '@::attr', '@::*', '@*', '@*::attr', '@*::*'
2301:                        case Token.XMLATTR:
2302:                            decompiler.addToken(Token.XMLATTR);
2303:                            pn = attributeAccess(pn, memberTypeFlags);
2304:                            break;
2305:
2306:                        default:
2307:                            reportError("msg.no.name.after.dot");
2308:                        }
2309:                    }
2310:                        break;
2311:
2312:                    case Token.DOTQUERY:
2313:                        consumeToken();
2314:                        mustHaveXML();
2315:                        decompiler.addToken(Token.DOTQUERY);
2316:                        pn = nf.createDotQuery(pn, expr(false), ts.getLineno());
2317:                        mustMatchToken(Token.RP, "msg.no.paren");
2318:                        decompiler.addToken(Token.RP);
2319:                        break;
2320:
2321:                    case Token.LB:
2322:                        consumeToken();
2323:                        decompiler.addToken(Token.LB);
2324:                        pn = nf.createElementGet(pn, null, expr(false), 0);
2325:                        mustMatchToken(Token.RB, "msg.no.bracket.index");
2326:                        decompiler.addToken(Token.RB);
2327:                        break;
2328:
2329:                    case Token.LP:
2330:                        if (!allowCallSyntax) {
2331:                            break tailLoop;
2332:                        }
2333:                        consumeToken();
2334:                        decompiler.addToken(Token.LP);
2335:                        pn = nf.createCallOrNew(Token.CALL, pn);
2336:                        /* Add the arguments to pn, if any are supplied. */
2337:                        argumentList(pn);
2338:                        break;
2339:
2340:                    default:
2341:                        break tailLoop;
2342:                    }
2343:                }
2344:                // <netbeans>
2345:                pn.setSourceBounds(startOffset, getEndOffset());
2346:                // </netbeans>
2347:
2348:                return pn;
2349:            }
2350:
2351:            /*
2352:             * Xml attribute expression:
2353:             *   '@attr', '@ns::attr', '@ns::*', '@ns::*', '@*', '@*::attr', '@*::*'
2354:             */
2355:            private Node attributeAccess(Node pn, int memberTypeFlags)
2356:                    throws IOException {
2357:                // <netbeans>
2358:                int startOffset = getStartOffset();
2359:                // </netbeans>
2360:
2361:                memberTypeFlags |= Node.ATTRIBUTE_FLAG;
2362:                int tt = nextToken();
2363:
2364:                switch (tt) {
2365:                // handles: @name, @ns::name, @ns::*, @ns::[expr]
2366:                case Token.NAME: {
2367:                    String s = ts.getString();
2368:                    decompiler.addName(s);
2369:                    pn = propertyName(pn, s, memberTypeFlags);
2370:                }
2371:                    break;
2372:
2373:                // handles: @*, @*::name, @*::*, @*::[expr]
2374:                case Token.MUL:
2375:                    decompiler.addName("*");
2376:                    pn = propertyName(pn, "*", memberTypeFlags);
2377:                    break;
2378:
2379:                // handles @[expr]
2380:                case Token.LB:
2381:                    decompiler.addToken(Token.LB);
2382:                    pn = nf.createElementGet(pn, null, expr(false),
2383:                            memberTypeFlags);
2384:                    mustMatchToken(Token.RB, "msg.no.bracket.index");
2385:                    decompiler.addToken(Token.RB);
2386:                    break;
2387:
2388:                default:
2389:                    reportError("msg.no.name.after.xmlAttr");
2390:                    pn = nf.createPropertyGet(pn, null, "?", memberTypeFlags);
2391:                    break;
2392:                }
2393:
2394:                // <netbeans>
2395:                setSourceOffsets(pn, startOffset);
2396:                // </netbeans>
2397:
2398:                return pn;
2399:            }
2400:
2401:            /**
2402:             * Check if :: follows name in which case it becomes qualified name
2403:             */
2404:            private Node propertyName(Node pn, String name, int memberTypeFlags)
2405:                    throws IOException, ParserException {
2406:                // <netbeans>
2407:                //int startOffset = getStartOffset();
2408:                int startOffset = matchedTokenStart;
2409:                // </netbeans>
2410:
2411:                String namespace = null;
2412:                if (matchToken(Token.COLONCOLON)) {
2413:                    decompiler.addToken(Token.COLONCOLON);
2414:                    namespace = name;
2415:
2416:                    int tt = nextToken();
2417:                    switch (tt) {
2418:                    // handles name::name
2419:                    case Token.NAME:
2420:                        name = ts.getString();
2421:                        decompiler.addName(name);
2422:                        break;
2423:
2424:                    // handles name::*
2425:                    case Token.MUL:
2426:                        decompiler.addName("*");
2427:                        name = "*";
2428:                        break;
2429:
2430:                    // handles name::[expr]
2431:                    case Token.LB:
2432:                        decompiler.addToken(Token.LB);
2433:                        pn = nf.createElementGet(pn, namespace, expr(false),
2434:                                memberTypeFlags);
2435:                        mustMatchToken(Token.RB, "msg.no.bracket.index");
2436:                        decompiler.addToken(Token.RB);
2437:
2438:                        // <netbeans>
2439:                        setSourceOffsets(pn, startOffset);
2440:                        // </netbeans>
2441:
2442:                        return pn;
2443:
2444:                    default:
2445:                        reportError("msg.no.name.after.coloncolon");
2446:                        name = "?";
2447:                    }
2448:                }
2449:
2450:                pn = nf.createPropertyGet(pn, namespace, name, memberTypeFlags);
2451:
2452:                // <netbeans>
2453:                setSourceOffsets(pn, startOffset);
2454:                // </netbeans>
2455:
2456:                return pn;
2457:            }
2458:
2459:            private Node primaryExpr() throws IOException, ParserException {
2460:                Node pn;
2461:
2462:                int ttFlagged = nextFlaggedToken();
2463:                int tt = ttFlagged & CLEAR_TI_MASK;
2464:                // <netbeans>
2465:                int startOffset = matchedTokenStart;
2466:                // </netbeans>
2467:
2468:                switch (tt) {
2469:
2470:                case Token.FUNCTION: {
2471:                    // <netbeans>
2472:                    //return function(FunctionNode.FUNCTION_EXPRESSION);
2473:                    Node fn = function(FunctionNode.FUNCTION_EXPRESSION);
2474:                    if (jsonMode) {
2475:                        addError("msg.json.error", Token.fullName(tt), fn);
2476:                    }
2477:                    return fn;
2478:                    // </netbeans>
2479:                }
2480:
2481:                case Token.LB: {
2482:                    ObjArray elems = new ObjArray();
2483:                    int skipCount = 0;
2484:                    decompiler.addToken(Token.LB);
2485:                    boolean after_lb_or_comma = true;
2486:                    for (;;) {
2487:                        tt = peekToken();
2488:
2489:                        if (tt == Token.COMMA) {
2490:                            consumeToken();
2491:                            decompiler.addToken(Token.COMMA);
2492:                            if (!after_lb_or_comma) {
2493:                                after_lb_or_comma = true;
2494:                            } else {
2495:                                elems.add(null);
2496:                                ++skipCount;
2497:                            }
2498:                        } else if (tt == Token.RB) {
2499:                            consumeToken();
2500:                            decompiler.addToken(Token.RB);
2501:                            break;
2502:                        } else {
2503:                            if (!after_lb_or_comma) {
2504:                                reportError("msg.no.bracket.arg");
2505:                            }
2506:                            elems.add(assignExpr(false));
2507:                            after_lb_or_comma = false;
2508:                        }
2509:                    }
2510:                    // <netbeans>
2511:                    //return nf.createArrayLiteral(elems, skipCount);
2512:                    return setSourceOffsets(nf.createArrayLiteral(elems,
2513:                            skipCount), startOffset);
2514:                    // </netbeans>
2515:                }
2516:
2517:                case Token.LC: {
2518:                    ObjArray elems = new ObjArray();
2519:                    // <netbeans>
2520:                    List<Node> nameNodes = new ArrayList<Node>();
2521:                    // </netbeans>
2522:                    decompiler.addToken(Token.LC);
2523:                    if (!matchToken(Token.RC)) {
2524:
2525:                        boolean first = true;
2526:                        commaloop: do {
2527:                            Object property;
2528:
2529:                            if (!first)
2530:                                decompiler.addToken(Token.COMMA);
2531:                            else
2532:                                first = false;
2533:
2534:                            tt = peekToken();
2535:                            switch (tt) {
2536:                            case Token.NAME:
2537:                                // <netbeans>
2538:                                if (jsonMode) {
2539:                                    addError("msg.json.error", Token
2540:                                            .fullName(tt), null);
2541:                                }
2542:                                // </netbeans>
2543:
2544:                            case Token.STRING:
2545:                                consumeToken();
2546:                                // map NAMEs to STRINGs in object literal context
2547:                                // but tell the decompiler the proper type
2548:                                String s = ts.getString();
2549:                                if (tt == Token.NAME) {
2550:                                    if (s.equals("get")
2551:                                            && peekToken() == Token.NAME) {
2552:                                        decompiler.addToken(Token.GET);
2553:                                        consumeToken();
2554:                                        s = ts.getString();
2555:                                        decompiler.addName(s);
2556:                                        property = ScriptRuntime
2557:                                                .getIndexObject(s);
2558:                                        if (!getterSetterProperty(elems,
2559:                                                property, true))
2560:                                            break commaloop;
2561:                                        break;
2562:                                    } else if (s.equals("set")
2563:                                            && peekToken() == Token.NAME) {
2564:                                        decompiler.addToken(Token.SET);
2565:                                        consumeToken();
2566:                                        s = ts.getString();
2567:                                        decompiler.addName(s);
2568:                                        property = ScriptRuntime
2569:                                                .getIndexObject(s);
2570:                                        if (!getterSetterProperty(elems,
2571:                                                property, false))
2572:                                            break commaloop;
2573:                                        break;
2574:                                    }
2575:                                    decompiler.addName(s);
2576:                                } else {
2577:                                    decompiler.addString(s);
2578:                                }
2579:                                // <netbeans>
2580:                                int nameStart = matchedTokenStart;
2581:                                // </netbeans>
2582:                                property = ScriptRuntime.getIndexObject(s);
2583:                                plainProperty(elems, property);
2584:                                // <netbeans>
2585:                                if (elems.size() > 0) {
2586:                                    Node rhs = (Node) elems
2587:                                            .get(elems.size() - 1);
2588:                                    Node objLitName = new Node.LabelledNode(s,
2589:                                            rhs);
2590:                                    objLitName.setSourceBounds(nameStart,
2591:                                            nameStart + s.length());
2592:                                    nameNodes.add(objLitName);
2593:                                }
2594:                                // </netbeans>
2595:                                break;
2596:
2597:                            case Token.NUMBER:
2598:                                consumeToken();
2599:                                double n = ts.getNumber();
2600:                                decompiler.addNumber(n);
2601:                                property = ScriptRuntime.getIndexObject(n);
2602:                                plainProperty(elems, property);
2603:                                break;
2604:
2605:                            case Token.RC:
2606:                                // trailing comma is OK.
2607:                                break commaloop;
2608:                            default:
2609:                                reportError("msg.bad.prop");
2610:                                break commaloop;
2611:                            }
2612:                        } while (matchToken(Token.COMMA));
2613:
2614:                        mustMatchToken(Token.RC, "msg.no.brace.prop");
2615:                    }
2616:                    decompiler.addToken(Token.RC);
2617:                    // <netbeans>
2618:                    //return nf.createObjectLiteral(elems);
2619:                    Node literal = nf.createObjectLiteral(elems);
2620:                    literal.setSourceBounds(startOffset, getEndOffset());
2621:                    for (Node n : nameNodes) {
2622:                        literal.addChildToBack(n);
2623:                    }
2624:                    return literal;
2625:                    // </netbeans>
2626:                }
2627:
2628:                case Token.LP:
2629:                    // <netbeans>
2630:                    if (jsonMode) {
2631:                        addError("msg.json.error", Token.fullName(tt), null);
2632:                    }
2633:                    // </netbeans>
2634:
2635:                    /* Brendan's IR-jsparse.c makes a new node tagged with
2636:                     * TOK_LP here... I'm not sure I understand why.  Isn't
2637:                     * the grouping already implicit in the structure of the
2638:                     * parse tree?  also TOK_LP is already overloaded (I
2639:                     * think) in the C IR as 'function call.'  */
2640:                    decompiler.addToken(Token.LP);
2641:                    pn = expr(false);
2642:                    pn.putProp(Node.PARENTHESIZED_PROP, Boolean.TRUE);
2643:                    decompiler.addToken(Token.RP);
2644:                    mustMatchToken(Token.RP, "msg.no.paren");
2645:                    // <netbeans>
2646:                    setSourceOffsets(pn, startOffset);
2647:                    // </netbeans>
2648:                    return pn;
2649:
2650:                case Token.XMLATTR:
2651:                    mustHaveXML();
2652:                    decompiler.addToken(Token.XMLATTR);
2653:                    pn = attributeAccess(null, 0);
2654:                    // <netbeans>
2655:                    setSourceOffsets(pn, startOffset);
2656:                    // </netbeans>
2657:                    return pn;
2658:
2659:                case Token.NAME: {
2660:                    // <netbeans>
2661:                    if (jsonMode) {
2662:                        addError("msg.json.error", Token.fullName(tt), null);
2663:                    }
2664:                    // </netbeans>
2665:                    String name = ts.getString();
2666:                    if ((ttFlagged & TI_CHECK_LABEL) != 0) {
2667:                        if (peekToken() == Token.COLON) {
2668:                            // Do not consume colon, it is used as unwind indicator
2669:                            // to return to statementHelper.
2670:                            // XXX Better way?
2671:                            // TODO - create position?
2672:                            return nf.createLabel(ts.getLineno());
2673:                        }
2674:                    }
2675:
2676:                    decompiler.addName(name);
2677:                    if (compilerEnv.isXmlAvailable()) {
2678:                        pn = propertyName(null, name, 0);
2679:                    } else {
2680:                        pn = nf.createName(name);
2681:                    }
2682:                    // <netbeans>
2683:                    if (pn.getType() == Token.NAME) {
2684:                        pn.setSourceBounds(startOffset, startOffset
2685:                                + name.length());
2686:                    } else {
2687:                        setSourceOffsets(pn, startOffset);
2688:                    }
2689:                    // </netbeans>
2690:                    return pn;
2691:                }
2692:
2693:                case Token.NUMBER: {
2694:                    double n = ts.getNumber();
2695:                    decompiler.addNumber(n);
2696:                    // <netbeans>
2697:                    //return nf.createNumber(n);
2698:                    return setSourceOffsets(nf.createNumber(n), startOffset);
2699:                    // </netbeans>
2700:                }
2701:
2702:                case Token.STRING: {
2703:                    String s = ts.getString();
2704:                    decompiler.addString(s);
2705:                    // <netbeans>
2706:                    //return nf.createString(s);
2707:                    return setSourceOffsets(nf.createString(s), startOffset);
2708:                    // </netbeans>
2709:                }
2710:
2711:                case Token.DIV:
2712:                case Token.ASSIGN_DIV: {
2713:                    // Got / or /= which should be treated as regexp in fact
2714:                    ts.readRegExp(tt);
2715:                    String flags = ts.regExpFlags;
2716:                    ts.regExpFlags = null;
2717:                    String re = ts.getString();
2718:                    decompiler.addRegexp(re, flags);
2719:                    int index = currentScriptOrFn.addRegexp(re, flags);
2720:                    // <netbeans>
2721:                    //return nf.createRegExp(index);
2722:                    // Regexp node processing doesn't use the match token calls,
2723:                    // it's character based, so I need to do manual arithmetic to
2724:                    // get the right results here rather than my usual
2725:                    //  setSourceOffsets(node, startOffset) call
2726:                    Node rn = nf.createRegExp(index);
2727:                    int endOffset = matchedTokenEnd + re.length()
2728:                            + flags.length() + 1; // +1: closing /
2729:                    rn.setSourceBounds(startOffset, endOffset);
2730:                    matchedTokenEnd = endOffset;
2731:                    return rn;
2732:                    // </netbeans>
2733:                }
2734:
2735:                case Token.NULL:
2736:                case Token.THIS:
2737:                case Token.FALSE:
2738:                case Token.TRUE:
2739:                    decompiler.addToken(tt);
2740:                    // <netbeans>
2741:                    //return nf.createLeaf(tt);
2742:                    return setSourceOffsets(nf.createLeaf(tt), startOffset);
2743:                    // </netbeans>
2744:
2745:                case Token.RESERVED:
2746:                    reportError("msg.reserved.id");
2747:                    break;
2748:
2749:                case Token.ERROR:
2750:                    /* the scanner or one of its subroutines reported the error. */
2751:                    break;
2752:
2753:                case Token.EOF:
2754:                    reportError("msg.unexpected.eof");
2755:                    break;
2756:
2757:                default:
2758:                    reportError("msg.syntax");
2759:                    break;
2760:                }
2761:                return null; // should never reach here
2762:            }
2763:
2764:            private void plainProperty(ObjArray elems, Object property)
2765:                    throws IOException {
2766:                mustMatchToken(Token.COLON, "msg.no.colon.prop");
2767:
2768:                // OBJLIT is used as ':' in object literal for
2769:                // decompilation to solve spacing ambiguity.
2770:                decompiler.addToken(Token.OBJECTLIT);
2771:                elems.add(property);
2772:                elems.add(assignExpr(false));
2773:            }
2774:
2775:            private boolean getterSetterProperty(ObjArray elems,
2776:                    Object property, boolean isGetter) throws IOException {
2777:                Node f = function(FunctionNode.FUNCTION_EXPRESSION);
2778:                if (f.getType() != Token.FUNCTION) {
2779:                    reportError("msg.bad.prop");
2780:                    return false;
2781:                }
2782:                int fnIndex = f.getExistingIntProp(Node.FUNCTION_PROP);
2783:                FunctionNode fn = currentScriptOrFn.getFunctionNode(fnIndex);
2784:                if (fn.getFunctionName().length() != 0) {
2785:                    reportError("msg.bad.prop");
2786:                    return false;
2787:                }
2788:                elems.add(property);
2789:                if (isGetter) {
2790:                    elems.add(nf.createUnary(Token.GET, f));
2791:                } else {
2792:                    elems.add(nf.createUnary(Token.SET, f));
2793:                }
2794:                return true;
2795:            }
2796:
2797:            // <netbeans>
2798:            public TokenStream getTokenStream() {
2799:                return ts;
2800:            }
2801:
2802:            public void setTokenStream(TokenStream ts) {
2803:                this .ts = ts;
2804:            }
2805:
2806:            public ScriptOrFnNode parseJson(String sourceString,
2807:                    String sourceURI, int lineno) {
2808:                this .sourceURI = sourceURI;
2809:                this .ts = new TokenStream(this , null, sourceString, lineno);
2810:                try {
2811:                    setJsonMode(true);
2812:                    return parseJson();
2813:                } catch (IOException ex) {
2814:                    // Should never happen
2815:                    throw new IllegalStateException();
2816:                }
2817:            }
2818:
2819:            private ScriptOrFnNode parseJson() throws IOException {
2820:                assert jsonMode;
2821:                this .decompiler = createDecompiler(compilerEnv);
2822:                this .nf = new IRFactory(this );
2823:                currentScriptOrFn = nf.createScript();
2824:                int sourceStartOffset = decompiler.getCurrentOffset();
2825:                // <netbeans>
2826:                int realSourceStartOffset = ts.getBufferOffset();
2827:                // </netbeans>
2828:                this .encodedSource = null;
2829:                decompiler.addToken(Token.SCRIPT);
2830:
2831:                this .currentFlaggedToken = Token.EOF;
2832:                this .syntaxErrorCount = 0;
2833:
2834:                int baseLineno = ts.getLineno(); // line number where source starts
2835:
2836:                /* so we have something to add nodes to until
2837:                 * we've collected all the source */
2838:                Node pn = nf.createLeaf(Token.BLOCK);
2839:
2840:                try {
2841:                    mustMatchToken(Token.LC, "msg.json.expectedlc");
2842:                    int startOffset = getStartOffset();
2843:                    ObjArray elems = new ObjArray();
2844:                    // <netbeans>
2845:                    List<Node> nameNodes = new ArrayList<Node>();
2846:                    // </netbeans>
2847:                    decompiler.addToken(Token.LC);
2848:                    if (!matchToken(Token.RC)) {
2849:
2850:                        boolean first = true;
2851:                        commaloop: do {
2852:                            Object property;
2853:
2854:                            if (!first)
2855:                                decompiler.addToken(Token.COMMA);
2856:                            else
2857:                                first = false;
2858:
2859:                            int tt = peekToken();
2860:                            switch (tt) {
2861:                            case Token.NAME:
2862:                            case Token.STRING:
2863:                                consumeToken();
2864:                                // map NAMEs to STRINGs in object literal context
2865:                                // but tell the decompiler the proper type
2866:                                String s = ts.getString();
2867:                                if (tt == Token.NAME) {
2868:                                    if (s.equals("get")
2869:                                            && peekToken() == Token.NAME) {
2870:                                        decompiler.addToken(Token.GET);
2871:                                        consumeToken();
2872:                                        s = ts.getString();
2873:                                        decompiler.addName(s);
2874:                                        property = ScriptRuntime
2875:                                                .getIndexObject(s);
2876:                                        if (!getterSetterProperty(elems,
2877:                                                property, true))
2878:                                            break commaloop;
2879:                                        break;
2880:                                    } else if (s.equals("set")
2881:                                            && peekToken() == Token.NAME) {
2882:                                        decompiler.addToken(Token.SET);
2883:                                        consumeToken();
2884:                                        s = ts.getString();
2885:                                        decompiler.addName(s);
2886:                                        property = ScriptRuntime
2887:                                                .getIndexObject(s);
2888:                                        if (!getterSetterProperty(elems,
2889:                                                property, false))
2890:                                            break commaloop;
2891:                                        break;
2892:                                    }
2893:                                    decompiler.addName(s);
2894:                                } else {
2895:                                    decompiler.addString(s);
2896:                                }
2897:                                // <netbeans>
2898:                                int nameStart = matchedTokenStart;
2899:                                // </netbeans>
2900:                                property = ScriptRuntime.getIndexObject(s);
2901:                                plainProperty(elems, property);
2902:                                // <netbeans>
2903:                                if (elems.size() > 0) {
2904:                                    Node rhs = (Node) elems
2905:                                            .get(elems.size() - 1);
2906:                                    Node objLitName = new Node.LabelledNode(s,
2907:                                            rhs);
2908:                                    objLitName.setSourceBounds(nameStart,
2909:                                            nameStart + s.length());
2910:                                    nameNodes.add(objLitName);
2911:                                }
2912:                                // </netbeans>
2913:                                break;
2914:
2915:                            case Token.NUMBER:
2916:                                consumeToken();
2917:                                double n = ts.getNumber();
2918:                                decompiler.addNumber(n);
2919:                                property = ScriptRuntime.getIndexObject(n);
2920:                                plainProperty(elems, property);
2921:                                break;
2922:
2923:                            case Token.RC:
2924:                                // trailing comma is OK.
2925:                                break commaloop;
2926:                            default:
2927:                                reportError("msg.bad.prop");
2928:                                break commaloop;
2929:                            }
2930:                        } while (matchToken(Token.COMMA));
2931:
2932:                        mustMatchToken(Token.RC, "msg.no.brace.prop");
2933:                    }
2934:                    decompiler.addToken(Token.RC);
2935:                    // <netbeans>
2936:                    //return nf.createObjectLiteral(elems);
2937:                    Node literal = nf.createObjectLiteral(elems);
2938:                    literal.setSourceBounds(startOffset, getEndOffset());
2939:                    for (Node n : nameNodes) {
2940:                        literal.addChildToBack(n);
2941:                    }
2942:                    pn.addChildToBack(literal);
2943:                } catch (StackOverflowError ex) {
2944:                    String msg = ScriptRuntime
2945:                            .getMessage0("msg.too.deep.parser.recursion");
2946:                    throw Context.reportRuntimeError(msg, sourceURI, ts
2947:                            .getLineno(), null, 0);
2948:                }
2949:
2950:                if (this .syntaxErrorCount != 0) {
2951:                    String msg = String.valueOf(this .syntaxErrorCount);
2952:                    msg = ScriptRuntime.getMessage1("msg.got.syntax.errors",
2953:                            msg);
2954:                    // <netbeans>
2955:                    //throw errorReporter.runtimeError(msg, sourceURI, baseLineno,
2956:                    //                                 null, 0);
2957:                    // Don't show an error for this at all!
2958:                    //EvaluatorException exc = errorReporter.runtimeError(msg, sourceURI, baseLineno,
2959:                    //                                 null, 0);
2960:                    //if (exc != null) {
2961:                    //    throw exc;
2962:                    //} else {
2963:                    //                currentScriptOrFn.setSourceName(sourceURI);
2964:                    //                currentScriptOrFn.setBaseLineno(baseLineno);
2965:                    //                currentScriptOrFn.setEndLineno(ts.getLineno());
2966:                    //
2967:                    //                return currentScriptOrFn;
2968:                    return null;
2969:                    //}
2970:                    // </netbeans>
2971:                }
2972:
2973:                currentScriptOrFn.setSourceName(sourceURI);
2974:                currentScriptOrFn.setBaseLineno(baseLineno);
2975:                currentScriptOrFn.setEndLineno(ts.getLineno());
2976:
2977:                int sourceEndOffset = decompiler.getCurrentOffset();
2978:                currentScriptOrFn.setEncodedSourceBounds(sourceStartOffset,
2979:                        sourceEndOffset);
2980:                // <netbeans>
2981:                int realSourceEndOffset = getEndOffset();
2982:                currentScriptOrFn.setSourceBounds(realSourceStartOffset,
2983:                        realSourceEndOffset);
2984:                // </netbeans>
2985:
2986:                nf.initScript(currentScriptOrFn, pn);
2987:
2988:                if (compilerEnv.isGeneratingSource()) {
2989:                    encodedSource = decompiler.getEncodedSource();
2990:                }
2991:                this .decompiler = null; // It helps GC
2992:
2993:                return currentScriptOrFn;
2994:            }
2995:            // </netbeans>
2996:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.