aboutsummaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
-rw-r--r--.gitignore5
-rw-r--r--CMakeLists.txt126
-rw-r--r--README.md135
-rw-r--r--booleancondition.cpp88
-rw-r--r--booleancondition.h8
-rw-r--r--cli/CMakeLists.txt62
-rw-r--r--cli/main.cpp57
-rw-r--r--compositevalidator.cpp111
-rw-r--r--compositevalidator.h18
-rw-r--r--diceparser.cpp131
-rw-r--r--diceparser.pc.in12
-rw-r--r--die.cpp4
-rw-r--r--die.h4
-rw-r--r--highlightdice.cpp2
-rw-r--r--include/dicealias.h (renamed from dicealias.h)0
-rw-r--r--include/diceparser.h (renamed from diceparser.h)69
-rw-r--r--include/diceparserhelper.h43
-rw-r--r--include/highlightdice.h (renamed from highlightdice.h)0
-rw-r--r--include/parsingtoolbox.h (renamed from parsingtoolbox.h)4
-rw-r--r--node/countexecutenode.cpp2
-rw-r--r--node/dicerollernode.cpp8
-rw-r--r--node/executionnode.cpp6
-rw-r--r--node/executionnode.h23
-rw-r--r--node/explodedicenode.cpp14
-rw-r--r--node/forloopnode.cpp2
-rw-r--r--node/ifnode.cpp4
-rw-r--r--node/jumpbackwardnode.cpp5
-rw-r--r--node/keepdiceexecnode.cpp7
-rw-r--r--node/listsetrollnode.cpp6
-rw-r--r--node/mergenode.cpp70
-rw-r--r--node/occurencecountnode.cpp1
-rw-r--r--node/paintnode.cpp15
-rw-r--r--node/paintnode.h1
-rw-r--r--node/rerolldicenode.cpp23
-rw-r--r--node/scalaroperatornode.cpp40
-rw-r--r--node/scalaroperatornode.h2
-rw-r--r--node/valueslistnode.cpp2
-rw-r--r--node/variablenode.cpp2
-rw-r--r--operationcondition.cpp47
-rw-r--r--operationcondition.h14
-rw-r--r--parsingtoolbox.cpp79
-rw-r--r--range.cpp16
-rw-r--r--range.h8
-rw-r--r--result/diceresult.cpp8
-rw-r--r--result/diceresult.h2
-rw-r--r--result/result.cpp9
-rw-r--r--result/result.h18
-rw-r--r--result/scalarresult.cpp6
-rw-r--r--result/scalarresult.h2
-rw-r--r--result/stringresult.cpp15
-rw-r--r--result/stringresult.h4
-rw-r--r--tests/CMakeLists.txt11
-rw-r--r--tests/dice/CMakeLists.txt19
-rw-r--r--tests/dice/Dice.pro25
-rw-r--r--tests/dice/testnode.cpp (renamed from tests/testnode.cpp)0
-rw-r--r--tests/dice/testnode.h (renamed from tests/testnode.h)0
-rw-r--r--tests/dice/tst_dice.cpp (renamed from tests/tst_dice.cpp)41
-rw-r--r--tests/fuzzer/CMakeLists.txt26
-rwxr-xr-xtests/fuzzer/run_test.sh27
-rw-r--r--tests/fuzzer/testcase.cpp37
-rw-r--r--tests/fuzzer/testcase_dir/gooddata.txt45
-rw-r--r--validator.cpp5
-rw-r--r--validator.h9
63 files changed, 1060 insertions, 525 deletions
diff --git a/.gitignore b/.gitignore
index c5b3072..6574b7a 100644
--- a/.gitignore
+++ b/.gitignore
@@ -20,3 +20,8 @@ qrc_*.cpp
Makefile
*-build-*
build*
+
+*crashes*
+*hangs*
+*queue*
+*fuzzer0*
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 9a9a340..f213bc4 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -1,6 +1,6 @@
cmake_minimum_required(VERSION 3.5)
-project(diceparser)
+project(diceparser VERSION 1.9.0 DESCRIPTION "Parser of dice command")
set(QT_REQUIRED_VERSION "5.12.0")
find_package(Qt5 ${QT_REQUIRED_VERSION} CONFIG REQUIRED COMPONENTS Core Test Gui Svg)
@@ -9,55 +9,91 @@ enable_testing(true)
include_directories(${CMAKE_CURRENT_SOURCE_DIR} result node)
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/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
+ ${CMAKE_CURRENT_SOURCE_DIR}/diceparser.cpp
+ ${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}/operationcondition.cpp
+ ${CMAKE_CURRENT_SOURCE_DIR}/die.cpp
+ ${CMAKE_CURRENT_SOURCE_DIR}/parsingtoolbox.cpp
+ ${CMAKE_CURRENT_SOURCE_DIR}/dicealias.cpp
+ ${CMAKE_CURRENT_SOURCE_DIR}/result/result.cpp
+ ${CMAKE_CURRENT_SOURCE_DIR}/result/scalarresult.cpp
+ ${CMAKE_CURRENT_SOURCE_DIR}/result/stringresult.cpp
+ ${CMAKE_CURRENT_SOURCE_DIR}/result/diceresult.cpp
+ ${CMAKE_CURRENT_SOURCE_DIR}/node/countexecutenode.cpp
+ ${CMAKE_CURRENT_SOURCE_DIR}/node/dicerollernode.cpp
+ ${CMAKE_CURRENT_SOURCE_DIR}/node/executionnode.cpp
+ ${CMAKE_CURRENT_SOURCE_DIR}/node/explodedicenode.cpp
+ ${CMAKE_CURRENT_SOURCE_DIR}/node/helpnode.cpp
+ ${CMAKE_CURRENT_SOURCE_DIR}/node/mergenode.cpp
+ ${CMAKE_CURRENT_SOURCE_DIR}/node/jumpbackwardnode.cpp
+ ${CMAKE_CURRENT_SOURCE_DIR}/node/keepdiceexecnode.cpp
+ ${CMAKE_CURRENT_SOURCE_DIR}/node/listaliasnode.cpp
+ ${CMAKE_CURRENT_SOURCE_DIR}/node/listsetrollnode.cpp
+ ${CMAKE_CURRENT_SOURCE_DIR}/node/numbernode.cpp
+ ${CMAKE_CURRENT_SOURCE_DIR}/node/parenthesesnode.cpp
+ # ${CMAKE_CURRENT_SOURCE_DIR}/ node/forloopnode.cpp
+ ${CMAKE_CURRENT_SOURCE_DIR}/node/paintnode.cpp
+ ${CMAKE_CURRENT_SOURCE_DIR}/node/rerolldicenode.cpp
+ ${CMAKE_CURRENT_SOURCE_DIR}/node/scalaroperatornode.cpp
+ ${CMAKE_CURRENT_SOURCE_DIR}/node/sortresult.cpp
+ ${CMAKE_CURRENT_SOURCE_DIR}/node/startingnode.cpp
+ ${CMAKE_CURRENT_SOURCE_DIR}/node/filternode.cpp
+ ${CMAKE_CURRENT_SOURCE_DIR}/node/stringnode.cpp
+ ${CMAKE_CURRENT_SOURCE_DIR}/node/ifnode.cpp
+ ${CMAKE_CURRENT_SOURCE_DIR}/node/splitnode.cpp
+ ${CMAKE_CURRENT_SOURCE_DIR}/node/groupnode.cpp
+ ${CMAKE_CURRENT_SOURCE_DIR}/node/bind.cpp
+ ${CMAKE_CURRENT_SOURCE_DIR}/node/occurencecountnode.cpp
+ ${CMAKE_CURRENT_SOURCE_DIR}/node/uniquenode.cpp
+ ${CMAKE_CURRENT_SOURCE_DIR}/highlightdice.cpp
+ ${CMAKE_CURRENT_SOURCE_DIR}/node/variablenode.cpp
+ ${CMAKE_CURRENT_SOURCE_DIR}/node/valueslistnode.cpp
)
-add_library(diceparser SHARED ${dice_sources} )
-target_link_libraries(diceparser PUBLIC Qt5::Core Qt5::Gui Qt5::Svg)
+IF(STATIC_BUILD)
+ add_library(diceparser_static STATIC ${dice_sources} )
+ target_include_directories(diceparser_static PRIVATE include)
+ SET_TARGET_PROPERTIES(diceparser_static PROPERTIES OUTPUT_NAME diceparser CLEAN_DIRECT_OUTPUT 1)
+ target_link_libraries(diceparser_static PUBLIC Qt5::Core Qt5::Gui Qt5::Svg)
+ install(TARGETS diceparser_static
+ ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR})
+endif()
+
+set(documentation README.md HelpMe.md)
+
+add_library(diceparser_shared SHARED ${dice_sources} ${documentation})
+
+target_include_directories(diceparser_shared PRIVATE include)
+
+
+SET_TARGET_PROPERTIES(diceparser_shared PROPERTIES OUTPUT_NAME diceparser CLEAN_DIRECT_OUTPUT 1)
+target_link_libraries(diceparser_shared PUBLIC Qt5::Core Qt5::Gui Qt5::Svg)
+
+set_target_properties(diceparser_shared PROPERTIES VERSION ${PROJECT_VERSION})
+set_target_properties(diceparser_shared PROPERTIES SOVERSION 1)
+
+set_target_properties(diceparser_shared PROPERTIES PUBLIC_HEADER "include/diceparser.h;include/highlightdice.h;include/parsingtoolbox.h;include/dicealias.h;include/diceparserhelper.h")
add_subdirectory(cli)
add_subdirectory( tests )
#add_subdirectory(irc)
#add_subdirectory(mobile)
#add_subdirectory(webserver)
+
+
+include(GNUInstallDirs)
+
+install(TARGETS diceparser_shared
+ LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
+ PUBLIC_HEADER DESTINATION ${CMAKE_INSTALL_INCLUDEDIR})
+
+
+configure_file(diceparser.pc.in diceparser.pc @ONLY)
+
+install(FILES ${CMAKE_BINARY_DIR}/diceparser.pc DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/pkgconfig)
+
+
+
diff --git a/README.md b/README.md
index 6460cca..41bdf73 100644
--- a/README.md
+++ b/README.md
@@ -59,44 +59,111 @@ More examples at : https://github.com/Rolisteam/DiceParser/blob/master/HelpMe.md
The grammar is something like this:
```
-Command =: Instruction [';',Instruction]*
-Instruction =: Expression
-Expression =: number | number Dice DiceOperation | ScalarOperator Expression | string | variable Expression
-Dice =: DiceOperator Number(faces) | DiceOperator ListOfValues
-DiceOperator =: D | L
-DiceOperation =: Keep | KeepAndExplode | Sort | Count | Reroll | RerollUntil | If | Explode | Jumpbackward | Merge | Filter | Split | Parenthese | Count | Paint | Group
+Program =: Instruction [InstructionSeparator, Instruction]* Comment
+InstructionSeparator = ;
+Instruction =: Expression ([Operator, Expression]* | [Option]*)
+Operator =: ScalarOperator
+Expression =: OpenParenthesis Expression closeParenthesis
+| Option*
+| [Operator, Expression]*
+| Operand Dice
+| Command
+| NodeOperator [Option]*
+| ValuesList
+| Dice (Operand == 1)
+Operand =: DynamicVariable | Number | String
+OpenParenthesis = (
+closeParenthesis = )
+OpenList = [
+CloseList = ]
+ListSeparator = ,
+ValuesList=: OpenList (DynamicVariable | Number)? [ ListSeparator,(DynamicVariable | Number)]* CloseList
+Dice =: DiceOperator [uniqueValue] DiceParameter
+DiceOperator =: D ParameterDice | L ParameterList
+DiceParameter =: ParameterDice | ParameterList
+ParameterDice =: Number|Range
+ParameterList =: List
+List=: OpenList String[Probability] [ListSeparator,String[Probability]]* CloseList
+Probability=: OpenList (Range|Percentage) CloseList
+Percentage =: number
+Option =: Keep
+| KeepAndExplode
+| Filter
+| Sort
+| Count
+| Reroll
+| RerollUntil
+| RerollAndAdd
+| Explode
+| Merge
+| Bind
+| Occurences
+| Unique
+| Paint
+| If
+| Split
+| Group
+Range =: OpenList Number RangeSeparator Number CloseList
+RangeSeparator =: -
ScalarOperator =: [x,-,*,x,/]
-number =: [0-9]+ | constantValue
-constantValue =: ${id | label}
-id=[_,a-z][_,A-z,0-9]*
-label=[_,a-z][_,A-z,0-9,é,è,ç,û,ê,â]*
-variable = ${[0-9]+}
-Validator =: BooleanValidator | RangeValidator | CompositeValidator
-CompositeValidator =: Validator LogicOpetator Validator
-LogicOpetator =: = | > | => | < | =<
-RangeValidator =: [ number - number ]
-BooleanValidator =: number | [operator number] |
+number =: [-] [0-9]+ | constantValue
+OpenVaribale=: ${
+CloseVariable=: }
+constantValue =: OpenVaribale (id | label) CloseVariable
+id=[_,a-z][_,A-z,0-9]* # must respect rules of QML id
+label=.*
+variable = OpenVaribale [0-9]+ CloseVariable
+CompositeValidator =: OpenList Validator [LogicOpetator,Validator]* CloseList
+LogicOpetator =: AND | XOR | OR
+AND =: &
+XOR =: ^
+OR =: |
+Ascendant=:l
+Validator =: BooleanValidator | RangeValidator | OperationValidator
+CompareOpetator =: = | > | => | < | =< | !=
+RangeValidator =: Range
+OperationValidator =: Modulo operandNode BooleanValidator
+Modulo =: %
+BooleanValidator =: [=]Operand | [CompareOpetator Operand]
ListOfValue=: String[Range],ListOfValue | String[Range]
-String =: [A-z0-9]+
-Keep =: k Number
-KeepAndExplode =: K number
-Reroll =: r
-RerollUntil =: R
-Exploding =: e
-RerollOnceAndAdd =: a
-RerollAndAdd =: A
-Painter =: p
-Split =: u
-Group =: g
+String =: .*[^ListSeparator]
+Keep =: k[Ascendant] Number
+KeepAndExplode =: K[Ascendant] number
+Filter =: f CompositeValidator
+Sort =: s[Ascendant]
+Count =: c CompositeValidator
+Reroll =: r CompositeValidator
+RerollUntil =: R CompositeValidator
+RerollAndAdd =: a CompositeValidator
+Merge =: m
+Bind =: b
+Occurences =: OccurencesWidth ( ListSeparator number | CompositeValidator)
+OccurencesWidth =: number
+unique =: u
+Painter =: p PainterParameters
+PainterParameters =: OpenList PairColorOccurence [ListSeparator , PairColorOccurence]* CloseList
+PairColorOccurence =: Color PairSeparator Number
+PairSeparator =: :
+If =: i [compareMethod] CompositeValidator Bloc[Bloc]
+compareMethod =: OnEach | OneOfThem | AllOfThem | onScalar
+OnEach =: ''
+OneOfThem = '.'
+AllOfThem = '*'
+onScalar = ':'
+Bloc =: OpenBranch Expression CloseBranch
+OpenBloc =: {
+CloseBloc =: }
+Split =: y
+Group =: g Number
Sort =: s
-If =: i compareMethod [Validator] {Expression}[{Expression}]
-Paint =: p [ Count : color ]
Group =: number
-Explode =: e Validator
-Jumpbackward =: @DiceOperation
+Explode =: e CompositeValidator
+NodeOperator = Jumpbackward
+Jumpbackward =: @
Merge =: m | m Expression
-Filter =: f Validator
-Parenthese =: (expression)
-Count =: c Validator
+Command =: help | la
+uniqueValue = u
+Comment =: StartComment String
+StartComment =: #
```
diff --git a/booleancondition.cpp b/booleancondition.cpp
index f62c900..82d599b 100644
--- a/booleancondition.cpp
+++ b/booleancondition.cpp
@@ -20,7 +20,66 @@
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
***************************************************************************/
#include "booleancondition.h"
-#include <QDebug>
+
+Dice::CONDITION_STATE testEqual(bool insideRange, const std::pair<qint64, qint64>& range)
+{
+ if(!insideRange)
+ return Dice::CONDITION_STATE::UNREACHABLE;
+ else if(insideRange && (range.first == range.second))
+ return Dice::CONDITION_STATE::ALWAYSTRUE;
+ else
+ return Dice::CONDITION_STATE::REACHABLE;
+}
+
+Dice::CONDITION_STATE testGreatherThan(qint64 value, const std::pair<qint64, qint64>& range)
+{
+ if(value >= std::max(range.first, range.second))
+ return Dice::CONDITION_STATE::UNREACHABLE;
+ else if(value < std::min(range.first, range.second))
+ return Dice::CONDITION_STATE::ALWAYSTRUE;
+ else
+ return Dice::CONDITION_STATE::REACHABLE;
+}
+
+Dice::CONDITION_STATE testLesserThan(qint64 value, const std::pair<qint64, qint64>& range)
+{
+ if(value <= std::min(range.first, range.second))
+ return Dice::CONDITION_STATE::UNREACHABLE;
+ else if(value > std::max(range.first, range.second))
+ return Dice::CONDITION_STATE::ALWAYSTRUE;
+ else
+ return Dice::CONDITION_STATE::REACHABLE;
+}
+
+Dice::CONDITION_STATE testGreaterOrEqual(qint64 value, const std::pair<qint64, qint64>& range)
+{
+ if(value > std::max(range.first, range.second))
+ return Dice::CONDITION_STATE::UNREACHABLE;
+ else if(value <= std::min(range.first, range.second))
+ return Dice::CONDITION_STATE::ALWAYSTRUE;
+ else
+ return Dice::CONDITION_STATE::REACHABLE;
+}
+
+Dice::CONDITION_STATE testLesserOrEqual(qint64 value, const std::pair<qint64, qint64>& range)
+{
+ if(value < std::min(range.first, range.second))
+ return Dice::CONDITION_STATE::UNREACHABLE;
+ else if(value >= std::max(range.first, range.second))
+ return Dice::CONDITION_STATE::ALWAYSTRUE;
+ else
+ return Dice::CONDITION_STATE::REACHABLE;
+}
+
+Dice::CONDITION_STATE testDifferent(bool inside, const std::pair<qint64, qint64>& range)
+{
+ if(inside && (range.first == range.second))
+ return Dice::CONDITION_STATE::UNREACHABLE;
+ else if(!inside)
+ return Dice::CONDITION_STATE::ALWAYSTRUE;
+ else
+ return Dice::CONDITION_STATE::REACHABLE;
+}
BooleanCondition::BooleanCondition() : m_operator(Equal) {}
@@ -117,39 +176,41 @@ QString BooleanCondition::toString()
}
return QStringLiteral("[%1%2]").arg(str).arg(valueToScalar());
}
-bool BooleanCondition::isValidRangeSize(std::pair<qint64, qint64> range) const
+
+Dice::CONDITION_STATE BooleanCondition::isValidRangeSize(const std::pair<qint64, qint64>& range) const
{
- bool isValid= false;
+ Dice::CONDITION_STATE state;
auto valueScalar= valueToScalar();
qint64 boundValue= qBound(range.first, valueScalar, range.second);
+ bool isInsideRange= (boundValue == valueScalar);
switch(m_operator)
{
case Equal:
- isValid= (boundValue == valueScalar);
+ state= testEqual(isInsideRange, range); //(isInsideRange && (range.first != range.second)) ? ;
break;
case GreaterThan:
- isValid= range.first <= valueScalar;
+ state= testGreatherThan(valueScalar, range);
break;
case LesserThan:
- isValid= range.second >= valueScalar;
+ state= testLesserThan(valueScalar, range);
break;
case GreaterOrEqual:
- isValid= range.first < valueScalar;
+ state= testGreaterOrEqual(valueScalar, range);
break;
case LesserOrEqual:
- isValid= range.second > valueScalar;
+ state= testLesserOrEqual(valueScalar, range);
break;
case Different:
- isValid= (boundValue == valueScalar);
+ state= testDifferent(isInsideRange, range);
break;
}
- return isValid;
+ return state;
}
Validator* BooleanCondition::getCopy() const
{
BooleanCondition* val= new BooleanCondition();
val->setOperator(m_operator);
- val->setValueNode(m_value);
+ val->setValueNode(m_value->getCopy());
return val;
}
qint64 BooleanCondition::valueToScalar() const
@@ -159,5 +220,8 @@ qint64 BooleanCondition::valueToScalar() const
m_value->run(nullptr);
auto result= m_value->getResult();
- return result->getResult(Result::SCALAR).toInt();
+ if(result)
+ return result->getResult(Dice::RESULT_TYPE::SCALAR).toInt();
+ else
+ return 0;
}
diff --git a/booleancondition.h b/booleancondition.h
index c542a0c..54c243a 100644
--- a/booleancondition.h
+++ b/booleancondition.h
@@ -42,20 +42,20 @@ public:
Different
};
BooleanCondition();
- virtual ~BooleanCondition();
+ virtual ~BooleanCondition() override;
- virtual qint64 hasValid(Die* b, bool recursive, bool unhighlight= false) const;
+ virtual qint64 hasValid(Die* b, bool recursive, bool unhighlight= false) const override;
void setOperator(LogicOperator m);
void setValueNode(ExecutionNode*);
QString toString();
- virtual bool isValidRangeSize(std::pair<qint64, qint64> range) const;
+ virtual Dice::CONDITION_STATE isValidRangeSize(const std::pair<qint64, qint64>& range) const override;
/**
* @brief getCopy
* @return
*/
- virtual Validator* getCopy() const;
+ virtual Validator* getCopy() const override;
private:
qint64 valueToScalar() const;
diff --git a/cli/CMakeLists.txt b/cli/CMakeLists.txt
index 215287d..c697899 100644
--- a/cli/CMakeLists.txt
+++ b/cli/CMakeLists.txt
@@ -3,15 +3,57 @@ cmake_minimum_required(VERSION 3.5)
option(UPDATE_TRANSLATIONS "update Translation" 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/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.
set(CMAKE_AUTOMOC ON)
-
set(EXECUTABLE_OUTPUT_PATH bin/)
# Find the QtWidgets library
@@ -38,7 +80,6 @@ set(dice_RESOURCES diceparser.qrc)
find_package(Qt5LinguistTools)
find_package(Qt5Svg)
-
IF(UPDATE_TRANSLATIONS)
MESSAGE( update Translation )
FILE(GLOB_RECURSE translate_dice_SRCS ../*.cpp ../*.h)
@@ -50,17 +91,8 @@ ELSE()
ENDIF(UPDATE_TRANSLATIONS)
if(Qt5Core_FOUND)
-
- #IF(UPDATE_TRANSLATIONS)
- MESSAGE(status "find" ${dice_TS} ${translate_SRCS} )
- #QT5_CREATE_TRANSLATION(dice_QM ${translate_SRCS} ${dice_TS})
- #ELSE()
- #QT5_ADD_TRANSLATION(dice_QM ${dice_TS})
- #ENDIF()
-
+ MESSAGE(status "find" ${dice_TS} ${translate_SRCS} )
QT5_ADD_RESOURCES(dice_RESOURCES_RCC ${dice_RESOURCES})
-
- # guess plugins and libraries directory
set(QT_PLUGINS_DIR "${Qt5Core_DIR}/../../../plugins")
get_target_property(QT_LIBRARY_DIR Qt5::Core LOCATION)
get_filename_component(QT_LIBRARY_DIR ${QT_LIBRARY_DIR} PATH)
@@ -73,7 +105,9 @@ SET( cli_sources
set(documentation_files ../HelpMe.md ../README.md)
-add_executable( dice ${cli_sources} ${dice_QM} ${documentation_files})
+add_executable( dice ${cli_sources} ${dice_QM} ${dice_sources} ${documentation_files})
+target_include_directories(dice PRIVATE ../include)
+
target_link_libraries(dice diceparser ${Qt5Core_LIBRARIES} ${Qt5Gui_LIBRARIES} ${Qt5Svg_LIBRARIES})
INSTALL_TARGETS(/bin dice)
diff --git a/cli/main.cpp b/cli/main.cpp
index d6f6398..c597dea 100644
--- a/cli/main.cpp
+++ b/cli/main.cpp
@@ -35,6 +35,7 @@
#include <QCoreApplication>
#endif
+#include "dicealias.h"
#include "diceparser.h"
#include "displaytoolbox.h"
#include "highlightdice.h"
@@ -115,7 +116,7 @@ QString diceToMarkdown(QJsonArray array, bool withColor, bool allSameColor, bool
}
void displayJSon(QString scalarText, QString resultStr, QJsonArray array, bool withColor, QString cmd, QString error,
- QString warning, QString comment, bool allSameFaceCount, bool allSameColor)
+ QString warning, QString comment, bool allSameFaceCount, bool allSameColor)
{
Q_UNUSED(withColor);
QJsonDocument doc;
@@ -133,7 +134,7 @@ void displayJSon(QString scalarText, QString resultStr, QJsonArray array, bool w
out << doc.toJson() << "\n";
}
void displayMarkdown(QString scalarText, QString resultStr, QJsonArray array, bool withColor, QString cmd,
- QString error, QString warning, QString comment, bool allSameFaceCount, bool allSameColor)
+ QString error, QString warning, QString comment, bool allSameFaceCount, bool allSameColor)
{
Q_UNUSED(withColor);
QString str("```Markdown\n");
@@ -165,7 +166,7 @@ void displayMarkdown(QString scalarText, QString resultStr, QJsonArray array, bo
out << str;
}
QString displaySVG(QString scalarText, QString resultStr, QJsonArray array, bool withColor, QString cmd, QString error,
- QString warning, QString comment, bool allSameFaceCount, bool allSameColor)
+ QString warning, QString comment, bool allSameFaceCount, bool allSameColor)
{
QString str(
"<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<svg version=\"1.1\" xmlns=\"http://www.w3.org/2000/svg\" "
@@ -222,16 +223,16 @@ QString displaySVG(QString scalarText, QString resultStr, QJsonArray array, bool
#ifdef PAINTER_OP
void displayImage(QString scalarText, QString resultStr, QJsonArray array, bool withColor, QString cmd, QString error,
- QString warning, QString comment, bool allSameFaceCount, bool allSameColor)
+ QString warning, QString comment, bool allSameFaceCount, bool allSameColor)
{
- auto svg= displaySVG(
- scalarText, resultStr, array, withColor, cmd, error, warning, comment, allSameFaceCount, allSameColor);
+ auto svg= displaySVG(scalarText, resultStr, array, withColor, cmd, error, warning, comment, allSameFaceCount,
+ allSameColor);
out << DisplayToolBox::makeImage(svg.toUtf8());
}
#endif
void displayCommandResult(QString scalarText, QString resultStr, QJsonArray array, bool withColor, QString cmd,
- QString error, QString warning, QString comment, bool allSameFaceCount, bool allSameColor)
+ QString error, QString warning, QString comment, bool allSameFaceCount, bool allSameColor)
{
// TODO display warning
if(!error.isEmpty())
@@ -366,11 +367,6 @@ int startDiceParsing(QStringList& cmds, QString& treeFile, bool withColor, EXPOR
stringResult.replace("\\n", "\n");
stringResult= ParsingToolBox::replaceVariableToValue(stringResult, strLst);
- /*for(auto it= strLst.rbegin(); it != strLst.rend(); ++it)
- {
- stringResult.replace(QStringLiteral("$%1").arg(i), (*it));
- --i;
- }*/
int i= strLst.size();
for(auto it= strLst.rbegin(); it != strLst.rend(); ++it)
@@ -405,26 +401,26 @@ int startDiceParsing(QStringList& cmds, QString& treeFile, bool withColor, EXPOR
{
case TERMINAL:
displayCommandResult(scalarText, resultStr, array, withColor, cmdRework, error, warnings, comment,
- allSameFaceCount, allSameColor);
+ allSameFaceCount, allSameColor);
break;
case SVG:
out << displaySVG(scalarText, resultStr, array, withColor, cmdRework, error, warnings, comment,
- allSameFaceCount, allSameColor)
+ allSameFaceCount, allSameColor)
<< "\n";
break;
case BOT:
case MARKDOWN:
displayMarkdown(scalarText, resultStr, array, withColor, cmdRework, error, warnings, comment,
- allSameFaceCount, allSameColor);
+ allSameFaceCount, allSameColor);
break;
case JSON:
displayJSon(scalarText, resultStr, array, withColor, cmdRework, error, warnings, comment,
- allSameFaceCount, allSameColor);
+ allSameFaceCount, allSameColor);
break;
#ifdef PAINTER_OP
case IMAGE:
displayImage(scalarText, resultStr, array, withColor, cmdRework, error, warnings, comment,
- allSameFaceCount, allSameColor);
+ allSameFaceCount, allSameColor);
break;
#endif
}
@@ -440,10 +436,12 @@ int startDiceParsing(QStringList& cmds, QString& treeFile, bool withColor, EXPOR
}
else
{
+ QString error= parser.humanReadableError();
+ err << "Error: " << error << "\n";
rt= 1;
}
}
-
+ parser.cleanAll();
return rt;
}
#include <QTextCodec>
@@ -466,38 +464,39 @@ int main(int argc, char* argv[])
QCommandLineParser optionParser;
QCommandLineOption color(QStringList() << "c"
<< "color-off",
- "Disable color to highlight result");
+ "Disable color to highlight result");
QCommandLineOption version(QStringList() << "v"
<< "version",
- "Show the version and quit.");
+ "Show the version and quit.");
QCommandLineOption reset(QStringList() << "reset-settings", "Erase the settings and use the default parameters");
QCommandLineOption alias(QStringList() << "a"
<< "alias",
- "path to alias json files: <aliasfile>", "aliasfile");
+ "path to alias json files: <aliasfile>", "aliasfile");
QCommandLineOption character(QStringList() << "s"
<< "charactersheet",
- "set Parameters to simulate character sheet: <sheetfile>", "sheetfile");
+ "set Parameters to simulate character sheet: <sheetfile>", "sheetfile");
QCommandLineOption markdown(QStringList() << "m"
<< "markdown",
- "The output is formatted in markdown.");
+ "The output is formatted in markdown.");
QCommandLineOption bot(QStringList() << "b"
<< "bot",
- "Discord bot.");
+ "Discord bot.");
QCommandLineOption svg(QStringList() << "g"
<< "svg",
- "The output is formatted in svg.");
+ "The output is formatted in svg.");
QCommandLineOption json(QStringList() << "j"
<< "json",
- "The output is formatted in json.");
+ "The output is formatted in json.");
QCommandLineOption dotFile(QStringList() << "d"
<< "dot-file",
- "Instead of rolling dice, generate the execution tree and write it in <dotfile>", "dotfile");
+ "Instead of rolling dice, generate the execution tree and write it in <dotfile>",
+ "dotfile");
QCommandLineOption translation(QStringList() << "t"
<< "translation",
- "path to the translation file: <translationfile>", "translationfile");
+ "path to the translation file: <translationfile>", "translationfile");
QCommandLineOption help(QStringList() << "h"
<< "help",
- "Display this help");
+ "Display this help");
optionParser.addOption(color);
optionParser.addOption(version);
diff --git a/compositevalidator.cpp b/compositevalidator.cpp
index 0715078..5116b16 100644
--- a/compositevalidator.cpp
+++ b/compositevalidator.cpp
@@ -21,22 +21,18 @@
***************************************************************************/
#include "compositevalidator.h"
-CompositeValidator::CompositeValidator() : m_operators(nullptr), m_validatorList(nullptr) {}
+CompositeValidator::CompositeValidator() {}
CompositeValidator::~CompositeValidator()
{
- qDeleteAll(*m_validatorList);
- if(nullptr != m_operators)
- {
- delete m_operators;
- }
+ qDeleteAll(m_validatorList);
}
qint64 CompositeValidator::hasValid(Die* b, bool recursive, bool unhighlight) const
{
int i= 0;
qint64 sum= 0;
bool highLight= false;
- for(auto& validator : *m_validatorList)
+ for(auto& validator : m_validatorList)
{
qint64 val= validator->hasValid(b, recursive, unhighlight);
if(i == 0)
@@ -49,7 +45,7 @@ qint64 CompositeValidator::hasValid(Die* b, bool recursive, bool unhighlight) co
}
else
{
- switch(m_operators->at(i - 1))
+ switch(m_operators.at(i - 1))
{
case OR:
sum|= val;
@@ -99,41 +95,98 @@ QString CompositeValidator::toString()
return QString("[%1%2]").arg(str).arg(m_value);*/
return str;
}
-bool CompositeValidator::isValidRangeSize(std::pair<qint64, qint64> range) const
+
+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)
{
- bool val= true;
- int i= -1;
- for(auto& tmp : *m_validatorList)
+ 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 CompositeValidator::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);
+
+ if((static_cast<int>(vec.size()) != m_operators.size() + 1) || (itError != vec.end()))
{
- bool rel= tmp->isValidRangeSize(range);
- val|= rel;
- ++i;
+ return Dice::CONDITION_STATE::ERROR;
}
+ std::size_t i= 0;
+ Dice::CONDITION_STATE val;
+ 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;
+ break;
+ }
+
+ ++i;
+ }
return val;
}
-void CompositeValidator::setOperationList(QVector<LogicOperation>* m)
+
+void CompositeValidator::setOperationList(const QVector<LogicOperation>& m)
{
m_operators= m;
}
-void CompositeValidator::setValidatorList(QList<Validator*>* m)
+void CompositeValidator::setValidatorList(const QList<Validator*>& valids)
{
- m_validatorList= m;
+ qDeleteAll(m_validatorList);
+ m_validatorList= valids;
}
Validator* CompositeValidator::getCopy() const
{
- QVector<LogicOperation>* vector= new QVector<LogicOperation>();
- *vector= *m_operators;
-
- QList<Validator*>* list= new QList<Validator*>();
- for(auto& val : *m_validatorList)
- {
- list->append(val->getCopy());
- }
-
CompositeValidator* val= new CompositeValidator();
- val->setOperationList(vector);
- val->setValidatorList(list);
+ val->setOperationList(m_operators);
+ val->setValidatorList(m_validatorList);
return val;
}
diff --git a/compositevalidator.h b/compositevalidator.h
index c49355d..2d7479d 100644
--- a/compositevalidator.h
+++ b/compositevalidator.h
@@ -43,22 +43,22 @@ public:
NONE
};
CompositeValidator();
- virtual ~CompositeValidator();
+ virtual ~CompositeValidator() override;
- virtual qint64 hasValid(Die* b, bool recursive, bool unhighlight= false) const;
+ virtual qint64 hasValid(Die* b, bool recursive, bool unhighlight= false) const override;
- void setOperationList(QVector<LogicOperation>* m);
- void setValidatorList(QList<Validator*>*);
+ void setOperationList(const QVector<LogicOperation>& m);
+ void setValidatorList(const QList<Validator*>& valids);
- QString toString();
+ QString toString() override;
- virtual bool isValidRangeSize(std::pair<qint64, qint64> range) const;
+ virtual Dice::CONDITION_STATE isValidRangeSize(const std::pair<qint64, qint64>& range) const override;
- virtual Validator* getCopy() const;
+ virtual Validator* getCopy() const override;
private:
- QVector<LogicOperation>* m_operators;
- QList<Validator*>* m_validatorList;
+ QVector<LogicOperation> m_operators;
+ QList<Validator*> m_validatorList;
};
#endif // BOOLEANCONDITION_H
diff --git a/diceparser.cpp b/diceparser.cpp
index 4ec44ef..ea8f251 100644
--- a/diceparser.cpp
+++ b/diceparser.cpp
@@ -29,6 +29,7 @@
#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"
@@ -164,11 +165,7 @@ bool DiceParser::parseLine(QString str, bool allowAlias)
{
m_errorMap.clear();
m_comment= QString("");
- if(!m_startNodes.empty())
- {
- qDeleteAll(m_startNodes);
- m_startNodes.clear();
- }
+ cleanAll();
m_currentTreeHasSeparator= false;
if(allowAlias)
{
@@ -180,7 +177,7 @@ bool DiceParser::parseLine(QString str, bool allowAlias)
if(!hasInstruction)
{
m_errorMap.insert(
- ExecutionNode::NOTHING_UNDERSTOOD,
+ 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/"
@@ -190,7 +187,7 @@ bool DiceParser::parseLine(QString str, bool allowAlias)
{
auto i= m_command.size() - str.size();
m_warningMap.insert(
- ExecutionNode::UNEXPECTED_CHARACTER,
+ 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())
@@ -226,7 +223,7 @@ bool DiceParser::readExpression(QString& str, ExecutionNode*& node)
}
else
{
- m_warningMap.insert(ExecutionNode::BAD_SYNTAXE,
+ m_warningMap.insert(Dice::ERROR_CODE::BAD_SYNTAXE,
QObject::tr("Expected closing parenthesis - can't validate the inside."));
}
}
@@ -373,6 +370,15 @@ bool DiceParser::readNode(QString& str, ExecutionNode*& node)
return false;
}
+void DiceParser::cleanAll()
+{
+ if(!m_startNodes.empty())
+ {
+ qDeleteAll(m_startNodes);
+ m_startNodes.clear();
+ }
+}
+
void DiceParser::start()
{
for(auto start : m_startNodes)
@@ -392,11 +398,11 @@ QList<qreal> DiceParser::getLastIntegerResults()
bool scalarDone= false;
while((result != nullptr) && (!scalarDone))
{
- if(result->hasResultOfType(Result::SCALAR))
+ if(result->hasResultOfType(Dice::RESULT_TYPE::SCALAR))
{
if(!alreadyVisitedNode.contains(result->getId()))
{
- resultValues << result->getResult(Result::SCALAR).toReal();
+ resultValues << result->getResult(Dice::RESULT_TYPE::SCALAR).toReal();
alreadyVisitedNode << result->getId();
}
scalarDone= true;
@@ -417,9 +423,9 @@ QStringList DiceParser::getStringResult()
bool found= false;
while((nullptr != result) && (!found))
{
- if(result->hasResultOfType(Result::STRING))
+ if(result->hasResultOfType(Dice::RESULT_TYPE::STRING))
{
- str= result->getResult(Result::STRING).toString();
+ str= result->getResult(Dice::RESULT_TYPE::STRING).toString();
found= true;
}
result= result->getPrevious();
@@ -440,7 +446,7 @@ QStringList DiceParser::getAllStringResult(bool& hasAlias)
while(nullptr != result)
{
- if(result->hasResultOfType(Result::STRING))
+ if(result->hasResultOfType(Dice::RESULT_TYPE::STRING))
{
StringResult* stringResult= dynamic_cast<StringResult*>(result);
if(nullptr != stringResult)
@@ -465,7 +471,7 @@ QStringList DiceParser::getAllDiceResult(bool& hasAlias)
while(nullptr != result)
{
- if(result->hasResultOfType(Result::DICE_LIST))
+ if(result->hasResultOfType(Dice::RESULT_TYPE::DICE_LIST))
{
DiceResult* stringResult= dynamic_cast<DiceResult*>(result);
if(nullptr != stringResult)
@@ -508,7 +514,7 @@ void DiceParser::getDiceResultFromAllInstruction(QList<ExportedDiceResult>& resu
ExportedDiceResult nodeResult;
while(nullptr != result)
{
- if(result->hasResultOfType(Result::DICE_LIST))
+ if(result->hasResultOfType(Dice::RESULT_TYPE::DICE_LIST))
{
DiceResult* diceResult= dynamic_cast<DiceResult*>(result);
QList<HighLightDice> list;
@@ -540,7 +546,7 @@ void DiceParser::getLastDiceResult(QList<ExportedDiceResult>& diceValuesList, bo
Result* result= next->getResult();
while(nullptr != result)
{
- if(result->hasResultOfType(Result::DICE_LIST))
+ if(result->hasResultOfType(Dice::RESULT_TYPE::DICE_LIST))
{
DiceResult* diceResult= dynamic_cast<DiceResult*>(result);
if(nullptr != diceResult)
@@ -604,7 +610,7 @@ bool DiceParser::hasIntegerResultNotInFirst()
bool result= false;
for(auto node : m_startNodes)
{
- result|= hasResultOfType(Result::SCALAR, node);
+ result|= hasResultOfType(Dice::RESULT_TYPE::SCALAR, node);
}
return result;
}
@@ -614,7 +620,7 @@ bool DiceParser::hasDiceResult()
bool result= false;
for(auto node : m_startNodes)
{
- result|= hasResultOfType(Result::DICE_LIST, node);
+ result|= hasResultOfType(Dice::RESULT_TYPE::DICE_LIST, node);
}
return result;
}
@@ -623,18 +629,22 @@ bool DiceParser::hasStringResult()
bool result= false;
for(auto node : m_startNodes)
{
- result|= hasResultOfType(Result::STRING, node);
+ result|= hasResultOfType(Dice::RESULT_TYPE::STRING, node);
}
return result;
}
-bool DiceParser::hasResultOfType(Result::RESULT_TYPE type, ExecutionNode* node, bool notthelast)
+bool DiceParser::hasResultOfType(Dice::RESULT_TYPE type, ExecutionNode* node, bool notthelast)
{
bool scalarDone= false;
ExecutionNode* next= getLeafNode(node);
Result* result= next->getResult();
while((result != nullptr) && (!scalarDone))
{
- if(result->hasResultOfType(type) && ((!notthelast) || (nullptr != result->getPrevious())))
+ bool lastResult= false;
+ if(notthelast)
+ lastResult= (nullptr != result->getPrevious());
+
+ if(result->hasResultOfType(type) && !lastResult)
{
scalarDone= true;
}
@@ -653,7 +663,7 @@ QList<qreal> DiceParser::getSumOfDiceResult()
bool found= false;
while((nullptr != result) && (!found))
{
- if(result->hasResultOfType(Result::DICE_LIST))
+ if(result->hasResultOfType(Dice::RESULT_TYPE::DICE_LIST))
{
DiceResult* myDiceResult= dynamic_cast<DiceResult*>(result);
if(nullptr != myDiceResult)
@@ -704,7 +714,7 @@ bool DiceParser::readDice(QString& str, ExecutionNode*& node)
if(max < 1)
{
m_errorMap.insert(
- ExecutionNode::BAD_SYNTAXE,
+ 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;
}
@@ -759,7 +769,7 @@ bool DiceParser::readDice(QString& str, ExecutionNode*& node)
else
{
m_errorMap.insert(
- ExecutionNode::BAD_SYNTAXE,
+ Dice::ERROR_CODE::BAD_SYNTAXE,
QObject::tr(
"List is missing after the L operator. Please, add it (e.g : 1L[sword,spear,gun,arrow])"));
}
@@ -1087,7 +1097,7 @@ bool DiceParser::readOption(QString& str, ExecutionNode* previous) //,
}
else
{
- m_errorMap.insert(ExecutionNode::BAD_SYNTAXE,
+ m_errorMap.insert(Dice::ERROR_CODE::BAD_SYNTAXE,
QObject::tr("Validator is missing after the c operator. Please, change it"));
}
}
@@ -1098,14 +1108,33 @@ bool DiceParser::readOption(QString& str, ExecutionNode* previous) //,
// 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)
{
- if(!m_parsingToolbox->isValidValidator(previous, validator))
+ switch(m_parsingToolbox->isValidValidator(previous, validator))
{
- m_errorMap.insert(
- ExecutionNode::BAD_SYNTAXE,
- QObject::tr("Validator is missing after the %1 operator. Please, change it")
- .arg(operatorName == Reroll ? "r" : "a"));
+ case Dice::CONDITION_STATE::ALWAYSTRUE:
+ if(operatorName == RerollAndAdd)
+ {
+ m_errorMap.insert(
+ Dice::ERROR_CODE::ENDLESS_LOOP_ERROR,
+ QObject::tr(
+ "Validator is always true missing after 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("Candition can be reached, causing endless loop. Please, "
+ "change the %1 option condition")
+ .arg(symbol));
+ }
+ break;
+ case Dice::CONDITION_STATE::ERROR:
+ default:
+ break;
}
auto reroll= (operatorName == RerollAndAdd || operatorName == Reroll);
@@ -1123,13 +1152,9 @@ bool DiceParser::readOption(QString& str, ExecutionNode* previous) //,
}
else
{
- m_errorMap.insert(ExecutionNode::BAD_SYNTAXE,
- QObject::tr("Validator is missing after the %1 operator. Please, change it")
- .arg(operatorName == Reroll ?
- QStringLiteral("r") :
- operatorName == RerollUntil ?
- QStringLiteral("R") :
- operatorName == RerollAndAdd ? QStringLiteral("a") : ""));
+ m_errorMap.insert(
+ Dice::ERROR_CODE::BAD_SYNTAXE,
+ QObject::tr("Validator is missing after the %1 operator. Please, change it").arg(symbol));
}
}
break;
@@ -1138,9 +1163,9 @@ bool DiceParser::readOption(QString& str, ExecutionNode* previous) //,
Validator* validator= m_parsingToolbox->readCompositeValidator(str);
if(nullptr != validator)
{
- if(!m_parsingToolbox->isValidValidator(previous, validator))
+ if(Dice::CONDITION_STATE::ALWAYSTRUE == m_parsingToolbox->isValidValidator(previous, validator))
{
- m_errorMap.insert(ExecutionNode::ENDLESS_LOOP_ERROR,
+ m_errorMap.insert(Dice::ERROR_CODE::ENDLESS_LOOP_ERROR,
QObject::tr("This condition %1 introduces an endless loop. Please, change it")
.arg(validator->toString()));
}
@@ -1152,7 +1177,7 @@ bool DiceParser::readOption(QString& str, ExecutionNode* previous) //,
}
else
{
- m_errorMap.insert(ExecutionNode::BAD_SYNTAXE,
+ m_errorMap.insert(Dice::ERROR_CODE::BAD_SYNTAXE,
QObject::tr("Validator is missing after the e operator. Please, change it"));
}
}
@@ -1210,10 +1235,18 @@ bool DiceParser::readOption(QString& str, ExecutionNode* previous) //,
case Painter:
{
PainterNode* painter= new PainterNode();
- m_parsingToolbox->readPainterParameter(painter, str);
- previous->setNextNode(painter);
- node= painter;
- found= true;
+ 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:
@@ -1345,9 +1378,9 @@ void DiceParser::setComment(const QString& comment)
m_comment= comment;
}
-QMap<ExecutionNode::DICE_ERROR_CODE, QString> DiceParser::getErrorMap()
+QMap<Dice::ERROR_CODE, QString> DiceParser::getErrorMap()
{
- QMap<ExecutionNode::DICE_ERROR_CODE, QString> map;
+ QMap<Dice::ERROR_CODE, QString> map;
for(auto start : m_startNodes)
{
@@ -1362,7 +1395,7 @@ QMap<ExecutionNode::DICE_ERROR_CODE, QString> DiceParser::getErrorMap()
}
QString DiceParser::humanReadableError()
{
- QMapIterator<ExecutionNode::DICE_ERROR_CODE, QString> i(m_errorMap);
+ QMapIterator<Dice::ERROR_CODE, QString> i(m_errorMap);
QString str("");
while(i.hasNext())
{
@@ -1372,7 +1405,7 @@ QString DiceParser::humanReadableError()
}
/// list
- QMapIterator<ExecutionNode::DICE_ERROR_CODE, QString> j(getErrorMap());
+ QMapIterator<Dice::ERROR_CODE, QString> j(getErrorMap());
while(j.hasNext())
{
j.next();
@@ -1384,7 +1417,7 @@ QString DiceParser::humanReadableError()
QString DiceParser::humanReadableWarning()
{
- QMapIterator<ExecutionNode::DICE_ERROR_CODE, QString> i(m_warningMap);
+ QMapIterator<Dice::ERROR_CODE, QString> i(m_warningMap);
QString str("");
while(i.hasNext())
{
diff --git a/diceparser.pc.in b/diceparser.pc.in
new file mode 100644
index 0000000..61b5aea
--- /dev/null
+++ b/diceparser.pc.in
@@ -0,0 +1,12 @@
+prefix=@CMAKE_INSTALL_PREFIX@
+exec_prefix=@CMAKE_INSTALL_PREFIX@
+libdir=${exec_prefix}/@CMAKE_INSTALL_LIBDIR@
+includedir=${prefix}/@CMAKE_INSTALL_INCLUDEDIR@
+
+Name: @PROJECT_NAME@
+Description: @PROJECT_DESCRIPTION@
+Version: @PROJECT_VERSION@
+
+Requires:
+Libs: -L${libdir} -ldiceparser
+Cflags: -I${includedir}
diff --git a/die.cpp b/die.cpp
index 2d2ff91..531853c 100644
--- a/die.cpp
+++ b/die.cpp
@@ -35,7 +35,7 @@ Die::Die()
, m_op(Die::PLUS) //,m_mt(m_randomDevice)
{
auto seed= std::chrono::high_resolution_clock::now().time_since_epoch().count();
- m_rng= std::mt19937(quintptr(this) + seed);
+ m_rng= std::mt19937(quintptr(this) + static_cast<unsigned long long>(seed));
}
Die::Die(const Die& die)
{
@@ -49,6 +49,8 @@ Die::Die(const Die& die)
m_base= die.m_base;
m_color= die.getColor();
m_op= die.getOp();
+ auto seed= std::chrono::high_resolution_clock::now().time_since_epoch().count();
+ m_rng= std::mt19937(quintptr(this) + static_cast<unsigned long long>(seed));
}
void Die::setValue(qint64 r)
diff --git a/die.h b/die.h
index f544808..eb43521 100644
--- a/die.h
+++ b/die.h
@@ -151,8 +151,8 @@ private:
bool m_hasValue= false;
bool m_displayStatus= false;
bool m_highlighted= true;
- qint64 m_maxValue;
- qint64 m_base;
+ qint64 m_maxValue= 0;
+ qint64 m_base= 0;
QString m_color;
Die::ArithmeticOperator m_op;
diff --git a/highlightdice.cpp b/highlightdice.cpp
index 02941d5..c2abdb6 100644
--- a/highlightdice.cpp
+++ b/highlightdice.cpp
@@ -17,7 +17,7 @@
* Free Software Foundation, Inc., *
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
***************************************************************************/
-#include "highlightdice.h"
+#include "include/highlightdice.h"
HighLightDice::HighLightDice(QList<qint64> result, bool isHighlighted, QString color, bool displayed, quint64 faces)
: m_result(result), m_hasHighlight(isHighlighted), m_color(color), m_displayed(displayed), m_faces(faces)
diff --git a/dicealias.h b/include/dicealias.h
index 463a654..463a654 100644
--- a/dicealias.h
+++ b/include/dicealias.h
diff --git a/diceparser.h b/include/diceparser.h
index 8ecfb50..32694a3 100644
--- a/diceparser.h
+++ b/include/diceparser.h
@@ -24,10 +24,11 @@
#include <QMap>
#include <QString>
+#include <vector>
-#include "dicealias.h"
#include "highlightdice.h"
-#include "node/executionnode.h"
+#include "diceparserhelper.h"
+//#include "node/executionnode.h"
typedef QList<HighLightDice> ListDiceResult;
typedef QMap<quint64, ListDiceResult> ExportedDiceResult;
@@ -35,6 +36,8 @@ typedef QMap<quint64, ListDiceResult> ExportedDiceResult;
class ExplodeDiceNode;
class ParsingToolBox;
class DiceRollerNode;
+class DiceAlias;
+class ExecutionNode;
/**
* @page DiceParser Dice Parser
*
@@ -123,18 +126,6 @@ public:
*
*/
void start();
-
- /**
- * @brief displayResult
- */
- QString displayResult();
- /**
- * @brief readExpression
- * @param str
- * @param node
- * @return
- */
- bool readExpression(QString& str, ExecutionNode*& node);
/**
* @brief displayDotTree - Write the execution tree into file using dot format.
* @param filepath absolute or relative path to the tree file.
@@ -204,7 +195,7 @@ public:
* @brief getErrorList
* @return
*/
- QMap<ExecutionNode::DICE_ERROR_CODE, QString> getErrorMap();
+ QMap<Dice::ERROR_CODE, QString> getErrorMap();
/**
* @brief setPathToHelp set the path to the documentation, this path must be adatped to the lang of application etc…
* @param l the path.
@@ -226,15 +217,7 @@ public:
* @return true when the command has separator, false otherwise.
*/
bool hasSeparator() const;
- /**
- * @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);
+
/**
* @brief setVariableDictionary
* @param variables
@@ -243,20 +226,33 @@ public:
QString getComment() const;
void setComment(const QString& comment);
- bool readOptionFromNull(QString& str, ExecutionNode*& node);
- bool readOperatorFromNull(QString& str, ExecutionNode*& node);
-
- bool readInstructionList(QString& str);
void getDiceResultFromAllInstruction(QList<ExportedDiceResult>& resultList);
QString humanReadableWarning();
bool readValuesList(QString& str, ExecutionNode*& node);
-
-protected:
- bool readParameterNode(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
@@ -336,7 +332,8 @@ private:
* @param notthelast
* @return
*/
- bool hasResultOfType(Result::RESULT_TYPE, ExecutionNode* node, bool notthelast= false);
+ bool hasResultOfType(Dice::RESULT_TYPE, ExecutionNode* node, bool notthelast= false);
+ bool readBlocInstruction(QString& str, ExecutionNode*& resultnode);
private:
QMap<QString, DiceOperator>* m_mapDiceOp;
@@ -345,17 +342,15 @@ private:
QList<DiceAlias*>* m_aliasList;
QStringList* m_commandList;
- QMap<ExecutionNode::DICE_ERROR_CODE, QString> m_errorMap;
- QMap<ExecutionNode::DICE_ERROR_CODE, QString> m_warningMap;
+ QMap<Dice::ERROR_CODE, QString> m_errorMap;
+ QMap<Dice::ERROR_CODE, QString> m_warningMap;
ExecutionNode* m_start= nullptr;
std::vector<ExecutionNode*> m_startNodes;
- // ExecutionNode* m_current;
QString m_command;
ParsingToolBox* m_parsingToolbox;
QString m_helpPath;
bool m_currentTreeHasSeparator;
- bool readBlocInstruction(QString& str, ExecutionNode*& resultnode);
QString m_comment;
};
diff --git a/include/diceparserhelper.h b/include/diceparserhelper.h
new file mode 100644
index 0000000..00b9362
--- /dev/null
+++ b/include/diceparserhelper.h
@@ -0,0 +1,43 @@
+#ifndef DICEPARSERHELPER_H
+#define DICEPARSERHELPER_H
+
+namespace Dice
+{
+
+enum class CONDITION_STATE : int
+{
+ ERROR,
+ ALWAYSTRUE,
+ UNREACHABLE,
+ REACHABLE
+};
+
+enum class ERROR_CODE : int
+{
+ NO_DICE_ERROR,
+ DIE_RESULT_EXPECTED,
+ BAD_SYNTAXE,
+ ENDLESS_LOOP_ERROR,
+ DIVIDE_BY_ZERO,
+ NOTHING_UNDERSTOOD,
+ NO_DICE_TO_ROLL,
+ TOO_MANY_DICE,
+ NO_VARIBALE,
+ INVALID_INDEX,
+ UNEXPECTED_CHARACTER,
+ NO_PREVIOUS_ERROR,
+ NO_VALID_RESULT
+};
+
+/**
+ * @brief The RESULT_TYPE enum or combinaison
+ */
+enum class RESULT_TYPE : int
+{
+ NONE= 0,
+ SCALAR= 1,
+ STRING= 2,
+ DICE_LIST= 4
+};
+}
+#endif // DICEPARSERHELPER_H
diff --git a/highlightdice.h b/include/highlightdice.h
index 2e8f08a..2e8f08a 100644
--- a/highlightdice.h
+++ b/include/highlightdice.h
diff --git a/parsingtoolbox.h b/include/parsingtoolbox.h
index b91db1a..8d5f62b 100644
--- a/parsingtoolbox.h
+++ b/include/parsingtoolbox.h
@@ -175,7 +175,7 @@ public:
* @param val
* @return
*/
- bool isValidValidator(ExecutionNode* previous, Validator* val);
+ Dice::CONDITION_STATE isValidValidator(ExecutionNode* previous, Validator* val);
/**
* @brief getDiceRollerNode
* @param previous
@@ -206,7 +206,7 @@ public:
bool readArithmeticOperator(QString& str, Die::ArithmeticOperator& op);
- static void readPainterParameter(PainterNode* painter, QString& str);
+ static bool readPainterParameter(PainterNode* painter, QString& str);
static QHash<QString, QString> getVariableHash();
static void setVariableHash(const QHash<QString, QString>& variableHash);
diff --git a/node/countexecutenode.cpp b/node/countexecutenode.cpp
index bc8e3b3..763a320 100644
--- a/node/countexecutenode.cpp
+++ b/node/countexecutenode.cpp
@@ -34,7 +34,7 @@ void CountExecuteNode::run(ExecutionNode* previous)
{
if(nullptr != m_validator)
{
- sum+= m_validator->hasValid(dice, true, true);
+ sum+= m_validator->hasValid(dice, true, true) ? 1 : 0;
}
}
m_scalarResult->setValue(sum);
diff --git a/node/dicerollernode.cpp b/node/dicerollernode.cpp
index f57d3e3..f87908f 100644
--- a/node/dicerollernode.cpp
+++ b/node/dicerollernode.cpp
@@ -19,10 +19,10 @@ void DiceRollerNode::run(ExecutionNode* previous)
Result* result= previous->getResult();
if(nullptr != result)
{
- auto num= result->getResult(Result::SCALAR).toReal();
+ auto num= result->getResult(Dice::RESULT_TYPE::SCALAR).toReal();
if(num <= 0)
{
- m_errors.insert(NO_DICE_TO_ROLL, QObject::tr("No dice to roll"));
+ m_errors.insert(Dice::ERROR_CODE::NO_DICE_TO_ROLL, QObject::tr("No dice to roll"));
}
m_diceCount= num > 0 ? static_cast<quint64>(num) : 0;
m_result->setPrevious(result);
@@ -30,7 +30,7 @@ void DiceRollerNode::run(ExecutionNode* previous)
auto possibleValue= static_cast<quint64>(std::abs((m_max - m_min) + 1));
if(possibleValue < m_diceCount && m_unique)
{
- m_errors.insert(TOO_MANY_DICE,
+ m_errors.insert(Dice::ERROR_CODE::TOO_MANY_DICE,
QObject::tr("More unique values asked than possible values (D operator)"));
return;
}
@@ -62,7 +62,7 @@ void DiceRollerNode::run(ExecutionNode* previous)
quint64 DiceRollerNode::getFaces() const
{
- return std::abs(m_max - m_min) + 1;
+ return static_cast<quint64>(std::abs(m_max - m_min) + 1);
}
std::pair<qint64, qint64> DiceRollerNode::getRange() const
diff --git a/node/executionnode.cpp b/node/executionnode.cpp
index 5bee091..4545934 100644
--- a/node/executionnode.cpp
+++ b/node/executionnode.cpp
@@ -6,7 +6,7 @@ ExecutionNode::ExecutionNode()
: m_previousNode(nullptr)
, m_result(nullptr)
, m_nextNode(nullptr)
- , m_errors(QMap<ExecutionNode::DICE_ERROR_CODE, QString>())
+ , m_errors(QMap<Dice::ERROR_CODE, QString>())
, m_id(QString("\"%1\"").arg(QUuid::createUuid().toString()))
{
}
@@ -40,7 +40,7 @@ ExecutionNode* ExecutionNode::getNextNode()
{
return m_nextNode;
}
-QMap<ExecutionNode::DICE_ERROR_CODE, QString> ExecutionNode::getExecutionErrorMap()
+QMap<Dice::ERROR_CODE, QString> ExecutionNode::getExecutionErrorMap()
{
if(nullptr != m_nextNode)
{
@@ -97,5 +97,5 @@ qint64 ExecutionNode::getScalarResult()
{
if(m_result == nullptr)
return 0;
- return m_result->getResult(Result::SCALAR).toInt();
+ return m_result->getResult(Dice::RESULT_TYPE::SCALAR).toInt();
}
diff --git a/node/executionnode.h b/node/executionnode.h
index e8eca1f..6321c83 100644
--- a/node/executionnode.h
+++ b/node/executionnode.h
@@ -1,8 +1,8 @@
#ifndef EXECUTIONNODE_H
#define EXECUTIONNODE_H
+#include "diceparserhelper.h"
#include "result/result.h"
-#include <QDebug>
/**
* @brief The ExecutionNode class
@@ -10,21 +10,6 @@
class ExecutionNode
{
public:
- enum DICE_ERROR_CODE
- {
- NO_DICE_ERROR,
- DIE_RESULT_EXPECTED,
- BAD_SYNTAXE,
- ENDLESS_LOOP_ERROR,
- DIVIDE_BY_ZERO,
- NOTHING_UNDERSTOOD,
- NO_DICE_TO_ROLL,
- TOO_MANY_DICE,
- NO_VARIBALE,
- INVALID_INDEX,
- UNEXPECTED_CHARACTER,
- NO_PREVIOUS_ERROR
- };
/**
* @brief ExecutionNode
*/
@@ -72,7 +57,7 @@ public:
* @brief getErrorList
* @return
*/
- virtual QMap<ExecutionNode::DICE_ERROR_CODE, QString> getExecutionErrorMap();
+ virtual QMap<Dice::ERROR_CODE, QString> getExecutionErrorMap();
/**
* @brief generateDotTree
@@ -101,7 +86,7 @@ protected:
/**
* @brief m_result
*/
- Result* m_result;
+ Result* m_result= nullptr;
/**
* @brief m_nextNode
*/
@@ -109,7 +94,7 @@ protected:
/**
* @brief m_errors
*/
- QMap<ExecutionNode::DICE_ERROR_CODE, QString> m_errors;
+ QMap<Dice::ERROR_CODE, QString> m_errors;
QString m_id;
};
diff --git a/node/explodedicenode.cpp b/node/explodedicenode.cpp
index 704ac8a..2292a05 100644
--- a/node/explodedicenode.cpp
+++ b/node/explodedicenode.cpp
@@ -16,7 +16,6 @@ void ExplodeDiceNode::run(ExecutionNode* previous)
for(auto& die : previous_result->getResultList())
{
Die* tmpdie= new Die(*die);
-// *tmpdie= *die;
m_diceResult->insertResult(tmpdie);
die->displayed();
}
@@ -25,12 +24,23 @@ void ExplodeDiceNode::run(ExecutionNode* previous)
for(auto& die : list)
{
+ if(Dice::CONDITION_STATE::ALWAYSTRUE
+ == m_validator->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")
+ .arg(toString(true))
+ .arg(QStringLiteral("d[%1,%2]")
+ .arg(static_cast<int>(die->getBase()))
+ .arg(static_cast<int>(die->getMaxValue()))));
+ continue;
+ }
+
while(m_validator->hasValid(die, false))
{
die->roll(true);
}
}
- // m_diceResult->setResultList(list);
if(nullptr != m_nextNode)
{
diff --git a/node/forloopnode.cpp b/node/forloopnode.cpp
index f65a389..aba6ff4 100644
--- a/node/forloopnode.cpp
+++ b/node/forloopnode.cpp
@@ -58,7 +58,7 @@ void ForLoopNode::run(ExecutionNode* previous)
tmp= tmp->getNextNode();
}
Result* internalResult= tmp->getResult();
- auto value= internalResult->getResult(Result::SCALAR).toInt();
+ auto value= internalResult->getResult(Dice::RESULT_TYPE::SCALAR).toInt();
Die* neodie= new Die();
*neodie= *dice;
diff --git a/node/ifnode.cpp b/node/ifnode.cpp
index 5470e15..f0f28aa 100644
--- a/node/ifnode.cpp
+++ b/node/ifnode.cpp
@@ -41,11 +41,11 @@ void IfNode::run(ExecutionNode* previous)
ExecutionNode* nextNode= nullptr;
bool runNext= (nullptr == m_nextNode) ? false : true;
Result* previousResult= previous->getResult();
- m_result= previousResult;
+ m_result= previousResult->getCopy();
if(nullptr != m_result)
{
- qreal value= previousResult->getResult(Result::SCALAR).toReal();
+ qreal value= previousResult->getResult(Dice::RESULT_TYPE::SCALAR).toReal();
if(nullptr != m_validator)
{
diff --git a/node/jumpbackwardnode.cpp b/node/jumpbackwardnode.cpp
index 15c7063..2870854 100644
--- a/node/jumpbackwardnode.cpp
+++ b/node/jumpbackwardnode.cpp
@@ -96,7 +96,7 @@ void JumpBackwardNode::run(ExecutionNode* previous)
if(nullptr != result)
{
//--i;
- if(/*(i==0)&&*/ (result->hasResultOfType(Result::DICE_LIST)))
+ if(/*(i==0)&&*/ (result->hasResultOfType(Dice::RESULT_TYPE::DICE_LIST)))
{
found= true;
m_backwardNode= parent;
@@ -118,7 +118,8 @@ void JumpBackwardNode::run(ExecutionNode* previous)
}
if(nullptr == result)
{
- m_errors.insert(DIE_RESULT_EXPECTED,
+ m_errors.insert(
+ Dice::ERROR_CODE::DIE_RESULT_EXPECTED,
QObject::tr(" The @ operator expects dice result. Please check the documentation to fix your command."));
}
else
diff --git a/node/keepdiceexecnode.cpp b/node/keepdiceexecnode.cpp
index 42b4c40..688c27b 100644
--- a/node/keepdiceexecnode.cpp
+++ b/node/keepdiceexecnode.cpp
@@ -58,9 +58,10 @@ void KeepDiceExecNode::run(ExecutionNode* previous)
if(m_numberOfDice > static_cast<qint64>(diceList.size()))
{
- m_errors.insert(TOO_MANY_DICE, QObject::tr(" You ask to keep %1 dice but the result only has %2")
- .arg(m_numberOfDice)
- .arg(diceList.size()));
+ m_errors.insert(Dice::ERROR_CODE::TOO_MANY_DICE,
+ QObject::tr(" You ask to keep %1 dice but the result only has %2")
+ .arg(m_numberOfDice)
+ .arg(diceList.size()));
}
for(auto& tmp : diceList.mid(static_cast<int>(m_numberOfDice), -1))
diff --git a/node/listsetrollnode.cpp b/node/listsetrollnode.cpp
index ffa0f03..565a609 100644
--- a/node/listsetrollnode.cpp
+++ b/node/listsetrollnode.cpp
@@ -62,11 +62,11 @@ void ListSetRollNode::run(ExecutionNode* previous)
Result* result= previous->getResult();
if(nullptr != result)
{
- quint64 diceCount= result->getResult(Result::SCALAR).toReal();
+ quint64 diceCount= result->getResult(Dice::RESULT_TYPE::SCALAR).toReal();
if(diceCount > static_cast<quint64>(m_values.size()) && m_unique)
{
- m_errors.insert(
- TOO_MANY_DICE, QObject::tr("More unique values asked than possible values (L operator)"));
+ m_errors.insert(Dice::ERROR_CODE::TOO_MANY_DICE,
+ QObject::tr("More unique values asked than possible values (L operator)"));
}
else
{
diff --git a/node/mergenode.cpp b/node/mergenode.cpp
index 4a11a76..15f2fa7 100644
--- a/node/mergenode.cpp
+++ b/node/mergenode.cpp
@@ -29,7 +29,7 @@ void MergeNode::run(ExecutionNode* previous)
{
if(nullptr == previous)
{
- m_errors.insert(ExecutionNode::NO_PREVIOUS_ERROR, QObject::tr("No previous node before Merge operator"));
+ m_errors.insert(Dice::ERROR_CODE::NO_PREVIOUS_ERROR, QObject::tr("No previous node before Merge operator"));
return;
}
@@ -40,46 +40,46 @@ 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;
+
+ startResult->setPrevious(previousLast->getResult());
+ previousLast->setNextNode(start);
+
+ previousLast= last;
+ Result* tmpResult= last->getResult();
+ while(nullptr != tmpResult)
{
- if(nullptr != previousLast)
+ DiceResult* dice= dynamic_cast<DiceResult*>(tmpResult);
+ if(nullptr == dice)
{
- auto startResult= start->getResult();
- 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)
+ ///@todo TODO improve here to set homogeneous while is really
+ m_diceResult->setHomogeneous(false);
+ for(auto& die : dice->getResultList())
{
- ///@todo TODO improve here to set homogeneous while is really
- m_diceResult->setHomogeneous(false);
- for(auto& die : dice->getResultList())
+ if(!m_diceResult->getResultList().contains(die) && (!die->hasBeenDisplayed()))
{
- if(!m_diceResult->getResultList().contains(die) && (!die->hasBeenDisplayed()))
- {
- Die* tmpdie= new Die(*die);
- //*tmpdie= *die;
- die->displayed();
- m_diceResult->getResultList().append(tmpdie);
- }
+ Die* tmpdie= new Die(*die);
+ die->displayed();
+ m_diceResult->getResultList().append(tmpdie);
}
}
- auto it= std::find_if(pastResult.begin(), pastResult.end(),
- [tmpResult](const Result* a) { return (a == tmpResult->getPrevious()); });
- if(it == pastResult.end())
- {
- pastResult.push_back(previousLast->getResult());
- tmpResult= tmpResult->getPrevious();
- }
- else
- {
- tmpResult->setPrevious(nullptr);
- tmpResult= nullptr;
- }
+ }
+ auto it= std::find_if(pastResult.begin(), pastResult.end(),
+ [tmpResult](const Result* a) { return (a == tmpResult->getPrevious()); });
+ if(it == pastResult.end())
+ {
+ pastResult.push_back(previousLast->getResult());
+ tmpResult= tmpResult->getPrevious();
+ }
+ else
+ {
+ tmpResult->setPrevious(nullptr);
+ tmpResult= nullptr;
}
}
}
diff --git a/node/occurencecountnode.cpp b/node/occurencecountnode.cpp
index e0117ef..0d69d2a 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 <QVector>
OccurenceCountNode::OccurenceCountNode() : ExecutionNode() {}
diff --git a/node/paintnode.cpp b/node/paintnode.cpp
index 02c7230..0cd4e10 100644
--- a/node/paintnode.cpp
+++ b/node/paintnode.cpp
@@ -47,7 +47,6 @@ void ColorItem::setColor(const QString& color)
PainterNode::PainterNode() : ExecutionNode()
{
- m_result= nullptr;
m_nextNode= nullptr;
}
@@ -61,15 +60,17 @@ void PainterNode::run(ExecutionNode* previous)
m_previousNode= previous;
if(nullptr == previous)
{
- m_errors.insert(ExecutionNode::NO_PREVIOUS_ERROR, QObject::tr("No previous node before Paint operator"));
+ m_errors.insert(Dice::ERROR_CODE::NO_PREVIOUS_ERROR, QObject::tr("No previous node before Paint operator"));
return;
}
Result* previousResult= previous->getResult();
- // m_result = previousResult;
- DiceResult* previousDiceResult= dynamic_cast<DiceResult*>(previousResult);
- if(nullptr != previousDiceResult)
+ if(nullptr == previousResult)
+ return;
+
+ m_diceResult= dynamic_cast<DiceResult*>(previousResult->getCopy());
+ if(nullptr != m_diceResult)
{
- QList<Die*> diceList= previousDiceResult->getResultList();
+ QList<Die*> diceList= m_diceResult->getResultList();
int pastDice= 0;
for(ColorItem& item : m_colors)
{
@@ -90,7 +91,7 @@ void PainterNode::run(ExecutionNode* previous)
}
Result* PainterNode::getResult()
{
- return (nullptr != m_previousNode) ? m_previousNode->getResult() : nullptr;
+ return m_diceResult;
}
QString PainterNode::toString(bool wl) const
diff --git a/node/paintnode.h b/node/paintnode.h
index 2675285..2283f83 100644
--- a/node/paintnode.h
+++ b/node/paintnode.h
@@ -55,6 +55,7 @@ public:
protected:
QList<ColorItem> m_colors;
+ DiceResult* m_diceResult= nullptr;
};
#endif
diff --git a/node/rerolldicenode.cpp b/node/rerolldicenode.cpp
index 56ee6d9..70475a5 100644
--- a/node/rerolldicenode.cpp
+++ b/node/rerolldicenode.cpp
@@ -1,5 +1,6 @@
#include "rerolldicenode.h"
#include "parsingtoolbox.h"
+#include <utility>
RerollDiceNode::RerollDiceNode(bool reroll, bool addingMode)
: m_diceResult(new DiceResult()), m_validator(nullptr), m_reroll(reroll), m_adding(addingMode)
@@ -26,7 +27,6 @@ void RerollDiceNode::run(ExecutionNode* previous)
for(auto& die : previous_result->getResultList())
{
Die* tmpdie= new Die(*die);
- //*tmpdie= *die;
m_diceResult->insertResult(tmpdie);
die->displayed();
}
@@ -35,10 +35,22 @@ void RerollDiceNode::run(ExecutionNode* previous)
QList<Die*>& list= m_diceResult->getResultList();
QList<Die*> toRemove;
- for(int i= 0; i < list.size(); ++i)
+ for(auto& die : list)
{
- auto die= list.at(i);
bool finished= false;
+ auto state
+ = m_validator->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))
+ {
+ m_errors.insert(Dice::ERROR_CODE::ENDLESS_LOOP_ERROR,
+ QObject::tr("Condition (%1) cause an endless loop with this dice: %2")
+ .arg(toString(true))
+ .arg(QStringLiteral("d[%1,%2]")
+ .arg(static_cast<int>(die->getBase()))
+ .arg(static_cast<int>(die->getMaxValue()))));
+ continue;
+ }
while(m_validator->hasValid(die, false) && !finished)
{
if(m_instruction != nullptr)
@@ -52,8 +64,8 @@ void RerollDiceNode::run(ExecutionNode* previous)
{
toRemove.append(die);
list.append(lastResult->getResultList());
+ lastResult->clear();
}
- lastResult->clear();
}
}
else
@@ -79,7 +91,8 @@ void RerollDiceNode::run(ExecutionNode* previous)
}
else
{
- m_errors.insert(ExecutionNode::DIE_RESULT_EXPECTED,
+ m_errors.insert(
+ Dice::ERROR_CODE::DIE_RESULT_EXPECTED,
QObject::tr(
" The a operator expects dice result. Please check the documentation and fix your command."));
}
diff --git a/node/scalaroperatornode.cpp b/node/scalaroperatornode.cpp
index 3a26fc7..821150b 100644
--- a/node/scalaroperatornode.cpp
+++ b/node/scalaroperatornode.cpp
@@ -66,31 +66,39 @@ void ScalarOperatorNode::run(ExecutionNode* previous)
m_internalNode->getResult()->setPrevious(previousResult);
}
+ if(internalResult == nullptr)
+ {
+ m_errors.insert(Dice::ERROR_CODE::NO_VALID_RESULT,
+ QObject::tr("No Valid result in arithmetic operatoion: %1").arg(toString(true)));
+ return;
+ }
+
switch(m_arithmeticOperator)
{
case Die::PLUS:
- m_scalarResult->setValue(add(previousResult->getResult(Result::SCALAR).toReal(),
- internalResult->getResult(Result::SCALAR).toReal()));
+ m_scalarResult->setValue(add(previousResult->getResult(Dice::RESULT_TYPE::SCALAR).toReal(),
+ internalResult->getResult(Dice::RESULT_TYPE::SCALAR).toReal()));
break;
case Die::MINUS:
- m_scalarResult->setValue(substract(previousResult->getResult(Result::SCALAR).toReal(),
- internalResult->getResult(Result::SCALAR).toReal()));
+ m_scalarResult->setValue(substract(previousResult->getResult(Dice::RESULT_TYPE::SCALAR).toReal(),
+ internalResult->getResult(Dice::RESULT_TYPE::SCALAR).toReal()));
break;
case Die::MULTIPLICATION:
- m_scalarResult->setValue(multiple(previousResult->getResult(Result::SCALAR).toReal(),
- internalResult->getResult(Result::SCALAR).toReal()));
+ m_scalarResult->setValue(multiple(previousResult->getResult(Dice::RESULT_TYPE::SCALAR).toReal(),
+ internalResult->getResult(Dice::RESULT_TYPE::SCALAR).toReal()));
break;
case Die::DIVIDE:
- m_scalarResult->setValue(divide(previousResult->getResult(Result::SCALAR).toReal(),
- internalResult->getResult(Result::SCALAR).toReal()));
+ m_scalarResult->setValue(divide(previousResult->getResult(Dice::RESULT_TYPE::SCALAR).toReal(),
+ internalResult->getResult(Dice::RESULT_TYPE::SCALAR).toReal()));
break;
case Die::INTEGER_DIVIDE:
- m_scalarResult->setValue(static_cast<int>(divide(previousResult->getResult(Result::SCALAR).toReal(),
- internalResult->getResult(Result::SCALAR).toReal())));
+ m_scalarResult->setValue(
+ static_cast<int>(divide(previousResult->getResult(Dice::RESULT_TYPE::SCALAR).toReal(),
+ internalResult->getResult(Dice::RESULT_TYPE::SCALAR).toReal())));
break;
case Die::POW:
- m_scalarResult->setValue(pow(previousResult->getResult(Result::SCALAR).toReal(),
- internalResult->getResult(Result::SCALAR).toReal()));
+ m_scalarResult->setValue(pow(previousResult->getResult(Dice::RESULT_TYPE::SCALAR).toReal(),
+ internalResult->getResult(Dice::RESULT_TYPE::SCALAR).toReal()));
break;
}
}
@@ -128,7 +136,7 @@ qreal ScalarOperatorNode::divide(qreal a, qreal b)
{
if(qFuzzyCompare(b, 0))
{
- m_errors.insert(DIVIDE_BY_ZERO, QObject::tr("Division by zero"));
+ m_errors.insert(Dice::ERROR_CODE::DIVIDE_BY_ZERO, QObject::tr("Division by zero"));
return 0;
}
return static_cast<qreal>(a / b);
@@ -240,12 +248,12 @@ void ScalarOperatorNode::generateDotTree(QString& s)
}
s.append(str);
}
-QMap<ExecutionNode::DICE_ERROR_CODE, QString> ScalarOperatorNode::getExecutionErrorMap()
+QMap<Dice::ERROR_CODE, QString> ScalarOperatorNode::getExecutionErrorMap()
{
if(nullptr != m_internalNode)
{
auto keys= m_internalNode->getExecutionErrorMap().keys();
- for(ExecutionNode::DICE_ERROR_CODE& key : keys)
+ for(const auto& key : keys)
{
m_errors.insert(key, m_internalNode->getExecutionErrorMap().value(key));
}
@@ -253,7 +261,7 @@ QMap<ExecutionNode::DICE_ERROR_CODE, QString> ScalarOperatorNode::getExecutionEr
if(nullptr != m_nextNode)
{
auto keys= m_nextNode->getExecutionErrorMap().keys();
- for(ExecutionNode::DICE_ERROR_CODE& key : keys)
+ for(auto const& key : keys)
{
m_errors.insert(key, m_nextNode->getExecutionErrorMap().value(key));
}
diff --git a/node/scalaroperatornode.h b/node/scalaroperatornode.h
index 2ac89b0..a58a8d3 100644
--- a/node/scalaroperatornode.h
+++ b/node/scalaroperatornode.h
@@ -76,7 +76,7 @@ public:
* @brief getErrorList
* @return
*/
- virtual QMap<ExecutionNode::DICE_ERROR_CODE, QString> getExecutionErrorMap();
+ virtual QMap<Dice::ERROR_CODE, QString> getExecutionErrorMap();
/**
* @brief getArithmeticOperator
* @return
diff --git a/node/valueslistnode.cpp b/node/valueslistnode.cpp
index b31ee84..d378350 100644
--- a/node/valueslistnode.cpp
+++ b/node/valueslistnode.cpp
@@ -16,7 +16,7 @@ void ValuesListNode::run(ExecutionNode* previous)
auto result= node->getResult();
if(!result)
continue;
- auto val= result->getResult(Result::SCALAR).toInt();
+ auto val= result->getResult(Dice::RESULT_TYPE::SCALAR).toInt();
Die* die= new Die();
auto dyna= dynamic_cast<VariableNode*>(node);
if(nullptr != dyna)
diff --git a/node/variablenode.cpp b/node/variablenode.cpp
index 1d13a2c..e45214d 100644
--- a/node/variablenode.cpp
+++ b/node/variablenode.cpp
@@ -24,7 +24,7 @@ void VariableNode::run(ExecutionNode* previous)
}
else
{
- m_errors.insert(NO_VARIBALE, QObject::tr("No variable at index:%1").arg(m_index + 1));
+ m_errors.insert(Dice::ERROR_CODE::NO_VARIBALE, QObject::tr("No variable at index:%1").arg(m_index + 1));
}
}
diff --git a/operationcondition.cpp b/operationcondition.cpp
index 53a994d..9ef8e1e 100644
--- a/operationcondition.cpp
+++ b/operationcondition.cpp
@@ -41,6 +41,10 @@ void OperationCondition::setBoolean(BooleanCondition* boolean)
qint64 OperationCondition::hasValid(Die* b, bool recursive, bool unhighlight) const
{
+ if(nullptr == m_boolean)
+ {
+ return 0;
+ }
QList<qint64> listValues;
if(recursive)
{
@@ -64,7 +68,7 @@ qint64 OperationCondition::hasValid(Die* b, bool recursive, bool unhighlight) co
if(valueScalar == 0)
valueScalar= 1;
die.insertRollValue(value % valueScalar);
- sum+= m_boolean->hasValid(&die, recursive, false);
+ sum+= m_boolean->hasValid(&die, recursive, false) ? 1 : 0;
}
break;
}
@@ -102,18 +106,26 @@ QString OperationCondition::toString()
}
return QStringLiteral("[%1%2%3]").arg(str).arg(valueToScalar()).arg(m_boolean->toString());
}
-bool OperationCondition::isValidRangeSize(std::pair<qint64, qint64>) const
+Dice::CONDITION_STATE OperationCondition::isValidRangeSize(const std::pair<qint64, qint64>& range) const
{
- auto value= valueToScalar();
- bool valid= true;
+ Dice::CONDITION_STATE valid= Dice::CONDITION_STATE::REACHABLE;
+
+ auto rangeIsClose= (range.first == range.second);
- if(value == 0)
- valid= false;
- /* else if(nullptr != m_boolean)
- valid = m_boolean->isValidRangeSize(range);*/
+ Die die;
+ die.insertRollValue(range.first);
+
+ if(nullptr == m_boolean)
+ return Dice::CONDITION_STATE::ERROR;
+
+ if(rangeIsClose && m_boolean->hasValid(&die, false, false))
+ valid= Dice::CONDITION_STATE::ALWAYSTRUE;
+ else if(rangeIsClose && !m_boolean->hasValid(&die, false, false))
+ valid= Dice::CONDITION_STATE::UNREACHABLE;
return valid;
}
+
Validator* OperationCondition::getCopy() const
{
OperationCondition* val= new OperationCondition();
@@ -131,5 +143,22 @@ qint64 OperationCondition::valueToScalar() const
m_value->run(nullptr);
auto result= m_value->getResult();
- return result->getResult(Result::SCALAR).toInt();
+ return result->getResult(Dice::RESULT_TYPE::SCALAR).toInt();
+}
+
+const std::set<qint64>& OperationCondition::getPossibleValues(const std::pair<qint64, qint64>& range)
+{
+ if(nullptr == m_boolean)
+ return m_values;
+
+ for(qint64 i= std::min(range.first, range.second); i <= std::max(range.first, range.second); ++i)
+ {
+ auto valueScalar= valueToScalar();
+ auto val= i % valueScalar;
+ Die die;
+ die.insertRollValue(val);
+ if(m_boolean->hasValid(&die, false, false))
+ m_values.insert(i);
+ }
+ return m_values;
}
diff --git a/operationcondition.h b/operationcondition.h
index 86562e6..002a669 100644
--- a/operationcondition.h
+++ b/operationcondition.h
@@ -34,27 +34,29 @@ public:
Modulo
};
OperationCondition();
- virtual ~OperationCondition();
+ virtual ~OperationCondition() override;
- virtual qint64 hasValid(Die* b, bool recursive, bool unhighlight= false) const;
+ virtual qint64 hasValid(Die* b, bool recursive, bool unhighlight= false) const override;
void setOperator(ConditionOperator m);
// void setValue(qint64);
void setValueNode(ExecutionNode* node);
- QString toString();
+ QString toString() override;
- virtual bool isValidRangeSize(std::pair<qint64, qint64> range) const;
+ virtual Dice::CONDITION_STATE isValidRangeSize(const std::pair<qint64, qint64>& range) const override;
BooleanCondition* getBoolean() const;
void setBoolean(BooleanCondition* boolean);
- virtual Validator* getCopy() const;
+ virtual Validator* getCopy() const override;
+
+ const std::set<qint64>& getPossibleValues(const std::pair<qint64, qint64>& range) override;
private:
qint64 valueToScalar() const;
private:
- ConditionOperator m_operator;
+ ConditionOperator m_operator= Modulo;
BooleanCondition* m_boolean= nullptr;
// qint64 m_value;
ExecutionNode* m_value= nullptr;
diff --git a/parsingtoolbox.cpp b/parsingtoolbox.cpp
index 702019d..4372b41 100644
--- a/parsingtoolbox.cpp
+++ b/parsingtoolbox.cpp
@@ -204,13 +204,17 @@ Validator* ParsingToolBox::readValidator(QString& str, bool hasSquare)
{
OperationCondition* condition= new OperationCondition();
condition->setValueNode(operandNode);
- Validator* valid= readValidator(str,hasSquare);
+ Validator* valid= readValidator(str, hasSquare);
BooleanCondition* boolC= dynamic_cast<BooleanCondition*>(valid);
if(nullptr != boolC)
{
condition->setBoolean(boolC);
+ returnVal= condition;
+ }
+ else
+ {
+ delete condition;
}
- returnVal= condition;
}
}
else if(readOperand(str, operandNode))
@@ -277,16 +281,16 @@ Validator* ParsingToolBox::readCompositeValidator(QString& str)
Validator* tmp= readValidator(str, expectSquareBrasket);
CompositeValidator::LogicOperation opLogic;
- QVector<CompositeValidator::LogicOperation>* operators= new QVector<CompositeValidator::LogicOperation>();
- QList<Validator*>* validatorList= new QList<Validator*>();
+ QVector<CompositeValidator::LogicOperation> operators;
+ QList<Validator*> validatorList;
while(nullptr != tmp)
{
bool hasOperator= readLogicOperation(str, opLogic);
if(hasOperator)
{
- operators->append(opLogic);
- validatorList->append(tmp);
+ operators.append(opLogic);
+ validatorList.append(tmp);
tmp= readValidator(str, expectSquareBrasket);
}
else
@@ -297,19 +301,19 @@ Validator* ParsingToolBox::readCompositeValidator(QString& str)
// isOk=true;
}
- if(!validatorList->isEmpty())
+ if(!validatorList.isEmpty())
{
- validatorList->append(tmp);
+ validatorList.append(tmp);
}
else
{
- delete operators;
+ operators.clear();
return tmp;
}
tmp= nullptr;
}
}
- if(!validatorList->isEmpty())
+ if(!validatorList.isEmpty())
{
CompositeValidator* validator= new CompositeValidator();
validator->setOperationList(operators);
@@ -318,7 +322,6 @@ Validator* ParsingToolBox::readCompositeValidator(QString& str)
}
else
{
- delete operators;
return nullptr;
}
}
@@ -597,19 +600,13 @@ bool ParsingToolBox::readAscending(QString& str)
}
return false;
}
-bool ParsingToolBox::isValidValidator(ExecutionNode* previous, Validator* val)
+Dice::CONDITION_STATE ParsingToolBox::isValidValidator(ExecutionNode* previous, Validator* val)
{
DiceRollerNode* node= getDiceRollerNode(previous);
- bool valid= false;
- if(nullptr != node)
- {
- valid= val->isValidRangeSize(node->getRange());
- }
- else
- {
- valid= true;
- }
- return valid;
+ if(nullptr == node)
+ return Dice::CONDITION_STATE::ERROR;
+
+ return val->isValidRangeSize(node->getRange());
}
DiceRollerNode* ParsingToolBox::getDiceRollerNode(ExecutionNode* previous)
{
@@ -663,28 +660,32 @@ ParsingToolBox::LIST_OPERATOR ParsingToolBox::readListOperator(QString& str)
return NONE;
}
-void ParsingToolBox::readPainterParameter(PainterNode* painter, QString& str)
+bool ParsingToolBox::readPainterParameter(PainterNode* painter, QString& str)
{
- if(str.startsWith('['))
- {
- str= str.remove(0, 1);
- int pos= str.indexOf(']');
+ if(!str.startsWith('['))
+ return false;
+
+ str= str.remove(0, 1);
+ int pos= str.indexOf(']');
+
+ if(pos == -1)
+ return false;
- if(pos > -1)
+ QString data= str.left(pos);
+ str= str.remove(0, pos + 1);
+ QStringList duos= data.split(',');
+ bool result= false;
+ for(QString& duoStr : duos)
+ {
+ QStringList keyValu= duoStr.split(':');
+ if(keyValu.size() == 2)
{
- QString data= str.left(pos);
- str= str.remove(0, pos + 1);
- QStringList duos= data.split(',');
- for(QString& duoStr : duos)
- {
- QStringList keyValu= duoStr.split(':');
- if(keyValu.size() == 2)
- {
- painter->insertColorItem(keyValu[1], keyValu[0].toInt());
- }
- }
+ painter->insertColorItem(keyValu[1], keyValu[0].toInt());
+ result= true;
}
}
+
+ return result;
}
QHash<QString, QString> ParsingToolBox::getVariableHash()
diff --git a/range.cpp b/range.cpp
index 471784c..8eeff4e 100644
--- a/range.cpp
+++ b/range.cpp
@@ -58,12 +58,20 @@ QString Range::toString()
{
return QStringLiteral("[%1-%2]").arg(m_start).arg(m_end);
}
-bool Range::isValidRangeSize(std::pair<qint64, qint64> range) const
+Dice::CONDITION_STATE Range::isValidRangeSize(const std::pair<qint64, qint64>& range) const
{
- auto newStart= qBound(range.first, m_start, range.second);
- auto newEnd= qBound(range.first, m_end, range.second);
+ auto minRange= std::min(m_start, m_end);
+ auto minPossibleValue= std::min(range.first, range.second);
- return (newStart == m_start && newEnd == m_end && m_end >= m_start);
+ auto maxRange= std::max(m_start, m_end);
+ auto maxPossibleValue= std::max(range.first, range.second);
+
+ if(minRange == minPossibleValue && maxRange == maxPossibleValue)
+ return Dice::CONDITION_STATE::ALWAYSTRUE;
+ else if(maxRange < minPossibleValue || minRange > maxPossibleValue)
+ return Dice::CONDITION_STATE::UNREACHABLE;
+ else
+ return Dice::CONDITION_STATE::UNREACHABLE;
}
void Range::setStart(qint64 start)
{
diff --git a/range.h b/range.h
index 17cc9ad..7a107b0 100644
--- a/range.h
+++ b/range.h
@@ -35,10 +35,10 @@ public:
void setValue(qint64, qint64);
void setStart(qint64);
void setEnd(qint64);
- virtual qint64 hasValid(Die* b, bool recursive, bool unlight= false) const;
+ virtual qint64 hasValid(Die* b, bool recursive, bool unlight= false) const override;
- virtual QString toString();
- virtual bool isValidRangeSize(std::pair<qint64, qint64> range) const;
+ virtual QString toString() override;
+ virtual Dice::CONDITION_STATE isValidRangeSize(const std::pair<qint64, qint64>& range) const override;
bool isFullyDefined() const;
qint64 getStart() const;
@@ -47,7 +47,7 @@ public:
void setEmptyRange(bool);
bool isEmptyRange();
- virtual Validator* getCopy() const;
+ virtual Validator* getCopy() const override;
private:
qint64 m_start= 0;
diff --git a/result/diceresult.cpp b/result/diceresult.cpp
index e66fc4f..23b925e 100644
--- a/result/diceresult.cpp
+++ b/result/diceresult.cpp
@@ -25,7 +25,7 @@
DiceResult::DiceResult() : m_operator(Die::PLUS)
{
- m_resultTypes= (DICE_LIST | SCALAR);
+ m_resultTypes= (static_cast<int>(Dice::RESULT_TYPE::DICE_LIST) | static_cast<int>(Dice::RESULT_TYPE::SCALAR));
m_homogeneous= true;
}
void DiceResult::insertResult(Die* die)
@@ -63,15 +63,15 @@ DiceResult::~DiceResult()
m_diceValues.clear();
}
}
-QVariant DiceResult::getResult(RESULT_TYPE type)
+QVariant DiceResult::getResult(Dice::RESULT_TYPE type)
{
switch(type)
{
- case SCALAR:
+ case Dice::RESULT_TYPE::SCALAR:
{
return getScalarResult();
}
- case DICE_LIST:
+ case Dice::RESULT_TYPE::DICE_LIST:
{
return QVariant();
}
diff --git a/result/diceresult.h b/result/diceresult.h
index 54e0b57..ce8ffb7 100644
--- a/result/diceresult.h
+++ b/result/diceresult.h
@@ -61,7 +61,7 @@ public:
* @brief getScalar
* @return
*/
- virtual QVariant getResult(RESULT_TYPE);
+ virtual QVariant getResult(Dice::RESULT_TYPE);
/**
* @brief toString
* @return
diff --git a/result/result.cpp b/result/result.cpp
index edd00e4..983f1f4 100644
--- a/result/result.cpp
+++ b/result/result.cpp
@@ -22,7 +22,10 @@
#include "result.h"
#include <QUuid>
-Result::Result() : m_resultTypes(NONE), m_id(QString("\"%1\"").arg(QUuid::createUuid().toString())), m_previous(nullptr)
+Result::Result()
+ : m_resultTypes(static_cast<int>(Dice::RESULT_TYPE::NONE))
+ , m_id(QString("\"%1\"").arg(QUuid::createUuid().toString()))
+ , m_previous(nullptr)
{
}
Result::~Result() {}
@@ -43,9 +46,9 @@ bool Result::isStringResult() const
return false;
}
void Result::clear() {}
-bool Result::hasResultOfType(RESULT_TYPE type) const
+bool Result::hasResultOfType(Dice::RESULT_TYPE type) const
{
- return (m_resultTypes & type);
+ return (m_resultTypes & static_cast<int>(type));
}
void Result::generateDotTree(QString& s)
{
diff --git a/result/result.h b/result/result.h
index 8f31c05..76f3a8c 100644
--- a/result/result.h
+++ b/result/result.h
@@ -22,7 +22,7 @@
#ifndef RESULT_H
#define RESULT_H
-//#include <Qt>
+#include "diceparserhelper.h"
#include <QString>
#include <QVariant>
/**
@@ -32,16 +32,6 @@ class Result
{
public:
/**
- * @brief The RESULT_TYPE enum or combinaison
- */
- enum RESULT_TYPE
- {
- NONE= 0,
- SCALAR= 1,
- STRING= 2,
- DICE_LIST= 4
- };
- /**
* @brief Result
*/
Result();
@@ -54,12 +44,12 @@ public:
* @brief isScalar
* @return
*/
- virtual bool hasResultOfType(RESULT_TYPE) const;
+ virtual bool hasResultOfType(Dice::RESULT_TYPE) const;
/**
* @brief getScalar
* @return
*/
- virtual QVariant getResult(RESULT_TYPE)= 0;
+ virtual QVariant getResult(Dice::RESULT_TYPE)= 0;
/**
* @brief getPrevious
* @return
@@ -100,7 +90,7 @@ protected:
QString m_id;
private:
- Result* m_previous; /// @brief
+ Result* m_previous= nullptr; /// @brief
};
#endif // RESULT_H
diff --git a/result/scalarresult.cpp b/result/scalarresult.cpp
index 089c4b8..d901c08 100644
--- a/result/scalarresult.cpp
+++ b/result/scalarresult.cpp
@@ -23,16 +23,16 @@
ScalarResult::ScalarResult()
{
- m_resultTypes= Result::SCALAR;
+ m_resultTypes= static_cast<int>(Dice::RESULT_TYPE::SCALAR);
}
void ScalarResult::setValue(qreal i)
{
m_value= i;
}
-QVariant ScalarResult::getResult(Result::RESULT_TYPE type)
+QVariant ScalarResult::getResult(Dice::RESULT_TYPE type)
{
- if(SCALAR == type)
+ if(Dice::RESULT_TYPE::SCALAR == type)
{
return m_value;
}
diff --git a/result/scalarresult.h b/result/scalarresult.h
index c20de0f..1eac73c 100644
--- a/result/scalarresult.h
+++ b/result/scalarresult.h
@@ -39,7 +39,7 @@ public:
* @brief getResult
* @return
*/
- virtual QVariant getResult(Result::RESULT_TYPE);
+ virtual QVariant getResult(Dice::RESULT_TYPE);
/**
* @brief setValue
* @param i
diff --git a/result/stringresult.cpp b/result/stringresult.cpp
index a44e24e..d5a7880 100644
--- a/result/stringresult.cpp
+++ b/result/stringresult.cpp
@@ -3,20 +3,21 @@
StringResult::StringResult()
{
m_highlight= true;
- m_resultTypes= Result::STRING;
+ m_resultTypes= static_cast<int>(Dice::RESULT_TYPE::STRING);
}
void StringResult::setText(QString text)
{
m_value= text;
}
StringResult::~StringResult() {}
-bool StringResult::hasResultOfType(RESULT_TYPE resultType) const
+bool StringResult::hasResultOfType(Dice::RESULT_TYPE resultType) const
{
- if(resultType & Result::STRING)
+
+ if(resultType == Dice::RESULT_TYPE::STRING)
{
return true;
}
- else if(resultType & Result::SCALAR)
+ else if(resultType == Dice::RESULT_TYPE::SCALAR)
{
bool ok= false;
getText().toInt(&ok);
@@ -28,13 +29,13 @@ QString StringResult::getText() const
{
return m_value;
}
-QVariant StringResult::getResult(RESULT_TYPE type)
+QVariant StringResult::getResult(Dice::RESULT_TYPE type)
{
switch(type)
{
- case STRING:
+ case Dice::RESULT_TYPE::STRING:
return getText();
- case SCALAR:
+ case Dice::RESULT_TYPE::SCALAR:
return getText().toInt();
default:
return QVariant();
diff --git a/result/stringresult.h b/result/stringresult.h
index ec6c3ce..0e469fe 100644
--- a/result/stringresult.h
+++ b/result/stringresult.h
@@ -31,7 +31,7 @@ public:
* @brief getScalar
* @return
*/
- virtual QVariant getResult(RESULT_TYPE);
+ virtual QVariant getResult(Dice::RESULT_TYPE);
/**
* @brief toString
* @return
@@ -40,7 +40,7 @@ public:
virtual void setHighLight(bool);
virtual bool hasHighLight() const;
- virtual bool hasResultOfType(RESULT_TYPE resultType) const;
+ virtual bool hasResultOfType(Dice::RESULT_TYPE resultType) const;
virtual Result* getCopy() const;
private:
diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt
index 4065cc5..6fb276b 100644
--- a/tests/CMakeLists.txt
+++ b/tests/CMakeLists.txt
@@ -1,9 +1,2 @@
-set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -fno-permissive -pedantic -Wall -Wextra")
-set(CMAKE_AUTOMOC ON)
-find_package(Qt5Test REQUIRED)
-
-set(test_source testnode.cpp tst_dice.cpp)
-
-add_executable(test_dice ${test_source} )
-target_link_libraries(test_dice diceparser Qt5::Test)
-add_test(tst_diceparser test_dice)
+#add_subdirectory(fuzzer)
+add_subdirectory(dice)
diff --git a/tests/dice/CMakeLists.txt b/tests/dice/CMakeLists.txt
index a0f27fd..d254624 100644
--- a/tests/dice/CMakeLists.txt
+++ b/tests/dice/CMakeLists.txt
@@ -1,17 +1,12 @@
-cmake_minimum_required(VERSION 3.5)
-project(tst_diceParser)
-
-enable_testing(true)
-
-# Tell CMake to run moc when necessary:
+set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -fno-permissive -pedantic -Wall -Wextra")
set(CMAKE_AUTOMOC ON)
+find_package(Qt5Test REQUIRED)
-# As moc files are generated in the binary dir, tell CMake
-# to always look for includes there:
-set(CMAKE_INCLUDE_CURRENT_DIR ON)
+set(test_source testnode.cpp tst_dice.cpp)
-find_package(Qt5Test REQUIRED)
+add_executable(test_dice ${test_source} ${dice_sources})
-add_test(tst_diceParser tst_dice.cpp)
+target_include_directories(test_dice PRIVATE ../../include)
-target_link_libraries(foo Qt5::Test)
+target_link_libraries(test_dice Qt5::Test)
+add_test(tst_diceparser test_dice)
diff --git a/tests/dice/Dice.pro b/tests/dice/Dice.pro
deleted file mode 100644
index 9d24f91..0000000
--- a/tests/dice/Dice.pro
+++ /dev/null
@@ -1,25 +0,0 @@
-include(../tests.pri)
-
-SOURCES += \
- tst_dice.cpp
-
-TEMPLATE = app
-TARGET= tst_diceParser
-MOC_DIR=trash
-OBJECTS_DIR=trash
-
-CONFIG+=testcase
-
-QT += testlib quick qml widgets
-
-INCLUDEPATH += $$ROLISTEAMSRC/diceparser/
-INCLUDEPATH += $$ROLISTEAMSRC/diceparser/node
-INCLUDEPATH += $$ROLISTEAMSRC/diceparser/result
-
-
-include($$ROLISTEAMSRC/diceparser/diceparser.pri)
-
-HEADERS -= ../../../rolisteam/client/diceparser/qmltypesregister.h
-SOURCES -= ../../../rolisteam/client/diceparser/qmltypesregister.cpp
-
-
diff --git a/tests/testnode.cpp b/tests/dice/testnode.cpp
index de9fc05..de9fc05 100644
--- a/tests/testnode.cpp
+++ b/tests/dice/testnode.cpp
diff --git a/tests/testnode.h b/tests/dice/testnode.h
index 5c918ee..5c918ee 100644
--- a/tests/testnode.h
+++ b/tests/dice/testnode.h
diff --git a/tests/tst_dice.cpp b/tests/dice/tst_dice.cpp
index 1fe2641..a35f918 100644
--- a/tests/tst_dice.cpp
+++ b/tests/dice/tst_dice.cpp
@@ -43,6 +43,7 @@
#include "node/splitnode.h"
#include "node/stringnode.h"
#include "node/uniquenode.h"
+#include "operationcondition.h"
#include "result/stringresult.h"
#include "testnode.h"
@@ -131,6 +132,8 @@ private slots:
void occurenceTest();
void occurenceTest_data();
+ void operatoionConditionValidatorTest();
+
private:
std::unique_ptr<Die> m_die;
std::unique_ptr<DiceParser> m_diceParser;
@@ -463,13 +466,13 @@ void TestDice::dangerousCommandsTest_data()
// QTest::addRow("cmd5") << "10d10g10";
}
-void makeResult(DiceResult& result, const QVector<int>& values)
+void makeResult(DiceResult& result, const QVector<int>& values, int base= 1, int max= 10)
{
for(int val : values)
{
auto die= new Die();
- die->setBase(1);
- die->setMaxValue(10);
+ die->setBase(base);
+ die->setMaxValue(max);
die->insertRollValue(val);
result.insertResult(die);
}
@@ -524,7 +527,7 @@ void TestDice::keepTest()
if(error)
return;
- auto resultScore= keepN.getResult()->getResult(Result::SCALAR).toInt();
+ auto resultScore= keepN.getResult()->getResult(Dice::RESULT_TYPE::SCALAR).toInt();
QCOMPARE(score, resultScore);
}
@@ -609,7 +612,7 @@ void TestDice::countTest()
node.run(nullptr);
- QCOMPARE(score, countN.getResult()->getResult(Result::SCALAR).toInt());
+ QCOMPARE(score, countN.getResult()->getResult(Dice::RESULT_TYPE::SCALAR).toInt());
countN.setValidator(nullptr);
}
@@ -722,7 +725,7 @@ void TestDice::rerollUntilTest()
RerollDiceNode reroll(false, false);
DiceResult result;
- makeResult(result, values);
+ makeResult(result, values, 0);
node.setResult(&result);
auto validator= makeValidator(condition, BooleanCondition::Equal);
@@ -742,7 +745,6 @@ void TestDice::rerollUntilTest()
resultDiff= true;
++i;
}
-
QCOMPARE(different, resultDiff);
}
void TestDice::rerollUntilTest_data()
@@ -1062,6 +1064,31 @@ void TestDice::ifCommandTest_data()
<< QStringList({"Complete Success:", "Success with Complications:", "Failure:"});
}
+void TestDice::operatoionConditionValidatorTest()
+{
+ OperationCondition validator;
+ NumberNode number;
+ number.setNumber(2);
+ validator.setValueNode(&number);
+
+ BooleanCondition subValidator;
+ subValidator.setOperator(BooleanCondition::Equal);
+ NumberNode subnumber;
+ subnumber.setNumber(0);
+ subValidator.setValueNode(&subnumber);
+
+ validator.setBoolean(&subValidator);
+
+ std::set<qint64> data= {2, 4, 6, 8, 10};
+ auto value= validator.getPossibleValues(std::make_pair<qint64, qint64>(1, 10));
+
+ subValidator.setValueNode(nullptr);
+ validator.setValueNode(nullptr);
+ validator.setBoolean(nullptr);
+
+ QCOMPARE(value, data);
+}
+
void TestDice::cleanupTestCase() {}
QTEST_MAIN(TestDice)
diff --git a/tests/fuzzer/CMakeLists.txt b/tests/fuzzer/CMakeLists.txt
new file mode 100644
index 0000000..c6d94ca
--- /dev/null
+++ b/tests/fuzzer/CMakeLists.txt
@@ -0,0 +1,26 @@
+cmake_minimum_required(VERSION 3.10)
+set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -fno-permissive -pedantic -Wall -Wextra")
+set(CMAKE_AUTOMOC ON)
+
+find_package(Qt5Core REQUIRED)
+find_package(Qt5Gui REQUIRED)
+find_package(Qt5Svg REQUIRED)
+find_package(Qt5Concurrent REQUIRED)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+set(CMAKE_AUTOMOC ON)
+
+#SET (CMAKE_EXE_LINKER_FLAGS "-static")
+
+add_definitions(-DPAINTER_OP)
+set(MODE "cli")
+
+
+
+set(fdsource testcase.cpp)
+
+add_executable(fuzzTestCase ${fdsource} )
+
+
+target_link_libraries(fuzzTestCase libdiceparser.a Qt5::Core Qt5::Gui Qt5::Svg Qt5::Concurrent)
+#target_link_libraries(fuzzTestCase )
diff --git a/tests/fuzzer/run_test.sh b/tests/fuzzer/run_test.sh
new file mode 100755
index 0000000..9ecdeef
--- /dev/null
+++ b/tests/fuzzer/run_test.sh
@@ -0,0 +1,27 @@
+#!/bin/sh
+
+rm -rf build
+mkdir build
+cd build
+CC=afl-gcc CXX=afl-g++ cmake ../ -DSTATIC_BUILD=ON && make
+#export LD_LIBRARY_PATH="/usr/local/lib:$LD_LIBRARY_PATH"
+
+
+#./fuzzTestCase ../testcase_dir/gooddata.txt
+# afl-fuzz -m 2G -i ../testcase_dir -o ../findings_dir ./fuzzTestCase @@
+afl-fuzz -m 2G -i ../testcase_dir -o ../sync_dir -M fuzzer01 ./fuzzTestCase @@ &
+screen -S fuzz1 -d -m touch afl-fuzz -m 2G -i ../testcase_dir -o ../sync_dir -S fuzzer02 ./fuzzTestCase @@ &
+screen -S fuzz2 -d -m touch afl-fuzz -m 2G -i ../testcase_dir -o ../sync_dir -S fuzzer03 ./fuzzTestCase @@ &
+screen -S fuzz3 -d -m touch afl-fuzz -m 2G -i ../testcase_dir -o ../sync_dir -S fuzzer04 ./fuzzTestCase @@ &
+screen -S fuzz4 -d -m touch afl-fuzz -m 2G -i ../testcase_dir -o ../sync_dir -S fuzzer05 ./fuzzTestCase @@ &
+screen -S fuzz5 -d -m touch afl-fuzz -m 2G -i ../testcase_dir -o ../sync_dir -S fuzzer06 ./fuzzTestCase @@
+
+
+
+# as root
+
+# echo core >/proc/sys/kernel/core_pattern
+
+# echo performance | tee cpu*/cpufreq/scaling_governor
+
+# echo ondemand | tee cpu*/cpufreq/scaling_governor
diff --git a/tests/fuzzer/testcase.cpp b/tests/fuzzer/testcase.cpp
new file mode 100644
index 0000000..87d1867
--- /dev/null
+++ b/tests/fuzzer/testcase.cpp
@@ -0,0 +1,37 @@
+#include <QCoreApplication>
+#include <QDebug>
+#include <QFile>
+#include <diceparser.h>
+
+static DiceParser* parser= new DiceParser();
+
+void runCommand(const QString& cmd)
+{
+ qDebug() << "cmd" << cmd;
+ if(parser->parseLine(cmd))
+ {
+ parser->start();
+ }
+}
+
+int main(int argc, char** argv)
+{
+ // qDebug() << "first";
+ QCoreApplication app(argc, argv);
+
+ // qDebug() << "start";
+ QFile file(app.arguments().at(1));
+ // qDebug() << "file" << app.arguments().at(1);
+ if(!file.open(QIODevice::ReadOnly))
+ return 1;
+
+ auto line= file.readLine();
+ while(!line.isEmpty())
+ {
+ // qDebug() << line;
+ runCommand(QString::fromUtf8(line));
+ line= file.readLine();
+ }
+
+ return 0;
+}
diff --git a/tests/fuzzer/testcase_dir/gooddata.txt b/tests/fuzzer/testcase_dir/gooddata.txt
new file mode 100644
index 0000000..d62c87e
--- /dev/null
+++ b/tests/fuzzer/testcase_dir/gooddata.txt
@@ -0,0 +1,45 @@
+1L[cheminée,chocolat,épée,arc,chute de pierre[40]]
+10d10c[>=6]-@c[=1]
+1+1D10
+1+(4*3)D10s
+2+4/4
+2D10*2D20*8
+1D100a[>=95]a[>=96]a[>=97]a[>=98]a[>=99]e[>=100]
+15D10e10c[8-10]
+(4+4)^4
+(1d20+20)*7/10
+20*7/10
+2d6c[%2=0]
+D25;D10
+8+8+8
+1D20-88
+100*1D20*2D6
+2D6 # comment
+100/28*3
+help
+la
+10D10c[<2|>7]
+10D6c[=2|=4|=6]
+10D10e[=1|=10]k4
+1L[t,b,s,r,j,v,i,p[8-10]]
+1d6e6;1d4e4mk1
+400D20/400000
+1d100e[>=95]i[<5]{-1d100e95}
+1d100i[<70]{1d10i[=10]{1d100i[<70]{1d10e10}}}
+5-5*5+5
+((3+4)*2)d6
+4d6i[=6]{+1d6}
+10d[-8--1]
+4d6e6i[=4]{-4}
+4d6e6f[!=4]
+5d10g10
+4d6p[4:blue]
+10d[0-9]
+1d8e8;1d6e6mk1+2
+3d100g5
+2d10k1+2d10k1+2d10k1
+(1)-1d6e6
+8d10o
+[100,200,300]k2
+100;200;300;[$1,$2,$3]k2
+0-2;$1+$1;$2i:[<1]{1}{0}
diff --git a/validator.cpp b/validator.cpp
index aba97c6..9f717f8 100644
--- a/validator.cpp
+++ b/validator.cpp
@@ -23,3 +23,8 @@
Validator::Validator() {}
Validator::~Validator() {}
+
+const std::set<qint64>& Validator::getPossibleValues(const std::pair<qint64, qint64>&)
+{
+ return m_values;
+}
diff --git a/validator.h b/validator.h
index 469a6fe..a1e7d65 100644
--- a/validator.h
+++ b/validator.h
@@ -22,9 +22,11 @@
#ifndef VALIDATOR_H
#define VALIDATOR_H
+#include "diceparserhelper.h"
#include "die.h"
#include <QString>
#include <Qt>
+#include <set>
/**
* @brief The Validator class is an abstract class for checking the validity of dice for some
* operator.
@@ -58,12 +60,17 @@ public:
* @param faces
* @return
*/
- virtual bool isValidRangeSize(std::pair<qint64, qint64> range) const= 0;
+ virtual Dice::CONDITION_STATE isValidRangeSize(const std::pair<qint64, qint64>& range) const= 0;
/**
* @brief getCopy
* @return return a copy of this validator
*/
virtual Validator* getCopy() const= 0;
+
+ virtual const std::set<qint64>& getPossibleValues(const std::pair<qint64, qint64>& range);
+
+protected:
+ std::set<qint64> m_values;
};
#endif // VALIDATOR_H