void PHPSourceFile::Parse(int exitDepth) { int retDepth = exitDepth; phpLexerToken token; while(NextToken(token)) { switch(token.type) { case '=': m_lookBackTokens.clear(); break; case '{': m_lookBackTokens.clear(); break; case '}': m_lookBackTokens.clear(); if(m_depth == retDepth) { return; } break; case ';': m_lookBackTokens.clear(); break; case kPHP_T_VARIABLE: if(!CurrentScope()->Is(kEntityTypeClass)) { // A global variable OnVariable(token); } break; case kPHP_T_CATCH: // found 'catch (...)' OnCatch(); break; case kPHP_T_PUBLIC: case kPHP_T_PRIVATE: case kPHP_T_PROTECTED: { int visibility = token.type; PHPEntityClass* cls = CurrentScope()->Cast<PHPEntityClass>(); if(cls) { /// keep the current token m_lookBackTokens.push_back(token); // Now we have a small problem here: // public can be a start for a member or a function // we let the lexer run forward until it finds kPHP_T_VARIABLE (for variable) // or kPHP_T_IDENTIFIER int what = ReadUntilFoundOneOf(kPHP_T_VARIABLE, kPHP_T_FUNCTION, token); if(what == kPHP_T_VARIABLE) { // A variable PHPEntityBase::Ptr_t member(new PHPEntityVariable()); member->SetFilename(m_filename.GetFullPath()); member->Cast<PHPEntityVariable>()->SetVisibility(visibility); member->Cast<PHPEntityVariable>()->SetFullName(token.text); size_t flags = LookBackForVariablesFlags(); member->Cast<PHPEntityVariable>()->SetFlag(kVar_Member); member->Cast<PHPEntityVariable>()->SetFlag(kVar_Const, flags & kVar_Const); member->Cast<PHPEntityVariable>()->SetFlag(kVar_Static, flags & kVar_Static); member->Cast<PHPEntityVariable>()->SetLine(token.lineNumber); CurrentScope()->AddChild(member); // Handle member assignment // public $memberVar = new Something(); // for such cases, assign $memberVar type of Something() phpLexerToken t; if(!NextToken(t)) { // EOF return; } if(t.type == '=') { // assignment wxString expr; if(!ReadExpression(expr)) { return; } // Optimize 'new ClassName(..)' expression if(expr.StartsWith("new")) { expr = expr.Mid(3); expr.Trim().Trim(false); expr = expr.BeforeFirst('('); expr.Trim().Trim(false); member->Cast<PHPEntityVariable>()->SetTypeHint(MakeIdentifierAbsolute(expr)); } else { // keep the expression member->Cast<PHPEntityVariable>()->SetExpressionHint(expr); } } else { // restore the token UngetToken(t); if(!ConsumeUntil(';')) return; } } else if(what == kPHP_T_FUNCTION) { // A function... OnFunction(); m_lookBackTokens.clear(); } } break; } case kPHP_T_DEFINE: // Define statement OnDefine(token); break; case kPHP_T_CONST: OnConstant(token); break; case kPHP_T_REQUIRE: case kPHP_T_REQUIRE_ONCE: case kPHP_T_INCLUDE: case kPHP_T_INCLUDE_ONCE: // Handle include files m_lookBackTokens.clear(); break; case kPHP_T_FOREACH: // found "foreach" statement OnForEach(); m_lookBackTokens.clear(); break; case kPHP_T_USE: // Found outer 'use' statement - construct the alias table if(Class()) { // inside a class, this means that this is a 'use <trait>;' OnUseTrait(); } else { // alias table OnUse(); } m_lookBackTokens.clear(); break; case kPHP_T_CLASS: case kPHP_T_INTERFACE: case kPHP_T_TRAIT: // Found class OnClass(token); m_lookBackTokens.clear(); break; case kPHP_T_NAMESPACE: // Found a namespace OnNamespace(); m_lookBackTokens.clear(); break; case kPHP_T_FUNCTION: // Found function OnFunction(); m_lookBackTokens.clear(); break; default: // Keep the token break; } } PhaseTwo(); }
void PHPSourceFile::Parse(int exitDepth) { int retDepth = exitDepth; phpLexerToken token; while(NextToken(token)) { switch(token.type) { case '=': m_lookBackTokens.clear(); break; case '{': m_lookBackTokens.clear(); break; case '}': m_lookBackTokens.clear(); if(m_depth == retDepth) { return; } break; case ';': m_lookBackTokens.clear(); break; case kPHP_T_VARIABLE: if(!CurrentScope()->Is(kEntityTypeClass)) { // A global variable OnVariable(token); } break; case kPHP_T_CATCH: // found 'catch (...)' OnCatch(); break; case kPHP_T_PUBLIC: case kPHP_T_PRIVATE: case kPHP_T_PROTECTED: { int visibility = token.type; PHPEntityClass* cls = CurrentScope()->Cast<PHPEntityClass>(); if(cls) { /// keep the current token m_lookBackTokens.push_back(token); // Now we have a small problem here: // public can be a start for a member or a function // we let the lexer run forward until it finds kPHP_T_VARIABLE (for variable) // or kPHP_T_IDENTIFIER int what = ReadUntilFoundOneOf(kPHP_T_VARIABLE, kPHP_T_FUNCTION, token); if(what == kPHP_T_VARIABLE) { // A variable PHPEntityBase::Ptr_t member(new PHPEntityVariable()); member->SetFilename(m_filename.GetFullPath()); PHPEntityVariable* var = member->Cast<PHPEntityVariable>(); var->SetVisibility(visibility); var->SetFullName(token.text); size_t flags = LookBackForVariablesFlags(); var->SetFlag(kVar_Member); var->SetFlag(kVar_Const, flags & kVar_Const); var->SetFlag(kVar_Static, flags & kVar_Static); var->SetLine(token.lineNumber); CurrentScope()->AddChild(member); if(!ConsumeUntil(';')) return; } else if(what == kPHP_T_FUNCTION) { // A function... OnFunction(); m_lookBackTokens.clear(); } } break; } case kPHP_T_DEFINE: // Define statement OnDefine(token); break; case kPHP_T_CONST: if(ReadUntilFound(kPHP_T_IDENTIFIER, token)) { // constant PHPEntityBase::Ptr_t member(new PHPEntityVariable()); member->SetFilename(m_filename.GetFullPath()); PHPEntityVariable* var = member->Cast<PHPEntityVariable>(); var->SetFullName(token.text); var->SetLine(token.lineNumber); var->SetFlag(kVar_Member); var->SetFlag(kVar_Const); CurrentScope()->AddChild(member); if(!ConsumeUntil(';')) return; } break; case kPHP_T_REQUIRE: case kPHP_T_REQUIRE_ONCE: case kPHP_T_INCLUDE: case kPHP_T_INCLUDE_ONCE: // Handle include files m_lookBackTokens.clear(); break; case kPHP_T_USE: // Found outer 'use' statement - construct the alias table if(Class()) { // inside a class, this means that this is a 'use <trait>;' OnUseTrait(); } else { // alias table OnUse(); } m_lookBackTokens.clear(); break; case kPHP_T_CLASS: case kPHP_T_INTERFACE: case kPHP_T_TRAIT: // Found class OnClass(token); m_lookBackTokens.clear(); break; case kPHP_T_NAMESPACE: // Found a namespace OnNamespace(); m_lookBackTokens.clear(); break; case kPHP_T_FUNCTION: // Found function OnFunction(); m_lookBackTokens.clear(); break; default: // Keep the token break; } } PhaseTwo(); }