📄 quercusparser.java
字号:
/* * Copyright (c) 1998-2008 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 Software Foundation, Inc. * 59 Temple Place, Suite 330 * Boston, MA 02111-1307 USA * * @author Scott Ferguson */package com.caucho.quercus.parser;import com.caucho.quercus.Location;import com.caucho.quercus.Quercus;import com.caucho.quercus.QuercusRuntimeException;import com.caucho.quercus.env.*;import com.caucho.quercus.expr.*;import com.caucho.quercus.program.*;import com.caucho.util.CharBuffer;import com.caucho.util.IntMap;import com.caucho.util.L10N;import com.caucho.vfs.*;import java.io.CharConversionException;import java.io.IOException;import java.util.ArrayList;import java.util.LinkedHashMap;/** * Parses a PHP program. */public class QuercusParser { private final static L10N L = new L10N(QuercusParser.class); private final static int M_STATIC = 0x1; private final static int M_PUBLIC = 0x2; private final static int M_PROTECTED = 0x4; private final static int M_PRIVATE = 0x8; private final static int M_FINAL = 0x10; private final static int M_ABSTRACT = 0x20; private final static int M_INTERFACE = 0x40; private final static int IDENTIFIER = 256; private final static int STRING = 257; private final static int LONG = 258; private final static int DOUBLE = 259; private final static int LSHIFT = 260; private final static int RSHIFT = 261; private final static int PHP_END = 262; private final static int EQ = 263; private final static int DEREF = 264; private final static int LEQ = 268; private final static int GEQ = 269; private final static int NEQ = 270; private final static int EQUALS = 271; private final static int NEQUALS = 272; private final static int C_AND = 273; private final static int C_OR = 274; private final static int PLUS_ASSIGN = 278; private final static int MINUS_ASSIGN = 279; private final static int APPEND_ASSIGN = 280; private final static int MUL_ASSIGN = 281; private final static int DIV_ASSIGN = 282; private final static int MOD_ASSIGN = 283; private final static int AND_ASSIGN = 284; private final static int OR_ASSIGN = 285; private final static int XOR_ASSIGN = 286; private final static int LSHIFT_ASSIGN = 287; private final static int RSHIFT_ASSIGN = 288; private final static int INCR = 289; private final static int DECR = 290; private final static int SCOPE = 291; private final static int ESCAPED_STRING = 292; private final static int HEREDOC = 293; private final static int ARRAY_RIGHT = 294; private final static int SIMPLE_STRING_ESCAPE = 295; private final static int COMPLEX_STRING_ESCAPE = 296; private final static int BINARY = 297; private final static int SIMPLE_BINARY_ESCAPE = 298; private final static int COMPLEX_BINARY_ESCAPE = 299; private final static int FIRST_IDENTIFIER_LEXEME = 512; private final static int ECHO = 512; private final static int NULL = 513; private final static int IF = 514; private final static int WHILE = 515; private final static int FUNCTION = 516; private final static int CLASS = 517; private final static int NEW = 518; private final static int RETURN = 519; private final static int VAR = 520; private final static int PRIVATE = 521; private final static int PROTECTED = 522; private final static int PUBLIC = 523; private final static int FOR = 524; private final static int DO = 525; private final static int BREAK = 526; private final static int CONTINUE = 527; private final static int ELSE = 528; private final static int EXTENDS = 529; private final static int STATIC = 530; private final static int INCLUDE = 531; private final static int REQUIRE = 532; private final static int INCLUDE_ONCE = 533; private final static int REQUIRE_ONCE = 534; private final static int UNSET = 535; private final static int FOREACH = 536; private final static int AS = 537; private final static int TEXT = 538; private final static int ISSET = 539; private final static int SWITCH = 540; private final static int CASE = 541; private final static int DEFAULT = 542; private final static int EXIT = 543; private final static int GLOBAL = 544; private final static int ELSEIF = 545; private final static int PRINT = 546; private final static int SYSTEM_STRING = 547; private final static int SIMPLE_SYSTEM_STRING = 548; private final static int COMPLEX_SYSTEM_STRING = 549; private final static int TEXT_ECHO = 550; private final static int ENDIF = 551; private final static int ENDWHILE = 552; private final static int ENDFOR = 553; private final static int ENDFOREACH = 554; private final static int ENDSWITCH = 555; private final static int XOR_RES = 556; private final static int AND_RES = 557; private final static int OR_RES = 558; private final static int LIST = 559; private final static int THIS = 560; private final static int TRUE = 561; private final static int FALSE = 562; private final static int CLONE = 563; private final static int INSTANCEOF = 564; private final static int CONST = 565; private final static int ABSTRACT = 566; private final static int FINAL = 567; private final static int DIE = 568; private final static int THROW = 569; private final static int TRY = 570; private final static int CATCH = 571; private final static int INTERFACE = 572; private final static int IMPLEMENTS = 573; private final static int IMPORT = 574; private final static int TEXT_PHP = 575; private final static int LAST_IDENTIFIER_LEXEME = 1024; private final static IntMap _insensitiveReserved = new IntMap(); private final static IntMap _reserved = new IntMap(); private Quercus _quercus; private Path _sourceFile; private ParserLocation _parserLocation = new ParserLocation(); private ExprFactory _factory; private boolean _hasCr; private int _peek = -1; private ReadStream _is; private String _encoding; private CharBuffer _sb = new CharBuffer(); private int _peekToken = -1; private String _lexeme = ""; private String _heredocEnd = null; private GlobalScope _globalScope; private boolean _returnsReference = false; private Scope _scope; private InterpretedClassDef _classDef; private FunctionInfo _function; private boolean _isTop; private boolean _isNewExpr; private boolean _isIfTest; QuercusParser(Quercus quercus) { _quercus = quercus; _factory = ExprFactory.create(); _globalScope = new GlobalScope(_factory); _scope = _globalScope; } public QuercusParser(Quercus quercus, Path sourceFile, ReadStream is) { this(quercus); if (quercus == null || quercus.isUnicodeSemantics()) init(sourceFile, is, "UTF-8"); else init(sourceFile, is, "ISO-8859-1"); } private void init(Path sourceFile) throws IOException { init(sourceFile, sourceFile.openRead(), "UTF-8"); } private void init(Path sourceFile, ReadStream is, String encoding) { _is = is; _encoding = encoding; if (sourceFile != null) { _parserLocation.setFileName(sourceFile.getPath()); _sourceFile = sourceFile; } else { _parserLocation.setFileName("eval:"); // php/2146 _sourceFile = new NullPath("eval:"); } _parserLocation.setLineNumber(1); _peek = -1; _peekToken = -1; } public void setLocation(String fileName, int line) { _parserLocation.setFileName(fileName); _parserLocation.setLineNumber(line); } public static QuercusProgram parse(Quercus quercus, Path path, String encoding) throws IOException { ReadStream is = path.openRead(); try { is.setEncoding(encoding); QuercusParser parser; parser = new QuercusParser(quercus, path, is); return parser.parse(); } finally { is.close(); } } public static QuercusProgram parse(Quercus quercus, Path path, String encoding, String fileName, int line) throws IOException { ReadStream is = path.openRead(); try { is.setEncoding(encoding); QuercusParser parser; parser = new QuercusParser(quercus, path, is); if (fileName != null && line >= 0) parser.setLocation(fileName, line); return parser.parse(); } finally { is.close(); } } public static QuercusProgram parse(Quercus quercus, ReadStream is) throws IOException { QuercusParser parser; parser = new QuercusParser(quercus, is.getPath(), is); return parser.parse(); } public static QuercusProgram parse(Quercus quercus, Path path, ReadStream is) throws IOException { return new QuercusParser(quercus, path, is).parse(); } public static QuercusProgram parseEval(Quercus quercus, String str) throws IOException { Path path = new StringPath(str); QuercusParser parser = new QuercusParser(quercus, path, path.openRead()); return parser.parseCode(); } public static QuercusProgram parseEvalExpr(Quercus quercus, String str) throws IOException { Path path = new StringPath(str); QuercusParser parser = new QuercusParser(quercus, path, path.openRead()); return parser.parseCode().createExprReturn(); } public static AbstractFunction parseFunction(Quercus quercus, String name, String args, String code) throws IOException { Path argPath = new StringPath(args); Path codePath = new StringPath(code); QuercusParser parser = new QuercusParser(quercus); Function fun = parser.parseFunction(name, argPath, codePath); return fun; } public static Expr parse(Quercus quercus, String str) throws IOException { Path path = new StringPath(str); return new QuercusParser(quercus, path, path.openRead()).parseExpr(); } public static Expr parseDefault(String str) { try { Path path = new StringPath(str); return new QuercusParser(null, path, path.openRead()).parseExpr(); } catch (IOException e) { throw new QuercusRuntimeException(e); } } /** * Returns the current filename. */ public String getFileName() { if (_sourceFile == null) return null; else return _sourceFile.getPath(); } /** * Returns the current line */ public int getLine() { return _parserLocation.getLineNumber(); } public ExprFactory getExprFactory() { return _factory; } public ExprFactory getFactory() { return _factory; } public QuercusProgram parse() throws IOException { _function = getFactory().createFunctionInfo(_quercus, ""); _function.setPageMain(true); // quercus/0b0d _function.setVariableVar(true); _function.setUsesSymbolTable(true); Statement stmt = parseTop(); QuercusProgram program = new QuercusProgram(_quercus, _sourceFile, _globalScope.getFunctionMap(), _globalScope.getClassMap(), _function, stmt); return program; /* com.caucho.vfs.WriteStream out = com.caucho.vfs.Vfs.lookup("stdout:").openWrite(); out.setFlushOnNewline(true); stmt.debug(new JavaWriter(out)); */ } QuercusProgram parseCode() throws IOException { _function = getFactory().createFunctionInfo(_quercus, "eval"); // XXX: need param or better function name for non-global? _function.setGlobal(false); Location location = getLocation(); ArrayList<Statement> stmtList = parseStatementList(); return new QuercusProgram(_quercus, _sourceFile, _globalScope.getFunctionMap(), _globalScope.getClassMap(), _function, _factory.createBlock(location, stmtList)); } Function parseFunction(String name, Path argPath, Path codePath) throws IOException { _function = getFactory().createFunctionInfo(_quercus, name); _function.setGlobal(false); _function.setPageMain(true); init(argPath); Arg []args = parseFunctionArgDefinition(); init(codePath); Statement []statements = parseStatements(); return _factory.createFunction(Location.UNKNOWN, name, _function, args, statements); } /** * Parses the top page. */ Statement parseTop() throws IOException { _isTop = true; ArrayList<Statement> statements = new ArrayList<Statement>(); Location location = getLocation(); int token = parsePhpText(); if (_lexeme.length() > 0) statements.add(_factory.createText(location, _lexeme)); if (token == TEXT_ECHO) { parseEcho(statements); } else if (token == TEXT_PHP) { _peekToken = parseToken(); if (_peekToken == IDENTIFIER && _lexeme.equalsIgnoreCase("php")) { _peekToken = -1; } } statements.addAll(parseStatementList()); return _factory.createBlock(location, statements); } /* * Parses a statement list. */ private Statement []parseStatements() throws IOException { ArrayList<Statement> statementList = parseStatementList(); Statement []statements = new Statement[statementList.size()]; statementList.toArray(statements); return statements; } /** * Parses a statement list. */ private ArrayList<Statement> parseStatementList() throws IOException { ArrayList<Statement> statementList = new ArrayList<Statement>(); while (true) { Location location = getLocation(); int token = parseToken(); switch (token) { case -1: return statementList; case ';': break; case ECHO: parseEcho(statementList); break; case PRINT: statementList.add(parsePrint()); break; case UNSET: parseUnset(statementList); break; case ABSTRACT: case FINAL: { _peekToken = token; int modifiers = 0; do { token = parseToken(); switch (token) { case ABSTRACT: modifiers |= M_ABSTRACT; break; case FINAL: modifiers |= M_FINAL; break; case CLASS: parseClassDefinition(modifiers); break; default: throw error(L.l("expected 'class' at {0}", tokenName(token))); } } while (token != CLASS); } break; case FUNCTION: { Location functionLocation = getLocation(); Function fun = parseFunctionDefinition(M_STATIC); if (! _isTop) { statementList.add(_factory.createFunctionDef(functionLocation, fun)); } } break; case CLASS: // parseClassDefinition(0); statementList.add(parseClassDefinition(0)); break; case INTERFACE: // parseClassDefinition(M_INTERFACE); statementList.add(parseClassDefinition(M_INTERFACE)); break; case IF: statementList.add(parseIf()); break; case SWITCH: statementList.add(parseSwitch()); break; case WHILE: statementList.add(parseWhile()); break; case DO: statementList.add(parseDo()); break; case FOR: statementList.add(parseFor());
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -