11#include <framework/utilities/CutHelpers.h>
12#include <framework/utilities/CutNodes.h>
13#include <framework/logging/Logger.h>
15#include <boost/python/tuple.hpp>
16#include <boost/python/extract.hpp>
17#include <boost/algorithm/string.hpp>
19namespace py = boost::python;
20typedef const py::tuple& Nodetuple;
31 template<
class AVariableManager>
32 class UnaryBooleanNode;
34 template<
class AVariableManager>
35 class BinaryBooleanNode;
37 template<
class AVariableManager>
38 class UnaryRelationalNode;
40 template<
class AVariableManager>
41 class BinaryRelationalNode;
43 template<
class AVariableManager>
44 class TernaryRelationalNode;
46 template<
class AVariableManager>
47 class UnaryExpressionNode;
49 template<
class AVariableManager>
50 class BinaryExpressionNode;
52 template<
class AVariableManager,
typename T>
55 template<
class AVariableManager>
58 template<
class AVariableManager>
79 template<
class AVariableManager>
82 if (py::len(tuple) == 0) B2FATAL(
"BooleanNode tuple is empty, this is invalid.");
84 NodeType node_type =
static_cast<NodeType>(
static_cast<int>(py::extract<int>(tuple[0])));
86 if (node_type == NodeType::UnaryBooleanNode) {
88 if (py::len(tuple) != 4) B2FATAL(
"UnaryBooleanNode tuple has to have length 4." <<
LogVar(
"actual length", py::len(tuple)));
89 Nodetuple child =
static_cast<const py::tuple
>(tuple[1]);
90 bool negation = py::extract<bool>(tuple[2]);
91 bool bracketized = py::extract<bool>(tuple[3]);
95 }
else if (node_type == NodeType::BinaryBooleanNode) {
96 if (py::len(tuple) != 4) B2FATAL(
"BinaryBooleanNode tuple has to have length 4." <<
LogVar(
"actual length", py::len(tuple)));
97 Nodetuple left_node =
static_cast<const py::tuple
>(tuple[1]);
98 Nodetuple right_node =
static_cast<const py::tuple
>(tuple[2]);
102 }
else if (node_type == NodeType::UnaryRelationalNode) {
103 if (py::len(tuple) != 2) B2FATAL(
"UnaryRelationalNode tuple has to have length 2." <<
LogVar(
"actual length", py::len(tuple)));
104 Nodetuple node =
static_cast<const py::tuple
>(tuple[1]);
106 }
else if (node_type == NodeType::BinaryRelationalNode) {
107 if (py::len(tuple) != 4) B2FATAL(
"BinaryRelationalNode tuple has to have length 4." <<
LogVar(
"actual length", py::len(tuple)));
108 Nodetuple left_node =
static_cast<const py::tuple
>(tuple[1]);
109 Nodetuple right_node =
static_cast<const py::tuple
>(tuple[2]);
112 right_node, coperator));
113 }
else if (node_type == NodeType::TernaryRelationalNode) {
114 if (py::len(tuple) != 6) B2FATAL(
"TernaryRelationalNode tuple has to have length 6." <<
LogVar(
"actual length", py::len(tuple)));
115 Nodetuple left_node =
static_cast<const py::tuple
>(tuple[1]);
116 Nodetuple center_node =
static_cast<const py::tuple
>(tuple[2]);
117 Nodetuple right_node =
static_cast<const py::tuple
>(tuple[3]);
122 center_node, right_node,
123 lc_coperator, cr_coperator));
125 throw std::runtime_error(
"error NodeFactory::compile_boolean_node: got invalid boolean NodeType.");
140 template<
class AVariableManager>
143 if (py::len(tuple) == 0) B2FATAL(
"ExpressionNode tuple is empty, this is invalid.");
146 NodeType node_type =
static_cast<NodeType>(
static_cast<int>(py::extract<int>(tuple[0])));
147 if (node_type == NodeType::UnaryExpressionNode) {
148 if (py::len(tuple) != 4) B2FATAL(
"UnaryExpression nodetuple has to have length 4." <<
LogVar(
"actual length", py::len(tuple)));
149 Nodetuple node =
static_cast<const py::tuple
>(tuple[1]);
150 bool unary_minus = py::extract<bool>(tuple[2]);
151 bool parenthesized = py::extract<bool>(tuple[3]);
153 unary_minus, parenthesized));
154 }
else if (node_type == NodeType::BinaryExpressionNode) {
155 if (py::len(tuple) != 4) B2FATAL(
"BinaryExpression nodetuple has to have length 4." <<
LogVar(
"actual length", py::len(tuple)));
156 Nodetuple left_node =
static_cast<const py::tuple
>(tuple[1]);
157 Nodetuple right_node =
static_cast<const py::tuple
>(tuple[2]);
162 }
else if (node_type == NodeType::IntegerNode) {
163 if (py::len(tuple) != 2) B2FATAL(
"IntegerNode nodetuple has to have length 2." <<
LogVar(
"actual length", py::len(tuple)));
164 double d = py::extract<double>(tuple[1]);
165 if (std::numeric_limits<int>::min() <= d && d <= std::numeric_limits<int>::max()) {
166 int i = py::extract<int>(tuple[1]);
169 B2WARNING(
"Overflow for integer constant in cut detected. Create Double Node instead.");
172 }
else if (node_type == NodeType::DoubleNode) {
173 if (py::len(tuple) != 2) B2FATAL(
"DoubleNode nodetuple has to have length 2." <<
LogVar(
"actual length", py::len(tuple)));
176 py::object math = py::import(
"math");
178 py::object data =
static_cast<py::object
>(tuple[1]);
179 if (py::extract<bool>(math.attr(
"isinf")(data))) {
181 double inf_sign = py::extract<double>(math.attr(
"copysign")(1.0, data));
184 inf = std::numeric_limits<double>::infinity();
186 inf = -1 * std::numeric_limits<double>::infinity();
190 if (py::extract<bool>(math.attr(
"isnan")(data))) {
191 double nan = std::nan(
"");
194 double d = py::extract<double>(tuple[1]);
196 }
else if (node_type == NodeType::BooleanNode) {
197 if (py::len(tuple) != 2) B2FATAL(
"BooleanNode nodetuple has to have length 2." <<
LogVar(
"actual length", py::len(tuple)));
198 bool b = py::extract<bool>(tuple[1]);
200 }
else if (node_type == NodeType::IdentifierNode) {
201 if (py::len(tuple) != 2) B2FATAL(
"IdentifierNode nodetuple has to have length 2." <<
LogVar(
"actual length", py::len(tuple)));
202 std::string identifier = py::extract<std::string>(tuple[1]);
204 }
else if (node_type == NodeType::FunctionNode) {
205 if (py::len(tuple) != 3) B2FATAL(
"FunctionNode nodetuple has to have length 3." <<
LogVar(
"actual length", py::len(tuple)));
208 std::string functionName = py::extract<std::string>(tuple[1]);
211 std::string argument = py::extract<std::string>(tuple[2]);
212 boost::algorithm::trim(argument);
215 for (
auto& str : functionArguments) {
216 boost::algorithm::trim(str);
218 B2WARNING(
"Empty parameter for metavariable '" << functionName <<
"' in cut.");
225 throw std::runtime_error(
"error NodeFactory::compile_expression_node: got invalid expression NodeType.");
Nodeclass with two AbstractBooleanNode as children and a Boolean Operator (AND, OR) Check() method ev...
BinaryExpressionNode Node which connects two expression nodes with an arithemtic operation.
BooleanNode which has two AbstractExpressionNodes nodes and a ComparisonOperator.
Template class for storing the Constants (int, double, bool) of the Cutstring.
FunctionNode Node class for handling MetaVariables in cuts.
Class which stores the name of a variable.
Wrapper class for static node compile functions.
static std::unique_ptr< const AbstractExpressionNode< AVariableManager > > compile_expression_node(Nodetuple tuple)
This template function creates a ExpressionNode from a boost::python::tuple The Python Parser encodes...
static std::unique_ptr< const AbstractBooleanNode< AVariableManager > > compile_boolean_node(Nodetuple tuple)
This template function creates a boolean node from a boost::python::tuple The Python Parser encodes t...
BooleanNode which has three AbstractExpressionNodes nodes and two ComparisonOperator.
Nodeclass with a single AbstractBooleanNode as child.
UnaryExpressionNode Node class with a single expression node as child.
Nodeclass with a single AbstractExpressioNode as child.
Class to store variables with their name which were sent to the logging service.
NodeType
Enum of possible Nodes in parsing tree.
std::vector< std::string > splitOnDelimiterAndConserveParenthesis(std::string str, char delimiter, char open, char close)
Split into std::vector on delimiter ignoring delimiters between parenthesis.
ComparisonOperator
Enum for decoding the comparison operator type.
BooleanOperator
Enum for decoding the boolean operator type.
ArithmeticOperation
Enum for decoding the comparison operator type.
Abstract base class for different kinds of events.