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

📄 parser.java

📁 RESIN 3.2 最新源码
💻 JAVA
📖 第 1 页 / 共 4 页
字号:
/* * Copyright (c) 1998-2006 Caucho Technology -- all rights reserved * * This file is part of Resin(R) Open Source * * Each copy or derived work must preserve the copyright notice and this * notice unmodified. * * Resin Open Source is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * Resin Open Source is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, or any warranty * of NON-INFRINGEMENT.  See the GNU General Public License for more * details. * * You should have received a copy of the GNU General Public License * along with Resin Open Source; if not, write to the *   Free SoftwareFoundation, Inc. *   59 Temple Place, Suite 330 *   Boston, MA 02111-1307  USA * * @author Scott Ferguson */package com.caucho.es.parser;import com.caucho.es.ESBase;import com.caucho.es.ESException;import com.caucho.es.ESId;import com.caucho.es.ESParseException;import com.caucho.es.Script;import com.caucho.java.JavaCompiler;import com.caucho.java.LineMap;import com.caucho.loader.SimpleLoader;import com.caucho.log.Log;import com.caucho.server.util.CauchoSystem;import com.caucho.util.CharBuffer;import com.caucho.util.IntArray;import com.caucho.util.L10N;import com.caucho.vfs.MergePath;import com.caucho.vfs.Path;import com.caucho.vfs.ReadStream;import com.caucho.vfs.Vfs;import com.caucho.vfs.WriteStream;import java.io.IOException;import java.util.ArrayList;import java.util.logging.Logger;/** * Parser is a factory for generating compiled Script objects. * * <p>Most applications will use the <code>parse(String)</code> interface * to parse JavaScript.  That method will try to load a precompiled * script from the work directory before trying to parse it. * * <p>Applications will often set the script path a directory for * script and include the classpath in the path.  Applications will * often override the work dir for a more appropriate work directory. * * <code><pre> * package com.caucho.vfs.*; * package com.caucho.es.*; * * ... * * com.caucho.es.parser.Parser parser; * parser = new com.caucho.es.parser.Parser(); * * // configure the path to search for *.js files * MergePath scriptPath = new MergePath(); * scriptPath.addMergePath(Vfs.lookup("/home/ferg/js")); * ClassLoader loader = Thread.currentThread().contextClassLoader(); * scriptPath.addClassPath(loader); * parser.setScriptPath(scriptPath); * * // configure the directory storing compiled scripts * Path workPath = Vfs.lookup("/tmp/caucho/work"); * parser.setWorkDir(workPath); *  * Script script = parser.parse("test.js"); * </pre></code> */public class Parser {  private static final Logger log = Log.open(Parser.class);  private static final L10N L = new L10N(Parser.class);  private static final Object LOCK = new Object();    static ESId CLINIT = ESId.intern("__clinit__");  static ESId PROTOTYPE = ESId.intern("prototype");  static ESId FINALLY = ESId.intern("finally");  static ESId ANONYMOUS = ESId.intern("anonymous");  static ESId OBJECT = ESId.intern("Object");  static ESId REGEXP = ESId.intern("RegExp");  static ESId ARRAY = ESId.intern("Array");  static ESId LENGTH = ESId.intern("length");  static ESId PACKAGES = ESId.intern("Packages");  static ESId JAVA = ESId.intern("java");  static ESId COM = ESId.intern("com");  static ESId CAUCHO = ESId.intern("caucho");  static final int PREC_DOT = 1;  static final int PREC_POST = PREC_DOT;  static final int PREC_FUN = PREC_POST + 1;  static final int PREC_UMINUS = PREC_FUN + 1;  static final int PREC_TIMES = PREC_UMINUS + 1;  static final int PREC_PLUS = PREC_TIMES + 1;  static final int PREC_SHIFT = PREC_PLUS + 1;  static final int PREC_CMP = PREC_SHIFT + 1;  static final int PREC_EQ = PREC_CMP + 1;  static final int PREC_BITAND = PREC_EQ + 1;  static final int PREC_BITXOR = PREC_BITAND + 1;  static final int PREC_BITOR = PREC_BITXOR + 1;  static final int PREC_AND = PREC_BITOR + 1;  static final int PREC_OR = PREC_AND + 1;  static final int PREC_COND = PREC_OR + 1;  static final int PREC_ASSIGN = PREC_COND + 1;  static final int PREC_COMMA = PREC_ASSIGN + 1;  static final int PREC_MAX = PREC_COMMA + 1;  ClassLoader parentLoader;  ClassLoader loader;    Path scriptPath;  boolean isEval;  // Name of the generated class  String className;    Lexer lexer;  IntArray hashes = new IntArray();  ArrayList importList = new ArrayList();  ParseClass parseClass;  Function globalFunction;  Function staticFunction;  Function function; // the current prototype, i.e. class  Block block;  LineMap lineMap;  Path workPath;  //JavaCompiler compiler;  boolean isFast;  public Parser()  {    workPath = CauchoSystem.getWorkPath();    //compiler.setEncoding("utf8");    addImport("java.lang.*");    addImport("com.caucho.jslib.*");  }  /**   * Sets the parent class loader.  If unspecified, defaults to the context   * classloader.  Most applications will just use the default.   *   * @param parentLoader the classloader to be used for the script's parent.   */  public void setParentLoader(ClassLoader parentLoader)  {    this.parentLoader = parentLoader;  }  /**   * Internal method to set the actual class loader.   * Normally, this should only be called from com.caucho.es functions.   */  public void setClassLoader(ClassLoader loader)  {    this.loader = loader;  }  /**   * Returns the current class loader.  If null, creates from the parent   * loader and the work-dir.   */  ClassLoader getClassLoader()  {    if (loader != null)      return loader;    if (parentLoader != null)      loader = SimpleLoader.create(parentLoader, workPath, null);    else      loader = SimpleLoader.create(null, workPath, null);    return loader;  }  /**   * Sets the path to search for imported javascript source files.   * Normally, ScriptPath will be a MergePath.  If the MergePath   * adds the classpath, then JavaScript files can be put in the   * normal Java classpath.   *   * <p>If the ScriptPath is not specified, it will use the   * current directory and the classpath from the context class loader.   *   * <code><pre>   * MergePath scriptPath = new MergePath();   * scriptPath.addMergePath(Vfs.lookup("/home/ferg/js"));   *   * ClassLoader loader = Thread.currentThread().contextClassLoader();   * scriptPath.addClassPath(loader);   *   * parser.setScriptPath(scriptPath);   * </pre></code>   *   * @param scriptPath path to search for imported scripts.   */  public void setScriptPath(Path scriptPath)  {    this.scriptPath = scriptPath;  }  /**   * Returns the path to search for imported javascript.  Normally, scriptPath   * will be a MergePath.   *   * @param scriptPath path to search for imported scripts.   */  public Path getScriptPath()  {    return scriptPath;  }  /**   * Adds a package/script to be automatically imported by the script.   * Each import is the equivalent of adding the following javascript:   *   * <code><pre>   * package <em>name</em>;   * </pre></code>   *   * @param name package or script name to be automatically imported.   */  public void addImport(String name)  {    if (! importList.contains(name))      importList.add(name);  }  /**   * Sets "fast" mode, i.e. JavaScript 2.0.  Fast mode lets the compiler   * make assumptions about types and classes, e.g. that class methods   * won't change dynamically.  This lets the compiler generate more code   * that directly translates to Java calls.   */  public void setFast(boolean isFast)  {    this.isFast = isFast;  }  /**   * Sets a line number map.  For generated files like JSP or XTP,   * the error messages need an extra translation to get to the original   * line numbers.   */  public void setLineMap(LineMap lineMap)  {    this.lineMap = lineMap;  }  /**   * Sets the name of the generated java class.  If unset, the parser will   * mangle the input name.   */  public void setClassName(String name)  {    this.className = name;  }  /**   * Sets the directory for generated *.java and *.class files.   * The parser will check this directory for any precompiled javascript   * classes.  The default work-dir is /tmp/caucho on unix and   * c:\temp\caucho on windows.   *   * @param path the work directory.   */  public void setWorkDir(Path path)  {    workPath = path;  }  /**   * Returns the directory for generated *.java and *.class files.   */  public Path getWorkDir()  {    return workPath;  }  /**   * Main application parsing method.  The parser will try to load   * the compiled script.  If the compiled script exists and the   * source file has not changed, parse will return the old script.   * Otherwise, it will parse and compile the javascript.   *   * @param name the name of the javascript source.   *   * @return the parsed script   */  public Script parse(String name) throws ESException, IOException  {    Path path;    try {      String className;      if (this.className != null)        className = this.className;      else        className = "_js." + JavaCompiler.mangleName(name);            if (scriptPath == null) {        MergePath mergePath = new MergePath();        mergePath.addMergePath(Vfs.lookup());        ClassLoader parentLoader = this.parentLoader;        if (parentLoader == null)          parentLoader = Thread.currentThread().getContextClassLoader();              mergePath.addClassPath(parentLoader);        scriptPath = mergePath;      }            Script script = loadScript(className);      if (! script.isModified()) {        script.setScriptPath(getScriptPath());        script.setClassDir(workPath);        return script;      }    } catch (Throwable e) {    }      path = getScriptPath().lookup(name);    ReadStream is = path.openRead();    try {      return parse(is, name, 1);    } finally {      is.close();    }  }  /**   * Alternative parsing method when the application only has an open   * stream to the file.  Since this method will always compile a new script,   * it can be significantly slower than the <code>parse(String)</code>   * method.   *   * @param is a read stream to the javascript source.   *   * @return the parsed script.   */  public Script parse(ReadStream is) throws ESException, IOException  {    return parse(is, null, 1);  }  /**   * An alternative parsing method given an open stream, a filename and   * a line number.   *   * @param is a stream to the javascript source.   * @param name filename to use for error messages.   * @param line initial line number.   *   * @return the compiled script   */  public Script parse(ReadStream is, String name, int line)    throws ESException, IOException  {    if (name == null)      name = is.getUserPath();    if (line <= 0)      line = 1;        return parse(is, name, line, false);  }  /**   * Parses a script for the JavaScript "eval" expression.  The   * semantics for "eval" are slightly different from standard   * scripts.   *   * @param is stream to the eval source.   * @param name filename to use for error messages   * @param line initial line number to use for error messages.   *   * @return the compiled script.   */  public Script parseEval(ReadStream is, String name, int line)    throws ESException, IOException  {    if (name == null)      name = "eval";    if (line <= 0)      line = 1;    return parse(is, name, line, true);  }  /**   * The main parser method.   *   * @param is stream to read the script.   * @param name the filename to use for error messages.   * @param line the line number to use for error messages.   * @param isEval if true, parse for an eval expression.   *   * @return the compiled javascript   */  private Script parse(ReadStream is, String name,                       int line, boolean isEval)    throws ESException, IOException  {    if (name == null)      name = "anonymous";    if (line <= 0)      line = 1;        lexer = new Lexer(is, name, line);    if (lineMap != null)      lexer.setLineMap(lineMap);        if (className == null)      className = "_js." + JavaCompiler.mangleName(name);          if (scriptPath == null) {      MergePath mergePath = new MergePath();      if (is.getPath() != null)        mergePath.addMergePath(is.getPath().getParent());      else        mergePath.addMergePath(Vfs.lookup());      ClassLoader parentLoader = this.parentLoader;      if (parentLoader == null)        parentLoader = Thread.currentThread().getContextClassLoader();            mergePath.addClassPath(parentLoader);      scriptPath = mergePath;    }        block = null;    JavaCompiler compiler = JavaCompiler.create(getClassLoader());    compiler.setClassDir(workPath);    parseClass = new ParseClass(name, className);    parseClass.setParser(this);    if (is.getPath() != null && is.getPath().getLastModified() > 0)      parseClass.setSourcePath(is.getPath());    globalFunction = parseClass.newFunction(null, ESId.intern("global"), false);    globalFunction.setFast(isFast);    staticFunction = parseClass.newFunction(null, ESId.intern("__es_static"), false);    parseClass.setGlobal(globalFunction);    if (isEval) {      block = Block.create(this, globalFunction);      block.finish();      function = parseClass.newFunction(globalFunction, ESId.intern("eval"), false);      function.setEval();    }    else      function = globalFunction;        block = Block.create(this, function);    parseBlock(true);    block.finish();    if (lexer.peek() != Lexer.EOF)      throw expect(L.l("end of file"));    block = Block.create(this, staticFunction);    block.finish();    synchronized (LOCK) {      Path path = workPath.lookup(className.replace('.', '/') + ".java");      path.getParent().mkdirs();          WriteStream os = path.openWrite();      os.setEncoding("JAVA");      parseClass.writeCode(os);      os.close();      Script script;      try {        compiler.compile(className.replace('.', '/') + ".java", null);

⌨️ 快捷键说明

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