📄 rpptreeevaluator.cpp
字号:
/******************************************************************************** Copyright (C) 2004-2006 Trolltech ASA. All rights reserved.** Copyright (C) 2001-2004 Roberto Raggi**** This file is part of the qt3to4 porting application of the Qt Toolkit.**** This file may be used under the terms of the GNU General Public** License version 2.0 as published by the Free Software Foundation** and appearing in the file LICENSE.GPL included in the packaging of** this file. Please review the following information to ensure GNU** General Public Licensing requirements will be met:** http://www.trolltech.com/products/qt/opensource.html**** If you are unsure which license is appropriate for your use, please** review the following information:** http://www.trolltech.com/products/qt/licensing.html or contact the** sales department at sales@trolltech.com.**** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.******************************************************************************/#include "rpptreeevaluator.h"#include <QChar>#include <QtDebug>using namespace TokenEngine;namespace Rpp {RppTreeEvaluator::RppTreeEvaluator(){ QByteArray text(" "); TokenEngine::Token token; token.start = 0; token.length = 1; QVector<TokenEngine::Token> tokenList; tokenList.append(token); TokenContainer newLineContainer(text, tokenList, new TokenEngine::GeneratedInfo()); newlineSection= new TokenSection(newLineContainer, 0, 1);}RppTreeEvaluator::~RppTreeEvaluator(){ delete newlineSection;}TokenSectionSequence RppTreeEvaluator::evaluate(const Source *source, DefineMap *activeDefinitions){ m_tokenSections.clear(); m_activeDefinitions = activeDefinitions; evaluateSource(source); return TokenSectionSequence(m_tokenSections);}void RppTreeEvaluator::evaluateText(const Text *textLine){ const int numTokens = textLine->count(); const TokenContainer tokenContainer = textLine->text().tokenContainer(0); int t = 0; int startTokenRun = 0; while(t < numTokens) { const Token *currentToken = textLine->token(t); int currentContainerIndex = currentToken->index(); //handle macro replacements if(currentToken->toIdToken()) { const int tokenIndex = currentToken->index(); const QByteArray tokenText = tokenContainer.tempText(tokenIndex); if(m_activeDefinitions->contains(tokenText)) { //crate section TokenSection section(tokenContainer, textLine->token(startTokenRun)->index(), t - startTokenRun); m_tokenSections.append(section); //evaluate macro const int oldContainerIndex = currentContainerIndex; TokenContainer evaluatedText = evaluateMacro(tokenContainer, currentContainerIndex); TokenSection evalSection(evaluatedText, 0, evaluatedText.count()); m_tokenSections.append(evalSection); t += currentContainerIndex - oldContainerIndex; startTokenRun = t; } ++t; continue; } //handle comments if(currentToken->toLineComment() || currentToken->toMultiLineComment()) { //create section TokenSection section(tokenContainer, textLine->token(startTokenRun)->index(), t - startTokenRun ); m_tokenSections.append(section); t++; //skip comment startTokenRun = t; t++; continue; } // handle escaped newlines if (currentContainerIndex + 1 < numTokens) { const TokenTempRef tokenRef1 = tokenContainer.tokenTempRef(currentContainerIndex); const TokenTempRef tokenRef2 = tokenContainer.tokenTempRef(currentContainerIndex + 1); // This is i slight hack. We want to check if the next token is a newline token, // but since we don't have any lexical info at this point we just check if it starts // with \r or \n if (tokenRef1.at(0) == '\\' && (tokenRef2.at(0) == '\n' || tokenRef2.at(0) == '\r')) { //create section TokenSection section(tokenContainer, textLine->token(startTokenRun)->index(), t - startTokenRun ); m_tokenSections.append(section); t += 2; startTokenRun = t; t++; continue; } } t++; } //round up any tokens at the end and put them in a section if(t - startTokenRun > 1) { TokenSection section(tokenContainer, textLine->token(startTokenRun)->index(), t - startTokenRun ); m_tokenSections.append(section); } m_tokenSections.append(*newlineSection);}/* Evaluates and ifsection by selecting which one of the if-elif-else groups and then evaling that.*/void RppTreeEvaluator::evaluateIfSection(const IfSection *ifSection){ ConditionalDirective *ifGroup = ifSection->ifGroup(); if(evaluateCondition(ifGroup)) { evaluateConditionalDirective(ifGroup); return; } QVector<ConditionalDirective *> elifGroups = ifSection->elifGroups(); foreach(ConditionalDirective *elifGroup, elifGroups) { if(evaluateCondition(elifGroup)) { evaluateConditionalDirective(elifGroup); return; } } ConditionalDirective *elseGroup = ifSection->elseGroup(); if(elseGroup) evaluateConditionalDirective(elseGroup);}/* Evaluate an IncludeDirective by evaluating the Source for the included file. The source is found by emitting the includeCallback signal, which must be handled outside RppTreeEvaluator.*/void RppTreeEvaluator::evaluateIncludeDirective(const IncludeDirective *directive){ Source *currentSource = getParentSource(directive); IncludeType includeType = includeTypeFromDirective(directive); Source *newSource = 0; emit includeCallback(newSource, currentSource, directive->filename(), includeType); Q_ASSERT(newSource); // If you get an assert here you probably // forgot to connect to the includeCallback signal evaluateSource(newSource);}void RppTreeEvaluator::evaluateDefineDirective(const DefineDirective *directive){ m_tokenSections.append(*newlineSection); m_activeDefinitions->insert(directive->identifier().fullText(), directive);}void RppTreeEvaluator::evaluateUndefDirective(const UndefDirective *directive){ m_tokenSections.append(*newlineSection); const QByteArray text = directive->identifier().fullText(); m_activeDefinitions->remove(text);}/* Evaluate the truth-value of an conditionalDirective*/bool RppTreeEvaluator::evaluateCondition(const ConditionalDirective *conditionalDirective){ if (IfDirective *ifDirective = conditionalDirective->toIfDirective()) return (evaluateExpression(ifDirective->expression()) != 0); if (ElifDirective *elifDirective = conditionalDirective->toElifDirective()) return (evaluateExpression(elifDirective->expression()) != 0); if (IfdefDirective *ifdefDirective = conditionalDirective->toIfdefDirective()) return m_activeDefinitions->contains(ifdefDirective->identifier().fullText()); if (IfndefDirective *ifndefDirective = conditionalDirective->toIfndefDirective()) return !m_activeDefinitions->contains(ifndefDirective->identifier().fullText()); else return false; //error!}/* Recursively evaluates an Expression*/int RppTreeEvaluator::evaluateExpression(Expression *expression){ if (IntLiteral *e = expression->toIntLiteral()) { return e->value(); } else if (StringLiteral *e = expression->toStringLiteral()) { return e->value().size(); } else if (MacroReference *e = expression->toMacroReference()) { switch(e->type()) { case MacroReference::DefinedRef: { return m_activeDefinitions->contains(e->name().fullText()) ? 1 : 0; } case MacroReference::ValueRef: { const QByteArray identifier = e->name().fullText(); if (m_activeDefinitions->contains(identifier)) { int token = e->name().containerIndex(0); TokenContainer value = evaluateMacro(e->name().tokenContainer(token), token); return QString(value.fullText()).toInt(0, 0); } else { return 0; // error } } default: Q_ASSERT(0); } } else if (MacroFunctionReference *e = expression->toMacroFunctionReference()) { Q_UNUSED(e); //TODO handle MacroFunctionReference// DefineDirective *def = e->findDefinition(e->name());// Q_ASSERT(def->toMacroFunctionDefinition());// qWarning("not implemented yet"); return 0; } else if (UnaryExpression *e = expression->toUnaryExpression()) { int result = evaluateExpression(e->expression()); switch (e->op()) { case '+': return + result; case '-': return - result; case '!': return ! result; case '~': return ~ result; default: Q_ASSERT(0); } } else if (BinaryExpression *e = expression->toBinaryExpression()) { int v1 = evaluateExpression(e->leftExpression()); int v2 = evaluateExpression(e->rightExpression()); switch (e->op()) { case '/': { return v2 ? v1 / v2 : 0; } //avoid division by zero case '*': return v1 * v2; case '%': { return v2 ? v1 % v2 : 0; } //avoid modulus by zero case '+': return v1 + v2; case '-': return v1 - v2; case '<': return v1 < v2; case '>': return v1 > v2; case '&': return v1 & v2; case '^': return v1 ^ v2; case '|': return v1 | v2; case Expression::LtEqOp: return v1 <= v2; case Expression::GtEqOp: return v1 >= v2; case Expression::EqOp: return v1 == v2; case Expression::NotEqOp: return v1 != v2; case Expression::AndOp: return v1 && v2; case Expression::OrOp: return v1 || v2; case Expression::LShiftOp: return v1 << v2; case Expression::RShiftOp: return v1 >> v2; default: Q_ASSERT(0); } } else if ( ConditionalExpression *e = expression->toConditionalExpression()){ return e->condition() ? evaluateExpression(e->leftExpression()) : evaluateExpression(e->rightExpression());
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -