Arquivos
hhvm/hphp/compiler/parser/parser.h
T
Sara Golemon 38f9fab773 Fix __HALT_COMPILER() support
Actually halt the compiler, and set __COMPILER_HALT_OFFSET__ constant
2013-05-01 20:59:44 -07:00

334 linhas
13 KiB
C++

/*
+----------------------------------------------------------------------+
| HipHop for PHP |
+----------------------------------------------------------------------+
| Copyright (c) 2010- Facebook, Inc. (http://www.facebook.com) |
+----------------------------------------------------------------------+
| This source file is subject to version 3.01 of the PHP license, |
| that is bundled with this package in the file LICENSE, and is |
| available through the world-wide-web at the following url: |
| http://www.php.net/license/3_01.txt |
| If you did not receive a copy of the PHP license and are unable to |
| obtain it through the world-wide-web, please send a note to |
| license@php.net so we can mail you a copy immediately. |
+----------------------------------------------------------------------+
*/
#ifndef incl_HPHP_COMPILER_PARSER_H_
#define incl_HPHP_COMPILER_PARSER_H_
#include "runtime/base/util/exceptions.h"
#include "util/parser/parser.h"
#include "compiler/construct.h"
#include "compiler/option.h"
#include "compiler/type_annotation.h"
#include "compiler/expression/scalar_expression.h"
#ifdef HPHP_PARSER_NS
#undef HPHP_PARSER_NS
#endif
#define HPHP_PARSER_NS Compiler
#ifdef HPHP_PARSER_ERROR
#undef HPHP_PARSER_ERROR
#endif
#define HPHP_PARSER_ERROR(fmt, p, args...) \
do { \
if (HPHP::Option::WholeProgram) { \
HPHP::Logger::Error(fmt " %s", ##args, (p)->getMessage(true).c_str()); \
} \
throw HPHP::ParseTimeFatalException((p)->file(), (p)->line1(), \
fmt, ##args); \
} while (0)
namespace HPHP {
///////////////////////////////////////////////////////////////////////////////
DECLARE_BOOST_TYPES(Expression);
DECLARE_BOOST_TYPES(Statement);
DECLARE_BOOST_TYPES(StatementList);
DECLARE_BOOST_TYPES(Location);
DECLARE_BOOST_TYPES(AnalysisResult);
DECLARE_BOOST_TYPES(BlockScope);
DECLARE_BOOST_TYPES(TypeAnnotation);
namespace Compiler {
///////////////////////////////////////////////////////////////////////////////
// scanner
class Token : public ScannerToken {
public:
ExpressionPtr exp;
StatementPtr stmt;
TypeAnnotationPtr typeAnnotation;
Token &operator+(const char *str) {
m_text += str;
return *this;
}
Token &operator+(const Token &token) {
m_num += token.m_num;
m_text += token.m_text;
return *this;
}
Token *operator->() {
return this;
}
void operator=(int num) {
m_num = num;
}
void operator=(Token &other) {
ScannerToken::operator=(other);
exp = other.exp;
stmt = other.stmt;
typeAnnotation = other.typeAnnotation;
}
void reset() {
exp.reset();
stmt.reset();
typeAnnotation.reset();
ScannerToken::reset();
}
const std::string typeAnnotationName() {
return (typeAnnotation) ? typeAnnotation->fullName() : "";
}
};
///////////////////////////////////////////////////////////////////////////////
DECLARE_BOOST_TYPES(Parser);
class Parser : public ParserBase {
public:
static StatementListPtr ParseString(CStrRef input, AnalysisResultPtr ar,
const char *fileName = nullptr,
bool lambdaMode = false);
public:
Parser(Scanner &scanner, const char *fileName,
AnalysisResultPtr ar, int fileSize = 0);
// implementing ParserBase
virtual bool parseImpl();
bool parse();
virtual void error(const char* fmt, ...);
virtual bool enableXHP();
virtual bool enableHipHopSyntax();
virtual bool enableFinallyStatement();
IMPLEMENT_XHP_ATTRIBUTES;
virtual void fatal(Location *loc, const char *msg);
std::string errString();
// result
StatementListPtr getTree() const { return m_tree;}
// parser handlers
void initParseTree();
void finiParseTree();
void onHaltCompiler();
void onName(Token &out, Token &name, NameKind kind);
void onVariable(Token &out, Token *exprs, Token &var, Token *value,
bool constant = false,
const std::string &docComment = "");
void onStaticVariable(Token &out, Token *exprs, Token &var, Token *value);
void onClassVariableModifer(Token &mod) {}
void onClassVariableStart(Token &out, Token *modifiers, Token &decl,
Token *type);
void onClassVariable(Token &out, Token *exprs, Token &var, Token *value);
void onClassConstant(Token &out, Token *exprs, Token &var, Token &value);
void onSimpleVariable(Token &out, Token &var);
void onSynthesizedVariable(Token &out, Token &var) {
onSimpleVariable(out, var);
}
void onDynamicVariable(Token &out, Token &expr, bool encap);
void onIndirectRef(Token &out, Token &refCount, Token &var);
void onStaticMember(Token &out, Token &cls, Token &name);
void onRefDim(Token &out, Token &var, Token &offset);
void onCallParam(Token &out, Token *params, Token &expr, bool ref);
void onCall(Token &out, bool dynamic, Token &name, Token &params,
Token *cls, bool fromCompiler = false);
void onEncapsList(Token &out, int type, Token &list);
void addEncap(Token &out, Token *list, Token &expr, int type);
void encapRefDim(Token &out, Token &var, Token &offset);
void encapObjProp(Token &out, Token &var, Token &name);
void encapArray(Token &out, Token &var, Token &expr);
void onConstantValue(Token &out, Token &constant);
void onScalar(Token &out, int type, Token &scalar);
void onExprListElem(Token &out, Token *exprs, Token &expr);
void onObjectProperty(Token &out, Token &base, Token &prop);
void onObjectMethodCall(Token &out, Token &base, Token &prop, Token &params);
void onListAssignment(Token &out, Token &vars, Token *expr,
bool rhsFirst = false);
void onAListVar(Token &out, Token *list, Token *var);
void onAListSub(Token &out, Token *list, Token &sublist);
void onAssign(Token &out, Token &var, Token &expr, bool ref,
bool rhsFirst = false);
void onAssignNew(Token &out, Token &var, Token &name, Token &args);
void onNewObject(Token &out, Token &name, Token &args);
void onUnaryOpExp(Token &out, Token &operand, int op, bool front);
void onBinaryOpExp(Token &out, Token &operand1, Token &operand2, int op);
void onQOp(Token &out, Token &exprCond, Token *expYes, Token &expNo);
void onArray(Token &out, Token &pairs, int op = T_ARRAY);
void onArrayPair(Token &out, Token *pairs, Token *name, Token &value,
bool ref);
void onEmptyCollection(Token &out);
void onCollectionPair(Token &out, Token *pairs, Token *name, Token &value);
void onUserAttribute(Token &out, Token *attrList, Token &name, Token &value);
void onClassConst(Token &out, Token &cls, Token &name, bool text);
void fixStaticVars();
void onFunctionStart(Token &name, bool doPushComment = true);
void onFunction(Token &out, Token *modifier, Token &ret, Token &ref,
Token &name, Token &params, Token &stmt, Token *attr);
void onParam(Token &out, Token *params, Token &type, Token &var,
bool ref, Token *defValue, Token *attr);
void onClassStart(int type, Token &name);
void onClass(Token &out, int type, Token &name, Token &base,
Token &baseInterface, Token &stmt, Token *attr);
void onInterface(Token &out, Token &name, Token &base, Token &stmt,
Token *attr);
void onInterfaceName(Token &out, Token *names, Token &name);
void onTraitUse(Token &out, Token &traits, Token &rules);
void onTraitName(Token &out, Token *names, Token &name);
void onTraitRule(Token &out, Token &stmtList, Token &newStmt);
void onTraitPrecRule(Token &out, Token &className, Token &methodName,
Token &otherClasses);
void onTraitAliasRuleStart(Token &out, Token &className, Token &methodName);
void onTraitAliasRuleModify(Token &out, Token &rule, Token &accessModifiers,
Token &newMethodName);
void onMethodStart(Token &name, Token &mods, bool doPushComment = true);
void onMethod(Token &out, Token &modifiers, Token &ret, Token &ref,
Token &name, Token &params, Token &stmt, Token *attr,
bool reloc = true);
void onMemberModifier(Token &out, Token *modifiers, Token &modifier);
void onStatementListStart(Token &out);
void addStatement(Token &out, Token &stmts, Token &new_stmt);
void addTopStatement(Token &new_stmt);
void onClassStatement(Token &out, Token &stmts, Token &new_stmt) {
addStatement(out, stmts, new_stmt);
}
void finishStatement(Token &out, Token &stmts);
void onBlock(Token &out, Token &stmts);
void onIf(Token &out, Token &cond, Token &stmt, Token &elseifs,
Token &elseStmt);
void onElseIf(Token &out, Token &elseifs, Token &cond, Token &stmt);
void onWhile(Token &out, Token &cond, Token &stmt);
void onDo(Token &out, Token &stmt, Token &cond);
void onFor(Token &out, Token &expr1, Token &expr2, Token &expr3,
Token &stmt);
void onSwitch(Token &out, Token &expr, Token &cases);
void onCase(Token &out, Token &cases, Token *cond, Token &stmt);
void onBreak(Token &out, Token *expr);
void onContinue(Token &out, Token *expr);
void onReturn(Token &out, Token *expr);
void onYield(Token &out, Token &expr);
void onYieldBreak(Token &out);
void onGlobal(Token &out, Token &expr);
void onGlobalVar(Token &out, Token *exprs, Token &expr);
void onStatic(Token &out, Token &expr);
void onEcho(Token &out, Token &expr, bool html);
void onUnset(Token &out, Token &expr);
void onExpStatement(Token &out, Token &expr);
void onForEachStart();
void onForEach(Token &out, Token &arr, Token &name, Token &value,
Token &stmt);
void onTry(Token &out, Token &tryStmt, Token &className, Token &var,
Token &catchStmt, Token &catches, Token &finallyStmt);
void onTry(Token &out, Token &tryStmt, Token &finallyStmt);
void onCatch(Token &out, Token &catches, Token &className, Token &var,
Token &stmt);
void onFinally(Token &out, Token &stmt);
void onThrow(Token &out, Token &expr);
void onClosureStart(Token &name);
void onClosure(Token &out, Token &ret, Token &ref, Token &params,
Token &cparams, Token &stmts, bool is_static);
void onClosureParam(Token &out, Token *params, Token &param, bool ref);
void onLabel(Token &out, Token &label);
void onGoto(Token &out, Token &label, bool limited);
void onTypedef(Token& out, const Token& name, const Token& type);
void onTypeAnnotation(Token& out, const Token& name, const Token& typeArgs);
void onTypeList(Token& type1, const Token& type2);
void onTypeSpecialization(Token& type, char specialization);
virtual void invalidateGoto(TStatementPtr stmt, GotoError error);
virtual void invalidateLabel(TStatementPtr stmt);
virtual TStatementPtr extractStatement(ScannerToken *stmt);
FileScopePtr getFileScope() { return m_file; }
private:
struct FunctionContext {
FunctionContext()
: isNotGenerator(false)
, isGenerator(false)
{}
// mark this function as generator; returns true on success
bool setIsGenerator() {
if (!isNotGenerator) isGenerator = true;
return !isNotGenerator;
}
// mark this function as non-generator; returns true on success
bool setIsNotGenerator() {
if (!isGenerator) isNotGenerator = true;
return !isGenerator;
}
void checkFinalAssertions() {
assert(!isGenerator || !isNotGenerator);
}
bool isNotGenerator; // function determined to not be a generator
bool isGenerator; // function determined to be a generator
};
AnalysisResultPtr m_ar;
FileScopePtr m_file;
std::vector<std::string> m_comments; // for docComment stack
std::vector<BlockScopePtrVec> m_scopes;
std::vector<FunctionContext> m_funcContexts;
std::vector<std::vector<StatementPtr> > m_prependingStatements;
std::vector<ScalarExpressionPtr> m_compilerHaltOffsetVec;
std::string m_clsName; // for T_CLASS_C inside a closure
std::string m_funcName;
bool m_inTrait;
// parser output
StatementListPtr m_tree;
std::string m_error;
std::vector<bool> m_hasCallToGetArgs;
std::vector<StringToExpressionPtrVecMap> m_staticVars;
bool m_lambdaMode;
bool m_closureGenerator;
void pushComment();
void pushComment(const std::string& s);
std::string popComment();
void newScope();
void completeScope(BlockScopePtr inner);
bool setIsGenerator();
ExpressionPtr getDynamicVariable(ExpressionPtr exp, bool encap);
ExpressionPtr createDynamicVariable(ExpressionPtr exp);
bool hasType(Token &type);
void checkAssignThis(Token &var);
void addStatement(StatementPtr stmt, StatementPtr new_stmt);
};
///////////////////////////////////////////////////////////////////////////////
}}
#endif