⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 rpptreeevaluator.cpp

📁 QT 开发环境里面一个很重要的文件
💻 CPP
📖 第 1 页 / 共 2 页
字号:
    }    return 0;}/*    Expands a macro at index identiferTokenIndex in tokenContainer. Returns    the expanded macro text, and updates identiferTokenIndex to point after    the last token consumed.    Given the construct 'FN(a)', the '(a)' part will be consumed if FN is    defined to be a macro function, but not if it is an ordenary macro.*/TokenContainer RppTreeEvaluator::evaluateMacro(TokenContainer tokenContainer, int &identiferTokenIndex){    QByteArray identifierText = tokenContainer.text(identiferTokenIndex);    if(!m_activeDefinitions->contains(identifierText))        return TokenContainer();    const Rpp::DefineDirective *directive = m_activeDefinitions->value(identifierText);    Q_ASSERT(directive);    // To prevent infinite recursive macro expansions, the skip set contains    // a set of identifers already seen.    QSet<QByteArray> skip;    if(directive->toMacroDefinition()) {        ++identiferTokenIndex;        QVector<TokenEngine::Token> tokenList;        tokenList.append(TokenEngine::Token(0, identifierText.count()));        return evaluateMacroInternal(skip, TokenContainer(identifierText, tokenList));    } else if (Rpp::MacroFunctionDefinition *macro = directive->toMacroFunctionDefinition()) {        MacroFunctionParser macroFunctionParser(tokenContainer, identiferTokenIndex);        if (macroFunctionParser.isValid() && macro->parameters().count() ==  macroFunctionParser.argumentCount()) {            TokenContainer macroFunctionContainer =                TokenEngine::copy(tokenContainer, identiferTokenIndex, macroFunctionParser.tokenCount());            identiferTokenIndex += macroFunctionParser.tokenCount();            return evaluateMacroInternal(skip, macroFunctionContainer);        } else {            // Error case, such as calling a macro function with the wrong number of parameters,            // or calling a macro function witout a parameter list.            return TokenEngine::copy(tokenContainer, identiferTokenIndex++, 1);        }    }    return TokenContainer();}/*    Recursively expands all macroes in macroInvokeTokens, returns a    TokenContainer with the new tokens.*/TokenEngine::TokenContainer RppTreeEvaluator::evaluateMacroInternal(QSet<QByteArray> skip, TokenEngine::TokenContainer macroInvokeTokens){    bool changed = false;    QByteArray tokenText;    QVector<TokenEngine::Token> tokenList;    const int numTokens = macroInvokeTokens.count();    for (int t = 0; t < numTokens; ++t) {        const QByteArray identifierText = macroInvokeTokens.text(t);        // if the current token text is not a part of a macro definition we just copy it.        if (!m_activeDefinitions->contains(identifierText)) {            tokenList.append(TokenEngine::Token(tokenText.count(), identifierText.count()));            tokenText.append(identifierText);            continue;        }        // If the token text is in the skip list we copy it.         if (skip.contains(identifierText)) {            tokenList.append(TokenEngine::Token(tokenText.count(), identifierText.count()));            tokenText.append(identifierText);            continue;        }        skip.insert(identifierText);        changed = true;        const Rpp::DefineDirective *directive = m_activeDefinitions->value(identifierText);        Q_ASSERT(directive);        // if it is a macro, we copy in the replacement list.        if (Rpp::MacroDefinition *macro = directive->toMacroDefinition()) {            TokenList replacementList = macro->replacementList();            TokenEngine::copy(tokenText, tokenList, replacementList, 0, replacementList.count());            // To avoid infinite loops, set changed to false if the replacement            // text is identical to the identifier text.            if (replacementList.fullText().simplified() == identifierText.simplified())                changed = false;        } else if (Rpp::MacroFunctionDefinition *macro = directive->toMacroFunctionDefinition()) {            TokenList replacementList = macro->replacementList();            TokenList paramenterList =  macro->parameters();            MacroFunctionParser macroFunctionParser(macroInvokeTokens, t);            if (macroFunctionParser.isValid() && macro->parameters().count() == macroFunctionParser.argumentCount()) {                t += macroFunctionParser.tokenCount();                // For each token in the replacement list: If the token matches a                // token in the parameter list, replace it with the                // corresponding argument tokens from the argument list.                for (int replacementToken = 0; replacementToken < replacementList.count(); ++replacementToken) {                    const QByteArray replacementTokenText = replacementList.text(replacementToken);                    bool replaced = false;                    for (int parameterToken = 0; parameterToken < paramenterList.count(); ++parameterToken) {                        const QByteArray parameterTokenText = paramenterList.text(parameterToken);                        if (parameterTokenText == replacementTokenText) {                            TokenSection argumentTokenSection = macroFunctionParser.argument(parameterToken);                            TokenEngine::copy(tokenText, tokenList, argumentTokenSection, 0, argumentTokenSection.count());                            replaced = true;                            break;                        }                    }                    if (! replaced) {                        TokenEngine::copy(tokenText, tokenList, replacementList, replacementToken, 1);                    }                }            }        }    }    if (!changed)        return macroInvokeTokens;    return evaluateMacroInternal(skip, TokenContainer(tokenText, tokenList));}TokenContainer RppTreeEvaluator::cloneTokenList(const TokenList &list){    QByteArray text;    QVector<TokenEngine::Token> tokens;    int index = 0;    for (int t = 0; t<list.count(); ++t) {        const QByteArray tokenText = list.text(t);        const int textLength = tokenText.count();        text += tokenText;        TokenEngine::Token token;        token.start = index;        token.length = textLength;        tokens.append(token);        index += textLength;    }    TokenContainer container(text, tokens, new GeneratedInfo());    return container;}/*    Returns the parent Source for a given item.*/Source *RppTreeEvaluator::getParentSource(const Item *item) const{    Q_ASSERT(item);    while(item->toSource() == 0) {        item = item->parent();        Q_ASSERT(item);    }    return item->toSource();}/*    We have two IncludeType enums, one in IncludeDirective and one in    RppTreeEvaluator. This function translates between them.*/RppTreeEvaluator::IncludeType RppTreeEvaluator::includeTypeFromDirective(                    const IncludeDirective *includeDirective) const{    if(includeDirective->includeType() == IncludeDirective::QuoteInclude)        return QuoteInclude;    else        return AngleBracketInclude;}/*    The MacrofunctionParser class is used to parse a macro function call (not    a macro function definition.)    startToken should give the token index for the identifier token for the macro function.*/MacroFunctionParser::MacroFunctionParser(const TokenEngine::TokenContainer &tokenContainer, int startToken):m_tokenContainer(tokenContainer),m_startToken(startToken),m_numTokens(0),m_valid(false){    int tokenIndex = startToken;    ++tokenIndex; //skip identifier token    int parenthesisCount = 0;    int currentArgumentStartToken = tokenIndex;    // Parse argument tokens, add arguments to the m_arguments list.    // Arguments may consist of multiple tokens. Parenthesis in arguments    // are allowed, as long as they match. Inside a pair of argument    // parenthesis, ',' no longer signals a new argument. For example,    // FN((a,b)) is legal and contains one argument.    while(tokenIndex < tokenContainer.count()) {        QByteArray currentText = tokenContainer.text(tokenIndex);        ++tokenIndex;        if (currentText == "(") {            ++parenthesisCount;            if (parenthesisCount == 1) {                // first parenthesis                currentArgumentStartToken = tokenIndex;                continue;            }        }        if (currentText == ")") {            --parenthesisCount;            if (parenthesisCount == 0) {                //end of argument                m_arguments.append(TokenSection(tokenContainer, currentArgumentStartToken, tokenIndex - currentArgumentStartToken - 1));                currentArgumentStartToken = tokenIndex;                //end of argument list                break;            }        }        if (currentText == "," && parenthesisCount == 1) {            //end of argument            m_arguments.append(TokenSection(tokenContainer, currentArgumentStartToken, tokenIndex - currentArgumentStartToken - 1));            currentArgumentStartToken = tokenIndex;            continue;        }        if (QChar(currentText.at(0)).isSpace()) {            continue;        }        // If we get here without having seen a paranthesis we have a syntax        // error in the macro function call.        if (parenthesisCount == 0) {            parenthesisCount = -1;            break;        }    }    m_numTokens = tokenIndex - startToken;    m_valid = (parenthesisCount == 0);}/*    Returns true if the MacroFunctionParser contains a valid macro function*/bool MacroFunctionParser::isValid(){    return m_valid;}/*    Returns the number of tokens in the tokenContainer that is covered by    the macro function.*/int MacroFunctionParser::tokenCount(){    return m_numTokens;}/*    Returns the number of arguments for the macro function.*/int MacroFunctionParser::argumentCount(){    return m_arguments.count();}/*    Returns the tokens for the argument given by argumentIndex.*/TokenSection MacroFunctionParser::argument(int argumentIndex){    Q_ASSERT(argumentIndex < m_arguments.count());    return m_arguments.at(argumentIndex);}} //namespace Rpp

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -