⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 parser.java

📁 java中比较著名的js引擎当属mozilla开源的rhino
💻 JAVA
📖 第 1 页 / 共 5 页
字号:
/* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- * * ***** BEGIN LICENSE BLOCK ***** * Version: MPL 1.1/GPL 2.0 * * The contents of this file are subject to the Mozilla Public License Version * 1.1 (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * http://www.mozilla.org/MPL/ * * Software distributed under the License is distributed on an "AS IS" basis, * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License * for the specific language governing rights and limitations under the * License. * * The Original Code is Rhino code, released * May 6, 1999. * * The Initial Developer of the Original Code is * Netscape Communications Corporation. * Portions created by the Initial Developer are Copyright (C) 1997-1999 * the Initial Developer. All Rights Reserved. * * Contributor(s): *   Mike Ang *   Igor Bukanov *   Yuh-Ruey Chen *   Ethan Hugg *   Terry Lucas *   Mike McCabe *   Milen Nankov * * Alternatively, the contents of this file may be used under the terms of * the GNU General Public License Version 2 or later (the "GPL"), in which * case the provisions of the GPL are applicable instead of those above. If * you wish to allow use of your version of this file only under the terms of * the GPL and not to allow others to use your version of this file under the * MPL, indicate your decision by deleting the provisions above and replacing * them with the notice and other provisions required by the GPL. If you do * not delete the provisions above, a recipient may use your version of this * file under either the MPL or the GPL. * * ***** END LICENSE BLOCK ***** */package org.mozilla.javascript;import java.io.Reader;import java.io.IOException;import java.util.Hashtable;/** * This class implements the JavaScript parser. * * It is based on the C source files jsparse.c and jsparse.h * in the jsref package. * * @see TokenStream * * @author Mike McCabe * @author Brendan Eich */public class Parser{    // TokenInformation flags : currentFlaggedToken stores them together    // with token type    final static int        CLEAR_TI_MASK  = 0xFFFF,   // mask to clear token information bits        TI_AFTER_EOL   = 1 << 16,  // first token of the source line        TI_CHECK_LABEL = 1 << 17;  // indicates to check for label    CompilerEnvirons compilerEnv;    private ErrorReporter errorReporter;    private String sourceURI;    boolean calledByCompileFunction;    private TokenStream ts;    private int currentFlaggedToken;    private int syntaxErrorCount;    private IRFactory nf;    private int nestingOfFunction;    private Decompiler decompiler;    private String encodedSource;// The following are per function variables and should be saved/restored// during function parsing.// XXX Move to separated class?    ScriptOrFnNode currentScriptOrFn;    private int nestingOfWith;    private Hashtable labelSet; // map of label names into nodes    private ObjArray loopSet;    private ObjArray loopAndSwitchSet;// end of per function variables    // Exception to unwind    private static class ParserException extends RuntimeException    {        static final long serialVersionUID = 5882582646773765630L;    }    public Parser(CompilerEnvirons compilerEnv, ErrorReporter errorReporter)    {        this.compilerEnv = compilerEnv;        this.errorReporter = errorReporter;    }    protected Decompiler createDecompiler(CompilerEnvirons compilerEnv)    {        return new Decompiler();    }    void addWarning(String messageId, String messageArg)    {        String message = ScriptRuntime.getMessage1(messageId, messageArg);        errorReporter.warning(message, sourceURI, ts.getLineno(),                              ts.getLine(), ts.getOffset());    }    void addError(String messageId)    {        ++syntaxErrorCount;        String message = ScriptRuntime.getMessage0(messageId);        errorReporter.error(message, sourceURI, ts.getLineno(),                            ts.getLine(), ts.getOffset());    }    RuntimeException reportError(String messageId)    {        addError(messageId);        // Throw a ParserException exception to unwind the recursive descent        // parse.        throw new ParserException();    }    private int peekToken()        throws IOException    {        int tt = currentFlaggedToken;        if (tt == Token.EOF) {            tt = ts.getToken();            if (tt == Token.EOL) {                do {                    tt = ts.getToken();                } while (tt == Token.EOL);                tt |= TI_AFTER_EOL;            }            currentFlaggedToken = tt;        }        return tt & CLEAR_TI_MASK;    }    private int peekFlaggedToken()        throws IOException    {        peekToken();        return currentFlaggedToken;    }    private void consumeToken()    {        currentFlaggedToken = Token.EOF;    }    private int nextToken()        throws IOException    {        int tt = peekToken();        consumeToken();        return tt;    }    private int nextFlaggedToken()        throws IOException    {        peekToken();        int ttFlagged = currentFlaggedToken;        consumeToken();        return ttFlagged;    }    private boolean matchToken(int toMatch)        throws IOException    {        int tt = peekToken();        if (tt != toMatch) {            return false;        }        consumeToken();        return true;    }    private int peekTokenOrEOL()        throws IOException    {        int tt = peekToken();        // Check for last peeked token flags        if ((currentFlaggedToken & TI_AFTER_EOL) != 0) {            tt = Token.EOL;        }        return tt;    }    private void setCheckForLabel()    {        if ((currentFlaggedToken & CLEAR_TI_MASK) != Token.NAME)            throw Kit.codeBug();        currentFlaggedToken |= TI_CHECK_LABEL;    }    private void mustMatchToken(int toMatch, String messageId)        throws IOException, ParserException    {        if (!matchToken(toMatch)) {            reportError(messageId);        }    }    private void mustHaveXML()    {        if (!compilerEnv.isXmlAvailable()) {            reportError("msg.XML.not.available");        }    }    public String getEncodedSource()    {        return encodedSource;    }    public boolean eof()    {        return ts.eof();    }    boolean insideFunction()    {        return nestingOfFunction != 0;    }    private Node enterLoop(Node loopLabel)    {        Node loop = nf.createLoopNode(loopLabel, ts.getLineno());        if (loopSet == null) {            loopSet = new ObjArray();            if (loopAndSwitchSet == null) {                loopAndSwitchSet = new ObjArray();            }        }        loopSet.push(loop);        loopAndSwitchSet.push(loop);        return loop;    }    private void exitLoop()    {        loopSet.pop();        loopAndSwitchSet.pop();    }    private Node enterSwitch(Node switchSelector, int lineno, Node switchLabel)    {        Node switchNode = nf.createSwitch(switchSelector, lineno);        if (loopAndSwitchSet == null) {            loopAndSwitchSet = new ObjArray();        }        loopAndSwitchSet.push(switchNode);        return switchNode;    }    private void exitSwitch()    {        loopAndSwitchSet.pop();    }    /*     * Build a parse tree from the given sourceString.     *     * @return an Object representing the parsed     * program.  If the parse fails, null will be returned.  (The     * parse failure will result in a call to the ErrorReporter from     * CompilerEnvirons.)     */    public ScriptOrFnNode parse(String sourceString,                                String sourceURI, int lineno)    {        this.sourceURI = sourceURI;        this.ts = new TokenStream(this, null, sourceString, lineno);        try {            return parse();        } catch (IOException ex) {            // Should never happen            throw new IllegalStateException();        }    }    /*     * Build a parse tree from the given sourceString.     *     * @return an Object representing the parsed     * program.  If the parse fails, null will be returned.  (The     * parse failure will result in a call to the ErrorReporter from     * CompilerEnvirons.)     */    public ScriptOrFnNode parse(Reader sourceReader,                                String sourceURI, int lineno)        throws IOException    {        this.sourceURI = sourceURI;        this.ts = new TokenStream(this, sourceReader, null, lineno);        return parse();    }    private ScriptOrFnNode parse()        throws IOException    {        this.decompiler = createDecompiler(compilerEnv);        this.nf = new IRFactory(this);        currentScriptOrFn = nf.createScript();        int sourceStartOffset = decompiler.getCurrentOffset();        this.encodedSource = null;        decompiler.addToken(Token.SCRIPT);        this.currentFlaggedToken = Token.EOF;        this.syntaxErrorCount = 0;        int baseLineno = ts.getLineno();  // line number where source starts        /* so we have something to add nodes to until         * we've collected all the source */        Node pn = nf.createLeaf(Token.BLOCK);        try {            for (;;) {                int tt = peekToken();                if (tt <= Token.EOF) {                    break;                }                Node n;                if (tt == Token.FUNCTION) {                    consumeToken();                    try {                        n = function(calledByCompileFunction                                     ? FunctionNode.FUNCTION_EXPRESSION                                     : FunctionNode.FUNCTION_STATEMENT);                    } catch (ParserException e) {                        break;                    }                } else {                    n = statement();                }                nf.addChildToBack(pn, n);            }        } catch (StackOverflowError ex) {            String msg = ScriptRuntime.getMessage0(                "mag.too.deep.parser.recursion");            throw Context.reportRuntimeError(msg, sourceURI,                                             ts.getLineno(), null, 0);        }        if (this.syntaxErrorCount != 0) {            String msg = String.valueOf(this.syntaxErrorCount);            msg = ScriptRuntime.getMessage1("msg.got.syntax.errors", msg);            throw errorReporter.runtimeError(msg, sourceURI, baseLineno,                                             null, 0);        }        currentScriptOrFn.setSourceName(sourceURI);        currentScriptOrFn.setBaseLineno(baseLineno);        currentScriptOrFn.setEndLineno(ts.getLineno());        int sourceEndOffset = decompiler.getCurrentOffset();        currentScriptOrFn.setEncodedSourceBounds(sourceStartOffset,                                                 sourceEndOffset);        nf.initScript(currentScriptOrFn, pn);        if (compilerEnv.isGeneratingSource()) {            encodedSource = decompiler.getEncodedSource();        }        this.decompiler = null; // It helps GC        return currentScriptOrFn;    }    /*     * The C version of this function takes an argument list,     * which doesn't seem to be needed for tree generation...     * it'd only be useful for checking argument hiding, which     * I'm not doing anyway...     */    private Node parseFunctionBody()        throws IOException    {        ++nestingOfFunction;        Node pn = nf.createBlock(ts.getLineno());        try {            bodyLoop: for (;;) {                Node n;                int tt = peekToken();

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -