File indexing completed on 2024-04-28 05:36:59
0001 /*************************************************************************** 0002 * Copyright (C) 2014 by Renaud Guezennec * 0003 * https://rolisteam.org/contact * 0004 * * 0005 * This file is part of DiceParser * 0006 * * 0007 * DiceParser is free software; you can redistribute it and/or modify * 0008 * it under the terms of the GNU General Public License as published by * 0009 * the Free Software Foundation; either version 2 of the License, or * 0010 * (at your option) any later version. * 0011 * * 0012 * This program is distributed in the hope that it will be useful, * 0013 * but WITHOUT ANY WARRANTY; without even the implied warranty of * 0014 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * 0015 * GNU General Public License for more details. * 0016 * * 0017 * You should have received a copy of the GNU General Public License * 0018 * along with this program; if not, write to the * 0019 * Free Software Foundation, Inc., * 0020 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * 0021 ***************************************************************************/ 0022 #include <diceparser/diceparser.h> 0023 0024 #include <QDebug> 0025 #include <QFile> 0026 #include <QJsonArray> 0027 #include <QJsonDocument> 0028 #include <QJsonObject> 0029 #include <QObject> 0030 #include <QStringList> 0031 #include <functional> 0032 #include <numeric> 0033 0034 #include "booleancondition.h" 0035 #include "range.h" 0036 #include "result/stringresult.h" 0037 #include "validator.h" 0038 #include <diceparser/dicealias.h> 0039 #include <diceparser/parsingtoolbox.h> 0040 0041 #define DEFAULT_FACES_NUMBER 10 0042 0043 DiceParser::DiceParser() : m_parsingToolbox(new ParsingToolBox()) {} 0044 DiceParser::~DiceParser() {} 0045 0046 const QList<DiceAlias*>& DiceParser::constAliases() const 0047 { 0048 return m_parsingToolbox->getAliases(); 0049 } 0050 0051 QList<DiceAlias*>* DiceParser::aliases() const 0052 { 0053 return m_parsingToolbox->aliases(); 0054 } 0055 0056 void DiceParser::cleanAliases() 0057 { 0058 m_parsingToolbox->cleanUpAliases(); 0059 } 0060 void DiceParser::insertAlias(DiceAlias* dice, int i) 0061 { 0062 m_parsingToolbox->insertAlias(dice, i); 0063 } 0064 0065 bool DiceParser::parseLine(QString str, bool allowAlias) 0066 { 0067 if(allowAlias) 0068 { 0069 str= m_parsingToolbox->convertAlias(str); 0070 } 0071 m_parsingToolbox->clearUp(); 0072 m_command= str; 0073 auto instructions= m_parsingToolbox->readInstructionList(str, true); 0074 m_command.remove(m_parsingToolbox->getComment()); 0075 bool value= !instructions.empty(); 0076 if(!value) 0077 { 0078 m_parsingToolbox->addError(Dice::ERROR_CODE::NOTHING_UNDERSTOOD, 0079 QObject::tr("Nothing was understood. To roll dice: !1d6 - full documentation: " 0080 "<a " 0081 "href=\"https://github.com/Rolisteam/DiceParser/blob/master/" 0082 "HelpMe.md\">https://github.com/" 0083 "Rolisteam/DiceParser/blob/master/HelpMe.md</a>")); 0084 } 0085 else if(value && !str.isEmpty()) 0086 { 0087 auto i= m_command.size() - str.size(); 0088 m_parsingToolbox->addWarning( 0089 Dice::ERROR_CODE::UNEXPECTED_CHARACTER, 0090 QObject::tr("Unexpected character at %1 - end of command was ignored \"%2\"").arg(i).arg(str)); 0091 } 0092 0093 if(m_parsingToolbox->hasError()) 0094 value= false; 0095 0096 return value; 0097 } 0098 0099 QString DiceParser::convertAlias(const QString& cmd) const 0100 { 0101 return m_parsingToolbox->convertAlias(cmd); 0102 } 0103 0104 void DiceParser::start() 0105 { 0106 for(auto start : m_parsingToolbox->getStartNodes()) 0107 { 0108 start->run(); 0109 } 0110 } 0111 0112 QString DiceParser::diceCommand() const 0113 { 0114 return m_command; 0115 } 0116 0117 bool DiceParser::hasIntegerResultNotInFirst() const 0118 { 0119 return m_parsingToolbox->hasIntegerResultNotInFirst(); 0120 } 0121 0122 bool DiceParser::hasDiceResult() const 0123 { 0124 return m_parsingToolbox->hasDiceResult(); 0125 } 0126 bool DiceParser::hasStringResult() const 0127 { 0128 return m_parsingToolbox->hasStringResult(); 0129 } 0130 0131 int DiceParser::startNodeCount() const 0132 { 0133 return static_cast<int>(m_parsingToolbox->getStartNodes().size()); 0134 } 0135 0136 QList<qreal> DiceParser::scalarResultsFromEachInstruction() const 0137 { 0138 return m_parsingToolbox->scalarResultsFromEachInstruction(); 0139 } 0140 0141 QStringList DiceParser::stringResultFromEachInstruction(bool& hasAlias) const 0142 { 0143 return m_parsingToolbox->allFirstResultAsString(hasAlias); 0144 } 0145 0146 void DiceParser::diceResultFromEachInstruction(QList<ExportedDiceResult>& resultList) const 0147 { 0148 resultList= m_parsingToolbox->diceResultFromEachInstruction(); 0149 } 0150 0151 QString DiceParser::comment() const 0152 { 0153 return m_parsingToolbox->getComment(); 0154 } 0155 0156 void DiceParser::setComment(const QString& comment) 0157 { 0158 m_parsingToolbox->setComment(comment); 0159 } 0160 0161 QMap<Dice::ERROR_CODE, QString> DiceParser::errorMap() const 0162 { 0163 QMap<Dice::ERROR_CODE, QString> map; 0164 0165 for(auto start : m_parsingToolbox->getStartNodes()) 0166 { 0167 auto mapTmp= start->getExecutionErrorMap(); 0168 auto keys= mapTmp.keys(); 0169 for(auto& key : keys) 0170 { 0171 map.insert(key, mapTmp[key]); 0172 } 0173 } 0174 return map; 0175 } 0176 QString DiceParser::humanReadableError() const 0177 { 0178 auto parsingError= m_parsingToolbox->getErrorList(); 0179 QString str; 0180 std::for_each(parsingError.begin(), parsingError.end(), 0181 [&str](const QString& text) 0182 { 0183 str.append(text); 0184 str.append(QStringLiteral("\n")); 0185 }); 0186 0187 /// list 0188 auto errMap= errorMap(); 0189 std::for_each(errMap.begin(), errMap.end(), 0190 [&str](const QString& text) 0191 { 0192 str.append(text); 0193 str.append(QStringLiteral("\n")); 0194 }); 0195 return str; 0196 } 0197 0198 QString DiceParser::humanReadableWarning() const 0199 { 0200 auto warningMap= m_parsingToolbox->getWarningList(); 0201 QMapIterator<Dice::ERROR_CODE, QString> i(warningMap); 0202 QString str(""); 0203 while(i.hasNext()) 0204 { 0205 i.next(); 0206 str.append(i.value()); 0207 str.append(QStringLiteral("\n")); 0208 } 0209 return str; 0210 } 0211 0212 QString DiceParser::finalStringResult(std::function<QString(const QString&, const QString&, bool)> colorize) const 0213 { 0214 return m_parsingToolbox->finalStringResult(colorize); 0215 } 0216 0217 QString DiceParser::resultAsJSon(std::function<QString(const QString&, const QString&, bool)> colorize, 0218 bool removeUnhighligthed) const 0219 { 0220 QJsonObject obj; 0221 QJsonArray instructions; 0222 for(auto start : m_parsingToolbox->getStartNodes()) 0223 { 0224 QJsonObject inst; 0225 0226 m_parsingToolbox->addResultInJson(inst, Dice::RESULT_TYPE::SCALAR, "scalar", start, true); 0227 m_parsingToolbox->addResultInJson(inst, Dice::RESULT_TYPE::STRING, "string", start, false); 0228 m_parsingToolbox->addDiceResultInJson(inst, start, colorize); 0229 0230 instructions.append(inst); 0231 } 0232 obj["instructions"]= instructions; 0233 obj["comment"]= m_parsingToolbox->getComment(); 0234 obj["error"]= humanReadableError(); 0235 obj["scalar"]= m_parsingToolbox->finalScalarResult().first; 0236 obj["string"]= m_parsingToolbox->finalStringResult(colorize, removeUnhighligthed); 0237 obj["warning"]= humanReadableWarning(); 0238 obj["command"]= m_command; 0239 0240 QJsonDocument doc; 0241 doc.setObject(obj); 0242 return doc.toJson(); 0243 } 0244 0245 void DiceParser::writeDownDotTree(QString filepath) 0246 { 0247 if(m_parsingToolbox->getStartNodes().empty()) 0248 return; 0249 0250 QString str(QStringLiteral("digraph ExecutionTree {\n")); 0251 for(auto start : m_parsingToolbox->getStartNodes()) 0252 { 0253 start->generateDotTree(str); 0254 } 0255 str.append(QStringLiteral("}\n")); 0256 0257 QFile file(filepath); 0258 if(file.open(QIODevice::WriteOnly)) 0259 { 0260 QTextStream in(&file); 0261 in << str; 0262 } 0263 } 0264 void DiceParser::setPathToHelp(QString l) 0265 { 0266 m_parsingToolbox->setHelpPath(l); 0267 } 0268 void DiceParser::setVariableDictionary(const QHash<QString, QString>& variables) 0269 { 0270 ParsingToolBox::setVariableHash(variables); 0271 }