aboutsummaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
authorRenaud G <renaud@rolisteam.org>2020-01-30 01:27:15 +0100
committerRenaud G <renaud@rolisteam.org>2020-03-28 02:05:05 +0100
commit653ba9395a36cc20ec1d68c9a9cae78973fa334c (patch)
tree72753ed3bdca117baf001cdf8251b1fb22276eeb
parent22d71d0032e2f44a8f267895aea3bd87864791b3 (diff)
downloadOneRoll-653ba9395a36cc20ec1d68c9a9cae78973fa334c.tar.gz
OneRoll-653ba9395a36cc20ec1d68c9a9cae78973fa334c.zip
add unicity and repeat function part2
-rw-r--r--CMakeLists.txt3
-rw-r--r--cli/CMakeLists.txt78
-rw-r--r--cli/main.cpp1
-rw-r--r--diceparser.cpp1106
-rw-r--r--include/diceparser.h167
-rw-r--r--include/diceparserhelper.h12
-rw-r--r--include/parsingtoolbox.h176
-rw-r--r--node/countexecutenode.cpp28
-rw-r--r--node/countexecutenode.h6
-rw-r--r--node/explodedicenode.cpp49
-rw-r--r--node/explodedicenode.h8
-rw-r--r--node/filternode.cpp40
-rw-r--r--node/filternode.h7
-rw-r--r--node/ifnode.cpp83
-rw-r--r--node/ifnode.h25
-rw-r--r--node/mergenode.cpp11
-rw-r--r--node/occurencecountnode.cpp17
-rw-r--r--node/occurencecountnode.h8
-rw-r--r--node/repeaternode.cpp108
-rw-r--r--node/repeaternode.h4
-rw-r--r--node/rerolldicenode.cpp22
-rw-r--r--node/rerolldicenode.h7
-rw-r--r--node/variablenode.h8
-rw-r--r--parsingtoolbox.cpp1174
-rw-r--r--result/diceresult.cpp2
-rw-r--r--result/diceresult.h2
-rw-r--r--tests/dice/CMakeLists.txt10
-rw-r--r--tests/dice/tst_dice.cpp212
-rw-r--r--validator.cpp84
-rw-r--r--validator.h30
-rw-r--r--validatorlist.cpp355
-rw-r--r--validatorlist.h92
32 files changed, 2245 insertions, 1690 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 319e510..d1b0f93 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -13,7 +13,7 @@ SET( dice_sources
${CMAKE_CURRENT_SOURCE_DIR}/range.cpp
${CMAKE_CURRENT_SOURCE_DIR}/booleancondition.cpp
${CMAKE_CURRENT_SOURCE_DIR}/validator.cpp
- ${CMAKE_CURRENT_SOURCE_DIR}/compositevalidator.cpp
+ ${CMAKE_CURRENT_SOURCE_DIR}/validatorlist.cpp
${CMAKE_CURRENT_SOURCE_DIR}/operationcondition.cpp
${CMAKE_CURRENT_SOURCE_DIR}/die.cpp
${CMAKE_CURRENT_SOURCE_DIR}/parsingtoolbox.cpp
@@ -52,6 +52,7 @@ SET( dice_sources
${CMAKE_CURRENT_SOURCE_DIR}/highlightdice.cpp
${CMAKE_CURRENT_SOURCE_DIR}/node/variablenode.cpp
${CMAKE_CURRENT_SOURCE_DIR}/node/valueslistnode.cpp
+ ${CMAKE_CURRENT_SOURCE_DIR}/node/repeaternode.cpp
)
IF(STATIC_BUILD)
diff --git a/cli/CMakeLists.txt b/cli/CMakeLists.txt
index 7fe65a4..6828d09 100644
--- a/cli/CMakeLists.txt
+++ b/cli/CMakeLists.txt
@@ -1,56 +1,11 @@
cmake_minimum_required(VERSION 3.5)
option(UPDATE_TRANSLATIONS "update Translation" OFF)
+option(NO_PAINTER_OPERATOR "No PAINTING" OFF)
MESSAGE(STATUS "UPDATE TRANSLATIONS: ${UPDATE_TRANSLATIONS}")
project(dice)
-SET( dice_sources
- ../diceparser.cpp
- ../range.cpp
- ../booleancondition.cpp
- ../validator.cpp
- ../compositevalidator.cpp
- ../operationcondition.cpp
- ../die.cpp
- ../parsingtoolbox.cpp
- ../dicealias.cpp
- ../result/result.cpp
- ../result/scalarresult.cpp
- ../result/stringresult.cpp
- ../result/diceresult.cpp
- ../node/countexecutenode.cpp
- ../node/dicerollernode.cpp
- ../node/executionnode.cpp
- ../node/explodedicenode.cpp
- ../node/helpnode.cpp
- ../node/mergenode.cpp
- ../node/jumpbackwardnode.cpp
- ../node/keepdiceexecnode.cpp
- ../node/listaliasnode.cpp
- ../node/allsamenode.cpp
- ../node/listsetrollnode.cpp
- ../node/numbernode.cpp
- ../node/parenthesesnode.cpp
- # ../ node/forloopnode.cpp
- ../node/paintnode.cpp
- ../node/rerolldicenode.cpp
- ../node/scalaroperatornode.cpp
- ../node/sortresult.cpp
- ../node/startingnode.cpp
- ../node/filternode.cpp
- ../node/stringnode.cpp
- ../node/ifnode.cpp
- ../node/splitnode.cpp
- ../node/groupnode.cpp
- ../node/bind.cpp
- ../node/occurencecountnode.cpp
- ../node/uniquenode.cpp
- ../highlightdice.cpp
- ../node/variablenode.cpp
- ../node/valueslistnode.cpp
-)
-
# Find includes in corresponding build directories
set(CMAKE_INCLUDE_CURRENT_DIR ON)
# Instruct CMake to run moc automatically when needed.
@@ -58,23 +13,23 @@ set(CMAKE_AUTOMOC ON)
set(EXECUTABLE_OUTPUT_PATH bin/)
# Find the QtWidgets library
-find_package(Qt5Core)
-include_directories(${Qt5Core_INCLUDES} ../)
-add_definitions(${Qt5Core_DEFINITIONS})
+set(QT_REQUIRED_VERSION "5.12.0")
+
+
-IF(NOT DEFINED NO_PAINTER_OPERATOR)
+IF(NO_PAINTER_OPERATOR)
+ find_package(Qt5 ${QT_REQUIRED_VERSION} CONFIG REQUIRED COMPONENTS Core Svg LinguistTools)
+else()
MESSAGE(STATUS "Compilation of operator Paint")
- find_package(Qt5Gui)
- include_directories(${Qt5Gui_INCLUDES} ../)
- add_definitions(${Qt5Gui_DEFINITIONS})
+ find_package(Qt5 ${QT_REQUIRED_VERSION} CONFIG REQUIRED COMPONENTS Core Gui Svg LinguistTools)
add_definitions(-DPAINTER_OP)
endif()
+
set(MODE "cli")
ADD_DEFINITIONS(
- -std=c++11 # Or -std=c++0x
- # Other flags
+ -std=c++11
)
set(dice_RESOURCES diceparser.qrc)
@@ -106,9 +61,12 @@ SET( cli_sources
set(documentation_files ../HelpMe.md ../README.md)
-add_executable( dice ${cli_sources} ${dice_QM} ${dice_sources} ${documentation_files})
-target_include_directories(dice PRIVATE ../include)
-
-
-target_link_libraries(dice ${Qt5Core_LIBRARIES} ${Qt5Gui_LIBRARIES} ${Qt5Svg_LIBRARIES})
+add_executable( dice ${cli_sources} ${dice_QM} ${documentation_files})
+set(diceparser_shared_INCLUDE_DIRS "../diceparser")
+target_include_directories(dice PRIVATE ../include ../ ../result ../node)
+IF(NO_PAINTER_OPERATOR)
+ target_link_libraries(dice PUBLIC Qt5::Core Qt5::Svg PRIVATE diceparser_shared)
+ELSE()
+ target_link_libraries(dice PUBLIC Qt5::Core Qt5::Gui Qt5::Svg PRIVATE diceparser_shared)
+ENDIF()
INSTALL_TARGETS(/bin dice)
diff --git a/cli/main.cpp b/cli/main.cpp
index e09a1de..0008cba 100644
--- a/cli/main.cpp
+++ b/cli/main.cpp
@@ -443,7 +443,6 @@ int startDiceParsing(QStringList& cmds, QString& treeFile, bool withColor, EXPOR
rt= 1;
}
}
- parser.cleanAll();
return rt;
}
#include <QTextCodec>
diff --git a/diceparser.cpp b/diceparser.cpp
index acce867..e78700b 100644
--- a/diceparser.cpp
+++ b/diceparser.cpp
@@ -26,364 +26,63 @@
#include <QStringList>
#include <functional>
-#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/rerolldicenode.h"
-#include "node/scalaroperatornode.h"
-#include "node/sortresult.h"
-#include "node/splitnode.h"
-#include "node/startingnode.h"
-#include "node/uniquenode.h"
-#include "node/valueslistnode.h"
-#include "node/variablenode.h"
-
#include "booleancondition.h"
+#include "dicealias.h"
#include "parsingtoolbox.h"
#include "range.h"
+#include "result/stringresult.h"
#include "validator.h"
#define DEFAULT_FACES_NUMBER 10
-DiceParser::DiceParser()
-//: //m_start(nullptr),m_current(nullptr)
-{
- m_currentTreeHasSeparator= false;
- m_parsingToolbox= new ParsingToolBox();
- ParsingToolBox::setStartNodes(&m_startNodes);
-
- m_mapDiceOp= new QMap<QString, DiceOperator>();
- m_mapDiceOp->insert(QStringLiteral("D"), D);
- m_mapDiceOp->insert(QStringLiteral("L"), L);
-
- m_OptionOp= new QMap<QString, OptionOperator>();
- 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);
+DiceParser::DiceParser() : m_parsingToolbox(new ParsingToolBox()) {}
+DiceParser::~DiceParser() {}
- m_aliasList= new QList<DiceAlias*>();
-
- m_nodeActionMap= new QMap<QString, NodeAction>();
- m_nodeActionMap->insert(QStringLiteral("@"), JumpBackward);
-
- m_commandList= new QStringList();
- m_commandList->append(QStringLiteral("help"));
- m_commandList->append(QStringLiteral("la"));
-}
-DiceParser::~DiceParser()
+const QList<DiceAlias*>& DiceParser::getAliases() const
{
- if(nullptr != m_commandList)
- {
- delete m_commandList;
- m_commandList= nullptr;
- }
- if(nullptr != m_nodeActionMap)
- {
- delete m_nodeActionMap;
- m_nodeActionMap= nullptr;
- }
- if(nullptr != m_OptionOp)
- {
- delete m_OptionOp;
- m_OptionOp= nullptr;
- }
- if(nullptr != m_mapDiceOp)
- {
- delete m_mapDiceOp;
- m_mapDiceOp= nullptr;
- }
- if(nullptr != m_parsingToolbox)
- {
- delete m_parsingToolbox;
- m_parsingToolbox= nullptr;
- }
- if(nullptr != m_aliasList)
- {
- delete m_aliasList;
- m_aliasList= nullptr;
- }
- if(nullptr != m_start)
- {
- delete m_start;
- m_start= nullptr;
- }
-}
-
-QString DiceParser::convertAlias(QString str)
-{
- for(auto& cmd : *m_aliasList)
- {
- if(cmd->isEnable())
- {
- cmd->resolved(str);
- }
- }
- return str;
-}
-QList<DiceAlias*>* DiceParser::getAliases()
-{
- return m_aliasList;
+ return m_parsingToolbox->getAliases();
}
void DiceParser::insertAlias(DiceAlias* dice, int i)
{
- if(i >= m_aliasList->size())
- {
- m_aliasList->insert(i, dice);
- }
+ m_parsingToolbox->insertAlias(dice, i);
}
bool DiceParser::parseLine(QString str, bool allowAlias)
{
- m_errorMap.clear();
- m_comment= QString("");
- cleanAll();
- m_currentTreeHasSeparator= false;
if(allowAlias)
{
- str= convertAlias(str);
+ str= m_parsingToolbox->convertAlias(str);
}
m_command= str;
- bool hasInstruction= readInstructionList(str);
- bool value= hasInstruction;
- if(!hasInstruction)
+ auto instructions= m_parsingToolbox->readInstructionList(str, true);
+ m_command.remove(m_parsingToolbox->getComment());
+ bool value= !instructions.empty();
+ if(!value)
{
- m_errorMap.insert(
+ m_parsingToolbox->addError(
Dice::ERROR_CODE::NOTHING_UNDERSTOOD,
QObject::tr("Nothing was understood. To roll dice: !1d6 - full documation: "
"<a "
"href=\"https://github.com/Rolisteam/DiceParser/blob/master/HelpMe.md\">https://github.com/"
"Rolisteam/DiceParser/blob/master/HelpMe.md</a>"));
}
- else if(hasInstruction && !str.isEmpty())
+ else if(value && !str.isEmpty())
{
auto i= m_command.size() - str.size();
- m_warningMap.insert(
+ m_parsingToolbox->addWarning(
Dice::ERROR_CODE::UNEXPECTED_CHARACTER,
QObject::tr("Unexpected character at %1 - end of command was ignored \"%2\"").arg(i).arg(str));
}
- if(!m_errorMap.isEmpty())
+
+ if(m_parsingToolbox->hasError())
value= false;
return value;
}
-bool DiceParser::readExpression(QString& str, ExecutionNode*& node)
-{
- ExecutionNode* operandNode= nullptr;
- if(m_parsingToolbox->readOpenParentheses(str))
- {
- ExecutionNode* internalNode= nullptr;
- if(readExpression(str, internalNode))
- {
- ParenthesesNode* parentheseNode= new ParenthesesNode();
- parentheseNode->setInternelNode(internalNode);
- node= parentheseNode;
- if(m_parsingToolbox->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(readOptionFromNull(str, operandNode))
- {
- node= operandNode;
- return true;
- }
- else if(readOperatorFromNull(str, operandNode))
- {
- node= operandNode;
- return true;
- }
- else if(m_parsingToolbox->readOperand(str, operandNode))
- {
- ExecutionNode* diceNode= nullptr;
- if(readDice(str, diceNode))
- {
- operandNode->setNextNode(diceNode);
- }
- node= operandNode;
-
- operandNode= ParsingToolBox::getLatestNode(operandNode);
- // ExecutionNode* operatorNode=nullptr;
- while(readOperator(str, operandNode))
- {
- // operandNode->setNextNode(operatorNode);
- operandNode= ParsingToolBox::getLatestNode(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 DiceParser::readOptionFromNull(QString& str, ExecutionNode*& node)
-{
- StartingNode nodePrevious;
- if(readOption(str, &nodePrevious))
- {
- auto nodeNext= nodePrevious.getNextNode();
- nodePrevious.setNextNode(nullptr);
- node= nodeNext;
- return true;
- }
- return false;
-}
-
-bool DiceParser::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 DiceParser::readValuesList(QString& str, ExecutionNode*& node)
-{
- if(str.startsWith("["))
- {
- str= str.remove(0, 1);
- int pos= ParsingToolBox::findClosingCharacterIndexOf('[', ']', str, 1); // str.indexOf("]");
- if(-1 != pos)
- {
- QString liststr= str.left(pos);
- auto list= liststr.split(",");
- str= str.remove(0, pos + 1);
- auto values= new ValuesListNode();
- for(auto var : list)
- {
- qint64 number= 1;
- QString error;
- 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;
- }
- }
- return false;
-}
-
-bool DiceParser::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;
-}
-
-void DiceParser::cleanAll()
-{
- if(!m_startNodes.empty())
- {
- qDeleteAll(m_startNodes);
- m_startNodes.clear();
- }
-}
-
void DiceParser::start()
{
- for(auto start : m_startNodes)
+ for(auto start : m_parsingToolbox->getStartNodes())
{
start->run();
}
@@ -393,9 +92,9 @@ QList<qreal> DiceParser::getLastIntegerResults()
{
QList<qreal> resultValues;
QStringList alreadyVisitedNode;
- for(auto node : m_startNodes)
+ for(auto node : m_parsingToolbox->getStartNodes())
{
- ExecutionNode* next= getLeafNode(node);
+ ExecutionNode* next= ParsingToolBox::getLeafNode(node);
Result* result= next->getResult();
bool scalarDone= false;
while((result != nullptr) && (!scalarDone))
@@ -417,9 +116,9 @@ QList<qreal> DiceParser::getLastIntegerResults()
QStringList DiceParser::getStringResult()
{
QStringList stringListResult;
- for(auto node : m_startNodes)
+ for(auto node : m_parsingToolbox->getStartNodes())
{
- ExecutionNode* next= getLeafNode(node);
+ ExecutionNode* next= ParsingToolBox::getLeafNode(node);
QString str;
Result* result= next->getResult();
bool found= false;
@@ -441,9 +140,9 @@ QStringList DiceParser::getAllStringResult(bool& hasAlias)
{
// QStringList allResult;
QStringList stringListResult;
- for(auto node : m_startNodes)
+ for(auto node : m_parsingToolbox->getStartNodes())
{
- ExecutionNode* next= getLeafNode(node);
+ ExecutionNode* next= ParsingToolBox::getLeafNode(node);
Result* result= next->getResult();
while(nullptr != result)
@@ -465,9 +164,9 @@ QStringList DiceParser::getAllStringResult(bool& hasAlias)
QStringList DiceParser::getAllDiceResult(bool& hasAlias)
{
QStringList stringListResult;
- for(auto node : m_startNodes)
+ for(auto node : m_parsingToolbox->getStartNodes())
{
- ExecutionNode* next= getLeafNode(node);
+ ExecutionNode* next= ParsingToolBox::getLeafNode(node);
Result* result= next->getResult();
QList<Die*> dieListResult;
@@ -508,9 +207,9 @@ QStringList DiceParser::getAllDiceResult(bool& hasAlias)
void DiceParser::getDiceResultFromAllInstruction(QList<ExportedDiceResult>& resultList)
{
- for(auto start : m_startNodes)
+ for(auto start : m_parsingToolbox->getStartNodes())
{
- ExecutionNode* next= getLeafNode(start);
+ ExecutionNode* next= ParsingToolBox::getLeafNode(start);
Result* result= next->getResult();
ExportedDiceResult nodeResult;
while(nullptr != result)
@@ -518,21 +217,18 @@ void DiceParser::getDiceResultFromAllInstruction(QList<ExportedDiceResult>& resu
if(result->hasResultOfType(Dice::RESULT_TYPE::DICE_LIST))
{
DiceResult* diceResult= dynamic_cast<DiceResult*>(result);
- if(diceResult)
- {
- QList<HighLightDice> list;
- quint64 faces= 0;
+ QList<HighLightDice> list;
+ quint64 faces= 0;
- for(auto& die : diceResult->getResultList())
- {
- faces= die->getFaces();
- // qDebug() << "face" << faces;
- HighLightDice hlDice(die->getListValue(), die->isHighlighted(), die->getColor(),
- die->hasBeenDisplayed(), die->getFaces());
- list.append(hlDice);
- }
- nodeResult.insert(faces, list);
+ for(auto& die : diceResult->getResultList())
+ {
+ faces= die->getFaces();
+ // qDebug() << "face" << faces;
+ HighLightDice hlDice(die->getListValue(), die->isHighlighted(), die->getColor(),
+ die->hasBeenDisplayed(), die->getFaces());
+ list.append(hlDice);
}
+ nodeResult.insert(faces, list);
}
result= result->getPrevious();
}
@@ -544,10 +240,10 @@ void DiceParser::getDiceResultFromAllInstruction(QList<ExportedDiceResult>& resu
void DiceParser::getLastDiceResult(QList<ExportedDiceResult>& diceValuesList, bool& homogeneous)
{
QSet<QString> alreadySeenDice;
- for(auto start : m_startNodes)
+ for(auto start : m_parsingToolbox->getStartNodes())
{
ExportedDiceResult diceValues;
- ExecutionNode* next= getLeafNode(start);
+ ExecutionNode* next= ParsingToolBox::getLeafNode(start);
Result* result= next->getResult();
while(nullptr != result)
{
@@ -614,7 +310,7 @@ QString DiceParser::getDiceCommand() const
bool DiceParser::hasIntegerResultNotInFirst()
{
bool result= false;
- for(auto node : m_startNodes)
+ for(auto node : m_parsingToolbox->getStartNodes())
{
result|= hasResultOfType(Dice::RESULT_TYPE::SCALAR, node);
}
@@ -624,7 +320,7 @@ bool DiceParser::hasIntegerResultNotInFirst()
bool DiceParser::hasDiceResult()
{
bool result= false;
- for(auto node : m_startNodes)
+ for(auto node : m_parsingToolbox->getStartNodes())
{
result|= hasResultOfType(Dice::RESULT_TYPE::DICE_LIST, node);
}
@@ -633,7 +329,7 @@ bool DiceParser::hasDiceResult()
bool DiceParser::hasStringResult()
{
bool result= false;
- for(auto node : m_startNodes)
+ for(auto node : m_parsingToolbox->getStartNodes())
{
result|= hasResultOfType(Dice::RESULT_TYPE::STRING, node);
}
@@ -642,7 +338,7 @@ bool DiceParser::hasStringResult()
bool DiceParser::hasResultOfType(Dice::RESULT_TYPE type, ExecutionNode* node, bool notthelast)
{
bool scalarDone= false;
- ExecutionNode* next= getLeafNode(node);
+ ExecutionNode* next= ParsingToolBox::getLeafNode(node);
Result* result= next->getResult();
while((result != nullptr) && (!scalarDone))
{
@@ -661,10 +357,10 @@ bool DiceParser::hasResultOfType(Dice::RESULT_TYPE type, ExecutionNode* node, bo
QList<qreal> DiceParser::getSumOfDiceResult()
{
QList<qreal> resultValues;
- for(auto node : m_startNodes)
+ for(auto node : m_parsingToolbox->getStartNodes())
{
qreal resultValue= 0;
- ExecutionNode* next= getLeafNode(node);
+ ExecutionNode* next= ParsingToolBox::getLeafNode(node);
Result* result= next->getResult();
bool found= false;
while((nullptr != result) && (!found))
@@ -689,714 +385,24 @@ QList<qreal> DiceParser::getSumOfDiceResult()
}
int DiceParser::getStartNodeCount() const
{
- return static_cast<int>(m_startNodes.size());
-}
-ExecutionNode* DiceParser::getLeafNode(ExecutionNode* start)
-{
- ExecutionNode* next= start;
- while(nullptr != next->getNextNode())
- {
- next= next->getNextNode();
- }
- return next;
-}
-
-bool DiceParser::readDice(QString& str, ExecutionNode*& node)
-{
- DiceOperator currentOperator;
-
- if(readDiceOperator(str, currentOperator))
- {
- if(currentOperator == D)
- {
- qint64 max;
- qint64 min;
- bool unique= (ParsingToolBox::UNIQUE == m_parsingToolbox->readListOperator(str)) ? true : false;
- Die::ArithmeticOperator op;
-
- bool hasOp= m_parsingToolbox->readArithmeticOperator(str, op);
- if(m_parsingToolbox->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::getLatestNode(current);
- }
- return true;
- }
- else if(m_parsingToolbox->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::getLatestNode(current);
- }
- return true;
- }
- }
- else if(currentOperator == L)
- {
- QStringList list;
- QList<Range> listRange;
- ParsingToolBox::LIST_OPERATOR op= m_parsingToolbox->readListOperator(str);
- if(m_parsingToolbox->readList(str, list, listRange))
- {
- ListSetRollNode* lsrNode= new ListSetRollNode();
- lsrNode->setRangeList(listRange);
- if(op == ParsingToolBox::UNIQUE)
- {
- lsrNode->setUnique(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 DiceParser::readDiceOperator(QString& str, DiceOperator& op)
-{
- QStringList listKey= m_mapDiceOp->keys();
- for(const QString& key : listKey)
- {
- if(str.startsWith(key, Qt::CaseInsensitive))
- {
- str= str.remove(0, key.size());
- op= m_mapDiceOp->value(key);
- return true;
- }
- }
- return false;
-}
-bool DiceParser::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 DiceParser::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 DiceParser::readInstructionOperator(QChar c)
-{
- if(c == ';')
- {
- return true;
- }
- return false;
-}
-bool DiceParser::readInstructionList(QString& str)
-{
- if(str.isEmpty())
- return false;
-
- bool hasInstruction= false;
- bool readInstruction= true;
- while(readInstruction)
- {
- ExecutionNode* startNode= nullptr;
- bool keepParsing= readExpression(str, startNode);
- if(nullptr != startNode)
- {
- hasInstruction= true;
- m_startNodes.push_back(startNode);
- auto latest= startNode;
- if(keepParsing)
- {
- latest= ParsingToolBox::getLatestNode(latest);
- keepParsing= !str.isEmpty();
- while(keepParsing)
- {
- auto before= str;
- if(readOperator(str, latest))
- {
- latest= ParsingToolBox::getLatestNode(latest);
- }
- keepParsing= (!str.isEmpty() && (before != str));
- }
- }
- if(!str.isEmpty() && readInstructionOperator(str[0]))
- {
- str= str.remove(0, 1);
- }
- else
- {
- QString result;
- QString comment;
- if(m_parsingToolbox->readComment(str, result, comment))
- {
- m_command.remove(comment);
- m_comment= result;
- }
- readInstruction= false;
- }
- }
- else
- {
- readInstruction= false;
- }
- }
- return hasInstruction;
-}
-
-bool DiceParser::readOperator(QString& str, ExecutionNode* previous)
-{
- if(str.isEmpty() || nullptr == previous)
- {
- return false;
- }
-
- Die::ArithmeticOperator op;
- if(m_parsingToolbox->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 false;
- }
- 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);
-
- return true;
- }
- else
- {
- delete node;
- }
- }
- else
- {
- while(readOption(str, previous))
- {
- previous= ParsingToolBox::getLatestNode(previous);
- }
- }
- return false;
-}
-bool DiceParser::hasSeparator() const
-{
- return m_currentTreeHasSeparator;
-}
-DiceRollerNode* DiceParser::addRollDiceNode(qint64 faces, ExecutionNode* previous)
-{
- DiceRollerNode* mydiceRoller= new DiceRollerNode(faces);
- previous->setNextNode(mydiceRoller);
- return mydiceRoller;
-}
-ExplodeDiceNode* DiceParser::addExplodeDiceNode(qint64 value, ExecutionNode* previous)
-{
- ExplodeDiceNode* explodeDiceNode= new ExplodeDiceNode();
- NumberNode* node= new NumberNode();
- node->setNumber(value);
- BooleanCondition* condition= new BooleanCondition();
- condition->setValueNode(node);
- condition->setOperator(BooleanCondition::Equal);
- m_parsingToolbox->isValidValidator(previous, condition);
- explodeDiceNode->setValidator(condition);
- previous->setNextNode(explodeDiceNode);
- return explodeDiceNode;
-}
-bool DiceParser::readOption(QString& str, ExecutionNode* previous) //,
-{
- if(str.isEmpty())
- {
- return false;
- }
-
- ExecutionNode* node= nullptr;
- 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:
- {
- qint64 myNumber= 0;
- bool ascending= m_parsingToolbox->readAscending(str);
-
- if(m_parsingToolbox->readNumber(str, myNumber))
- {
- node= m_parsingToolbox->addSort(previous, ascending);
- KeepDiceExecNode* nodeK= new KeepDiceExecNode();
- nodeK->setDiceKeepNumber(myNumber);
- node->setNextNode(nodeK);
- node= nodeK;
- found= true;
- }
- }
- break;
- case KeepAndExplode:
- {
- qint64 myNumber= 0;
- bool ascending= m_parsingToolbox->readAscending(str);
- if(m_parsingToolbox->readNumber(str, myNumber))
- {
- /* if(!hasDice)
- {
- previous = addRollDiceNode(DEFAULT_FACES_NUMBER,previous);
- }*/
- DiceRollerNode* nodeTmp= dynamic_cast<DiceRollerNode*>(previous);
- if(nullptr != nodeTmp)
- {
- previous= addExplodeDiceNode(static_cast<qint64>(nodeTmp->getFaces()), previous);
- }
-
- node= m_parsingToolbox->addSort(previous, ascending);
-
- KeepDiceExecNode* nodeK= new KeepDiceExecNode();
- nodeK->setDiceKeepNumber(myNumber);
-
- node->setNextNode(nodeK);
- node= nodeK;
- found= true;
- }
- }
- break;
- case Filter:
- {
- Validator* validator= m_parsingToolbox->readCompositeValidator(str);
- if(nullptr != validator)
- {
- m_parsingToolbox->isValidValidator(previous, validator);
-
- FilterNode* filterNode= new FilterNode();
- filterNode->setValidator(validator);
-
- previous->setNextNode(filterNode);
- node= filterNode;
- found= true;
- }
- }
- break;
- case Sort:
- {
- bool ascending= m_parsingToolbox->readAscending(str);
- node= m_parsingToolbox->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:
- {
- Validator* validator= m_parsingToolbox->readCompositeValidator(str);
- if(nullptr != validator)
- {
- m_parsingToolbox->isValidValidator(previous, validator);
-
- CountExecuteNode* countNode= new CountExecuteNode();
- countNode->setValidator(validator);
-
- previous->setNextNode(countNode);
- node= 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
- {
- Validator* validator= m_parsingToolbox->readCompositeValidator(str);
- QString symbol= m_OptionOp->key(operatorName);
- if(nullptr != validator)
- {
- switch(m_parsingToolbox->isValidValidator(previous, validator))
- {
- 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->setValidator(validator);
- previous->setNextNode(rerollNode);
- node= 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:
- {
- Validator* validator= m_parsingToolbox->readCompositeValidator(str);
- if(nullptr != validator)
- {
- if(Dice::CONDITION_STATE::ALWAYSTRUE == m_parsingToolbox->isValidValidator(previous, validator))
- {
- m_errorMap.insert(Dice::ERROR_CODE::ENDLESS_LOOP_ERROR,
- QObject::tr("This condition %1 introduces an endless loop. Please, change it")
- .arg(validator->toString()));
- }
- ExplodeDiceNode* explodedNode= new ExplodeDiceNode();
- explodedNode->setValidator(validator);
- previous->setNextNode(explodedNode);
- node= 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);
- node= mergeNode;
- found= true;
- }
- break;
- case AllSameExplode:
- {
- AllSameNode* allSame= new AllSameNode();
- previous->setNextNode(allSame);
- node= allSame;
- found= true;
- }
- break;
- case Bind:
- {
- BindNode* bindNode= new BindNode();
- bindNode->setStartList(&m_startNodes);
- previous->setNextNode(bindNode);
- node= bindNode;
- found= true;
- }
- break;
- case Occurences:
- {
- qint64 number= 0;
- auto occNode= new OccurenceCountNode();
- if(m_parsingToolbox->readNumber(str, number))
- {
- occNode->setWidth(number);
- Validator* validator= m_parsingToolbox->readCompositeValidator(str);
- if(validator)
- {
- occNode->setValidator(validator);
- }
- else if(m_parsingToolbox->readComma(str))
- {
- if(m_parsingToolbox->readNumber(str, number))
- {
- occNode->setHeight(number);
- }
- }
- }
- previous->setNextNode(occNode);
- node= occNode;
- found= true;
- }
- break;
- case Unique:
- {
- node= new UniqueNode();
- previous->setNextNode(node);
- found= true;
- }
- break;
- case Painter:
- {
- PainterNode* painter= new PainterNode();
- if(!m_parsingToolbox->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);
- node= painter;
- found= true;
- }
- }
- break;
- case ifOperator:
- {
- IfNode* nodeif= new IfNode();
- nodeif->setConditionType(m_parsingToolbox->readConditionType(str));
- Validator* validator= m_parsingToolbox->readCompositeValidator(str);
- if(nullptr != validator)
- {
- ExecutionNode* trueNode= nullptr;
- ExecutionNode* falseNode= nullptr;
- if(readIfInstruction(str, trueNode, falseNode))
- {
- nodeif->setInstructionTrue(trueNode);
- nodeif->setInstructionFalse(falseNode);
- nodeif->setValidator(validator);
- previous->setNextNode(nodeif);
- node= nodeif;
- found= true;
- }
- else
- {
- delete nodeif;
- }
- }
- else
- {
- delete nodeif;
- }
- break;
- }
- case Split:
- {
- SplitNode* splitnode= new SplitNode();
- previous->setNextNode(splitnode);
- node= splitnode;
- found= true;
- }
- break;
- case Group:
- {
- qint64 groupNumber= 0;
- if(m_parsingToolbox->readNumber(str, groupNumber))
- {
- GroupNode* groupNode= new GroupNode();
- groupNode->setGroupValue(groupNumber);
- previous->setNextNode(groupNode);
- node= groupNode;
- found= true;
- }
- }
- break;
- }
- }
- }
- return found;
-}
-bool DiceParser::readIfInstruction(QString& str, ExecutionNode*& trueNode, ExecutionNode*& falseNode)
-{
- if(readBlocInstruction(str, trueNode))
- {
- if(readBlocInstruction(str, falseNode))
- {
- return true;
- }
- return true;
- }
- return false;
-}
-
-bool DiceParser::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 DiceParser::readBlocInstruction(QString& str, ExecutionNode*& resultnode)
-{
- if(str.startsWith('{'))
- {
- str= str.remove(0, 1);
- ExecutionNode* node= nullptr;
- Die::ArithmeticOperator op;
- ScalarOperatorNode* scalarNode= nullptr;
- if(m_parsingToolbox->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;
+ return static_cast<int>(m_parsingToolbox->getStartNodes().size());
}
QString DiceParser::getComment() const
{
- return m_comment;
+ return m_parsingToolbox->getComment();
}
void DiceParser::setComment(const QString& comment)
{
- m_comment= comment;
+ m_parsingToolbox->setComment(comment);
}
QMap<Dice::ERROR_CODE, QString> DiceParser::getErrorMap()
{
QMap<Dice::ERROR_CODE, QString> map;
- for(auto start : m_startNodes)
+ for(auto start : m_parsingToolbox->getStartNodes())
{
auto mapTmp= start->getExecutionErrorMap();
auto keys= mapTmp.keys();
@@ -1409,7 +415,8 @@ QMap<Dice::ERROR_CODE, QString> DiceParser::getErrorMap()
}
QString DiceParser::humanReadableError()
{
- QMapIterator<Dice::ERROR_CODE, QString> i(m_errorMap);
+ auto errorMap= m_parsingToolbox->getErrorList();
+ QMapIterator<Dice::ERROR_CODE, QString> i(errorMap);
QString str("");
while(i.hasNext())
{
@@ -1431,7 +438,8 @@ QString DiceParser::humanReadableError()
QString DiceParser::humanReadableWarning()
{
- QMapIterator<Dice::ERROR_CODE, QString> i(m_warningMap);
+ auto warningMap= m_parsingToolbox->getWarningList();
+ QMapIterator<Dice::ERROR_CODE, QString> i(warningMap);
QString str("");
while(i.hasNext())
{
@@ -1444,11 +452,11 @@ QString DiceParser::humanReadableWarning()
void DiceParser::writeDownDotTree(QString filepath)
{
- if(m_startNodes.empty())
+ if(m_parsingToolbox->getStartNodes().empty())
return;
QString str(QStringLiteral("digraph ExecutionTree {\n"));
- for(auto start : m_startNodes)
+ for(auto start : m_parsingToolbox->getStartNodes())
{
start->generateDotTree(str);
}
@@ -1463,7 +471,7 @@ void DiceParser::writeDownDotTree(QString filepath)
}
void DiceParser::setPathToHelp(QString l)
{
- m_helpPath= l;
+ m_parsingToolbox->setHelpPath(l);
}
void DiceParser::setVariableDictionary(const QHash<QString, QString>& variables)
{
diff --git a/include/diceparser.h b/include/diceparser.h
index 31f9760..e60f30d 100644
--- a/include/diceparser.h
+++ b/include/diceparser.h
@@ -24,6 +24,7 @@
#include <QMap>
#include <QString>
+#include <memory>
#include <vector>
#include "diceparserhelper.h"
@@ -53,52 +54,6 @@ class DiceParser
{
public:
/**
- * @brief The DiceOperator enum gathering all dice operators
- */
- enum DiceOperator
- {
- D,
- L
- };
- /**
- * @brief The DiceSymbol enum
- */
- enum NodeAction
- {
- JumpBackward
- };
- /**
- * @brief The OptionOperator enum gathering all options availables for result.
- */
- enum OptionOperator
- {
- KeepAndExplode,
- Keep,
- Reroll,
- RerollUntil,
- Explode,
- Sort,
- Count,
- RerollAndAdd,
- Merge,
- ifOperator,
- Painter,
- Filter,
- Split,
- Group,
- Occurences,
- Unique,
- Bind,
- AllSameExplode
- };
- /**
- * @brief The CommandOperator enum
- */
- enum CommandOperator
- {
- };
-
- /**
* @brief DiceParser default constructor
*/
DiceParser();
@@ -178,18 +133,12 @@ public:
* @brief getAliases
* @return
*/
- QList<DiceAlias*>* getAliases();
+ const QList<DiceAlias*>& getAliases() const;
/**
* @brief insertAlias
*/
void insertAlias(DiceAlias*, int);
/**
- * @brief DiceParser::convertAlias
- * @param str
- * @return
- */
- QString convertAlias(QString str);
- /**
* @brief getErrorList
* @return
*/
@@ -227,106 +176,10 @@ public:
void getDiceResultFromAllInstruction(QList<ExportedDiceResult>& resultList);
QString humanReadableWarning();
- bool readValuesList(QString& str, ExecutionNode*& node);
void cleanAll();
private:
/**
- * @brief readIfInstruction reads the current command to build if node with proper parameters.
- * @param str is the command string, if IF istruction is found, the str will be changed, in other case the string is
- * unmodified
- * @param trueNode is the branch's beginning to be executed if the IfNode is true.
- * @param falseNode is the branch's beginning to be executed if the IfNode is false.
- * @return true, ifNode has been found, false otherwise
- */
- bool readIfInstruction(QString& str, ExecutionNode*& trueNode, ExecutionNode*& falseNode);
- bool readInstructionList(QString& str);
- bool readOptionFromNull(QString& str, ExecutionNode*& node);
- bool readOperatorFromNull(QString& str, ExecutionNode*& node);
- bool readParameterNode(QString& str, ExecutionNode*& node);
- /**
- * @brief readExpression
- * @param str
- * @param node
- * @return
- */
- bool readExpression(QString& str, ExecutionNode*& node);
- /**
- * @brief readDice
- * @param str
- * @return
- */
- bool readDice(QString& str, ExecutionNode*& node);
- /**
- * @brief readDiceOperator
- * @return
- */
- bool readDiceOperator(QString&, DiceOperator&);
- /**
- * @brief readDiceExpression
- * @param node
- * @return
- */
- bool readDiceExpression(QString&, ExecutionNode*& node);
- /**
- * @brief readOperator
- * @return
- */
- bool readOperator(QString&, ExecutionNode* previous);
- /**
- * @brief DiceParser::readCommand
- * @param str
- * @param node
- * @return
- */
- bool readCommand(QString& str, ExecutionNode*& node);
-
- /**
- * @brief readOption
- */
- bool readOption(QString&, ExecutionNode* node); // OptionOperator& option,
-
- /**
- * @brief addRollDiceNode
- * @param faces
- * @return
- */
- DiceRollerNode* addRollDiceNode(qint64 faces, ExecutionNode*);
- /**
- * @brief addExplodeDiceNode
- * @param faces
- * @param previous
- * @return
- */
- ExplodeDiceNode* addExplodeDiceNode(qint64 faces, ExecutionNode* previous);
- /**
- * @brief readOperand
- * @param node
- * @return
- */
- bool readOperand(QString&, ExecutionNode*& node);
-
- /**
- * @brief readInstructionOperator
- * @param c
- * @return
- */
- bool readInstructionOperator(QChar c);
- /**
- * @brief readNode
- * @param str
- * @param node
- * @return
- */
- bool readNode(QString& str, ExecutionNode*& node);
-
- /**
- * @brief getLeafNode
- * @return
- */
- ExecutionNode* getLeafNode(ExecutionNode* node);
-
- /**
* @brief hasResultOfType
* @param notthelast
* @return
@@ -335,22 +188,8 @@ private:
bool readBlocInstruction(QString& str, ExecutionNode*& resultnode);
private:
- QMap<QString, DiceOperator>* m_mapDiceOp;
- QMap<QString, OptionOperator>* m_OptionOp;
- QMap<QString, NodeAction>* m_nodeActionMap;
- QList<DiceAlias*>* m_aliasList;
- QStringList* m_commandList;
-
- QMap<Dice::ERROR_CODE, QString> m_errorMap;
- QMap<Dice::ERROR_CODE, QString> m_warningMap;
-
- ExecutionNode* m_start= nullptr;
- std::vector<ExecutionNode*> m_startNodes;
+ std::unique_ptr<ParsingToolBox> m_parsingToolbox;
QString m_command;
- ParsingToolBox* m_parsingToolbox;
- QString m_helpPath;
- bool m_currentTreeHasSeparator;
- QString m_comment;
};
#endif // DICEPARSER_H
diff --git a/include/diceparserhelper.h b/include/diceparserhelper.h
index 1b91285..461d127 100644
--- a/include/diceparserhelper.h
+++ b/include/diceparserhelper.h
@@ -39,5 +39,15 @@ enum class RESULT_TYPE : int
STRING= 2,
DICE_LIST= 4
};
-}
+/**
+ * @brief The ConditionType enum defines compare method
+ */
+enum ConditionType
+{
+ OnEach,
+ OneOfThem,
+ AllOfThem,
+ OnScalar
+};
+} // namespace Dice
#endif // DICEPARSERHELPER_H
diff --git a/include/parsingtoolbox.h b/include/parsingtoolbox.h
index 038427f..701d2d3 100644
--- a/include/parsingtoolbox.h
+++ b/include/parsingtoolbox.h
@@ -23,9 +23,9 @@
#define PARSINGTOOLBOX_H
#include <QMap>
+#include <vector>
#include "booleancondition.h"
-#include "compositevalidator.h"
#include "highlightdice.h"
#include "node/dicerollernode.h"
#include "node/executionnode.h"
@@ -34,6 +34,11 @@
#include "node/scalaroperatornode.h"
#include "operationcondition.h"
#include "range.h"
+#include "validatorlist.h"
+
+class RepeaterNode;
+class DiceAlias;
+class ExplodeDiceNode;
class SubtituteInfo
{
@@ -73,7 +78,49 @@ public:
NONE,
UNIQUE
};
-
+ enum Function
+ {
+ REPEAT
+ };
+ /**
+ * @brief The OptionOperator enum gathering all options availables for result.
+ */
+ enum OptionOperator
+ {
+ KeepAndExplode,
+ Keep,
+ Reroll,
+ RerollUntil,
+ Explode,
+ Sort,
+ Count,
+ RerollAndAdd,
+ Merge,
+ ifOperator,
+ Painter,
+ Filter,
+ Split,
+ Group,
+ Occurences,
+ Unique,
+ Bind,
+ AllSameExplode
+ };
+ /**
+ * @brief The DiceOperator enum gathering all dice operators
+ */
+ enum DiceOperator
+ {
+ D,
+ L
+ };
+ /**
+ * @brief The DiceSymbol enum
+ */
+ enum NodeAction
+ {
+ JumpBackward
+ };
/**
* @brief ParsingToolBox
*/
@@ -87,6 +134,8 @@ public:
* @brief ~ParsingToolBox
*/
virtual ~ParsingToolBox();
+
+ void clearUp();
/**
* @brief addSort
* @param e
@@ -118,7 +167,7 @@ public:
* @param str
* @return
*/
- Validator* readCompositeValidator(QString& str);
+ ValidatorList* readValidatorList(QString& str);
/**
* @brief readNumber read number in the given str and remove from the string the read character.
@@ -176,7 +225,7 @@ public:
* @param val
* @return
*/
- Dice::CONDITION_STATE isValidValidator(ExecutionNode* previous, Validator* val);
+ Dice::CONDITION_STATE isValidValidator(ExecutionNode* previous, ValidatorList* val);
/**
* @brief getDiceRollerNode
* @param previous
@@ -201,11 +250,12 @@ public:
void readProbability(QStringList& str, QList<Range>& ranges);
- bool readLogicOperation(QString& str, CompositeValidator::LogicOperation& op);
+ bool readLogicOperation(QString& str, ValidatorList::LogicOperation& op);
bool readDiceLogicOperator(QString& str, OperationCondition::ConditionOperator& op);
bool readArithmeticOperator(QString& str, Die::ArithmeticOperator& op);
+ std::vector<ExecutionNode*> readInstructionList(QString& str, bool startNode);
static bool readPainterParameter(PainterNode* painter, QString& str);
@@ -216,15 +266,15 @@ public:
* @param str
* @return
*/
- static IfNode::ConditionType readConditionType(QString& str);
+ static Dice::ConditionType readConditionType(QString& str);
bool readComment(QString& str, QString&, QString&);
static ExecutionNode* getLatestNode(ExecutionNode* node);
- static std::vector<ExecutionNode*>* getStartNodes();
+ const std::vector<ExecutionNode*>& getStartNodes();
static void setStartNodes(std::vector<ExecutionNode*>* startNodes);
- static bool readOperand(QString& str, ExecutionNode*& node);
+ bool readOperand(QString& str, ExecutionNode*& node);
static int findClosingCharacterIndexOf(QChar open, QChar closing, const QString& str, int offset);
static QString replaceVariableToValue(const QString& source, QStringList values);
@@ -237,14 +287,114 @@ public:
static bool readComma(QString& str);
+ bool readReaperArguments(RepeaterNode* node, QString& source);
+
+ DiceRollerNode* addRollDiceNode(qint64 faces, ExecutionNode*);
+
+ ExplodeDiceNode* addExplodeDiceNode(qint64 faces, ExecutionNode* previous);
+
+ bool readExpression(QString& str, ExecutionNode*& node);
+
+ static ExecutionNode* getLeafNode(ExecutionNode* start);
+
+ bool hasError() const;
+
+ bool readInstructionOperator(QChar c);
+
+ bool readNode(QString& str, ExecutionNode*& node);
+ /**
+ * @brief readIfInstruction reads the current command to build if node with proper parameters.
+ * @param str is the command string, if IF istruction is found, the str will be changed, in other case the string is
+ * unmodified
+ * @param trueNode is the branch's beginning to be executed if the IfNode is true.
+ * @param falseNode is the branch's beginning to be executed if the IfNode is false.
+ * @return true, ifNode has been found, false otherwise
+ */
+ bool readIfInstruction(QString& str, ExecutionNode*& trueNode, ExecutionNode*& falseNode);
+
+ bool readOptionFromNull(QString& str, ExecutionNode*& node);
+ bool readOperatorFromNull(QString& str, ExecutionNode*& node);
+ bool readParameterNode(QString& str, ExecutionNode*& node);
+
+ /**
+ *
+ */
+ bool readFunction(QString& str, ExecutionNode*& node);
+ /**
+ * @brief readDice
+ * @param str
+ * @return
+ */
+ bool readDice(QString& str, ExecutionNode*& node);
+ /**
+ * @brief readDiceOperator
+ * @return
+ */
+ bool readDiceOperator(QString&, DiceOperator&);
+ /**
+ * @brief readDiceExpression
+ * @param node
+ * @return
+ */
+ bool readDiceExpression(QString&, ExecutionNode*& node);
+ /**
+ * @brief readOperator
+ * @return
+ */
+ bool readOperator(QString&, ExecutionNode* previous);
+ /**
+ * @brief DiceParser::readCommand
+ * @param str
+ * @param node
+ * @return
+ */
+ bool readCommand(QString& str, ExecutionNode*& node);
+
+ /**
+ * @brief readOption
+ */
+ bool readOption(QString&, ExecutionNode* node); // OptionOperator& option,
+
+ bool readValuesList(QString& str, ExecutionNode*& node);
+
+ void addError(Dice::ERROR_CODE code, const QString& msg);
+ void addWarning(Dice::ERROR_CODE code, const QString& msg);
+
+ void setComment(const QString& comment);
+ QString getComment() const;
+
+ const QMap<Dice::ERROR_CODE, QString>& getErrorList() const;
+ const QMap<Dice::ERROR_CODE, QString>& getWarningList() const;
+
+ QString convertAlias(QString str);
+
+ bool readBlocInstruction(QString& str, ExecutionNode*& resultnode);
+
+ void setHelpPath(const QString& path);
+
+ void insertAlias(DiceAlias* dice, int i);
+ const QList<DiceAlias*>& getAliases() const;
+
private:
- QMap<QString, BooleanCondition::LogicOperator>* m_logicOp;
- QMap<QString, CompositeValidator::LogicOperation>* m_logicOperation;
- QMap<QString, OperationCondition::ConditionOperator>* m_conditionOperation;
- QHash<QString, Die::ArithmeticOperator>* m_arithmeticOperation;
+ QMap<QString, BooleanCondition::LogicOperator> m_logicOp;
+ QMap<QString, ValidatorList::LogicOperation> m_logicOperation;
+ QMap<QString, OperationCondition::ConditionOperator> m_conditionOperation;
+ QHash<QString, Die::ArithmeticOperator> m_arithmeticOperation;
+ QMap<QString, DiceOperator> m_mapDiceOp;
+ QMap<QString, OptionOperator> m_OptionOp;
+ QMap<QString, NodeAction> m_nodeActionMap;
+ std::map<QString, Function> m_functionMap;
+ QStringList m_commandList;
+
+ QMap<Dice::ERROR_CODE, QString> m_errorMap;
+ QMap<Dice::ERROR_CODE, QString> m_warningMap;
+ std::vector<ExecutionNode*> m_startNodes;
+
+ QString m_comment;
static QHash<QString, QString> m_variableHash;
- static std::vector<ExecutionNode*>* m_startNodes;
+ QString m_helpPath;
+ QList<DiceAlias*> m_aliasList;
};
#endif // PARSINGTOOLBOX_H
diff --git a/node/countexecutenode.cpp b/node/countexecutenode.cpp
index c9b78b2..7d684c6 100644
--- a/node/countexecutenode.cpp
+++ b/node/countexecutenode.cpp
@@ -1,19 +1,20 @@
#include "countexecutenode.h"
#include "result/diceresult.h"
+#include "validatorlist.h"
-CountExecuteNode::CountExecuteNode() : m_scalarResult(new ScalarResult()), m_validator(nullptr)
+CountExecuteNode::CountExecuteNode() : m_scalarResult(new ScalarResult()), m_validatorList(nullptr)
{
m_result= m_scalarResult;
}
-void CountExecuteNode::setValidator(Validator* validator)
+void CountExecuteNode::setValidatorList(ValidatorList* validatorlist)
{
- m_validator= validator;
+ m_validatorList= validatorlist;
}
CountExecuteNode::~CountExecuteNode()
{
- if(nullptr != m_validator)
+ if(nullptr != m_validatorList)
{
- delete m_validator;
+ delete m_validatorList;
}
}
@@ -28,17 +29,10 @@ void CountExecuteNode::run(ExecutionNode* previous)
if(nullptr != previousResult)
{
m_result->setPrevious(previousResult);
- QList<Die*> diceList= previousResult->getResultList();
qint64 sum= 0;
- for(Die* dice : diceList)
- {
- if(nullptr != m_validator)
- {
- sum+= m_validator->hasValid(dice, true, true);
- }
- }
+ std::function<void(Die*, qint64)> f= [&sum](const Die*, qint64 score) { sum+= score; };
+ m_validatorList->validResult(previousResult, true, true, f);
m_scalarResult->setValue(sum);
-
if(nullptr != m_nextNode)
{
m_nextNode->run(this);
@@ -49,7 +43,7 @@ QString CountExecuteNode::toString(bool withlabel) const
{
if(withlabel)
{
- return QString("%1 [label=\"CountExecuteNode %2\"]").arg(m_id, m_validator->toString());
+ return QString("%1 [label=\"CountExecuteNode %2\"]").arg(m_id, m_validatorList->toString());
}
else
{
@@ -69,9 +63,9 @@ qint64 CountExecuteNode::getPriority() const
ExecutionNode* CountExecuteNode::getCopy() const
{
CountExecuteNode* node= new CountExecuteNode();
- if(nullptr != m_validator)
+ if(nullptr != m_validatorList)
{
- node->setValidator(m_validator->getCopy());
+ node->setValidatorList(m_validatorList->getCopy());
}
if(nullptr != m_nextNode)
{
diff --git a/node/countexecutenode.h b/node/countexecutenode.h
index 8969a41..37b7a4f 100644
--- a/node/countexecutenode.h
+++ b/node/countexecutenode.h
@@ -4,8 +4,8 @@
#include "executionnode.h"
#include "result/scalarresult.h"
-#include "validator.h"
+class ValidatorList;
/**
* @brief The CountExecuteNode class
*/
@@ -25,7 +25,7 @@ public:
/**
* @brief setValidator
*/
- virtual void setValidator(Validator*);
+ virtual void setValidatorList(ValidatorList*);
/**
* @brief toString
* @return
@@ -44,7 +44,7 @@ public:
private:
ScalarResult* m_scalarResult;
- Validator* m_validator;
+ ValidatorList* m_validatorList;
};
#endif // COUNTEXECUTENODE_H
diff --git a/node/explodedicenode.cpp b/node/explodedicenode.cpp
index 2292a05..1546883 100644
--- a/node/explodedicenode.cpp
+++ b/node/explodedicenode.cpp
@@ -1,6 +1,7 @@
#include "explodedicenode.h"
+#include "validatorlist.h"
-ExplodeDiceNode::ExplodeDiceNode() : m_diceResult(new DiceResult()), m_validator(nullptr)
+ExplodeDiceNode::ExplodeDiceNode() : m_diceResult(new DiceResult())
{
m_result= m_diceResult;
}
@@ -13,19 +14,22 @@ void ExplodeDiceNode::run(ExecutionNode* previous)
m_result->setPrevious(previous_result);
if(nullptr != previous_result)
{
+ Die* exampleDie;
for(auto& die : previous_result->getResultList())
{
Die* tmpdie= new Die(*die);
m_diceResult->insertResult(tmpdie);
die->displayed();
+ exampleDie= tmpdie;
}
- QList<Die*> list= m_diceResult->getResultList();
+ // QList<Die*> list= m_diceResult->getResultList();
- for(auto& die : list)
- {
+ bool hasExploded= false;
+ std::function<void(Die*, qint64)> f= [&hasExploded, this](Die* die, qint64) {
if(Dice::CONDITION_STATE::ALWAYSTRUE
- == m_validator->isValidRangeSize(std::make_pair<qint64, qint64>(die->getBase(), die->getMaxValue())))
+ == m_validatorList->isValidRangeSize(
+ std::make_pair<qint64, qint64>(die->getBase(), die->getMaxValue())))
{
m_errors.insert(Dice::ERROR_CODE::ENDLESS_LOOP_ERROR,
QObject::tr("Condition (%1) cause an endless loop with this dice: %2")
@@ -33,14 +37,31 @@ void ExplodeDiceNode::run(ExecutionNode* previous)
.arg(QStringLiteral("d[%1,%2]")
.arg(static_cast<int>(die->getBase()))
.arg(static_cast<int>(die->getMaxValue()))));
+ }
+ hasExploded= true;
+ die->roll(true);
+ };
+ do
+ {
+ hasExploded= false;
+ m_validatorList->validResult(m_diceResult, false, false, f);
+ } while(hasExploded);
+
+ /*for(auto& die : list)
+ {
+ if(Dice::CONDITION_STATE::ALWAYSTRUE
+ == m_validatorList->isValidRangeSize(
+ std::make_pair<qint64, qint64>(die->getBase(), die->getMaxValue())))
+ {
+
continue;
}
- while(m_validator->hasValid(die, false))
+ while(m_validatorList->hasValid(die, false))
{
die->roll(true);
}
- }
+ }*/
if(nullptr != m_nextNode)
{
@@ -51,20 +72,20 @@ void ExplodeDiceNode::run(ExecutionNode* previous)
}
ExplodeDiceNode::~ExplodeDiceNode()
{
- if(nullptr != m_validator)
+ if(nullptr != m_validatorList)
{
- delete m_validator;
+ delete m_validatorList;
}
}
-void ExplodeDiceNode::setValidator(Validator* val)
+void ExplodeDiceNode::setValidatorList(ValidatorList* val)
{
- m_validator= val;
+ m_validatorList= val;
}
QString ExplodeDiceNode::toString(bool withlabel) const
{
if(withlabel)
{
- return QString("%1 [label=\"ExplodeDiceNode %2\"]").arg(m_id, m_validator->toString());
+ return QString("%1 [label=\"ExplodeDiceNode %2\"]").arg(m_id, m_validatorList->toString());
}
else
{
@@ -84,9 +105,9 @@ qint64 ExplodeDiceNode::getPriority() const
ExecutionNode* ExplodeDiceNode::getCopy() const
{
ExplodeDiceNode* node= new ExplodeDiceNode();
- if(nullptr != m_validator)
+ if(nullptr != m_validatorList)
{
- node->setValidator(m_validator->getCopy());
+ node->setValidatorList(m_validatorList->getCopy());
}
if(nullptr != m_nextNode)
{
diff --git a/node/explodedicenode.h b/node/explodedicenode.h
index e72298a..77b4a44 100644
--- a/node/explodedicenode.h
+++ b/node/explodedicenode.h
@@ -3,8 +3,8 @@
#include "executionnode.h"
#include "result/diceresult.h"
-#include "validator.h"
-#include <QDebug>
+
+class ValidatorList;
/**
* @brief The ExplodeDiceNode class explode dice while is valid by the validator.
@@ -15,7 +15,7 @@ public:
ExplodeDiceNode();
virtual ~ExplodeDiceNode();
virtual void run(ExecutionNode* previous= nullptr);
- virtual void setValidator(Validator*);
+ virtual void setValidatorList(ValidatorList*);
virtual QString toString(bool) const;
virtual qint64 getPriority() const;
@@ -23,7 +23,7 @@ public:
protected:
DiceResult* m_diceResult;
- Validator* m_validator;
+ ValidatorList* m_validatorList= nullptr;
};
#endif // EXPLOSEDICENODE_H
diff --git a/node/filternode.cpp b/node/filternode.cpp
index d5d155a..4424b4b 100644
--- a/node/filternode.cpp
+++ b/node/filternode.cpp
@@ -1,4 +1,5 @@
#include "filternode.h"
+#include "validatorlist.h"
FilterNode::FilterNode() : m_diceResult(new DiceResult()), m_eachValue(false)
{
@@ -7,14 +8,14 @@ FilterNode::FilterNode() : m_diceResult(new DiceResult()), m_eachValue(false)
FilterNode::~FilterNode()
{
- if(nullptr != m_validator)
+ if(nullptr != m_validatorList)
{
- delete m_validator;
+ delete m_validatorList;
}
}
-void FilterNode::setValidator(Validator* validator)
+void FilterNode::setValidatorList(ValidatorList* validatorlist)
{
- m_validator= validator;
+ m_validatorList= validatorlist;
}
void FilterNode::run(ExecutionNode* previous)
{
@@ -25,24 +26,27 @@ void FilterNode::run(ExecutionNode* previous)
}
DiceResult* previousDiceResult= dynamic_cast<DiceResult*>(previous->getResult());
m_result->setPrevious(previousDiceResult);
+
if(nullptr != previousDiceResult)
{
- QList<Die*> diceList= previousDiceResult->getResultList();
QList<Die*> diceList2;
+ std::function<void(Die*, qint64)> f= [&diceList2](Die* die, qint64) {
+ if(die == nullptr)
+ return;
+ Die* tmpdie= new Die(*die);
+ diceList2.append(tmpdie);
+ die->displayed();
+ };
+ m_validatorList->validResult(previousDiceResult, true, true, f);
+
+ QList<Die*> diceList= previousDiceResult->getResultList();
+ diceList.erase(std::remove_if(diceList.begin(), diceList.end(),
+ [&diceList2](Die* die) { return diceList2.contains(die); }),
+ diceList.end());
for(Die* tmp : diceList)
{
- if(m_validator->hasValid(tmp, m_eachValue))
- {
- Die* tmpdie= new Die(*tmp);
- //*tmpdie= *tmp;
- diceList2.append(tmpdie);
- tmp->displayed();
- }
- else
- {
- tmp->setHighlighted(false);
- }
+ tmp->setHighlighted(false);
}
m_diceResult->setResultList(diceList2);
@@ -77,9 +81,9 @@ qint64 FilterNode::getPriority() const
ExecutionNode* FilterNode::getCopy() const
{
FilterNode* node= new FilterNode();
- if(nullptr != m_validator)
+ if(nullptr != m_validatorList)
{
- node->setValidator(m_validator->getCopy());
+ node->setValidatorList(m_validatorList->getCopy());
}
if(nullptr != m_nextNode)
{
diff --git a/node/filternode.h b/node/filternode.h
index 77ae7b6..7af6fe2 100644
--- a/node/filternode.h
+++ b/node/filternode.h
@@ -4,7 +4,8 @@
#include "executionnode.h"
#include "result/diceresult.h"
-#include "validator.h"
+
+class ValidatorList;
class FilterNode : public ExecutionNode
{
@@ -16,7 +17,7 @@ public:
/**
* @brief setValidator
*/
- virtual void setValidator(Validator*);
+ virtual void setValidatorList(ValidatorList*);
/**
* @brief toString
* @return
@@ -32,7 +33,7 @@ public:
private:
DiceResult* m_diceResult;
- Validator* m_validator;
+ ValidatorList* m_validatorList;
bool m_eachValue;
};
diff --git a/node/ifnode.cpp b/node/ifnode.cpp
index 5fa68b0..b2f183c 100644
--- a/node/ifnode.cpp
+++ b/node/ifnode.cpp
@@ -19,7 +19,7 @@
***************************************************************************/
#include "ifnode.h"
#include "result/diceresult.h"
-#include "result/stringresult.h"
+#include "validatorlist.h"
PartialDiceRollNode::PartialDiceRollNode() : m_diceResult(new DiceResult)
{
@@ -80,9 +80,8 @@ DiceResult* getFirstDiceResult(Result* result)
return found;
}
-//
-IfNode::IfNode() : m_validator(nullptr), m_conditionType(AllOfThem), m_true(nullptr), m_false(nullptr)
+IfNode::IfNode() : m_conditionType(Dice::AllOfThem), m_true(nullptr), m_false(nullptr)
{
// m_result = new DiceResult();
}
@@ -109,24 +108,20 @@ void IfNode::run(ExecutionNode* previous)
{
qreal value= previousResult->getResult(Dice::RESULT_TYPE::SCALAR).toReal();
- if(nullptr != m_validator)
+ if(nullptr != m_validatorList)
{
DiceResult* previousDiceResult= getFirstDiceResult(previousResult);
if(nullptr != previousDiceResult)
{
QList<Die*> diceList= previousDiceResult->getResultList();
- if(m_conditionType == OnEach)
+ if(m_conditionType == Dice::OnEach)
{
- auto resultOnEach= m_result;
for(Die* dice : diceList)
{
- auto diceResult= new DiceResult;
- StringResult* stringResult= nullptr;
auto diceNode= new PartialDiceRollNode();
- auto cpyDice= new Die(*dice);
- diceNode->insertDie(cpyDice);
- if(m_validator->hasValid(dice, true, true))
+ diceNode->insertDie(new Die(*dice));
+ if(m_validatorList->hasValid(dice, true, true))
{
nextNode= (nullptr == m_true) ? nullptr : m_true->getCopy();
}
@@ -141,49 +136,17 @@ void IfNode::run(ExecutionNode* previous)
{
previousLoop->setNextNode(nextNode);
}
+ if(nullptr == m_nextNode)
+ {
+ m_nextNode= nextNode;
+ }
diceNode->setNextNode(nextNode);
diceNode->run(previousLoop);
previousLoop= getLeafNode(nextNode);
}
-
- if(nullptr == nextNode)
- {
- diceResult->insertResult(cpyDice);
- }
- else
- {
- delete cpyDice;
- auto branchResult= previousLoop->getResult();
- if(branchResult->hasResultOfType(Dice::RESULT_TYPE::SCALAR))
- {
- auto val= branchResult->getResult(Dice::RESULT_TYPE::SCALAR).toInt();
- auto valDie= new Die();
- valDie->insertRollValue(val);
- diceResult->insertResult(valDie);
- }
- else if(branchResult->hasResultOfType(Dice::RESULT_TYPE::STRING))
- {
- auto val= branchResult->getResult(Dice::RESULT_TYPE::STRING).toString();
- stringResult= new StringResult;
- stringResult->setText(val);
- }
- }
- if(nullptr != stringResult)
- {
- stringResult->setPrevious(resultOnEach);
- resultOnEach= stringResult;
- delete diceResult;
- }
- else
- {
- diceResult->setPrevious(resultOnEach);
- resultOnEach= diceResult;
- }
}
-
- m_result= resultOnEach;
}
- else if((m_conditionType == OneOfThem) || (m_conditionType == AllOfThem))
+ else if((m_conditionType == Dice::OneOfThem) || (m_conditionType == Dice::AllOfThem))
{
bool trueForAll= true;
bool falseForAll= true;
@@ -193,14 +156,14 @@ void IfNode::run(ExecutionNode* previous)
for(Die* dice : diceList)
{
- bool result= m_validator->hasValid(dice, true, true);
+ bool result= m_validatorList->hasValid(dice, true, true);
trueForAll= trueForAll ? result : false;
falseForAll= falseForAll ? result : false;
oneIsTrue|= result;
oneIsFalse= !result ? true : oneIsFalse;
}
- if(m_conditionType == OneOfThem)
+ if(m_conditionType == Dice::OneOfThem)
{
if(oneIsTrue)
{
@@ -211,7 +174,7 @@ void IfNode::run(ExecutionNode* previous)
nextNode= (nullptr == m_false) ? nullptr : m_false->getCopy();
}
}
- else if(m_conditionType == AllOfThem)
+ else if(m_conditionType == Dice::AllOfThem)
{
if(trueForAll)
{
@@ -235,14 +198,14 @@ void IfNode::run(ExecutionNode* previous)
}
}
- if(m_conditionType == OnScalar)
+ if(m_conditionType == Dice::OnScalar)
{
Die dice;
auto val= static_cast<qint64>(value);
dice.setValue(val);
dice.insertRollValue(val);
dice.setMaxValue(val);
- if(m_validator->hasValid(&dice, true, true))
+ if(m_validatorList->hasValid(&dice, true, true))
{
nextNode= m_true;
}
@@ -269,9 +232,9 @@ void IfNode::run(ExecutionNode* previous)
}
}
-void IfNode::setValidator(Validator* val)
+void IfNode::setValidatorList(ValidatorList* val)
{
- m_validator= val;
+ m_validatorList= val;
}
void IfNode::setInstructionTrue(ExecutionNode* node)
{
@@ -292,7 +255,7 @@ void IfNode::generateDotTree(QString& s)
s.append(toString(false));
s.append(" -> ");
s.append(m_true->toString(false));
- s.append("[label=\"true" + m_validator->toString() + "\"];\n");
+ s.append("[label=\"true" + m_validatorList->toString() + "\"];\n");
m_true->generateDotTree(s);
}
@@ -357,12 +320,12 @@ ExecutionNode* IfNode::getLeafNode(ExecutionNode* node)
return next;
}
-IfNode::ConditionType IfNode::getConditionType() const
+Dice::ConditionType IfNode::getConditionType() const
{
return m_conditionType;
}
-void IfNode::setConditionType(const IfNode::ConditionType& conditionType)
+void IfNode::setConditionType(const Dice::ConditionType& conditionType)
{
m_conditionType= conditionType;
}
@@ -371,9 +334,9 @@ ExecutionNode* IfNode::getCopy() const
IfNode* node= new IfNode();
node->setConditionType(m_conditionType);
- if(nullptr != m_validator)
+ if(nullptr != m_validatorList)
{
- node->setValidator(m_validator->getCopy());
+ node->setValidatorList(m_validatorList->getCopy());
}
if(nullptr != m_false)
{
diff --git a/node/ifnode.h b/node/ifnode.h
index 55a6051..f0046f0 100644
--- a/node/ifnode.h
+++ b/node/ifnode.h
@@ -20,10 +20,11 @@
#ifndef IFNODE_H
#define IFNODE_H
+#include "diceparserhelper.h"
#include "executionnode.h"
#include "result/diceresult.h"
-#include "validator.h"
-#include <QDebug>
+
+class ValidatorList;
class PartialDiceRollNode : public ExecutionNode
{
public:
@@ -46,16 +47,6 @@ class IfNode : public ExecutionNode
{
public:
/**
- * @brief The ConditionType enum
- */
- enum ConditionType
- {
- OnEach,
- OneOfThem,
- AllOfThem,
- OnScalar
- };
- /**
* @brief IfNode
*/
IfNode();
@@ -71,7 +62,7 @@ public:
/**
* @brief setValidator
*/
- virtual void setValidator(Validator*);
+ virtual void setValidatorList(ValidatorList*);
/**
* @brief setInstructionTrue
*/
@@ -105,20 +96,20 @@ public:
* @brief getConditionType
* @return
*/
- ConditionType getConditionType() const;
+ Dice::ConditionType getConditionType() const;
/**
* @brief setConditionType
* @param conditionType
*/
- void setConditionType(const IfNode::ConditionType& conditionType);
+ void setConditionType(const Dice::ConditionType& conditionType);
protected:
ExecutionNode* getLeafNode(ExecutionNode* node);
protected:
- Validator* m_validator;
- ConditionType m_conditionType;
+ ValidatorList* m_validatorList= nullptr;
+ Dice::ConditionType m_conditionType;
ExecutionNode* m_true;
ExecutionNode* m_false;
diff --git a/node/mergenode.cpp b/node/mergenode.cpp
index 575613f..15f2fa7 100644
--- a/node/mergenode.cpp
+++ b/node/mergenode.cpp
@@ -40,25 +40,22 @@ void MergeNode::run(ExecutionNode* previous)
for(auto start : *m_startList)
{
ExecutionNode* last= getLatestNode(start);
- if(nullptr == last)
+ if(nullptr == last || nullptr == previousLast)
continue;
auto startResult= start->getResult();
if(nullptr == startResult)
continue;
- if(nullptr != previousLast)
- {
- startResult->setPrevious(previousLast->getResult());
- previousLast->setNextNode(start);
- }
+ startResult->setPrevious(previousLast->getResult());
+ previousLast->setNextNode(start);
previousLast= last;
Result* tmpResult= last->getResult();
while(nullptr != tmpResult)
{
DiceResult* dice= dynamic_cast<DiceResult*>(tmpResult);
- if(nullptr != dice)
+ if(nullptr == dice)
{
///@todo TODO improve here to set homogeneous while is really
m_diceResult->setHomogeneous(false);
diff --git a/node/occurencecountnode.cpp b/node/occurencecountnode.cpp
index 0d69d2a..f82fa35 100644
--- a/node/occurencecountnode.cpp
+++ b/node/occurencecountnode.cpp
@@ -20,6 +20,7 @@
#include "occurencecountnode.h"
#include "result/diceresult.h"
#include "result/stringresult.h"
+#include "validatorlist.h"
#include <QVector>
OccurenceCountNode::OccurenceCountNode() : ExecutionNode() {}
@@ -106,14 +107,14 @@ void OccurenceCountNode::setHeight(const qint64& height)
m_height= height;
}
-Validator* OccurenceCountNode::getValidator() const
+ValidatorList* OccurenceCountNode::getValidatorList() const
{
- return m_validator;
+ return m_validatorList;
}
-void OccurenceCountNode::setValidator(Validator* validator)
+void OccurenceCountNode::setValidatorList(ValidatorList* validatorlist)
{
- m_validator= validator;
+ m_validatorList= validatorlist;
}
void OccurenceCountNode::runForStringResult(const std::map<qint64, qint64>& mapOccurence, QVector<qint64>& vec)
{
@@ -122,11 +123,11 @@ void OccurenceCountNode::runForStringResult(const std::map<qint64, qint64>& mapO
QStringList list;
for(auto key : mapOccurence)
{
- if(nullptr != m_validator)
+ if(nullptr != m_validatorList)
{
Die die;
die.insertRollValue(key.first);
- if(!m_validator->hasValid(&die, true))
+ if(!m_validatorList->hasValid(&die, true))
continue;
}
@@ -156,11 +157,11 @@ void OccurenceCountNode::runForDiceResult(const std::map<qint64, qint64>& mapOcc
QStringList list;
for(auto key : mapOccurence)
{
- if(nullptr != m_validator)
+ if(nullptr != m_validatorList)
{
Die die;
die.insertRollValue(key.first);
- if(!m_validator->hasValid(&die, true))
+ if(!m_validatorList->hasValid(&die, true))
continue;
}
diff --git a/node/occurencecountnode.h b/node/occurencecountnode.h
index 492b295..aa5c2de 100644
--- a/node/occurencecountnode.h
+++ b/node/occurencecountnode.h
@@ -21,8 +21,8 @@
#define OCCURENCECOUNTNODE_H
#include "executionnode.h"
-#include "validator.h"
+class ValidatorList;
class StringResult;
class DiceResult;
class OccurenceCountNode : public ExecutionNode
@@ -42,8 +42,8 @@ public:
qint64 getHeight() const;
void setHeight(const qint64& height);
- Validator* getValidator() const;
- void setValidator(Validator* validator);
+ ValidatorList* getValidatorList() const;
+ void setValidatorList(ValidatorList* validator);
private:
void runForStringResult(const std::map<qint64, qint64>& mapOccurence, QVector<qint64>& vec);
@@ -52,7 +52,7 @@ private:
private:
qint64 m_width= 1;
qint64 m_height= 0;
- Validator* m_validator= nullptr;
+ ValidatorList* m_validatorList= nullptr;
StringResult* m_stringResult= nullptr;
DiceResult* m_diceResult= nullptr;
};
diff --git a/node/repeaternode.cpp b/node/repeaternode.cpp
index 09e88bd..26fab8f 100644
--- a/node/repeaternode.cpp
+++ b/node/repeaternode.cpp
@@ -26,63 +26,87 @@
#include "parsingtoolbox.h"
#include "result/stringresult.h"
+std::vector<ExecutionNode*> makeCopy(std::vector<ExecutionNode*> cmds)
+{
+ std::vector<ExecutionNode*> copy;
+ std::transform(cmds.begin(), cmds.end(), std::back_inserter(copy),
+ [](ExecutionNode* node) { return node->getCopy(); });
+ return copy;
+}
+
RepeaterNode::RepeaterNode() {}
void RepeaterNode::run(ExecutionNode* previousNode)
{
m_previousNode= previousNode;
+
+ if(nullptr == m_times || m_cmd.empty())
+ return;
+
m_times->run(this);
m_times= ParsingToolBox::getLeafNode(m_times);
auto times= m_times->getResult();
auto timeCount= times->getResult(Dice::RESULT_TYPE::SCALAR).toInt();
- auto cmd= m_cmd->getCopy();
+ auto cmd= makeCopy(m_cmd);
+ std::vector<Result*> resultVec;
for(int i= 0; i < timeCount; ++i)
{
- m_cmd->run(this);
- auto end= ParsingToolBox::getLeafNode(cmd);
- auto result= end->getResult();
+ std::for_each(cmd.begin(), cmd.end(), [this, &resultVec](ExecutionNode* node) {
+ node->run(this);
+ auto end= ParsingToolBox::getLeafNode(node);
+ auto leafResult= end->getResult();
- if(nullptr == result)
- continue;
+ if(nullptr == leafResult)
+ return;
- if(result->hasResultOfType(Dice::RESULT_TYPE::SCALAR))
- {
- if(m_sumAll)
- {
- auto res= new ScalarResult();
-
- m_result= res;
- }
- else
- {
- auto res= new StringResult();
- m_result= res;
- }
- }
- else if(result->hasResultOfType(Dice::RESULT_TYPE::STRING))
- {
- auto res= new StringResult();
-
- m_result= res;
- }
- else if(result->hasResultOfType(Dice::RESULT_TYPE::DICE_LIST))
- {
- if(m_sumAll)
- {
- auto res= new ScalarResult();
-
- m_result= res;
- }
+ resultVec.push_back(leafResult);
+ });
+ cmd= makeCopy(m_cmd);
+ }
+ if(m_sumAll)
+ {
+ auto scalar= new ScalarResult();
+ qreal value= 0.0;
+ std::for_each(resultVec.begin(), resultVec.end(),
+ [&value](Result* result) { value+= result->getResult(Dice::RESULT_TYPE::SCALAR).toDouble(); });
+ scalar->setValue(value);
+ m_result= scalar;
+ }
+ else
+ {
+ auto string= new StringResult();
+ QStringList list;
+ std::for_each(resultVec.begin(), resultVec.end(), [&list](Result* result) {
+ auto value= result->getResult(Dice::RESULT_TYPE::SCALAR).toDouble();
+ auto diceList= result->getResult(Dice::RESULT_TYPE::DICE_LIST).value<QList<Die*>>();
+ auto string= result->getResult(Dice::RESULT_TYPE::STRING).toString();
+
+ if(!string.isEmpty())
+ list.append(string);
else
{
- auto res= new StringResult();
-
- m_result= res;
+ QStringList diceStr;
+ std::transform(diceList.begin(), diceList.end(), std::back_inserter(diceStr), [](Die* die) {
+ auto values= die->getListValue();
+
+ QStringList valuesStr;
+ std::transform(values.begin(), values.end(), std::back_inserter(valuesStr),
+ [](qint64 val) { return QString::number(val); });
+
+ if(valuesStr.size() == 1)
+ return QStringLiteral("%1").arg(die->getValue());
+ else
+ return QStringLiteral("%1 [%2]").arg(die->getValue()).arg(valuesStr.join(","));
+ });
+ list.append(QStringLiteral("%1 - Details [%2]").arg(value).arg(diceStr.join(",")));
}
- }
-
- cmd= m_cmd->getCopy();
+ });
+ string->setText(list.join('\n'));
+ m_result= string;
}
+
+ if(nullptr != m_nextNode)
+ m_nextNode->run(this);
}
QString RepeaterNode::toString(bool withLabel) const
@@ -100,9 +124,9 @@ ExecutionNode* RepeaterNode::getCopy() const
return nullptr;
}
-void RepeaterNode::setCommand(ExecutionNode* cmd)
+void RepeaterNode::setCommand(const std::vector<ExecutionNode*>& cmd)
{
- m_cmd.reset(cmd);
+ m_cmd= cmd;
}
void RepeaterNode::setTimeNode(ExecutionNode* time)
diff --git a/node/repeaternode.h b/node/repeaternode.h
index 847db17..fa1a50a 100644
--- a/node/repeaternode.h
+++ b/node/repeaternode.h
@@ -35,12 +35,12 @@ public:
virtual ExecutionNode* getCopy() const override;
- void setCommand(ExecutionNode* node);
+ void setCommand(const std::vector<ExecutionNode*>& node);
void setTimeNode(ExecutionNode* times);
void setSumAll(bool b);
private:
- std::unique_ptr<ExecutionNode> m_cmd;
+ std::vector<ExecutionNode*> m_cmd;
ExecutionNode* m_times= nullptr;
bool m_sumAll= false;
};
diff --git a/node/rerolldicenode.cpp b/node/rerolldicenode.cpp
index 70475a5..370e95e 100644
--- a/node/rerolldicenode.cpp
+++ b/node/rerolldicenode.cpp
@@ -3,16 +3,16 @@
#include <utility>
RerollDiceNode::RerollDiceNode(bool reroll, bool addingMode)
- : m_diceResult(new DiceResult()), m_validator(nullptr), m_reroll(reroll), m_adding(addingMode)
+ : m_diceResult(new DiceResult()), m_validatorList(nullptr), m_reroll(reroll), m_adding(addingMode)
{
m_result= m_diceResult;
}
RerollDiceNode::~RerollDiceNode()
{
- if(nullptr != m_validator)
+ if(nullptr != m_validatorList)
{
- delete m_validator;
- m_validator= nullptr;
+ delete m_validatorList;
+ m_validatorList= nullptr;
}
}
void RerollDiceNode::run(ExecutionNode* previous)
@@ -38,8 +38,8 @@ void RerollDiceNode::run(ExecutionNode* previous)
for(auto& die : list)
{
bool finished= false;
- auto state
- = m_validator->isValidRangeSize(std::make_pair<qint64, qint64>(die->getBase(), die->getMaxValue()));
+ auto state= m_validatorList->isValidRangeSize(
+ std::make_pair<qint64, qint64>(die->getBase(), die->getMaxValue()));
if((Dice::CONDITION_STATE::ALWAYSTRUE == state && m_adding)
|| (!m_reroll && !m_adding && state == Dice::CONDITION_STATE::UNREACHABLE))
{
@@ -51,7 +51,7 @@ void RerollDiceNode::run(ExecutionNode* previous)
.arg(static_cast<int>(die->getMaxValue()))));
continue;
}
- while(m_validator->hasValid(die, false) && !finished)
+ while(m_validatorList->hasValid(die, false) && !finished)
{
if(m_instruction != nullptr)
{
@@ -98,15 +98,15 @@ void RerollDiceNode::run(ExecutionNode* previous)
}
}
}
-void RerollDiceNode::setValidator(Validator* val)
+void RerollDiceNode::setValidatorList(ValidatorList* val)
{
- m_validator= val;
+ m_validatorList= val;
}
QString RerollDiceNode::toString(bool wl) const
{
if(wl)
{
- return QString("%1 [label=\"RerollDiceNode validatior: %2\"]").arg(m_id, m_validator->toString());
+ return QString("%1 [label=\"RerollDiceNode validatior: %2\"]").arg(m_id, m_validatorList->toString());
}
else
{
@@ -127,7 +127,7 @@ qint64 RerollDiceNode::getPriority() const
ExecutionNode* RerollDiceNode::getCopy() const
{
RerollDiceNode* node= new RerollDiceNode(m_reroll, m_adding);
- node->setValidator(m_validator);
+ node->setValidatorList(m_validatorList);
if(nullptr != m_nextNode)
{
node->setNextNode(m_nextNode->getCopy());
diff --git a/node/rerolldicenode.h b/node/rerolldicenode.h
index 32fad79..68b732e 100644
--- a/node/rerolldicenode.h
+++ b/node/rerolldicenode.h
@@ -3,7 +3,8 @@
#include "executionnode.h"
#include "result/diceresult.h"
-#include "validator.h"
+
+class ValidatorList;
/**
* @brief The RerollDiceNode class reroll dice given a condition and replace(or add) the result.
*/
@@ -38,7 +39,7 @@ public:
/**
* @brief setValidator
*/
- virtual void setValidator(Validator*);
+ virtual void setValidatorList(ValidatorList*);
/**
* @brief toString
* @return
@@ -61,7 +62,7 @@ public:
private:
DiceResult* m_diceResult= nullptr;
- Validator* m_validator= nullptr;
+ ValidatorList* m_validatorList= nullptr;
ExecutionNode* m_instruction= nullptr;
const bool m_reroll;
diff --git a/node/variablenode.h b/node/variablenode.h
index 45133c6..5306ddb 100644
--- a/node/variablenode.h
+++ b/node/variablenode.h
@@ -11,14 +11,14 @@ class VariableNode : public ExecutionNode
{
public:
VariableNode();
- void run(ExecutionNode* previous);
- virtual QString toString(bool withLabel) const;
- virtual qint64 getPriority() const;
+ void run(ExecutionNode* previous) override;
+ virtual QString toString(bool withLabel) const override;
+ virtual qint64 getPriority() const override;
/**
* @brief getCopy
* @return
*/
- virtual ExecutionNode* getCopy() const;
+ virtual ExecutionNode* getCopy() const override;
quint64 getIndex() const;
void setIndex(quint64 index);
diff --git a/parsingtoolbox.cpp b/parsingtoolbox.cpp
index 6ad1c62..02b1130 100644
--- a/parsingtoolbox.cpp
+++ b/parsingtoolbox.cpp
@@ -19,73 +19,107 @@
* Free Software Foundation, Inc., *
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
***************************************************************************/
-#include <QString>
+#include "parsingtoolbox.h"
+#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/rerolldicenode.h"
+#include "node/scalaroperatornode.h"
#include "node/sortresult.h"
+#include "node/splitnode.h"
+#include "node/startingnode.h"
#include "node/stringnode.h"
+#include "node/uniquenode.h"
+#include "node/valueslistnode.h"
#include "node/variablenode.h"
-#include "parsingtoolbox.h"
+
+#include <QString>
QHash<QString, QString> ParsingToolBox::m_variableHash;
-std::vector<ExecutionNode*>* ParsingToolBox::m_startNodes= nullptr;
ParsingToolBox::ParsingToolBox()
- : m_logicOp(new QMap<QString, BooleanCondition::LogicOperator>())
- , m_logicOperation(new QMap<QString, CompositeValidator::LogicOperation>())
- , m_conditionOperation(new QMap<QString, OperationCondition::ConditionOperator>())
- , m_arithmeticOperation(new QHash<QString, Die::ArithmeticOperator>())
{
// m_logicOp = ;
- m_logicOp->insert(">=", BooleanCondition::GreaterOrEqual);
- m_logicOp->insert("<=", BooleanCondition::LesserOrEqual);
- m_logicOp->insert("<", BooleanCondition::LesserThan);
- m_logicOp->insert("=", BooleanCondition::Equal);
- m_logicOp->insert(">", BooleanCondition::GreaterThan);
- m_logicOp->insert("!=", BooleanCondition::Different);
+ m_logicOp.insert(">=", BooleanCondition::GreaterOrEqual);
+ m_logicOp.insert("<=", BooleanCondition::LesserOrEqual);
+ m_logicOp.insert("<", BooleanCondition::LesserThan);
+ m_logicOp.insert("=", BooleanCondition::Equal);
+ m_logicOp.insert(">", BooleanCondition::GreaterThan);
+ m_logicOp.insert("!=", BooleanCondition::Different);
// m_logicOperation = ;
- m_logicOperation->insert("|", CompositeValidator::OR);
- m_logicOperation->insert("^", CompositeValidator::EXCLUSIVE_OR);
- m_logicOperation->insert("&", CompositeValidator::AND);
+ m_logicOperation.insert("|", ValidatorList::OR);
+ m_logicOperation.insert("^", ValidatorList::EXCLUSIVE_OR);
+ m_logicOperation.insert("&", ValidatorList::AND);
// m_conditionOperation = ;
- m_conditionOperation->insert("%", OperationCondition::Modulo);
+ m_conditionOperation.insert("%", OperationCondition::Modulo);
// m_arithmeticOperation = new QHash<QString,ScalarOperatorNode::ArithmeticOperator>();
- m_arithmeticOperation->insert(QStringLiteral("+"), Die::PLUS);
- m_arithmeticOperation->insert(QStringLiteral("-"), Die::MINUS);
- m_arithmeticOperation->insert(QStringLiteral("*"), Die::MULTIPLICATION);
- m_arithmeticOperation->insert(QStringLiteral("x"), Die::MULTIPLICATION);
- m_arithmeticOperation->insert(QStringLiteral("|"), Die::INTEGER_DIVIDE);
- m_arithmeticOperation->insert(QStringLiteral("/"), Die::DIVIDE);
- m_arithmeticOperation->insert(QStringLiteral("÷"), Die::DIVIDE);
- m_arithmeticOperation->insert(QStringLiteral("**"), Die::POW);
+ m_arithmeticOperation.insert(QStringLiteral("+"), Die::PLUS);
+ m_arithmeticOperation.insert(QStringLiteral("-"), Die::MINUS);
+ m_arithmeticOperation.insert(QStringLiteral("**"), Die::POW);
+ m_arithmeticOperation.insert(QStringLiteral("*"), Die::MULTIPLICATION);
+ m_arithmeticOperation.insert(QStringLiteral("x"), Die::MULTIPLICATION);
+ m_arithmeticOperation.insert(QStringLiteral("|"), Die::INTEGER_DIVIDE);
+ m_arithmeticOperation.insert(QStringLiteral("/"), Die::DIVIDE);
+ m_arithmeticOperation.insert(QStringLiteral("÷"), Die::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_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()
+ParsingToolBox::~ParsingToolBox() {}
+
+void ParsingToolBox::clearUp()
{
- if(nullptr != m_logicOp)
- {
- delete m_logicOp;
- m_logicOp= nullptr;
- }
- if(nullptr != m_logicOperation)
- {
- delete m_logicOperation;
- m_logicOperation= nullptr;
- }
- if(nullptr != m_conditionOperation)
- {
- delete m_conditionOperation;
- m_conditionOperation= nullptr;
- }
- if(nullptr != m_arithmeticOperation)
- {
- delete m_arithmeticOperation;
- m_arithmeticOperation= nullptr;
- }
+ m_errorMap.clear();
+ m_comment= QString("");
}
ExecutionNode* ParsingToolBox::addSort(ExecutionNode* e, bool b)
{
@@ -94,11 +128,27 @@ ExecutionNode* ParsingToolBox::addSort(ExecutionNode* e, bool b)
e->setNextNode(nodeSort);
return nodeSort;
}
-
+ExecutionNode* ParsingToolBox::getLeafNode(ExecutionNode* start)
+{
+ ExecutionNode* next= start;
+ while(nullptr != next->getNextNode())
+ {
+ next= next->getNextNode();
+ }
+ return next;
+}
+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, OperationCondition::ConditionOperator& op)
{
QString longKey;
- auto const& keys= m_conditionOperation->keys();
+ auto const& keys= m_conditionOperation.keys();
for(const QString& tmp : keys)
{
if(str.startsWith(tmp))
@@ -112,7 +162,7 @@ bool ParsingToolBox::readDiceLogicOperator(QString& str, OperationCondition::Con
if(longKey.size() > 0)
{
str= str.remove(0, longKey.size());
- op= m_conditionOperation->value(longKey);
+ op= m_conditionOperation.value(longKey);
return true;
}
@@ -124,7 +174,7 @@ bool ParsingToolBox::readArithmeticOperator(QString& str, Die::ArithmeticOperato
bool found= false;
// QHash<QString,ScalarOperatorNode::ArithmeticOperator>::Iterator
- for(auto i= m_arithmeticOperation->begin(); i != m_arithmeticOperation->end() && !found; ++i)
+ for(auto i= m_arithmeticOperation.begin(); i != m_arithmeticOperation.end() && !found; ++i)
{
if(str.startsWith(i.key()))
{
@@ -139,7 +189,7 @@ bool ParsingToolBox::readArithmeticOperator(QString& str, Die::ArithmeticOperato
bool ParsingToolBox::readLogicOperator(QString& str, BooleanCondition::LogicOperator& op)
{
QString longKey;
- auto const& keys= m_logicOp->keys();
+ auto const& keys= m_logicOp.keys();
for(const QString& tmp : keys)
{
if(str.startsWith(tmp))
@@ -153,13 +203,29 @@ bool ParsingToolBox::readLogicOperator(QString& str, BooleanCondition::LogicOper
if(longKey.size() > 0)
{
str= str.remove(0, longKey.size());
- op= m_logicOp->value(longKey);
+ 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;
@@ -168,7 +234,7 @@ bool ParsingToolBox::readOperand(QString& str, ExecutionNode*& node)
{
VariableNode* variableNode= new VariableNode();
variableNode->setIndex(static_cast<quint64>(intValue - 1));
- variableNode->setData(m_startNodes);
+ variableNode->setData(&m_startNodes);
node= variableNode;
return true;
}
@@ -192,6 +258,7 @@ bool ParsingToolBox::readOperand(QString& str, ExecutionNode*& node)
Validator* ParsingToolBox::readValidator(QString& str, bool hasSquare)
{
Validator* returnVal= nullptr;
+ auto opCompare= readConditionType(str);
BooleanCondition::LogicOperator myLogicOp= BooleanCondition::Equal;
readLogicOperator(str, myLogicOp);
@@ -203,6 +270,7 @@ Validator* ParsingToolBox::readValidator(QString& str, bool hasSquare)
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);
@@ -229,6 +297,7 @@ Validator* ParsingToolBox::readValidator(QString& str, bool hasSquare)
str= str.remove(0, 1);
qint64 start= operandNode->getScalarResult();
Range* range= new Range();
+ range->setConditionType(opCompare);
range->setValue(start, end);
returnVal= range;
isRange= true;
@@ -238,6 +307,7 @@ Validator* ParsingToolBox::readValidator(QString& str, bool hasSquare)
if(!isRange)
{
BooleanCondition* condition= new BooleanCondition();
+ condition->setConditionType(opCompare);
condition->setValueNode(operandNode);
condition->setOperator(myLogicOp);
returnVal= condition;
@@ -245,28 +315,32 @@ Validator* ParsingToolBox::readValidator(QString& str, bool hasSquare)
}
return returnVal;
}
-IfNode::ConditionType ParsingToolBox::readConditionType(QString& str)
+
+Dice::ConditionType ParsingToolBox::readConditionType(QString& str)
{
- IfNode::ConditionType type= IfNode::OnEach;
+ Dice::ConditionType type= Dice::OnEach;
if(str.startsWith('.'))
{
str= str.remove(0, 1);
- type= IfNode::OneOfThem;
+ type= Dice::OneOfThem;
}
else if(str.startsWith('*'))
{
str= str.remove(0, 1);
- type= IfNode::AllOfThem;
+ type= Dice::AllOfThem;
}
else if(str.startsWith(':'))
{
str= str.remove(0, 1);
- type= IfNode::OnScalar;
+ type= Dice::OnScalar;
}
return type;
}
-
-Validator* ParsingToolBox::readCompositeValidator(QString& str)
+bool ParsingToolBox::hasError() const
+{
+ return !m_errorMap.isEmpty();
+}
+ValidatorList* ParsingToolBox::readValidatorList(QString& str)
{
bool expectSquareBrasket= false;
if((str.startsWith("[")))
@@ -275,9 +349,9 @@ Validator* ParsingToolBox::readCompositeValidator(QString& str)
expectSquareBrasket= true;
}
Validator* tmp= readValidator(str, expectSquareBrasket);
- CompositeValidator::LogicOperation opLogic;
+ ValidatorList::LogicOperation opLogic;
- QVector<CompositeValidator::LogicOperation> operators;
+ QVector<ValidatorList::LogicOperation> operators;
QList<Validator*> validatorList;
while(nullptr != tmp)
@@ -296,24 +370,15 @@ Validator* ParsingToolBox::readCompositeValidator(QString& str)
str= str.remove(0, 1);
// isOk=true;
}
-
- if(!validatorList.isEmpty())
- {
- validatorList.append(tmp);
- }
- else
- {
- operators.clear();
- return tmp;
- }
+ validatorList.append(tmp);
tmp= nullptr;
}
}
if(!validatorList.isEmpty())
{
- CompositeValidator* validator= new CompositeValidator();
+ ValidatorList* validator= new ValidatorList();
validator->setOperationList(operators);
- validator->setValidatorList(validatorList);
+ validator->setValidators(validatorList);
return validator;
}
else
@@ -321,10 +386,10 @@ Validator* ParsingToolBox::readCompositeValidator(QString& str)
return nullptr;
}
}
-bool ParsingToolBox::readLogicOperation(QString& str, CompositeValidator::LogicOperation& op)
+bool ParsingToolBox::readLogicOperation(QString& str, ValidatorList::LogicOperation& op)
{
QString longKey;
- auto const& keys= m_logicOperation->keys();
+ auto const& keys= m_logicOperation.keys();
for(auto& tmp : keys)
{
if(str.startsWith(tmp))
@@ -338,7 +403,7 @@ bool ParsingToolBox::readLogicOperation(QString& str, CompositeValidator::LogicO
if(longKey.size() > 0)
{
str= str.remove(0, longKey.size());
- op= m_logicOperation->value(longKey);
+ op= m_logicOperation.value(longKey);
return true;
}
@@ -412,16 +477,11 @@ ExecutionNode* ParsingToolBox::getLatestNode(ExecutionNode* node)
return next;
}
-std::vector<ExecutionNode*>* ParsingToolBox::getStartNodes()
+const std::vector<ExecutionNode*>& ParsingToolBox::getStartNodes()
{
return m_startNodes;
}
-void ParsingToolBox::setStartNodes(std::vector<ExecutionNode*>* startNodes)
-{
- m_startNodes= startNodes;
-}
-
bool ParsingToolBox::readString(QString& str, QString& strResult)
{
if(str.isEmpty())
@@ -596,7 +656,7 @@ bool ParsingToolBox::readAscending(QString& str)
}
return false;
}
-Dice::CONDITION_STATE ParsingToolBox::isValidValidator(ExecutionNode* previous, Validator* val)
+Dice::CONDITION_STATE ParsingToolBox::isValidValidator(ExecutionNode* previous, ValidatorList* val)
{
DiceRollerNode* node= getDiceRollerNode(previous);
if(nullptr == node)
@@ -895,7 +955,6 @@ QString ParsingToolBox::replacePlaceHolderToValue(const QString& source, const Q
// return source;
}
-
void ParsingToolBox::readSubtitutionParameters(SubtituteInfo& info, QString& rest)
{
auto sizeS= rest.size();
@@ -915,6 +974,951 @@ void ParsingToolBox::readSubtitutionParameters(SubtituteInfo& info, QString& res
info.setLength(info.length() + sizeS - rest.size());
}
+bool ParsingToolBox::readReaperArguments(RepeaterNode* node, QString& source)
+{
+ if(readOpenParentheses(source))
+ {
+ auto instructions= readInstructionList(source, false);
+ if(!instructions.empty())
+ {
+ 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::getLatestNode(operandNode);
+ // ExecutionNode* operatorNode=nullptr;
+ while(readOperator(str, operandNode))
+ {
+ // operandNode->setNextNode(operatorNode);
+ operandNode= ParsingToolBox::getLatestNode(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("["))
+ {
+ str= str.remove(0, 1);
+ int pos= ParsingToolBox::findClosingCharacterIndexOf('[', ']', str, 1); // str.indexOf("]");
+ if(-1 != pos)
+ {
+ QString liststr= str.left(pos);
+ auto list= liststr.split(",");
+ str= str.remove(0, pos + 1);
+ auto values= new ValuesListNode();
+ for(auto var : list)
+ {
+ qint64 number= 1;
+ QString error;
+ 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;
+ }
+ }
+ return false;
+}
+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;
+ }
+
+ ExecutionNode* node= nullptr;
+ 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:
+ {
+ qint64 myNumber= 0;
+ bool ascending= readAscending(str);
+
+ if(readNumber(str, myNumber))
+ {
+ node= addSort(previous, ascending);
+ KeepDiceExecNode* nodeK= new KeepDiceExecNode();
+ nodeK->setDiceKeepNumber(myNumber);
+ node->setNextNode(nodeK);
+ node= nodeK;
+ found= true;
+ }
+ }
+ break;
+ case KeepAndExplode:
+ {
+ qint64 myNumber= 0;
+ bool ascending= readAscending(str);
+ if(readNumber(str, myNumber))
+ {
+ /* if(!hasDice)
+ {
+ previous = addRollDiceNode(DEFAULT_FACES_NUMBER,previous);
+ }*/
+ DiceRollerNode* nodeTmp= dynamic_cast<DiceRollerNode*>(previous);
+ if(nullptr != nodeTmp)
+ {
+ previous= addExplodeDiceNode(static_cast<qint64>(nodeTmp->getFaces()), previous);
+ }
+
+ node= addSort(previous, ascending);
+
+ KeepDiceExecNode* nodeK= new KeepDiceExecNode();
+ nodeK->setDiceKeepNumber(myNumber);
+
+ 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);
+ node= filterNode;
+ found= true;
+ }
+ }
+ break;
+ case Sort:
+ {
+ bool ascending= readAscending(str);
+ node= 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);
+ node= 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);
+ node= 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);
+ node= 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);
+ node= mergeNode;
+ found= true;
+ }
+ break;
+ case AllSameExplode:
+ {
+ AllSameNode* allSame= new AllSameNode();
+ previous->setNextNode(allSame);
+ node= allSame;
+ found= true;
+ }
+ break;
+ case Bind:
+ {
+ BindNode* bindNode= new BindNode();
+ bindNode->setStartList(&m_startNodes);
+ previous->setNextNode(bindNode);
+ node= 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);
+ node= occNode;
+ found= true;
+ }
+ break;
+ case Unique:
+ {
+ 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);
+ node= 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);
+ node= nodeif;
+ found= true;
+ }
+ else
+ {
+ delete nodeif;
+ }
+ }
+ else
+ {
+ delete nodeif;
+ }
+ break;
+ }
+ case Split:
+ {
+ SplitNode* splitnode= new SplitNode();
+ previous->setNextNode(splitnode);
+ node= splitnode;
+ found= true;
+ }
+ break;
+ case Group:
+ {
+ qint64 groupNumber= 0;
+ if(readNumber(str, groupNumber))
+ {
+ GroupNode* groupNode= new GroupNode();
+ groupNode->setGroupValue(groupNumber);
+ previous->setNextNode(groupNode);
+ node= groupNode;
+ found= true;
+ }
+ }
+ break;
+ }
+ }
+ }
+ return found;
+}
+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(BooleanCondition::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::readBlocInstruction(QString& str, ExecutionNode*& resultnode)
+{
+ if(str.startsWith('{'))
+ {
+ str= str.remove(0, 1);
+ ExecutionNode* node= nullptr;
+ Die::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;
+ Die::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::getLatestNode(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::getLatestNode(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)
+ {
+ lsrNode->setUnique(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 : 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)
+{
+ if(str.isEmpty() || nullptr == previous)
+ {
+ return false;
+ }
+
+ Die::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 false;
+ }
+ 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);
+
+ return true;
+ }
+ else
+ {
+ delete node;
+ }
+ }
+ else
+ {
+ while(readOption(str, previous))
+ {
+ previous= ParsingToolBox::getLatestNode(previous);
+ }
+ }
+ return false;
+}
+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;
+}
+
+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::getLatestNode(latest);
+ keepParsing= !str.isEmpty();
+ while(keepParsing)
+ {
+ auto before= str;
+ if(readOperator(str, latest))
+ {
+ latest= ParsingToolBox::getLatestNode(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;
diff --git a/result/diceresult.cpp b/result/diceresult.cpp
index 23b925e..083c683 100644
--- a/result/diceresult.cpp
+++ b/result/diceresult.cpp
@@ -73,7 +73,7 @@ QVariant DiceResult::getResult(Dice::RESULT_TYPE type)
}
case Dice::RESULT_TYPE::DICE_LIST:
{
- return QVariant();
+ return QVariant::fromValue(m_diceValues);
}
default:
break;
diff --git a/result/diceresult.h b/result/diceresult.h
index ce8ffb7..8f30340 100644
--- a/result/diceresult.h
+++ b/result/diceresult.h
@@ -92,5 +92,5 @@ private:
bool m_homogeneous;
Die::ArithmeticOperator m_operator;
};
-
+Q_DECLARE_METATYPE(QList<Die*>)
#endif // DICERESULT_H
diff --git a/tests/dice/CMakeLists.txt b/tests/dice/CMakeLists.txt
index d254624..e2e580a 100644
--- a/tests/dice/CMakeLists.txt
+++ b/tests/dice/CMakeLists.txt
@@ -1,12 +1,14 @@
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -fno-permissive -pedantic -Wall -Wextra")
set(CMAKE_AUTOMOC ON)
-find_package(Qt5Test REQUIRED)
+find_package(Qt5 ${QT_REQUIRED_VERSION} CONFIG REQUIRED COMPONENTS Core Gui Svg Test)
set(test_source testnode.cpp tst_dice.cpp)
-add_executable(test_dice ${test_source} ${dice_sources})
+add_executable(test_dice ${test_source})
-target_include_directories(test_dice PRIVATE ../../include)
+target_include_directories(test_dice PRIVATE ../../include ../../ ../../node ../../result)
-target_link_libraries(test_dice Qt5::Test)
+find_library(DICEPARSER_LIBRARY diceparser HINTS ${CMAKE_CURRENT_BINARY_DIR}/../../)
+
+target_link_libraries(test_dice PUBLIC Qt5::Core Qt5::Gui Qt5::Test diceparser_shared)
add_test(tst_diceparser test_dice)
diff --git a/tests/dice/tst_dice.cpp b/tests/dice/tst_dice.cpp
index 757969f..8eed852 100644
--- a/tests/dice/tst_dice.cpp
+++ b/tests/dice/tst_dice.cpp
@@ -44,8 +44,57 @@
#include "node/stringnode.h"
#include "node/uniquenode.h"
#include "operationcondition.h"
+#include "parsingtoolbox.h"
#include "result/stringresult.h"
#include "testnode.h"
+#include "validatorlist.h"
+
+void makeResult(DiceResult& result, const QVector<int>& values, const QVector<int>& subvalues= QVector<int>(),
+ int base= 1, int max= 10)
+{
+ int i= 0;
+ for(int val : values)
+ {
+ auto die= new Die();
+ die->setBase(base);
+ die->setMaxValue(max);
+ die->insertRollValue(val);
+ if(i == 0 && !subvalues.empty())
+ {
+ for(int sval : subvalues)
+ {
+ die->insertRollValue(sval);
+ }
+ }
+ result.insertResult(die);
+ ++i;
+ }
+}
+
+void makeResultExplode(DiceResult& result, const QVector<int>& values)
+{
+ auto die= new Die();
+ die->setBase(1);
+ die->setMaxValue(10);
+ for(int val : values)
+ {
+ die->insertRollValue(val);
+ }
+ result.insertResult(die);
+}
+
+ValidatorList* makeValidator(int number, BooleanCondition::LogicOperator op)
+{
+ BooleanCondition* validator= new BooleanCondition();
+ NumberNode* node= new NumberNode();
+ node->setNumber(number);
+ validator->setValueNode(node);
+ validator->setOperator(op);
+
+ ValidatorList* list= new ValidatorList();
+ list->setValidators(QList<Validator*>() << validator);
+ return list;
+}
class TestDice : public QObject
{
@@ -57,6 +106,10 @@ public:
private slots:
void init();
void getAndSetTest();
+
+ void validatorListTest();
+ void validatorListTest_data();
+
void diceRollD10Test();
void diceRollD20Test();
void commandEndlessLoop();
@@ -138,6 +191,7 @@ private slots:
private:
std::unique_ptr<Die> m_die;
std::unique_ptr<DiceParser> m_diceParser;
+ std::unique_ptr<ParsingToolBox> m_parsingToolBox;
};
TestDice::TestDice() {}
@@ -146,6 +200,7 @@ void TestDice::init()
{
m_die.reset(new Die());
m_diceParser.reset(new DiceParser());
+ m_parsingToolBox.reset(new ParsingToolBox());
}
void TestDice::getAndSetTest()
@@ -163,6 +218,34 @@ void TestDice::getAndSetTest()
QVERIFY(m_die->isSelected() == false);
}
+void TestDice::validatorListTest()
+{
+ QFETCH(QString, cmd);
+ QFETCH(int, result);
+
+ auto parsing= m_diceParser->parseLine(cmd);
+ QVERIFY2(parsing, "parsing");
+
+ m_diceParser->start();
+ QVERIFY2(m_diceParser->humanReadableError().isEmpty(), "no error");
+ QVERIFY2(m_diceParser->humanReadableWarning().isEmpty(), "no warning");
+
+ auto resultCmd= m_diceParser->getLastIntegerResults();
+
+ QCOMPARE(resultCmd.size(), 1);
+
+ QCOMPARE(resultCmd.first(), result);
+}
+
+void TestDice::validatorListTest_data()
+{
+ QTest::addColumn<QString>("cmd");
+ QTest::addColumn<int>("result");
+
+ QTest::addRow("cmd1") << "2d[6-6]c6" << 2;
+ QTest::addRow("cmd2") << "[6,2]c[:>6&%2=0]" << 2;
+}
+
void TestDice::diceRollD10Test()
{
m_die->setMaxValue(10);
@@ -183,6 +266,7 @@ void TestDice::diceRollD20Test()
QVERIFY(m_die->getValue() < 21);
}
}
+
void TestDice::commandEndlessLoop()
{
bool a= m_diceParser->parseLine("1D10e[>0]");
@@ -373,14 +457,14 @@ void TestDice::scopeDF_data()
}
void TestDice::testAlias()
{
- m_diceParser->insertAlias(new DiceAlias("!", "3d6c"), 0);
- m_diceParser->insertAlias(new DiceAlias("g", "d10k"), 1);
- m_diceParser->insertAlias(new DiceAlias("(.*)C(.*)", QStringLiteral("\\1d10e10c[>=\\2]"), false), 2);
+ m_parsingToolBox->insertAlias(new DiceAlias("!", "3d6c"), 0);
+ m_parsingToolBox->insertAlias(new DiceAlias("g", "d10k"), 1);
+ m_parsingToolBox->insertAlias(new DiceAlias("(.*)C(.*)", QStringLiteral("\\1d10e10c[>=\\2]"), false), 2);
QFETCH(QString, cmd);
QFETCH(QString, expected);
- auto result= m_diceParser->convertAlias(cmd);
+ auto result= m_parsingToolBox->convertAlias(cmd);
QCOMPARE(result, expected);
}
@@ -452,12 +536,9 @@ void TestDice::dangerousCommandsTest()
{
QFETCH(QString, cmd);
- for(int i= 0; i < 1000; ++i)
- {
- auto b= m_diceParser->parseLine(cmd);
- QVERIFY(b);
- m_diceParser->start();
- }
+ auto b= m_diceParser->parseLine(cmd);
+ QVERIFY(b);
+ m_diceParser->start();
}
void TestDice::dangerousCommandsTest_data()
{
@@ -470,50 +551,6 @@ void TestDice::dangerousCommandsTest_data()
// QTest::addRow("cmd5") << "10d10g10";
}
-void makeResult(DiceResult& result, const QVector<int>& values, const QVector<int>& subvalues= QVector<int>(),
- int base= 1, int max= 10)
-{
- int i= 0;
- for(int val : values)
- {
- auto die= new Die();
- die->setBase(base);
- die->setMaxValue(max);
- die->insertRollValue(val);
- if(i == 0 && !subvalues.empty())
- {
- for(int sval : subvalues)
- {
- die->insertRollValue(sval);
- }
- }
- result.insertResult(die);
- ++i;
- }
-}
-
-void makeResultExplode(DiceResult& result, const QVector<int>& values)
-{
- auto die= new Die();
- die->setBase(1);
- die->setMaxValue(10);
- for(int val : values)
- {
- die->insertRollValue(val);
- }
- result.insertResult(die);
-}
-
-Validator* makeValidator(int number, BooleanCondition::LogicOperator op)
-{
- BooleanCondition* validator= new BooleanCondition();
- NumberNode* node= new NumberNode();
- node->setNumber(number);
- validator->setValueNode(node);
- validator->setOperator(op);
- return validator;
-}
-
void TestDice::keepTest()
{
QFETCH(QVector<int>, values);
@@ -618,7 +655,7 @@ void TestDice::countTest()
auto validator= makeValidator(condition, BooleanCondition::GreaterThan);
- countN.setValidator(validator);
+ countN.setValidatorList(validator);
DiceResult result;
node.setResult(&result);
node.setNextNode(&countN);
@@ -629,7 +666,7 @@ void TestDice::countTest()
QCOMPARE(score, countN.getResult()->getResult(Dice::RESULT_TYPE::SCALAR).toInt());
- countN.setValidator(nullptr);
+ countN.setValidatorList(nullptr);
}
void TestDice::countTest_data()
@@ -658,7 +695,7 @@ void TestDice::rerollTest()
node.setResult(&result);
auto validator= makeValidator(condition, BooleanCondition::GreaterThan);
- reroll.setValidator(validator);
+ reroll.setValidatorList(validator);
node.setNextNode(&reroll);
node.run(nullptr);
@@ -702,7 +739,7 @@ void TestDice::explodeTest()
node.setResult(&result);
auto validator= makeValidator(condition, BooleanCondition::Equal);
- explode.setValidator(validator);
+ explode.setValidatorList(validator);
node.setNextNode(&explode);
node.run(nullptr);
@@ -746,7 +783,7 @@ void TestDice::rerollUntilTest()
node.setResult(&result);
auto validator= makeValidator(condition, BooleanCondition::Equal);
- reroll.setValidator(validator);
+ reroll.setValidatorList(validator);
node.setNextNode(&reroll);
node.run(nullptr);
@@ -788,7 +825,7 @@ void TestDice::rerollAddTest()
node.setResult(&result);
auto validator= makeValidator(condition, BooleanCondition::Equal);
- reroll.setValidator(validator);
+ reroll.setValidatorList(validator);
node.setNextNode(&reroll);
node.run(nullptr);
@@ -827,7 +864,7 @@ void TestDice::ifTest()
QFETCH(int, valCondition);
QFETCH(QString, expectedResult);
- IfNode::ConditionType conditionType= static_cast<IfNode::ConditionType>(condition);
+ Dice::ConditionType conditionType= static_cast<Dice::ConditionType>(condition);
TestNode node;
IfNode ifNode;
@@ -846,16 +883,12 @@ void TestDice::ifTest()
ifNode.setInstructionFalse(&falseNode);
auto validator= makeValidator(valCondition, BooleanCondition::Equal);
- ifNode.setValidator(validator);
+ ifNode.setValidatorList(validator);
node.setNextNode(&ifNode);
node.run(nullptr);
- QString text;
- if(nullptr != ifNode.getNextNode())
- text= dynamic_cast<StringResult*>(ifNode.getNextNode()->getResult())->getText();
- else
- text= dynamic_cast<StringResult*>(ifNode.getResult())->getText();
+ auto text= dynamic_cast<StringResult*>(ifNode.getNextNode()->getResult())->getText();
QCOMPARE(expectedResult, text);
@@ -893,39 +926,34 @@ void TestDice::paintTest_data() {}
void TestDice::filterTest()
{
- QFETCH(QVector<int>, values);
- QFETCH(int, condition);
- QFETCH(bool, different);
-
- TestNode node;
- FilterNode filter;
-
- DiceResult result;
- makeResult(result, values);
- node.setResult(&result);
+ QFETCH(QString, cmd);
+ QFETCH(int, result);
- auto validator= makeValidator(condition, BooleanCondition::Different);
- filter.setValidator(validator);
- node.setNextNode(&filter);
+ auto parsing= m_diceParser->parseLine(cmd);
+ QVERIFY2(parsing, "parsing");
- node.run(nullptr);
+ m_diceParser->start();
+ QVERIFY2(m_diceParser->humanReadableError().isEmpty(), "no error");
+ QVERIFY2(m_diceParser->humanReadableWarning().isEmpty(), "no warning");
- auto list= dynamic_cast<DiceResult*>(filter.getResult())->getResultList();
+ auto resultCmd= m_diceParser->getLastIntegerResults();
- auto expected= result.getResultList();
- bool resultDiff= (list.size() != expected.size());
+ QCOMPARE(resultCmd.size(), 1);
- QCOMPARE(different, resultDiff);
+ QCOMPARE(resultCmd.first(), result);
}
void TestDice::filterTest_data()
{
- QTest::addColumn<QVector<int>>("values");
- QTest::addColumn<int>("condition");
- QTest::addColumn<bool>("different");
-
- QTest::addRow("cmd1") << QVector<int>({8, 4, 2}) << 4 << true;
- QTest::addRow("cmd2") << QVector<int>({0, 0, 0}) << 1 << false;
+ QTest::addColumn<QString>("cmd");
+ QTest::addColumn<int>("result");
+
+ QTest::addRow("cmd1") << "[8, 4, 2]f4" << 4;
+ QTest::addRow("cmd2") << "[0, 0, 0]f1" << 0;
+ QTest::addRow("cmd3") << "[1, 2, 3]f[.>2&:>5]" << 6;
+ QTest::addRow("cmd4") << "[1, 2, 6]f[.<2&>5]" << 6;
+ QTest::addRow("cmd5") << "[2, 2, 6]f[.<2&>5]" << 0;
+ QTest::addRow("cmd5") << "[1, 5, 1]f[.<2&>5]" << 0;
}
void TestDice::uniqueTest()
@@ -1008,7 +1036,7 @@ void TestDice::occurenceTest()
node.setResult(&result);
auto validator= makeValidator(condition, BooleanCondition::GreaterThan);
- count.setValidator(validator);
+ count.setValidatorList(validator);
node.setNextNode(&count);
node.run(nullptr);
diff --git a/validator.cpp b/validator.cpp
index 9f717f8..3d0b7af 100644
--- a/validator.cpp
+++ b/validator.cpp
@@ -24,7 +24,91 @@
Validator::Validator() {}
Validator::~Validator() {}
+template <typename Functor>
+qint64 Validator::onEach(const std::vector<Die*>& b, bool recursive, bool unlight, Functor functor) const
+{
+ qint64 result= 0;
+ std::for_each(b.begin(), b.end(), [this, recursive, unlight, functor, &result](Die* die) {
+ if(hasValid(die, recursive, unlight))
+ {
+ ++result;
+ functor(die, recursive, unlight);
+ }
+ });
+ return result;
+}
+
+template <typename Functor>
+qint64 Validator::oneOfThem(const std::vector<Die*>& b, bool recursive, bool unlight, Functor functor) const
+{
+ auto oneOfThem= std::any_of(b.begin(), b.end(),
+ [this, recursive, unlight](Die* die) { return hasValid(die, recursive, unlight); });
+ if(oneOfThem)
+ functor(recursive, unlight);
+ return oneOfThem ? 1 : 0;
+}
+
+template <typename Functor>
+qint64 Validator::allOfThem(const std::vector<Die*>& b, bool recursive, bool unlight, Functor functor) const
+{
+ auto all= std::all_of(b.begin(), b.end(),
+ [this, recursive, unlight](Die* die) { return hasValid(die, recursive, unlight); });
+ if(all)
+ functor(recursive, unlight);
+ return all ? 1 : 0;
+}
+
+template <typename Functor>
+qint64 Validator::onScalar(const std::vector<Die*>& b, bool recursive, bool unlight, Functor functor) const
+{
+ qint64 result= 0;
+ for(const auto& die : b)
+ {
+ result+= die->getValue();
+ }
+ Die die;
+ die.setValue(result);
+ if(hasValid(&die, recursive, unlight))
+ {
+ functor(recursive, unlight);
+ return 1;
+ }
+ return 0;
+}
+
const std::set<qint64>& Validator::getPossibleValues(const std::pair<qint64, qint64>&)
{
return m_values;
}
+
+template <typename Functor>
+qint64 Validator::validResult(const std::vector<Die*>& b, bool recursive, bool unlight, Functor functor) const
+{
+ qint64 result;
+ switch(m_conditionType)
+ {
+ case Dice::OnEach:
+ result= onEach(b, recursive, unlight, functor);
+ break;
+ case Dice::OneOfThem:
+ result= oneOfThem(b, recursive, unlight, functor);
+ break;
+ case Dice::AllOfThem:
+ result= allOfThem(b, recursive, unlight, functor);
+ break;
+ case Dice::OnScalar:
+ result= onScalar(b, recursive, unlight, functor);
+ break;
+ }
+ return result;
+}
+
+Dice::ConditionType Validator::getConditionType() const
+{
+ return m_conditionType;
+}
+
+void Validator::setConditionType(const Dice::ConditionType& conditionType)
+{
+ m_conditionType= conditionType;
+}
diff --git a/validator.h b/validator.h
index a1e7d65..c9f0b4c 100644
--- a/validator.h
+++ b/validator.h
@@ -31,6 +31,7 @@
* @brief The Validator class is an abstract class for checking the validity of dice for some
* operator.
*/
+// template <Dice::ConditionType C>
class Validator
{
public:
@@ -66,11 +67,38 @@ public:
* @return return a copy of this validator
*/
virtual Validator* getCopy() const= 0;
-
+ /**
+ * @brief getPossibleValues
+ * @param range
+ * @return
+ */
virtual const std::set<qint64>& getPossibleValues(const std::pair<qint64, qint64>& range);
+ /**
+ * @brief validResult
+ * @param b
+ * @param recursive
+ * @param unlight
+ * @return
+ */
+ template <typename Functor>
+ qint64 validResult(const std::vector<Die*>& b, bool recursive, bool unlight, Functor functor) const;
+
+ Dice::ConditionType getConditionType() const;
+ void setConditionType(const Dice::ConditionType& conditionType);
+
+protected:
+ template <typename Functor>
+ qint64 onEach(const std::vector<Die*>& b, bool recursive, bool unlight, Functor functor) const;
+ template <typename Functor>
+ qint64 oneOfThem(const std::vector<Die*>& b, bool recursive, bool unlight, Functor functor) const;
+ template <typename Functor>
+ qint64 allOfThem(const std::vector<Die*>& b, bool recursive, bool unlight, Functor functor) const;
+ template <typename Functor>
+ qint64 onScalar(const std::vector<Die*>& b, bool recursive, bool unlight, Functor functor) const;
protected:
std::set<qint64> m_values;
+ Dice::ConditionType m_conditionType= Dice::OnEach;
};
#endif // VALIDATOR_H
diff --git a/validatorlist.cpp b/validatorlist.cpp
new file mode 100644
index 0000000..0d0abb5
--- /dev/null
+++ b/validatorlist.cpp
@@ -0,0 +1,355 @@
+/***************************************************************************
+ * Copyright (C) 2014 by Renaud Guezennec *
+ * http://www.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 "validatorlist.h"
+
+#include "diceresult.h"
+#include "result.h"
+#include "validator.h"
+#include <utility>
+
+bool isValid(Die* die, const ValidatorResult& diceList, ValidatorList::LogicOperation op)
+{
+ if(op == ValidatorList::OR)
+ return true;
+
+ bool newResult= false;
+
+ if(diceList.m_allTrue)
+ {
+ newResult= true;
+ }
+ else
+ {
+ auto it= std::find_if(diceList.m_validDice.begin(), diceList.m_validDice.end(),
+ [die](const std::pair<Die*, qint64>& pair) { return die == pair.first; });
+ if(it != diceList.m_validDice.end())
+ newResult= true;
+ }
+
+ if(op == ValidatorList::EXCLUSIVE_OR)
+ return !newResult;
+
+ return newResult;
+}
+
+DiceResult* getDiceResult(Result* result)
+{
+ auto dice= dynamic_cast<DiceResult*>(result);
+ if(nullptr == dice)
+ {
+ qFatal("Error, no dice result");
+ // TODO: manage error here.
+ }
+ return dice;
+}
+
+ValidatorList::ValidatorList() {}
+
+ValidatorList::~ValidatorList()
+{
+ qDeleteAll(m_validatorList);
+}
+qint64 ValidatorList::hasValid(Die* b, bool recursive, bool unhighlight) const
+{
+ int i= 0;
+ qint64 sum= 0;
+ bool highLight= false;
+ for(auto& validator : m_validatorList)
+ {
+ qint64 val= validator->hasValid(b, recursive, unhighlight);
+ if(i == 0)
+ {
+ sum= val;
+ if(b->isHighlighted())
+ {
+ highLight= b->isHighlighted();
+ }
+ }
+ else
+ {
+ switch(m_operators.at(i - 1))
+ {
+ case OR:
+ sum|= val;
+
+ if(highLight)
+ {
+ b->setHighlighted(highLight);
+ }
+ break;
+ case EXCLUSIVE_OR:
+ sum^= val; /// @todo may required to be done by hand
+ break;
+ case AND:
+ sum&= val;
+ break;
+ default:
+ break;
+ }
+ }
+ ++i;
+ }
+
+ return sum;
+}
+
+QString ValidatorList::toString()
+{
+ QString str= "";
+ /*switch (m_operator)
+ {
+ case Equal:
+ str.append("=");
+ break;
+ case GreaterThan:
+ str.append(">");
+ break;
+ case LesserThan:
+ str.append("<");
+ break;
+ case GreaterOrEqual:
+ str.append(">=");
+ break;
+ case LesserOrEqual:
+ str.append("<=");
+ break;
+ }
+ return QString("[%1%2]").arg(str).arg(m_value);*/
+ return str;
+}
+
+Dice::CONDITION_STATE testAND(Dice::CONDITION_STATE before, Dice::CONDITION_STATE current)
+{
+ if(before == Dice::CONDITION_STATE::UNREACHABLE || current == Dice::CONDITION_STATE::UNREACHABLE)
+ return Dice::CONDITION_STATE::UNREACHABLE;
+ else if(before == Dice::CONDITION_STATE::ALWAYSTRUE && current == Dice::CONDITION_STATE::ALWAYSTRUE)
+ return Dice::CONDITION_STATE::ALWAYSTRUE;
+ else
+ return Dice::CONDITION_STATE::REACHABLE;
+}
+
+Dice::CONDITION_STATE testOR(Dice::CONDITION_STATE before, Dice::CONDITION_STATE current)
+{
+ if(before == Dice::CONDITION_STATE::UNREACHABLE && current == Dice::CONDITION_STATE::UNREACHABLE)
+ return Dice::CONDITION_STATE::UNREACHABLE;
+ else if(before == Dice::CONDITION_STATE::ALWAYSTRUE || current == Dice::CONDITION_STATE::ALWAYSTRUE)
+ return Dice::CONDITION_STATE::ALWAYSTRUE;
+ else
+ return Dice::CONDITION_STATE::REACHABLE;
+}
+
+Dice::CONDITION_STATE testXOR(Dice::CONDITION_STATE before, Dice::CONDITION_STATE current)
+{
+ if(before == current
+ && (before == Dice::CONDITION_STATE::UNREACHABLE || before == Dice::CONDITION_STATE::ALWAYSTRUE))
+ return Dice::CONDITION_STATE::UNREACHABLE;
+ else if((before != current)
+ && (before == Dice::CONDITION_STATE::ALWAYSTRUE || before == Dice::CONDITION_STATE::UNREACHABLE)
+ && (before != Dice::CONDITION_STATE::REACHABLE || current != Dice::CONDITION_STATE::REACHABLE))
+ return Dice::CONDITION_STATE::ALWAYSTRUE;
+ else
+ return Dice::CONDITION_STATE::REACHABLE;
+}
+
+Dice::CONDITION_STATE ValidatorList::isValidRangeSize(const std::pair<qint64, qint64>& range) const
+{
+ std::vector<Dice::CONDITION_STATE> vec;
+ std::transform(
+ m_validatorList.begin(), m_validatorList.end(), std::back_inserter(vec),
+ [range](Validator* validator) -> Dice::CONDITION_STATE { return validator->isValidRangeSize(range); });
+
+ auto itError= std::find(vec.begin(), vec.end(), Dice::CONDITION_STATE::ERROR_STATE);
+
+ if(vec.size() == 1)
+ return vec.front();
+
+ if((static_cast<int>(vec.size()) != m_operators.size() + 1) || (itError != vec.end()))
+ {
+ return Dice::CONDITION_STATE::ERROR_STATE;
+ }
+
+ std::size_t i= 0;
+ Dice::CONDITION_STATE val= Dice::CONDITION_STATE::ERROR_STATE;
+ for(const auto& op : m_operators)
+ {
+ auto currentState= vec[i + 1];
+ if(i == 0)
+ {
+ val= vec[i];
+ }
+ switch(op)
+ {
+ case OR:
+ val= testAND(val, currentState);
+ break;
+ case EXCLUSIVE_OR:
+ val= testOR(val, currentState);
+ break;
+ case AND:
+ val= testXOR(val, currentState);
+ break;
+ case NONE:
+ val= Dice::CONDITION_STATE::ERROR_STATE;
+ break;
+ }
+
+ ++i;
+ }
+ return val;
+}
+
+void ValidatorList::setOperationList(const QVector<LogicOperation>& m)
+{
+ m_operators= m;
+}
+
+void ValidatorList::setValidators(const QList<Validator*>& valids)
+{
+ qDeleteAll(m_validatorList);
+ m_validatorList= valids;
+}
+
+void ValidatorList::validResult(Result* result, bool recursive, bool unlight,
+ std::function<void(Die*, qint64)> functor) const
+{
+ std::vector<ValidatorResult> validityData;
+ for(auto& validator : m_validatorList)
+ {
+ ValidatorResult validResult({{}, false});
+ switch(validator->getConditionType())
+ {
+ case Dice::OnScalar:
+ {
+ Die die;
+ auto scalar= result->getResult(Dice::RESULT_TYPE::SCALAR).toInt();
+ die.insertRollValue(scalar);
+ if(validator->hasValid(&die, recursive, unlight))
+ {
+ validResult.m_allTrue= true;
+ }
+ }
+ break;
+ case Dice::OnEach:
+ {
+ DiceResult* diceResult= getDiceResult(result);
+ if(nullptr == diceResult)
+ break;
+ for(auto die : diceResult->getResultList())
+ {
+ auto score= validator->hasValid(die, recursive, unlight);
+ if(score)
+ {
+ validResult.m_validDice.push_back({die, score});
+ }
+ }
+ }
+ break;
+ case Dice::AllOfThem:
+ {
+ DiceResult* diceResult= getDiceResult(result);
+ if(nullptr == diceResult)
+ break;
+ auto diceList= diceResult->getResultList();
+ auto all= std::all_of(diceList.begin(), diceList.end(), [validator, recursive, unlight](Die* die) {
+ return validator->hasValid(die, recursive, unlight);
+ });
+ if(all)
+ {
+ validResult.m_allTrue= true;
+ }
+ }
+ break;
+ case Dice::OneOfThem:
+ {
+ DiceResult* diceResult= getDiceResult(result);
+ if(nullptr == diceResult)
+ break;
+ auto diceList= diceResult->getResultList();
+ auto any= std::any_of(diceList.begin(), diceList.end(), [validator, recursive, unlight](Die* die) {
+ return validator->hasValid(die, recursive, unlight);
+ });
+ if(any)
+ {
+ validResult.m_allTrue= true;
+ }
+ }
+ }
+ validityData.push_back(validResult);
+ }
+ if(validityData.empty())
+ return;
+
+ std::size_t i= 0;
+ ValidatorResult finalResult({{}, false});
+ {
+ auto vec= validityData[i];
+ finalResult.m_validDice.reserve(vec.m_validDice.size());
+ finalResult= vec;
+ }
+ ++i;
+ for(auto op : m_operators)
+ {
+ ValidatorResult tmpResult({{}, false});
+ if(validityData.size() > i)
+ {
+ auto vec= validityData[i];
+
+ auto bigger= (vec > finalResult) ? vec : finalResult;
+ auto smaller= (vec > finalResult) ? finalResult : vec;
+
+ if(bigger.m_allTrue && smaller.m_allTrue)
+ tmpResult.m_allTrue= true;
+ for(auto die : bigger.m_validDice)
+ {
+ if(isValid(die.first, smaller, op))
+ {
+ tmpResult.m_validDice.push_back(die);
+ }
+ }
+ finalResult= tmpResult;
+ }
+ }
+
+ if(finalResult.m_allTrue)
+ {
+ DiceResult* diceResult= getDiceResult(result);
+ if(nullptr == diceResult)
+ return;
+ auto diceList= diceResult->getResultList();
+ std::transform(diceList.begin(), diceList.end(), std::back_inserter(finalResult.m_validDice), [](Die* die) {
+ return std::pair<Die*, qint64>({die, 0});
+ });
+ }
+
+ for(auto die : finalResult.m_validDice)
+ {
+ functor(die.first, die.second);
+ }
+}
+
+ValidatorList* ValidatorList::getCopy() const
+{
+ ValidatorList* val= new ValidatorList();
+ val->setOperationList(m_operators);
+ val->setValidators(m_validatorList);
+ return val;
+}
diff --git a/validatorlist.h b/validatorlist.h
new file mode 100644
index 0000000..5d29817
--- /dev/null
+++ b/validatorlist.h
@@ -0,0 +1,92 @@
+/***************************************************************************
+ * Copyright (C) 2014 by Renaud Guezennec *
+ * http://www.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. *
+ ***************************************************************************/
+#ifndef VALIDATORLIST_H
+#define VALIDATORLIST_H
+
+#include <QList>
+#include <QString>
+#include <QVector>
+#include <Qt>
+
+#include "diceparserhelper.h"
+#include <functional>
+
+class Validator;
+class Die;
+class Result;
+
+struct ValidatorResult
+{
+ std::vector<std::pair<Die*, qint64>> m_validDice;
+ bool m_allTrue;
+
+ friend bool operator>(const ValidatorResult& a, const ValidatorResult& b)
+ {
+ if(a.m_validDice.size() > b.m_validDice.size())
+ return true;
+ if(a.m_validDice.size() == b.m_validDice.size())
+ {
+ if(!a.m_allTrue && b.m_allTrue)
+ return true;
+ else
+ return false;
+ }
+ return false;
+ }
+};
+/**
+ * @brief The BooleanCondition class is a Validator class checking validity from logic expression.
+ * It manages many operators (see : @ref LogicOperator).
+ */
+class ValidatorList
+{
+public:
+ enum LogicOperation
+ {
+ OR,
+ EXCLUSIVE_OR,
+ AND,
+ NONE
+ };
+
+ ValidatorList();
+ virtual ~ValidatorList();
+
+ virtual qint64 hasValid(Die* b, bool recursive, bool unhighlight= false) const;
+
+ void setOperationList(const QVector<LogicOperation>& m);
+ void setValidators(const QList<Validator*>& valids);
+
+ QString toString();
+
+ virtual Dice::CONDITION_STATE isValidRangeSize(const std::pair<qint64, qint64>& range) const;
+
+ virtual ValidatorList* getCopy() const;
+
+ void validResult(Result* result, bool recursive, bool unlight, std::function<void(Die*, qint64)> functor) const;
+
+private:
+ QVector<LogicOperation> m_operators;
+ QList<Validator*> m_validatorList;
+};
+
+#endif // VALIDATORLIST_H