diff options
| author | 2022-04-29 10:48:09 +0200 | |
|---|---|---|
| committer | 2022-04-29 10:48:09 +0200 | |
| commit | 07c5f6ec23fcf9237a24e71adcfacabce677f818 (patch) | |
| tree | 588e8c5f82b9163181fad3581f610e6f1d88cba4 /parsingtoolbox.cpp | |
| parent | a9153f1615a842cfb9e9bcda4d9071e202618569 (diff) | |
| download | OneRoll-07c5f6ec23fcf9237a24e71adcfacabce677f818.tar.gz OneRoll-07c5f6ec23fcf9237a24e71adcfacabce677f818.zip | |
Change file organization.
Diffstat (limited to 'parsingtoolbox.cpp')
| -rw-r--r-- | parsingtoolbox.cpp | 2641 |
1 files changed, 0 insertions, 2641 deletions
diff --git a/parsingtoolbox.cpp b/parsingtoolbox.cpp deleted file mode 100644 index dfde37f..0000000 --- a/parsingtoolbox.cpp +++ /dev/null @@ -1,2641 +0,0 @@ -/*************************************************************************** - * Copyright (C) 2014 by Renaud Guezennec * - * https://rolisteam.org/contact * - * * - * This file is part of DiceParser * - * * - * DiceParser is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * - ***************************************************************************/ -#include "diceparser/parsingtoolbox.h" - -#include <QDebug> -#include <QJsonArray> -#include <QJsonObject> -#include <QRegularExpression> -#include <QString> -#include <set> - -#include "node/allsamenode.h" -#include "node/bind.h" -#include "node/countexecutenode.h" -#include "node/dicerollernode.h" -#include "node/executionnode.h" -#include "node/explodedicenode.h" -#include "node/filternode.h" -#include "node/groupnode.h" -#include "node/helpnode.h" -#include "node/ifnode.h" -#include "node/jumpbackwardnode.h" -#include "node/keepdiceexecnode.h" -#include "node/listaliasnode.h" -#include "node/listsetrollnode.h" -#include "node/mergenode.h" -#include "node/numbernode.h" -#include "node/occurencecountnode.h" -#include "node/paintnode.h" -#include "node/parenthesesnode.h" -#include "node/repeaternode.h" -#include "node/replacevaluenode.h" -#include "node/rerolldicenode.h" -#include "node/scalaroperatornode.h" -#include "node/sortresult.h" -#include "node/splitnode.h" -#include "node/startingnode.h" -#include "node/stringnode.h" -#include "node/switchcasenode.h" -#include "node/uniquenode.h" -#include "node/valueslistnode.h" -#include "node/variablenode.h" -#include "operationcondition.h" -#include "range.h" -#include "validatorlist.h" - -QHash<QString, QString> ParsingToolBox::m_variableHash; - -ParsingToolBox::ParsingToolBox() -{ - // m_logicOp = ; - m_logicOp.insert(">=", Dice::CompareOperator::GreaterOrEqual); - m_logicOp.insert("<=", Dice::CompareOperator::LesserOrEqual); - m_logicOp.insert("<", Dice::CompareOperator::LesserThan); - m_logicOp.insert("=", Dice::CompareOperator::Equal); - m_logicOp.insert(">", Dice::CompareOperator::GreaterThan); - m_logicOp.insert("!=", Dice::CompareOperator::Different); - - // m_logicOperation = ; - m_logicOperation.insert("|", Dice::LogicOperation::OR); - m_logicOperation.insert("^", Dice::LogicOperation::EXCLUSIVE_OR); - m_logicOperation.insert("&", Dice::LogicOperation::AND); - - // m_conditionOperation = ; - m_conditionOperation.insert("%", Dice::ConditionOperator::Modulo); - - // m_arithmeticOperation = new QHash<QString,ScalarOperatorNode::ArithmeticOperator>(); - m_arithmeticOperation.push_back({QStringLiteral("**"), Dice::ArithmeticOperator::POW}); - m_arithmeticOperation.push_back({QStringLiteral("+"), Dice::ArithmeticOperator::PLUS}); - m_arithmeticOperation.push_back({QStringLiteral("-"), Dice::ArithmeticOperator::MINUS}); - m_arithmeticOperation.push_back({QStringLiteral("*"), Dice::ArithmeticOperator::MULTIPLICATION}); - m_arithmeticOperation.push_back({QStringLiteral("x"), Dice::ArithmeticOperator::MULTIPLICATION}); - m_arithmeticOperation.push_back({QStringLiteral("|"), Dice::ArithmeticOperator::INTEGER_DIVIDE}); - m_arithmeticOperation.push_back({QStringLiteral("/"), Dice::ArithmeticOperator::DIVIDE}); - m_arithmeticOperation.push_back({QStringLiteral("÷"), Dice::ArithmeticOperator::DIVIDE}); - - m_mapDiceOp.insert(QStringLiteral("D"), D); - m_mapDiceOp.insert(QStringLiteral("L"), L); - - m_OptionOp.insert(QStringLiteral("k"), Keep); - m_OptionOp.insert(QStringLiteral("K"), KeepAndExplode); - m_OptionOp.insert(QStringLiteral("s"), Sort); - m_OptionOp.insert(QStringLiteral("c"), Count); - m_OptionOp.insert(QStringLiteral("r"), Reroll); - m_OptionOp.insert(QStringLiteral("e"), Explode); - m_OptionOp.insert(QStringLiteral("R"), RerollUntil); - m_OptionOp.insert(QStringLiteral("a"), RerollAndAdd); - m_OptionOp.insert(QStringLiteral("m"), Merge); - m_OptionOp.insert(QStringLiteral("i"), ifOperator); - m_OptionOp.insert(QStringLiteral("p"), Painter); - m_OptionOp.insert(QStringLiteral("f"), Filter); - m_OptionOp.insert(QStringLiteral("y"), Split); - m_OptionOp.insert(QStringLiteral("u"), Unique); - m_OptionOp.insert(QStringLiteral("t"), AllSameExplode); - m_OptionOp.insert(QStringLiteral("g"), Group); - m_OptionOp.insert(QStringLiteral("b"), Bind); - m_OptionOp.insert(QStringLiteral("o"), Occurences); - m_OptionOp.insert(QStringLiteral("S"), SwitchCaseOption); - m_OptionOp.insert(QStringLiteral("T"), TransformOption); - - m_functionMap.insert({QStringLiteral("repeat"), REPEAT}); - - m_nodeActionMap.insert(QStringLiteral("@"), JumpBackward); - - m_commandList.append(QStringLiteral("help")); - m_commandList.append(QStringLiteral("la")); -} - -ParsingToolBox::ParsingToolBox(const ParsingToolBox&) {} -ParsingToolBox::~ParsingToolBox() {} - -void ParsingToolBox::clearUp() -{ - m_errorMap.clear(); - m_comment= QString(""); -} - -void ParsingToolBox::cleanUpAliases() -{ - m_aliasList.clear(); -} - -ExecutionNode* ParsingToolBox::addSort(ExecutionNode* e, bool b) -{ - SortResultNode* nodeSort= new SortResultNode(); - nodeSort->setSortAscending(b); - if(nullptr != e) - e->setNextNode(nodeSort); - return nodeSort; -} - -void ParsingToolBox::addError(Dice::ERROR_CODE code, const QString& msg) -{ - m_errorMap.insert(code, msg); -} -void ParsingToolBox::addWarning(Dice::ERROR_CODE code, const QString& msg) -{ - m_warningMap.insert(code, msg); -} -bool ParsingToolBox::readDiceLogicOperator(QString& str, Dice::ConditionOperator& op) -{ - QString longKey; - auto const& keys= m_conditionOperation.keys(); - for(const QString& tmp : keys) - { - if(str.startsWith(tmp)) - { - if(longKey.size() < tmp.size()) - { - longKey= tmp; - } - } - } - if(longKey.size() > 0) - { - str= str.remove(0, longKey.size()); - op= m_conditionOperation.value(longKey); - return true; - } - - return false; -} - -bool ParsingToolBox::readArithmeticOperator(QString& str, Dice::ArithmeticOperator& op) -{ - - auto it= std::find_if(m_arithmeticOperation.begin(), m_arithmeticOperation.end(), - [str](const std::pair<QString, Dice::ArithmeticOperator>& pair) - { return str.startsWith(pair.first); }); - if(it == m_arithmeticOperation.end()) - return false; - - op= it->second; - str= str.remove(0, it->first.size()); - return true; -} - -bool ParsingToolBox::readLogicOperator(QString& str, Dice::CompareOperator& op) -{ - QString longKey; - auto const& keys= m_logicOp.keys(); - for(const QString& tmp : keys) - { - if(str.startsWith(tmp)) - { - if(longKey.size() < tmp.size()) - { - longKey= tmp; - } - } - } - if(longKey.size() > 0) - { - str= str.remove(0, longKey.size()); - op= m_logicOp.value(longKey); - return true; - } - - return false; -} -QString ParsingToolBox::getComment() const -{ - return m_comment; -} - -void ParsingToolBox::setComment(const QString& comment) -{ - m_comment= comment; -} -const QMap<Dice::ERROR_CODE, QString>& ParsingToolBox::getErrorList() const -{ - return m_errorMap; -} -const QMap<Dice::ERROR_CODE, QString>& ParsingToolBox::getWarningList() const -{ - return m_warningMap; -} -bool ParsingToolBox::readOperand(QString& str, ExecutionNode*& node) -{ - qint64 intValue= 1; - QString resultStr; - if(readDynamicVariable(str, intValue)) - { - VariableNode* variableNode= new VariableNode(); - variableNode->setIndex(static_cast<quint64>(intValue - 1)); - variableNode->setData(&m_startNodes); - node= variableNode; - return true; - } - else if(readNumber(str, intValue)) - { - NumberNode* numberNode= new NumberNode(); - numberNode->setNumber(intValue); - node= numberNode; - return true; - } - else if(readString(str, resultStr)) - { - StringNode* strNode= new StringNode(); - strNode->setString(resultStr); - node= strNode; - return true; - } - return false; -} - -Validator* ParsingToolBox::readValidator(QString& str, bool hasSquare) -{ - Validator* returnVal= nullptr; - auto opCompare= readConditionType(str); - Dice::CompareOperator myLogicOp{Dice::CompareOperator::Equal}; - readLogicOperator(str, myLogicOp); - - Dice::ConditionOperator condiOp{Dice::ConditionOperator::Modulo}; - bool hasDiceLogicOperator= readDiceLogicOperator(str, condiOp); - ExecutionNode* operandNode= nullptr; - if(hasDiceLogicOperator) - { - if(readOperand(str, operandNode)) - { - OperationCondition* condition= new OperationCondition(); - condition->setConditionType(opCompare); - condition->setValueNode(operandNode); - Validator* valid= readValidator(str, hasSquare); - BooleanCondition* boolC= dynamic_cast<BooleanCondition*>(valid); - if(nullptr != boolC) - { - condition->setBoolean(boolC); - returnVal= condition; - } - else - { - delete condition; - } - } - } - else if(readOperand(str, operandNode)) - { - bool isRange= false; - if(str.startsWith("..") && hasSquare) - { - str= str.remove(0, 2); - qint64 end= 0; - if(readNumber(str, end)) - { - str= str.remove(0, 1); - qint64 start= operandNode->getScalarResult(); - Range* range= new Range(); - range->setConditionType(opCompare); - range->setValue(start, end); - returnVal= range; - isRange= true; - } - } - - if(!isRange) - { - BooleanCondition* condition= new BooleanCondition(); - condition->setConditionType(opCompare); - condition->setValueNode(operandNode); - condition->setOperator(myLogicOp); - returnVal= condition; - } - } - return returnVal; -} - -Dice::ConditionType ParsingToolBox::readConditionType(QString& str) -{ - Dice::ConditionType type= Dice::OnEach; - if(str.startsWith('.')) - { - str= str.remove(0, 1); - type= Dice::OneOfThem; - } - else if(str.startsWith('?')) - { - str= str.remove(0, 1); - type= Dice::OnEachValue; - } - else if(str.startsWith('*')) - { - str= str.remove(0, 1); - type= Dice::AllOfThem; - } - else if(str.startsWith(':')) - { - str= str.remove(0, 1); - type= Dice::OnScalar; - } - return type; -} -bool ParsingToolBox::hasError() const -{ - return !m_errorMap.isEmpty(); -} -ValidatorList* ParsingToolBox::readValidatorList(QString& str) -{ - bool expectSquareBrasket= false; - if((str.startsWith("["))) - { - str= str.remove(0, 1); - expectSquareBrasket= true; - } - Validator* tmp= readValidator(str, expectSquareBrasket); - Dice::LogicOperation opLogic; - - QVector<Dice::LogicOperation> operators; - QList<Validator*> validatorList; - - while(nullptr != tmp) - { - bool hasOperator= readLogicOperation(str, opLogic); - if(hasOperator) - { - operators.append(opLogic); - validatorList.append(tmp); - tmp= readValidator(str, expectSquareBrasket); - } - else - { - if((expectSquareBrasket) && (str.startsWith("]"))) - { - str= str.remove(0, 1); - // isOk=true; - } - validatorList.append(tmp); - tmp= nullptr; - } - } - if(!validatorList.isEmpty()) - { - ValidatorList* validator= new ValidatorList(); - validator->setOperationList(operators); - validator->setValidators(validatorList); - return validator; - } - else - { - return nullptr; - } -} -bool ParsingToolBox::readLogicOperation(QString& str, Dice::LogicOperation& op) -{ - QString longKey; - auto const& keys= m_logicOperation.keys(); - for(auto& tmp : keys) - { - if(str.startsWith(tmp)) - { - if(longKey.size() < tmp.size()) - { - longKey= tmp; - } - } - } - if(longKey.size() > 0) - { - str= str.remove(0, longKey.size()); - op= m_logicOperation.value(longKey); - return true; - } - - return false; -} - -bool ParsingToolBox::readNumber(QString& str, qint64& myNumber) -{ - if(str.isEmpty()) - return false; - - QString number; - int i= 0; - while(i < str.length() && ((str[i].isNumber()) || ((i == 0) && (str[i] == '-')))) - { - number+= str[i]; - ++i; - } - - if(number.isEmpty()) - { - QString reason; - return readVariable(str, myNumber, reason); - } - - bool ok; - myNumber= number.toLongLong(&ok); - if(ok) - { - str= str.remove(0, number.size()); - return true; - } - - return false; -} -bool ParsingToolBox::readDynamicVariable(QString& str, qint64& index) -{ - if(str.isEmpty()) - return false; - if(str.startsWith('$')) - { - QString number; - int i= 1; - while(i < str.length() && (str[i].isNumber())) - { - number+= str[i]; - ++i; - } - - bool ok; - index= number.toLongLong(&ok); - if(ok) - { - str= str.remove(0, number.size() + 1); - return true; - } - } - return false; -} - -ExecutionNode* ParsingToolBox::getLeafNode(ExecutionNode* start) -{ - if(nullptr == start) - return nullptr; - - ExecutionNode* next= start; - while(nullptr != next->getNextNode()) - { - next= next->getNextNode(); - } - return next; -} - -const std::vector<ExecutionNode*>& ParsingToolBox::getStartNodes() -{ - return m_startNodes; -} - -QStringList ParsingToolBox::allFirstResultAsString(bool& hasAlias) const -{ - // QStringList allResult; - QStringList stringListResult; - for(auto node : m_startNodes) - { - QVariant var; - auto stringPair= hasResultOfType(Dice::RESULT_TYPE::STRING, node); - auto scalarPair= hasResultOfType(Dice::RESULT_TYPE::SCALAR, node); - if(stringPair.first) - { - stringListResult << stringPair.second.toString(); - hasAlias= true; - } - else if(scalarPair.first) - { - stringListResult << number(scalarPair.second.toReal()); - hasAlias= true; - } - } - return stringListResult; -} -std::pair<bool, QVariant> ParsingToolBox::hasResultOfType(Dice::RESULT_TYPE type, ExecutionNode* node, - bool notthelast) const -{ - bool hasValidResult= false; - QVariant var; - ExecutionNode* next= ParsingToolBox::getLeafNode(node); - Result* result= next->getResult(); - while((result != nullptr) && (!hasValidResult)) - { - bool lastResult= false; - if(notthelast) - lastResult= (nullptr == result->getPrevious()); - - if(result->hasResultOfType(type) && !lastResult) - { - hasValidResult= true; - var= result->getResult(type); - } - result= result->getPrevious(); - } - return {hasValidResult, var}; -} - -QList<qreal> ParsingToolBox::scalarResultsFromEachInstruction() const -{ - QList<qreal> resultValues; - std::set<QString> alreadyVisitedNode; - for(auto node : m_startNodes) - { - ExecutionNode* next= ParsingToolBox::getLeafNode(node); - Result* result= next->getResult(); - bool scalarDone= false; - while((result != nullptr) && (!scalarDone)) - { - if(result->hasResultOfType(Dice::RESULT_TYPE::SCALAR)) - { - if(alreadyVisitedNode.find(result->getId()) == alreadyVisitedNode.end()) - { - resultValues << result->getResult(Dice::RESULT_TYPE::SCALAR).toReal(); - alreadyVisitedNode.insert(result->getId()); - } - scalarDone= true; - } - result= result->getPrevious(); - } - } - return resultValues; -} - -QList<qreal> ParsingToolBox::sumOfDiceResult() const -{ - QList<qreal> resultValues; - for(auto node : m_startNodes) - { - qreal resultValue= 0; - ExecutionNode* next= ParsingToolBox::getLeafNode(node); - Result* result= next->getResult(); - bool found= false; - while((nullptr != result) && (!found)) - { - if(result->hasResultOfType(Dice::RESULT_TYPE::DICE_LIST)) - { - DiceResult* myDiceResult= dynamic_cast<DiceResult*>(result); - if(nullptr != myDiceResult) - { - for(auto& die : myDiceResult->getResultList()) - { - resultValue+= die->getValue(); - } - found= true; - } - } - result= result->getPrevious(); - } - resultValues << resultValue; - } - return resultValues; -} - -std::pair<QString, QString> ParsingToolBox::finalScalarResult() const -{ - QString scalarText; - QString lastScalarText; - auto listDie= diceResultFromEachInstruction(); - if(hasIntegerResultNotInFirst()) - { - QStringList strLst; - auto listScalar= scalarResultsFromEachInstruction(); - for(auto val : listScalar) - { - strLst << number(val); - } - scalarText= QString("%1").arg(strLst.join(',')); - lastScalarText= strLst.last(); - } - else if(!listDie.isEmpty()) - { - auto values= sumOfDiceResult(); - QStringList strLst; - for(auto val : values) - { - strLst << number(val); - } - scalarText= QString("%1").arg(strLst.join(',')); - } - return {scalarText, lastScalarText}; -} - -bool ParsingToolBox::hasIntegerResultNotInFirst() const -{ - bool result= false; - for(auto node : m_startNodes) - { - result|= hasResultOfType(Dice::RESULT_TYPE::SCALAR, node, true).first; - } - return result; -} - -bool ParsingToolBox::hasDiceResult() const -{ - bool result= false; - for(auto node : m_startNodes) - { - result|= hasResultOfType(Dice::RESULT_TYPE::DICE_LIST, node).first; - } - return result; -} -bool ParsingToolBox::hasStringResult() const -{ - bool result= false; - for(auto node : m_startNodes) - { - result|= hasResultOfType(Dice::RESULT_TYPE::STRING, node).first; - } - return result; -} - -QList<ExportedDiceResult> ParsingToolBox::diceResultFromEachInstruction() const -{ - QList<ExportedDiceResult> resultList; - for(auto start : m_startNodes) - { - resultList.append(ParsingToolBox::finalDiceResultFromInstruction(start)); - } - return resultList; -} - -QStringList listOfDiceResult(const QList<ExportedDiceResult>& list, bool removeDouble= false) -{ - QStringList listOfDiceResult; - std::set<QString> alreadyAdded; - for(auto map : list) - { - for(auto key : map.keys()) - { - auto listOfList= map.value(key); - for(auto dice : listOfList) - { - QString stringVal; - for(auto val : dice) - { - if(removeDouble && (alreadyAdded.end() != alreadyAdded.find(val.uuid()))) - continue; - - alreadyAdded.insert(val.uuid()); - - qint64 total= 0; - QStringList dicelist; - for(auto score : val.result()) - { - total+= score; - dicelist << QString::number(score); - } - if(val.result().size() > 1) - { - stringVal= QString("%1 [%2]").arg(total).arg(dicelist.join(',')); - listOfDiceResult << stringVal; - } - else - { - listOfDiceResult << QString::number(total); - } - } - } - } - } - return listOfDiceResult; -} - -QString ParsingToolBox::finalStringResult(std::function<QString(const QString&, const QString&, bool)> colorize, - bool removeUnhighlighted) const -{ - bool ok; - QStringList allStringlist= allFirstResultAsString(ok); - auto listFull= diceResultFromEachInstruction(); - - QStringList resultWithPlaceHolder; - std::for_each(allStringlist.begin(), allStringlist.end(), - [&resultWithPlaceHolder](const QString& sub) - { - QRegularExpression ex("%[1-3]?|\\$[1-9]+|@[1-9]+"); - if(sub.contains(ex)) - resultWithPlaceHolder.append(sub); - }); - auto stringResult= resultWithPlaceHolder.isEmpty() ? allStringlist.join(",") : resultWithPlaceHolder.join(","); - - auto pairScalar= finalScalarResult(); - - stringResult.replace("%1", pairScalar.first); - stringResult.replace("%2", listOfDiceResult(diceResultFromEachInstruction(), true).join(",").trimmed()); - stringResult.replace("%3", pairScalar.second); - stringResult.replace("\\n", "\n"); - - QMap<Dice::ERROR_CODE, QString> errorMap; - stringResult= ParsingToolBox::replaceVariableToValue(stringResult, allStringlist, errorMap); - stringResult= ParsingToolBox::replacePlaceHolderToValue(stringResult, listFull, removeUnhighlighted, colorize); - - return stringResult; -} - -bool ParsingToolBox::readString(QString& str, QString& strResult) -{ - if(str.isEmpty()) - return false; - - if(str.startsWith('"')) - { - str= str.remove(0, 1); - - int i= 0; - int j= 0; - bool previousEscape= false; - QString result; - /*&& - (((!previousEscape) && !(str[i]=='"')) || (previousEscape) && !(str[i]=='"')) - || (str[i]=='\\'))*/ - while(i < str.length() && (!(!previousEscape && (str[i] == '"')) || (previousEscape && str[i] != '"'))) - { - if(str[i] == '\\') - { - previousEscape= true; - } - else - { - if(previousEscape && str[i] != '\"') - { - result+= '\\'; - ++j; - } - result+= str[i]; - previousEscape= false; - } - ++i; - } - - if(!result.isEmpty()) - { - str= str.remove(0, i); - strResult= result; - if(str.startsWith('"')) - { - str= str.remove(0, 1); - return true; - } - } - } - - return false; -} - -bool ParsingToolBox::readVariable(QString& str, qint64& myNumber, QString& reasonFail) -{ - if(str.isEmpty()) - return false; - - if(str.startsWith("${")) - { - str= str.remove(0, 2); - } - QString key; - int post= str.indexOf('}'); - key= str.left(post); - - if(!m_variableHash.isEmpty()) - { - if(m_variableHash.contains(key)) - { - QString value= m_variableHash.value(key); - bool ok; - int valueInt= value.toInt(&ok); - if(ok) - { - myNumber= valueInt; - str= str.remove(0, post + 1); - return true; - } - else - { - reasonFail= QStringLiteral("Variable value is %1, not a number").arg(value); - } - } - else - { - reasonFail= QStringLiteral("Variable not found"); - } - } - else - { - reasonFail= QStringLiteral("No Variables are defined"); - } - - return false; -} -bool ParsingToolBox::readComma(QString& str) -{ - if(str.startsWith(",")) - { - str= str.remove(0, 1); - return true; - } - else - return false; -} -bool ParsingToolBox::readOpenParentheses(QString& str) -{ - if(str.startsWith("(")) - { - str= str.remove(0, 1); - return true; - } - else - return false; -} - -bool ParsingToolBox::readCloseParentheses(QString& str) -{ - if(str.startsWith(")")) - { - str= str.remove(0, 1); - return true; - } - else - return false; -} - -int ParsingToolBox::findClosingCharacterIndexOf(QChar open, QChar closing, const QString& str, int offset) -{ - int counter= offset; - int i= 0; - for(auto const& letter : str) - { - if(letter == open) - ++counter; - else if(letter == closing) - --counter; - - if(counter == 0) - return i; - - ++i; - } - return -1; -} - -bool ParsingToolBox::readList(QString& str, QStringList& list, QList<Range>& ranges) -{ - if(str.startsWith("[")) - { - str= str.remove(0, 1); - int pos= findClosingCharacterIndexOf('[', ']', str, 1); // str.indexOf("]"); - if(-1 != pos) - { - QString liststr= str.left(pos); - list= liststr.split(","); - str= str.remove(0, pos + 1); - readProbability(list, ranges); - return true; - } - } - return false; -} -bool ParsingToolBox::readAscending(QString& str) -{ - if(str.isEmpty()) - { - return false; - } - else if(str.at(0) == 'l') - { - str= str.remove(0, 1); - return true; - } - return false; -} - -bool ParsingToolBox::readStopAtFirst(QString& str) -{ - if(str.isEmpty()) - return false; - else if(str.at(0) == '^') - { - str= str.remove(0, 1); - return true; - } - return false; -} - -Dice::CONDITION_STATE ParsingToolBox::isValidValidator(ExecutionNode* previous, ValidatorList* val) -{ - DiceRollerNode* node= getDiceRollerNode(previous); - if(nullptr == node) - return Dice::CONDITION_STATE::ERROR_STATE; - - return val->isValidRangeSize(node->getRange()); -} -DiceRollerNode* ParsingToolBox::getDiceRollerNode(ExecutionNode* previous) -{ - while(nullptr != previous) - { - DiceRollerNode* node= dynamic_cast<DiceRollerNode*>(previous); - if(nullptr != node) - { - return node; - } - previous= previous->getPreviousNode(); - } - return nullptr; -} -bool ParsingToolBox::readDiceRange(QString& str, qint64& start, qint64& end) -{ - bool expectSquareBrasket= false; - - if((str.startsWith("["))) - { - str= str.remove(0, 1); - expectSquareBrasket= true; - } - if(readNumber(str, start)) - { - if(str.startsWith("..")) - { - str= str.remove(0, 2); - if(readNumber(str, end)) - { - if(expectSquareBrasket) - { - if(str.startsWith("]")) - { - str= str.remove(0, 1); - return true; - } - } - } - } - else if(expectSquareBrasket) - { - if(str.startsWith("]")) - { - str= str.remove(0, 1); - end= start; - return true; - } - } - } - return false; -} -ParsingToolBox::LIST_OPERATOR ParsingToolBox::readListOperator(QString& str) -{ - QHash<QChar, ParsingToolBox::LIST_OPERATOR> hash; - hash.insert('u', UNIQUE); - hash.insert('n', NOCOMMA); - bool findOne= false; - ParsingToolBox::LIST_OPERATOR op= NONE; - int i= 0; - do - { - auto keys= hash.keys(); - findOne= false; - for(auto const& key : qAsConst(keys)) - { - if(str.startsWith(key)) - { - str= str.remove(0, 1); - op= hash[key]; - findOne= true; - ++i; - } - } - } while(findOne); - - return i > 1 ? UniqueAndNoComma : op; -} - -bool ParsingToolBox::readPainterParameter(PainterNode* painter, QString& str) -{ - if(!str.startsWith('[')) - return false; - - str= str.remove(0, 1); - int pos= str.indexOf(']'); - - if(pos == -1) - return false; - - QString data= str.left(pos); - str= str.remove(0, pos + 1); - QStringList duos= data.split(','); - bool result= false; - for(QString& duoStr : duos) - { - QStringList keyValu= duoStr.split(':'); - if(keyValu.size() == 2) - { - painter->insertColorItem(keyValu[1], keyValu[0].toInt()); - result= true; - } - } - - return result; -} - -QHash<QString, QString> ParsingToolBox::getVariableHash() -{ - return m_variableHash; -} - -void ParsingToolBox::setVariableHash(const QHash<QString, QString>& variableHash) -{ - m_variableHash= variableHash; -} - -void ParsingToolBox::setStartNodes(std::vector<ExecutionNode*> nodes) -{ - m_startNodes= nodes; -} - -void ParsingToolBox::readProbability(QStringList& str, QList<Range>& ranges) -{ - quint64 totalDistance= 0; - quint64 undefDistance= 0; - int undefCount= 0; - int maxValue= 0; - int i= 0; - int j= 0; - bool hasPercentage= false; - for(QString line : str) - { - int pos= line.indexOf('['); - if(-1 != pos) - { - QString rangeStr= line.right(line.length() - pos); - line= line.left(pos); - str[j]= line; - qint64 start= 0; - qint64 end= 0; - if(readDiceRange(rangeStr, start, end)) - { - Range range; - range.setValue(start, end); - ranges.append(range); - totalDistance+= static_cast<quint64>(end - start + 1); - ++i; - } - else // percentage - { - hasPercentage= true; - Range range; - range.setStart(start); - ranges.append(range); - ++undefCount; - undefDistance+= static_cast<quint64>(start); - } - if((end > maxValue) || (i == 1)) - { - maxValue= static_cast<int>(end); - } - } - else - { - Range range; - range.setEmptyRange(true); - ranges.append(range); - } - ++j; - } - - if((hasPercentage) && (undefDistance != 0)) - { - qreal ratio= 100.0 / static_cast<qreal>(undefDistance); - qint64 realStart= 0; - for(int i= 0; i < ranges.size(); ++i) - { - Range tmp= ranges.at(i); - if(!tmp.isFullyDefined()) - { - int dist= static_cast<int>(tmp.getStart()); - tmp.setStart(realStart + 1); - double truc= dist * ratio; - - tmp.setEnd(static_cast<int>(realStart + truc)); - realStart= tmp.getEnd(); - ranges[i]= tmp; - } - } - } - else - { - int limitUp= 1; - for(int i= 0; i < ranges.size(); ++i) - { - Range range= ranges.at(i); - if(range.isEmptyRange()) - { - range.setStart(limitUp); - range.setEnd(limitUp); - range.setEmptyRange(false); - } - else - { - qint64 sizeRange= range.getEnd() - range.getStart(); - range.setStart(limitUp); - limitUp+= sizeRange; - range.setEnd(limitUp); - } - ++limitUp; - ranges[i]= range; - } - } -} -bool ParsingToolBox::readComment(QString& str, QString& result, QString& comment) -{ - QString left= str; - str= str.trimmed(); - if(str.startsWith("#")) - { - comment= left; - str= str.remove(0, 1); - result= str.trimmed(); - str= ""; - return true; - } - return false; -} - -QString ParsingToolBox::replaceVariableToValue(const QString& source, QStringList values, - QMap<Dice::ERROR_CODE, QString>& errorMap) -{ - QString result= source; - - int start= source.size() - 1; - bool valid= true; - do - { - auto ref= readVariableFromString(source, start); - if(ref.resultIndex() > values.size()) - { - auto error= QString("No valid value at index: $%1").arg(ref.resultIndex()); - errorMap.insert(Dice::ERROR_CODE::INVALID_INDEX, error); - return error; - } - - valid= ref.isValid(); - if(!valid) - continue; - - result.remove(ref.position(), ref.length()); - auto val= values[ref.resultIndex() - 1]; - - if(ref.subIndex() >= 0) - { - auto valSplit= val.split(","); - if(ref.subIndex() < valSplit.size()) - val= valSplit[ref.subIndex()]; - } - - if(ref.digitNumber() != 0) - { - auto realVal= QString("%1").arg(val, ref.digitNumber(), QChar('0')); - result.insert(ref.position(), realVal); - } - else - { - result.insert(ref.position(), val); - } - } while(valid); - - return result; -} - -QString ParsingToolBox::replacePlaceHolderFromJson(const QString& source, const QJsonObject& obj) -{ - QStringList resultList; - auto instructions= obj["instructions"].toArray(); - std::vector<std::vector<std::pair<int, QList<QStringList>>>> instructionResult; - for(auto inst : qAsConst(instructions)) - { - std::vector<std::pair<int, QList<QStringList>>> map; - auto obj= inst.toObject(); - auto vals= obj["diceval"].toArray(); - int lastFace= -1; - for(auto const& valRef : qAsConst(vals)) - { - auto diceObj= valRef.toObject(); - auto face= diceObj["face"].toInt(); - auto it= std::find_if(std::begin(map), std::end(map), - [face](const std::pair<int, QList<QStringList>>& val) { return val.first == face; }); - - auto realVal= diceObj["string"].toString(); - if(lastFace == -1 || lastFace != face) - { - QList<QStringList> listOfList; - listOfList << (QStringList() << realVal); - map.push_back({face, listOfList}); - } - else if(lastFace == face) - { - auto& valList= it->second.last(); - valList.append(realVal); - } - lastFace= face; - } - instructionResult.push_back(map); - } - std::transform(std::begin(instructionResult), std::end(instructionResult), std::back_inserter(resultList), - [](const std::vector<std::pair<int, QList<QStringList>>>& map) - { - QStringList valuesStr; - auto multiKey= (map.size() > 1); - for(auto item : map) - { - auto face= item.first; - auto valueList= item.second; - QStringList strs; - for(auto list : valueList) - { - strs << list.join(","); - } - if(!multiKey) - valuesStr << strs.join(","); - else - valuesStr << QString("d%1:(%2)").arg(face).arg(strs.join(",")); - } - return valuesStr.join(" - "); - }); - - QString result= source; - int start= source.size() - 1; - bool valid= true; - do - { - auto ref= readPlaceHolderFromString(source, start); - if(ref.isValid()) - { - result.remove(ref.position(), ref.length()); - auto val= resultList[ref.resultIndex() - 1]; - result.insert(ref.position(), val); - } - else - { - valid= false; - } - } while(valid); - - return result; -} - -QString ParsingToolBox::replacePlaceHolderToValue(const QString& source, const QList<ExportedDiceResult>& list, - bool removeUnhighlighted, - std::function<QString(const QString&, const QString&, bool)> colorize) -{ - QStringList resultList; - std::transform( - std::begin(list), std::end(list), std::back_inserter(resultList), - [removeUnhighlighted, colorize](const ExportedDiceResult& dice) - { - QStringList valuesStr; - if(dice.size() == 1) - { - auto values= dice.values(); - std::transform( - std::begin(values), std::end(values), std::back_inserter(valuesStr), - [removeUnhighlighted, colorize](const QList<ListDiceResult>& dice) - { - QStringList textList; - std::transform( - std::begin(dice), std::end(dice), std::back_inserter(textList), - [removeUnhighlighted, colorize](const ListDiceResult& dice) - { - QStringList list; - ListDiceResult values= dice; - if(removeUnhighlighted) - { - values.clear(); - std::copy_if(std::begin(dice), std::end(dice), std::back_inserter(values), - [](const HighLightDice& hl) { return hl.isHighlighted(); }); - } - - std::transform(std::begin(values), std::end(values), std::back_inserter(list), - [colorize](const HighLightDice& hl) - { return colorize(hl.getResultString(), {}, hl.isHighlighted()); }); - return list.join(","); - }); - textList.removeAll(QString()); - return textList.join(","); - }); - } - else if(dice.size() > 1) - { - for(auto key : dice.keys()) - { - auto list= dice.value(key); - for(auto values : list) - { - QStringList textVals; - std::transform(std::begin(values), std::end(values), std::back_inserter(textVals), - [](const HighLightDice& dice) { return dice.getResultString(); }); - valuesStr.append(QString("d%1 [%2]").arg(key).arg(textVals.join(","))); - } - } - } - return valuesStr.join(","); - }); - - QString result= source; - int start= source.size() - 1; - bool valid= true; - do - { - auto ref= readPlaceHolderFromString(source, start); - if(ref.isValid()) - { - result.remove(ref.position(), ref.length()); - auto val= resultList[ref.resultIndex() - 1]; - result.insert(ref.position(), val); - } - else - { - valid= false; - } - } while(valid); - - return result; -} -void ParsingToolBox::readSubtitutionParameters(SubtituteInfo& info, QString& rest) -{ - auto sizeS= rest.size(); - if(rest.startsWith("{")) - { - rest= rest.remove(0, 1); - qint64 number; - if(readNumber(rest, number)) - { - if(rest.startsWith("}")) - { - rest= rest.remove(0, 1); - info.setDigitNumber(static_cast<int>(number)); - } - } - } - if(rest.startsWith("[")) - { - rest= rest.remove(0, 1); - qint64 number; - if(readNumber(rest, number)) - { - if(rest.startsWith("]")) - { - rest= rest.remove(0, 1); - info.setSubIndex(static_cast<int>(number)); - } - } - } - info.setLength(info.length() + sizeS - rest.size()); -} - -bool ParsingToolBox::readReaperArguments(RepeaterNode* node, QString& source) -{ - if(!readOpenParentheses(source)) - return false; - - auto instructions= readInstructionList(source, false); - if(instructions.empty()) - return false; - - readComma(source); - ExecutionNode* tmp; - if(readOperand(source, tmp)) - { - if(source.startsWith("+")) - { - node->setSumAll(true); - source= source.remove(0, 1); - } - if(readCloseParentheses(source)) - { - node->setCommand(instructions); - node->setTimeNode(tmp); - return true; - } - } - - return false; -} -bool ParsingToolBox::readExpression(QString& str, ExecutionNode*& node) -{ - ExecutionNode* operandNode= nullptr; - if(readOpenParentheses(str)) - { - ExecutionNode* internalNode= nullptr; - if(readExpression(str, internalNode)) - { - ParenthesesNode* parentheseNode= new ParenthesesNode(); - parentheseNode->setInternelNode(internalNode); - node= parentheseNode; - if(readCloseParentheses(str)) - { - ExecutionNode* diceNode= nullptr; - ExecutionNode* operatorNode= nullptr; - if(readDice(str, diceNode)) - { - parentheseNode->setNextNode(diceNode); - } - else if(readExpression(str, operatorNode)) - { - parentheseNode->setNextNode(operatorNode); - } - return true; - } - else - { - m_warningMap.insert(Dice::ERROR_CODE::BAD_SYNTAXE, - QObject::tr("Expected closing parenthesis - can't validate the inside.")); - } - } - } - else if(readFunction(str, operandNode)) - { - node= operandNode; - return true; - } - else if(readOptionFromNull(str, operandNode)) - { - node= operandNode; - return true; - } - else if(readOperatorFromNull(str, operandNode)) - { - node= operandNode; - return true; - } - else if(readOperand(str, operandNode)) - { - ExecutionNode* diceNode= nullptr; - if(readDice(str, diceNode)) - { - operandNode->setNextNode(diceNode); - } - node= operandNode; - - operandNode= ParsingToolBox::getLeafNode(operandNode); - // ExecutionNode* operatorNode=nullptr; - while(readOperator(str, operandNode)) - { - // operandNode->setNextNode(operatorNode); - operandNode= ParsingToolBox::getLeafNode(operandNode); - } - return true; - } - else if(readCommand(str, operandNode)) - { - node= operandNode; - return true; - } - else if(readNode(str, operandNode)) - { - node= operandNode; - return true; - } - else if(readValuesList(str, operandNode)) - { - node= operandNode; - return true; - } - else - { - ExecutionNode* diceNode= nullptr; - if(readDice(str, diceNode)) - { - NumberNode* numberNode= new NumberNode(); - numberNode->setNumber(1); - numberNode->setNextNode(diceNode); - node= numberNode; - return true; - } - else - { - return false; - } - } - return false; -} - -bool ParsingToolBox::readValuesList(QString& str, ExecutionNode*& node) -{ - if(!str.startsWith("[")) - return false; - - str= str.remove(0, 1); - int pos= ParsingToolBox::findClosingCharacterIndexOf('[', ']', str, 1); // str.indexOf("]"); - if(-1 == pos) - return false; - - QString liststr= str.left(pos); - auto list= liststr.split(","); - str= str.remove(0, pos + 1); - auto values= new ValuesListNode(); - for(auto var : qAsConst(list)) - { - qint64 number= 1; - var= var.trimmed(); - if(ParsingToolBox::readDynamicVariable(var, number)) - { - VariableNode* variableNode= new VariableNode(); - variableNode->setIndex(static_cast<quint64>(number - 1)); - variableNode->setData(&m_startNodes); - values->insertValue(variableNode); - } - else if(ParsingToolBox::readNumber(var, number)) - { - NumberNode* numberNode= new NumberNode(); - numberNode->setNumber(number); - values->insertValue(numberNode); - } - } - node= values; - return true; -} -bool ParsingToolBox::readOptionFromNull(QString& str, ExecutionNode*& node) -{ - StartingNode nodePrevious; - if(readOption(str, &nodePrevious)) - { - auto nodeNext= nodePrevious.getNextNode(); - nodePrevious.setNextNode(nullptr); - node= nodeNext; - return true; - } - return false; -} - -void ParsingToolBox::setHelpPath(const QString& path) -{ - m_helpPath= path; -} - -bool ParsingToolBox::readOperatorFromNull(QString& str, ExecutionNode*& node) -{ - StartingNode nodePrevious; - if(readOperator(str, &nodePrevious)) - { - auto nodeNext= nodePrevious.getNextNode(); - nodePrevious.setNextNode(nullptr); - node= nodeNext; - return true; - } - return false; -} - -bool ParsingToolBox::readOption(QString& str, ExecutionNode* previous) //, -{ - if(str.isEmpty()) - { - return false; - } - - bool found= false; - auto keys= m_OptionOp.keys(); - for(int i= 0; ((i < keys.size()) && (!found)); ++i) - { - QString key= keys.at(i); - - if(str.startsWith(key)) - { - str= str.remove(0, key.size()); - auto operatorName= m_OptionOp.value(key); - switch(operatorName) - { - case Keep: - { - ExecutionNode* value= nullptr; - bool ascending= readAscending(str); - - if(readOperand(str, value)) - { - auto node= addSort(previous, ascending); - KeepDiceExecNode* nodeK= new KeepDiceExecNode(); - nodeK->setDiceKeepNumber(value); - node->setNextNode(nodeK); - found= true; - } - } - break; - case KeepAndExplode: - { - bool ascending= readAscending(str); - ExecutionNode* value= nullptr; - if(readOperand(str, value)) - { - DiceRollerNode* nodeTmp= dynamic_cast<DiceRollerNode*>(previous); - if(nullptr != nodeTmp) - { - previous= addExplodeDiceNode(static_cast<qint64>(nodeTmp->getFaces()), previous); - } - - auto node= addSort(previous, ascending); - - KeepDiceExecNode* nodeK= new KeepDiceExecNode(); - nodeK->setDiceKeepNumber(value); - - node->setNextNode(nodeK); - node= nodeK; - found= true; - } - } - break; - case Filter: - { - auto validatorList= readValidatorList(str); - if(nullptr != validatorList) - { - auto validity= isValidValidator(previous, validatorList); - - FilterNode* filterNode= new FilterNode(); - filterNode->setValidatorList(validatorList); - - previous->setNextNode(filterNode); - found= true; - } - } - break; - case Sort: - { - bool ascending= readAscending(str); - addSort(previous, ascending); - /*if(!hasDice) - { - m_errorMap.insert(ExecutionNode::BAD_SYNTAXE,QObject::tr("Sort Operator does not support default - dice. You should add dice command before the s")); - }*/ - found= true; - } - break; - case Count: - { - auto validatorList= readValidatorList(str); - if(nullptr != validatorList) - { - auto validity= isValidValidator(previous, validatorList); - - CountExecuteNode* countNode= new CountExecuteNode(); - countNode->setValidatorList(validatorList); - - previous->setNextNode(countNode); - found= true; - } - else - { - m_errorMap.insert(Dice::ERROR_CODE::BAD_SYNTAXE, - QObject::tr("Validator is missing after the c operator. Please, change it")); - } - } - break; - case Reroll: - case RerollUntil: - case RerollAndAdd: - // Todo: I think that Exploding and Rerolling could share the same code - { - auto validatorList= readValidatorList(str); - QString symbol= m_OptionOp.key(operatorName); - if(nullptr != validatorList) - { - switch(isValidValidator(previous, validatorList)) - { - case Dice::CONDITION_STATE::ALWAYSTRUE: - if(operatorName == RerollAndAdd) - { - m_errorMap.insert( - Dice::ERROR_CODE::ENDLESS_LOOP_ERROR, - QObject::tr("Validator is always true for the %1 operator. Please, change it") - .arg(symbol)); - } - break; - case Dice::CONDITION_STATE::UNREACHABLE: - if(operatorName == RerollUntil) - { - m_errorMap.insert( - Dice::ERROR_CODE::ENDLESS_LOOP_ERROR, - QObject::tr("Condition can't be reached, causing endless loop. Please, " - "change the %1 option condition") - .arg(symbol)); - } - break; - case Dice::CONDITION_STATE::ERROR_STATE: - default: - break; - } - - auto reroll= (operatorName == RerollAndAdd || operatorName == Reroll); - auto addingMode= (operatorName == RerollAndAdd); - RerollDiceNode* rerollNode= new RerollDiceNode(reroll, addingMode); - ExecutionNode* nodeParam= nullptr; - if(readParameterNode(str, nodeParam)) - { - rerollNode->setInstruction(nodeParam); - } - rerollNode->setValidatorList(validatorList); - previous->setNextNode(rerollNode); - found= true; - } - else - { - m_errorMap.insert( - Dice::ERROR_CODE::BAD_SYNTAXE, - QObject::tr("Validator is missing after the %1 operator. Please, change it").arg(symbol)); - } - } - break; - case Explode: - { - auto validatorList= readValidatorList(str); - if(nullptr != validatorList) - { - if(Dice::CONDITION_STATE::ALWAYSTRUE == isValidValidator(previous, validatorList)) - { - m_errorMap.insert(Dice::ERROR_CODE::ENDLESS_LOOP_ERROR, - QObject::tr("This condition %1 introduces an endless loop. Please, change it") - .arg(validatorList->toString())); - } - ExplodeDiceNode* explodedNode= new ExplodeDiceNode(); - explodedNode->setValidatorList(validatorList); - previous->setNextNode(explodedNode); - found= true; - } - else - { - m_errorMap.insert(Dice::ERROR_CODE::BAD_SYNTAXE, - QObject::tr("Validator is missing after the e operator. Please, change it")); - } - } - break; - case Merge: - { - MergeNode* mergeNode= new MergeNode(); - mergeNode->setStartList(&m_startNodes); - previous->setNextNode(mergeNode); - found= true; - } - break; - case AllSameExplode: - { - AllSameNode* allSame= new AllSameNode(); - previous->setNextNode(allSame); - found= true; - } - break; - case SwitchCaseOption: - { - auto scNode= new SwitchCaseNode(); - found= readSwitchCaseNode(str, scNode); - previous->setNextNode(scNode); - } - break; - case TransformOption: - { - auto scNode= new ReplaceValueNode(); - found= readReplaceValueNode(str, scNode); - previous->setNextNode(scNode); - } - break; - case Bind: - { - BindNode* bindNode= new BindNode(); - bindNode->setStartList(&m_startNodes); - previous->setNextNode(bindNode); - found= true; - } - break; - case Occurences: - { - qint64 number= 0; - auto occNode= new OccurenceCountNode(); - if(readNumber(str, number)) - { - occNode->setWidth(number); - auto validatorList= readValidatorList(str); - if(validatorList) - { - occNode->setValidatorList(validatorList); - } - else if(readComma(str)) - { - if(readNumber(str, number)) - { - occNode->setHeight(number); - } - } - } - previous->setNextNode(occNode); - found= true; - } - break; - case Unique: - { - auto node= new UniqueNode(); - previous->setNextNode(node); - found= true; - } - break; - case Painter: - { - PainterNode* painter= new PainterNode(); - if(!readPainterParameter(painter, str)) - { - m_errorMap.insert(Dice::ERROR_CODE::BAD_SYNTAXE, - QObject::tr("Missing parameter for Painter node (p)")); - delete painter; - } - else - { - previous->setNextNode(painter); - found= true; - } - } - break; - case ifOperator: - { - IfNode* nodeif= new IfNode(); - nodeif->setConditionType(readConditionType(str)); - auto validatorList= readValidatorList(str); - if(nullptr != validatorList) - { - ExecutionNode* trueNode= nullptr; - ExecutionNode* falseNode= nullptr; - if(readIfInstruction(str, trueNode, falseNode)) - { - nodeif->setInstructionTrue(trueNode); - nodeif->setInstructionFalse(falseNode); - nodeif->setValidatorList(validatorList); - previous->setNextNode(nodeif); - found= true; - } - else - { - delete nodeif; - } - } - else - { - delete nodeif; - } - break; - } - case Split: - { - SplitNode* splitnode= new SplitNode(); - previous->setNextNode(splitnode); - found= true; - } - break; - case Group: - { - bool stringResult= readStringResultParameter(str); - qint64 groupNumber= 0; - if(readNumber(str, groupNumber)) - { - GroupNode* groupNode= new GroupNode(stringResult); - groupNode->setGroupValue(groupNumber); - previous->setNextNode(groupNode); - found= true; - } - } - break; - } - } - } - return found; -} -bool ParsingToolBox::readStringResultParameter(QString& str) -{ - if(str.startsWith("s")) - { - str.remove(0, 1); - return true; - } - return false; -} -bool ParsingToolBox::readIfInstruction(QString& str, ExecutionNode*& trueNode, ExecutionNode*& falseNode) -{ - if(readBlocInstruction(str, trueNode)) - { - if(readBlocInstruction(str, falseNode)) - { - return true; - } - return true; - } - return false; -} -DiceRollerNode* ParsingToolBox::addRollDiceNode(qint64 faces, ExecutionNode* previous) -{ - DiceRollerNode* mydiceRoller= new DiceRollerNode(faces); - previous->setNextNode(mydiceRoller); - return mydiceRoller; -} -ExplodeDiceNode* ParsingToolBox::addExplodeDiceNode(qint64 value, ExecutionNode* previous) -{ - ExplodeDiceNode* explodeDiceNode= new ExplodeDiceNode(); - NumberNode* node= new NumberNode(); - node->setNumber(value); - BooleanCondition* condition= new BooleanCondition(); - condition->setConditionType(Dice::OnEach); - condition->setValueNode(node); - condition->setOperator(Dice::CompareOperator::Equal); - auto valList= new ValidatorList(); - valList->setValidators(QList<Validator*>() << condition); - auto validity= isValidValidator(previous, valList); - explodeDiceNode->setValidatorList(valList); - previous->setNextNode(explodeDiceNode); - return explodeDiceNode; -} -bool ParsingToolBox::readParameterNode(QString& str, ExecutionNode*& node) -{ - if(str.startsWith("(")) - { - str= str.remove(0, 1); - if(readExpression(str, node)) - { - if(str.startsWith(")")) - { - str= str.remove(0, 1); - return true; - } - } - } - return false; -} - -bool ParsingToolBox::readSwitchCaseNode(QString& str, SwitchCaseNode* node) -{ - bool res= false; - node->setStopAtFirt(ParsingToolBox::readStopAtFirst(str)); - bool hasInstructionBloc= false; - do - { - auto validator= readValidatorList(str); - ExecutionNode* exeNode= nullptr; - hasInstructionBloc= readBlocInstruction(str, exeNode); - if(hasInstructionBloc) - { - node->insertCase(exeNode, validator); - res= true; - } - - } while(hasInstructionBloc); - - return res; -} - -bool ParsingToolBox::readReplaceValueNode(QString& str, ReplaceValueNode* node) -{ - bool res= false; - bool hasInstructionBloc= false; - do - { - auto validator= readValidatorList(str); - ExecutionNode* exeNode= nullptr; - hasInstructionBloc= readBlocInstruction(str, exeNode); - if(hasInstructionBloc) - { - node->insertCase(exeNode, validator); - res= true; - } - - } while(hasInstructionBloc); - - return res; -} - -bool ParsingToolBox::readBlocInstruction(QString& str, ExecutionNode*& resultnode) -{ - if(str.startsWith('{')) - { - str= str.remove(0, 1); - ExecutionNode* node= nullptr; - Dice::ArithmeticOperator op; - ScalarOperatorNode* scalarNode= nullptr; - if(readArithmeticOperator(str, op)) - { - scalarNode= new ScalarOperatorNode(); - scalarNode->setArithmeticOperator(op); - } - if(readExpression(str, node)) - { - if(str.startsWith('}')) - { - if(nullptr == scalarNode) - { - resultnode= node; - } - else - { - resultnode= scalarNode; - scalarNode->setInternalNode(node); - } - str= str.remove(0, 1); - return true; - } - } - } - return false; -} -bool ParsingToolBox::readDice(QString& str, ExecutionNode*& node) -{ - DiceOperator currentOperator; - - if(readDiceOperator(str, currentOperator)) - { - if(currentOperator == D) - { - qint64 max; - qint64 min; - bool unique= (ParsingToolBox::UNIQUE == readListOperator(str)) ? true : false; - Dice::ArithmeticOperator op; - - bool hasOp= readArithmeticOperator(str, op); - if(readNumber(str, max)) - { - if(max < 1) - { - m_errorMap.insert( - Dice::ERROR_CODE::BAD_SYNTAXE, - QObject::tr("Dice with %1 face(s) does not exist. Please, put a value higher than 0").arg(max)); - return false; - } - DiceRollerNode* drNode= new DiceRollerNode(max); - drNode->setUnique(unique); - if(hasOp) - { - drNode->setOperator(op); - } - node= drNode; - ExecutionNode* current= drNode; - while(readOption(str, current)) - { - current= ParsingToolBox::getLeafNode(current); - } - return true; - } - else if(readDiceRange(str, min, max)) - { - DiceRollerNode* drNode= new DiceRollerNode(max, min); - drNode->setUnique(unique); - if(hasOp) - { - drNode->setOperator(op); - } - node= drNode; - ExecutionNode* current= drNode; - while(readOption(str, current)) - { - current= ParsingToolBox::getLeafNode(current); - } - return true; - } - } - else if(currentOperator == L) - { - QStringList list; - QList<Range> listRange; - ParsingToolBox::LIST_OPERATOR op= readListOperator(str); - if(readList(str, list, listRange)) - { - ListSetRollNode* lsrNode= new ListSetRollNode(); - lsrNode->setRangeList(listRange); - if(op == ParsingToolBox::UNIQUE || op == ParsingToolBox::UniqueAndNoComma) - { - lsrNode->setUnique(true); - } - if(op == ParsingToolBox::NOCOMMA || op == ParsingToolBox::UniqueAndNoComma) - { - lsrNode->setNoComma(true); - } - lsrNode->setListValue(list); - node= lsrNode; - return true; - } - else - { - m_errorMap.insert( - Dice::ERROR_CODE::BAD_SYNTAXE, - QObject::tr( - "List is missing after the L operator. Please, add it (e.g : 1L[sword,spear,gun,arrow])")); - } - } - } - - return false; -} -bool ParsingToolBox::readDiceOperator(QString& str, DiceOperator& op) -{ - QStringList listKey= m_mapDiceOp.keys(); - for(const QString& key : qAsConst(listKey)) - { - if(str.startsWith(key, Qt::CaseInsensitive)) - { - str= str.remove(0, key.size()); - op= m_mapDiceOp.value(key); - return true; - } - } - return false; -} -QString ParsingToolBox::convertAlias(QString str) -{ - for(auto& cmd : m_aliasList) - { - if(cmd->isEnable()) - { - cmd->resolved(str); - } - } - return str; -} - -bool ParsingToolBox::readCommand(QString& str, ExecutionNode*& node) -{ - if(m_commandList.contains(str)) - { - if(str == QLatin1String("help")) - { - str= str.remove(0, QLatin1String("help").size()); - HelpNode* help= new HelpNode(); - if(!m_helpPath.isEmpty()) - { - help->setHelpPath(m_helpPath); - } - node= help; - } - else if(str == QLatin1String("la")) - { - str= str.remove(0, QLatin1String("la").size()); - node= new ListAliasNode(m_aliasList); - } - return true; - } - return false; -} - -bool ParsingToolBox::readDiceExpression(QString& str, ExecutionNode*& node) -{ - bool returnVal= false; - - ExecutionNode* next= nullptr; - if(readDice(str, next)) - { - ExecutionNode* latest= next; - while(readOption(str, latest)) - { - while(nullptr != latest->getNextNode()) - { - latest= latest->getNextNode(); - } - } - - node= next; - returnVal= true; - } - else - { - returnVal= false; - } - return returnVal; -} - -bool ParsingToolBox::readOperator(QString& str, ExecutionNode* previous) -{ - bool result= false; - if(str.isEmpty() || nullptr == previous) - { - return result; - } - - Dice::ArithmeticOperator op; - if(readArithmeticOperator(str, op)) - { - ScalarOperatorNode* node= new ScalarOperatorNode(); - node->setArithmeticOperator(op); - ExecutionNode* nodeExec= nullptr; - if(readExpression(str, nodeExec)) - { - node->setInternalNode(nodeExec); - if(nullptr == nodeExec) - { - delete node; - return result; - } - ExecutionNode* nodeExecOrChild= nodeExec; - ExecutionNode* parent= nullptr; - - while((nullptr != nodeExecOrChild) && (node->getPriority() < nodeExecOrChild->getPriority())) - { - parent= nodeExecOrChild; - nodeExecOrChild= nodeExecOrChild->getNextNode(); - } - // management of operator priority - if((nullptr != nodeExecOrChild) && (nodeExec != nodeExecOrChild)) - { - // good 1 1 2 ; bad 1 0 4 - if(nodeExecOrChild->getPriority() >= node->getPriority()) - { - node->setNextNode(nodeExecOrChild); - parent->setNextNode(nullptr); - } - } - else if(node->getPriority() >= nodeExec->getPriority()) - { - node->setNextNode(nodeExec->getNextNode()); - nodeExec->setNextNode(nullptr); - } - - // nodeResult = node; - previous->setNextNode(node); - - result= true; - } - else - { - delete node; - } - } - else - { - while(readOption(str, previous)) - { - previous= ParsingToolBox::getLeafNode(previous); - result= true; - } - } - return result; -} -bool ParsingToolBox::readFunction(QString& str, ExecutionNode*& node) -{ - for(const auto& kv : m_functionMap) - { - if(str.startsWith(kv.first)) - { - str= str.remove(0, kv.first.size()); - switch(kv.second) - { - case REPEAT: - { - auto repeaterNode= new RepeaterNode(); - if(ParsingToolBox::readReaperArguments(repeaterNode, str)) - { - node= repeaterNode; - } - } - break; - } - } - } - - if(node == nullptr) - return false; - return true; -} - -bool ParsingToolBox::readNode(QString& str, ExecutionNode*& node) -{ - if(str.isEmpty()) - return false; - - QString key= str.at(0); - if(m_nodeActionMap.contains(key)) - { - JumpBackwardNode* jumpNode= new JumpBackwardNode(); - node= jumpNode; - str= str.remove(0, 1); - readOption(str, jumpNode); - return true; - } - return false; -} - -bool ParsingToolBox::readInstructionOperator(QChar c) -{ - if(c == ';') - { - return true; - } - return false; -} - -void ParsingToolBox::insertAlias(DiceAlias* dice, int i) -{ - if(i >= m_aliasList.size()) - { - m_aliasList.insert(i, dice); - } -} -const QList<DiceAlias*>& ParsingToolBox::getAliases() const -{ - return m_aliasList; -} - -QList<DiceAlias*>* ParsingToolBox::aliases() -{ - return &m_aliasList; -} - -void ParsingToolBox::setAliases(const QList<DiceAlias*> list) -{ - qDeleteAll(m_aliasList); - m_aliasList.clear(); - m_aliasList= list; -} - -std::vector<ExecutionNode*> ParsingToolBox::readInstructionList(QString& str, bool global) -{ - if(str.isEmpty()) - return {}; - - std::vector<ExecutionNode*> startNodes; - - bool hasInstruction= false; - bool readInstruction= true; - while(readInstruction) - { - ExecutionNode* startNode= nullptr; - bool keepParsing= readExpression(str, startNode); - if(nullptr != startNode) - { - hasInstruction= true; - startNodes.push_back(startNode); - auto latest= startNode; - if(keepParsing) - { - latest= ParsingToolBox::getLeafNode(latest); - keepParsing= !str.isEmpty(); - while(keepParsing) - { - auto before= str; - if(readOperator(str, latest)) - { - latest= ParsingToolBox::getLeafNode(latest); - } - keepParsing= (!str.isEmpty() && (before != str)); - } - } - if(!str.isEmpty() && readInstructionOperator(str[0])) - { - str= str.remove(0, 1); - } - else - { - QString result; - QString comment; - if(readComment(str, result, comment)) - { - m_comment= result; - } - readInstruction= false; - } - } - else - { - readInstruction= false; - } - } - if(global) - m_startNodes= startNodes; - return startNodes; -} - -SubtituteInfo ParsingToolBox::readVariableFromString(const QString& source, int& start) -{ - bool found= false; - SubtituteInfo info; - int i= start; - for(; i >= 0 && !found; --i) - { - if(source.at(i) == '$') - { - auto rest= source.mid(i + 1, 1 + start - i); - qint64 number; - if(readNumber(rest, number)) - { - auto len= QString::number(number).size() - 1; - readSubtitutionParameters(info, rest); - info.setLength(info.length() + len); - info.setResultIndex(static_cast<int>(number)); - info.setPosition(i); - found= true; - } - } - } - start= i; - return info; -} - -SubtituteInfo ParsingToolBox::readPlaceHolderFromString(const QString& source, int& start) -{ - bool found= false; - SubtituteInfo info; - int i= start; - for(; i >= 0 && !found; --i) - { - if(source.at(i) == '@') - { - auto rest= source.mid(i + 1, 1 + start - i); - qint64 number; - if(readNumber(rest, number)) - { - auto len= QString::number(number).size() - 1; - readSubtitutionParameters(info, rest); - info.setLength(info.length() + len); - info.setResultIndex(static_cast<int>(number)); - info.setPosition(i); - found= true; - } - } - } - start= i; - return info; -} - -QString ParsingToolBox::number(qreal value) -{ - if(value > 1000000) - return QString::number(value, 'f', 20); - else - return QString::number(value); -} - -ExportedDiceResult ParsingToolBox::finalDiceResultFromInstruction(ExecutionNode* start) -{ - ExecutionNode* next= ParsingToolBox::getLeafNode(start); - Result* result= next->getResult(); - ExportedDiceResult nodeResult; - std::set<QString> alreadyAdded; - while(nullptr != result) - { - if(result->hasResultOfType(Dice::RESULT_TYPE::DICE_LIST)) - { - DiceResult* diceResult= dynamic_cast<DiceResult*>(result); - QList<HighLightDice> list; - quint64 faces= 0; - for(auto& die : diceResult->getResultList()) - { - faces= die->getFaces(); - HighLightDice hlDice(die->getListValue(), die->isHighlighted(), die->getColor(), - die->hasBeenDisplayed(), die->getFaces(), die->getUuid()); - if(alreadyAdded.find(die->getUuid()) == alreadyAdded.end() && !hlDice.displayed()) - { - list.append(hlDice); - alreadyAdded.insert(die->getUuid()); - } - } - if(!list.isEmpty()) - { - auto vals= nodeResult.value(faces); - vals.append(list); - nodeResult.insert(faces, vals); - } - } - /*if(nodeResult.isEmpty()) - result= result->getPrevious(); - else*/ - result= result->getPrevious(); - } - return nodeResult; -} - -ExportedDiceResult ParsingToolBox::allDiceResultFromInstruction(ExecutionNode* start) -{ - ExecutionNode* next= ParsingToolBox::getLeafNode(start); - Result* result= next->getResult(); - ExportedDiceResult nodeResult; - std::set<QString> alreadyAdded; - while(nullptr != result) - { - if(result->hasResultOfType(Dice::RESULT_TYPE::DICE_LIST)) - { - DiceResult* diceResult= dynamic_cast<DiceResult*>(result); - QList<HighLightDice> list; - quint64 faces= 0; - for(auto& die : diceResult->getResultList()) - { - faces= die->getFaces(); - HighLightDice hlDice(die->getListValue(), die->isHighlighted(), die->getColor(), - die->hasBeenDisplayed(), die->getFaces(), die->getUuid()); - if(alreadyAdded.find(die->getUuid()) == alreadyAdded.end()) - { - list.append(hlDice); - alreadyAdded.insert(die->getUuid()); - } - } - if(!list.isEmpty()) - { - auto vals= nodeResult.value(faces); - vals.append(list); - nodeResult.insert(faces, vals); - } - } - result= result->getPrevious(); - } - return nodeResult; -} - -void ParsingToolBox::addResultInJson(QJsonObject& obj, Dice::RESULT_TYPE type, const QString& key, ExecutionNode* start, - bool b) -{ - auto pair= hasResultOfType(type, start, b); - if(pair.first) - obj[key]= QJsonValue::fromVariant(pair.second); -} - -void ParsingToolBox::addDiceResultInJson( - QJsonObject& obj, ExecutionNode* start, - std::function<QString(const QString& value, const QString& color, bool highlighted)> colorize) -{ - QJsonArray diceValues; - auto result= ParsingToolBox::allDiceResultFromInstruction(start); - for(auto listOfList : result.values()) - { - for(auto listDiceResult : listOfList) - { - for(auto hlDice : listDiceResult) - { - QJsonObject diceObj; - diceObj["face"]= static_cast<qreal>(hlDice.faces()); - diceObj["color"]= hlDice.color(); - diceObj["displayed"]= hlDice.displayed(); - diceObj["string"]= colorize(hlDice.getResultString(), hlDice.color(), hlDice.isHighlighted()); - diceObj["highlight"]= hlDice.isHighlighted(); - diceObj["uuid"]= hlDice.uuid(); - auto val= hlDice.result(); - if(!val.isEmpty()) - { - diceObj["value"]= std::accumulate(val.begin(), val.end(), 0); - if(val.size() > 1) - { - QJsonArray intValues; - std::transform(val.begin(), val.end(), std::back_inserter(intValues), - [](qint64 val) { return static_cast<int>(val); }); - diceObj["subvalues"]= intValues; - } - } - diceValues.append(diceObj); - } - } - } - if(!diceValues.isEmpty()) - obj["diceval"]= diceValues; -} - -SubtituteInfo::SubtituteInfo() {} - -bool SubtituteInfo::isValid() const -{ - return !(m_position + m_resultIndex < 0); -} - -int SubtituteInfo::length() const -{ - return m_length; -} - -void SubtituteInfo::setLength(int length) -{ - m_length= length; -} - -int SubtituteInfo::resultIndex() const -{ - return m_resultIndex; -} - -void SubtituteInfo::setResultIndex(int valueIndex) -{ - m_resultIndex= valueIndex; -} - -int SubtituteInfo::position() const -{ - return m_position; -} - -void SubtituteInfo::setPosition(int position) -{ - m_position= position; -} - -int SubtituteInfo::digitNumber() const -{ - return m_digitNumber; -} - -void SubtituteInfo::setDigitNumber(int digitNumber) -{ - m_digitNumber= digitNumber; -} - -int SubtituteInfo::subIndex() const -{ - return m_subIndex; -} - -void SubtituteInfo::setSubIndex(int subindex) -{ - m_subIndex= subindex; -} |