/* +----------------------------------------------------------------------+ | 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 __HPHP_UTIL_PARSER_PARSER_H__ #define __HPHP_UTIL_PARSER_PARSER_H__ #include #include #include #define IMPLEMENT_XHP_ATTRIBUTES \ Token m_xhpAttributes; \ Token *xhpGetAttributes() { \ if (m_xhpAttributes.num()) { \ return &m_xhpAttributes; \ } \ return nullptr; \ } \ void xhpSetAttributes(Token &t) { \ m_xhpAttributes = t; \ m_xhpAttributes = 1; \ } \ void xhpResetAttributes() { \ m_xhpAttributes.reset(); \ } \ // NOTE: system/classes/closure.php may have reference to these strings: #define CONTINUATION_OBJECT_NAME "__cont__" #define TYPED_CONTINUATION_OBJECT_NAME "__typedCont__" #define FOREACH_VAR_PREFIX "__foreach__" #define NAMESPACE_SEP '\\' namespace HPHP { /////////////////////////////////////////////////////////////////////////////// typedef void * TStatementPtr; class ParserBase { public: enum NameKind { StringName, VarName, ExprName, StaticClassExprName, StaticName }; /** * These numbers are scattered throughout the code base (often hardcoded). * Do not change unless you change all the occurances. */ enum AnonFuncKind { Closure, CreateFunction, ContinuationFromClosure, Continuation }; enum AnonFuncKindChar { CharClosure = '0', CharCreateFunction, CharContinuationFromClosure, CharContinuation }; static char GetAnonPrefix(AnonFuncKind kind); static bool IsClosureName (const std::string &name); static bool IsCreateFunctionName (const std::string &name); static bool IsContinuationName (const std::string &name); static bool IsContinuationFromClosureName(const std::string &name); static bool IsClosureOrContinuationName (const std::string &name); static bool IsAnonFunctionName (const std::string &name) { return IsAnonFunctionName(name.c_str()); } static bool IsAnonFunctionName (const char *name); /** * Reset parser static variables. Good for unit tests. */ static void Reset(); public: ParserBase(Scanner &scanner, const char *fileName); virtual ~ParserBase(); Scanner &scanner() { return m_scanner;} /** * Main function to call to start parsing the file. This function is already * implemented in hphp.y. Therefore, a subclass only has to declare it. */ virtual bool parseImpl() = 0; /** * Raise a parser error. */ virtual void error(const char* fmt, ...) = 0; /** * How to decide whether to turn on XHP. */ virtual bool enableXHP() = 0; /** * Check if HipHop syntax is enabled. */ virtual bool enableHipHopSyntax() = 0; /** * Public accessors. */ const char *file() const { return m_fileName;} std::string getMessage(bool filename = false) const; std::string getMessage(Location *loc, bool filename = false) const; LocationPtr getLocation() const; void getLocation(Location &loc) const { loc = m_loc; loc.file = file(); } int line0() const { return m_loc.line0;} int char0() const { return m_loc.char0;} int line1() const { return m_loc.line1;} int char1() const { return m_loc.char1;} // called by generated code int scan(ScannerToken *token, Location *loc) { return m_scanner.getNextToken(*token, *loc); } void setRuleLocation(Location *loc) { m_loc = *loc; } virtual void fatal(Location *loc, const char *msg) {} void pushFuncLocation(); LocationPtr popFuncLocation(); void pushClass(bool isXhpClass); bool peekClass(); void popClass(); std::string getAnonFuncName(AnonFuncKind kind); // for typevar checking void pushTypeScope(); void popTypeScope(); void addTypeVar(const std::string &name); bool isTypeVar(const std::string &name); // for goto syntax checking void pushLabelInfo(); void pushLabelScope(); void popLabelScope(); void addLabel(const std::string &label, LocationPtr loc, ScannerToken *stmt); void addGoto(const std::string &label, LocationPtr loc, ScannerToken *stmt); void popLabelInfo(); // for namespace support void onNamespaceStart(const std::string &ns); void onNamespaceEnd(); void onUse(const std::string &ns, const std::string &as); void nns(bool declare = false); std::string nsDecl(const std::string &name); std::string resolve(const std::string &ns, bool cls); enum GotoError { UndefLabel = 1, InvalidBlock, }; virtual void invalidateGoto(TStatementPtr expr, GotoError error) = 0; virtual void invalidateLabel(TStatementPtr expr) = 0; virtual TStatementPtr extractStatement(ScannerToken *stmt) = 0; protected: Scanner &m_scanner; const char *m_fileName; Location m_loc; LocationPtrVec m_funcLocs; std::vector m_classes; // used to determine if we are currently // inside a regular class or an XHP class struct LabelStmtInfo { int scopeId; TStatementPtr stmt; bool inTryCatchBlock; LocationPtr loc; }; typedef std::map LabelMap; // name => LabelStmtInfo typedef std::set TypevarScope; typedef std::vector TypevarScopeStack; TypevarScope m_typeVars; TypevarScopeStack m_typeScopes; // for goto syntax checking typedef std::vector LabelScopes; struct GotoInfo { std::string label; LabelScopes scopes; LocationPtr loc; TStatementPtr stmt; }; class LabelInfo { public: LabelInfo() : scopeId(0) {} int scopeId; LabelScopes scopes; LabelMap labels; std::vector gotos; }; std::vector m_labelInfos; // stack by function // for namespace support enum NamespaceState { SeenNothing, SeenNonNamespaceStatement, SeenNamespaceStatement, InsideNamespace, }; NamespaceState m_nsState; std::string m_namespace; // current namespace hphp_string_imap m_aliases; // for closure hidden name static Mutex s_mutex; static std::map s_closureIds; }; /////////////////////////////////////////////////////////////////////////////// } #endif // __HPHP_UTIL_PARSER_PARSER_H__