Example #1
0
void XMLBuffer::Parse()
{
    m_elements.clear();
    CHECK_PTR_RET(m_scanner);
    XMLLexerToken token;
    m_state = kNormal;
    while(::xmlLexerNext(m_scanner, token)) {
        switch(token.type) {
        case kXML_T_CDATA_START:
            m_state = kCdata;
            if(ConsumeUntil(kXML_T_CDATA_END)) {
                m_state = kNormal;
            }
            break;
        case kXML_T_COMMENT_START:
            m_state = kComment;
            if(ConsumeUntil(kXML_T_COMMENT_END)) {
                m_state = kNormal;
            }
            break;
        case '<':
            // "<" was found
            OnOpenTag();
            break;
        case '>':
            // ">" was found. If in HTML mode and the current scope is an open tag
            // pop it
            OnCloseTag();
            break;
        case kXML_T_CLOSE_TAG_PREFIX:
            // "</" was found
            OnTagClosePrefix();
            break;
        case kXML_T_CLOSE_TAG_SUFFIX:
            // "/>" closing tag was found
            if(!m_elements.empty()) m_elements.pop_back();
            break;
        default:
            break;
        }
    }
}
Example #2
0
void PHPSourceFile::OnDefine(const phpLexerToken& tok)
{
    phpLexerToken token;
    if(!NextToken(token)) return; // EOF
    if(token.type != '(') {
        ConsumeUntil(';');
        return;
    }
    if(!NextToken(token)) return; // EOF
    if(token.type != kPHP_T_CONSTANT_ENCAPSED_STRING) {
        ConsumeUntil(';');
        return;
    }
    // Remove the quotes
    wxString varName = token.text;
    if((varName.StartsWith("\"") && varName.EndsWith("\"")) || (varName.StartsWith("'") && varName.EndsWith("'"))) {
        varName.Remove(0, 1);
        varName.RemoveLast();
        // define() defines constants exactly as it was instructed
        // i.e. it does not take the current namespace into consideration
        PHPEntityBase::Ptr_t var(new PHPEntityVariable());

        // Convert the variable into fullpath + relative name
        if(!varName.StartsWith("\\")) {
            varName.Prepend("\\");
        }
        wxString shortName = varName.AfterLast('\\');
        var->SetFullName(varName);
        var->SetShortName(shortName);
        var->SetFlag(kVar_Define);
        var->SetFilename(GetFilename());
        var->SetLine(tok.lineNumber);

        // We keep the defines in a special list
        // this is because 'define' does not obay to the current scope
        m_defines.push_back(var);
    }
    // Always consume the 'define' statement
    ConsumeUntil(';');
}
Example #3
0
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();
}
Example #4
0
void PHPSourceFile::OnFunction()
{
    // read the next token
    phpLexerToken token;
    if(!NextToken(token)) {
        return;
    }

    bool funcReturnRef = false;
    if(token.type == '&') {
        funcReturnRef = true;
        if(!NextToken(token)) {
            return;
        }
    }

    PHPEntityFunction* func(NULL);
    int funcDepth(0);
    if(token.type == kPHP_T_IDENTIFIER) {
        // the function name
        func = new PHPEntityFunction();
        func->SetFullName(token.text);
        func->SetLine(token.lineNumber);

    } else if(token.type == '(') {
        funcDepth = 1; // Since we already consumed the open brace
        // anonymous function
        func = new PHPEntityFunction();
        func->SetLine(token.lineNumber);
    }

    if(!func) return;
    PHPEntityBase::Ptr_t funcPtr(func);
    if(funcReturnRef) {
        funcPtr->SetFlag(kFunc_ReturnReference);
    }

    // add the function to the current scope
    CurrentScope()->AddChild(funcPtr);

    // Set the function as the current scope
    m_scopes.push_back(funcPtr);

    // update function attributes
    ParseFunctionSignature(funcDepth);
    func->SetFlags(LookBackForFunctionFlags());
    if(LookBackTokensContains(kPHP_T_ABSTRACT) || // The 'abstract modifier was found for this this function
        (funcPtr->Parent() && funcPtr->Parent()->Is(kEntityTypeClass) &&
            funcPtr->Parent()->Cast<PHPEntityClass>()->IsInterface())) // We are inside an interface
    {
        // Mark this function as an abstract function
        func->SetFlags(func->GetFlags() | kFunc_Abstract);
    }

    if(func->HasFlag(kFunc_Abstract)) {
        // an abstract function - it has no body
        if(!ConsumeUntil(';')) {
            // could not locate the function delimiter, remove it from the stack
            // we probably reached EOF here
            m_scopes.pop_back();
        }

    } else {
        if(!NextToken(token)) return;
        if(token.type == ':') {
            // PHP 7 signature type
            // function foobar(...) : RETURN_TYPE
            wxString returnValuetype = ReadType();
            if(returnValuetype.IsEmpty()) return; // parse error
            func->SetReturnValue(returnValuetype);

        } else {
            // untake the token and place it back on the "unget" list
            UngetToken(token);
        }

        if(ReadUntilFound('{', token)) {
            // found the function body starting point
            if(IsParseFunctionBody()) {
                ParseFunctionBody();
            } else {
                // Consume the function body
                ConsumeFunctionBody();
            }
        } else {
            // could not locate the open brace!
            // remove this function from the stack
            m_scopes.pop_back();
        }
    }

    // Remove the current function from the scope list
    if(!m_reachedEOF) {
        m_scopes.pop_back();
    }
    m_lookBackTokens.clear();
}
Example #5
0
void PHPSourceFile::ParseUseTraitsBody()
{
    wxString fullname, alias, temp;
    phpLexerToken token;
    bool cont = true;
    while(cont && NextToken(token)) {
        switch(token.type) {
        case '}': {
            cont = false;
        } break;
        case ',':
        case ';': {
            if(fullname.IsEmpty()) {
                // no full name yet
                fullname.swap(temp);

            } else if(alias.IsEmpty()) {
                alias.swap(temp);
            }

            if(alias.IsEmpty()) {
                // no alias provided, use the last part of the fullname
                alias = fullname.AfterLast('\\');
            }

            if(!fullname.IsEmpty() && !alias.IsEmpty()) {
                // Use namespace is alway refered as fullpath namespace
                // So writing:
                // use Zend\Mvc\Controll\Action;
                // is equal for writing:
                // use \Zend\Mvc\Controll\Action;
                // For simplicitiy, we change it to fully qualified path
                // so parsing is easier
                if(!fullname.StartsWith("\\")) {
                    fullname.Prepend("\\");
                }
                PHPEntityBase::Ptr_t funcAlias(new PHPEntityFunctionAlias());
                funcAlias->Cast<PHPEntityFunctionAlias>()->SetRealname(MakeIdentifierAbsolute(fullname));
                funcAlias->Cast<PHPEntityFunctionAlias>()->SetScope(CurrentScope()->GetFullName());
                funcAlias->SetShortName(alias);
                funcAlias->SetFullName(CurrentScope()->GetFullName() + "\\" + alias);
                funcAlias->SetFilename(GetFilename());
                funcAlias->SetLine(token.lineNumber);
                CurrentScope()->AddChild(funcAlias);
            }

            temp.clear();
            fullname.clear();
            alias.clear();
        } break;
        case kPHP_T_PAAMAYIM_NEKUDOTAYIM: {
            // Convert "::" into "\\"
            temp << "\\";
        } break;
        case kPHP_T_AS: {
            fullname.swap(temp);
            temp.clear();
        } break;
        case kPHP_T_INSTEADOF: {
            // For now, we are not interested in
            // A insteadof b; statements, so just clear the collected data so far
            fullname.clear();
            temp.clear();
            alias.clear();
            if(!ConsumeUntil(';')) return;
        } break;
        default:
            temp << token.text;
            break;
        }
    }
}
Example #6
0
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();
}