This template function creates a ExpressionNode from a boost::python::tuple The Python Parser encodes the node type as int in the first argument of each tuple.
142 {
143 if (py::len(tuple) == 0) B2FATAL("ExpressionNode tuple is empty, this is invalid.");
144
145
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]);
152 return std::unique_ptr<const AbstractExpressionNode<AVariableManager>>(new UnaryExpressionNode<AVariableManager>(node,
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]);
159 return std::unique_ptr<const AbstractExpressionNode<AVariableManager>>(new BinaryExpressionNode<AVariableManager>(left_node,
160 right_node,
161 aoperation));
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]);
167 return std::unique_ptr<const AbstractExpressionNode<AVariableManager>>(new DataNode<AVariableManager, int>(i));
168 } else {
169 B2WARNING("Overflow for integer constant in cut detected. Create Double Node instead.");
170 return std::unique_ptr<const AbstractExpressionNode<AVariableManager>>(new DataNode<AVariableManager, double>(d));
171 }
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)));
174
175
176 py::object math = py::import("math");
177
178 py::object data = static_cast<py::object>(tuple[1]);
179 if (py::extract<bool>(math.attr("isinf")(data))) {
180
181 double inf_sign = py::extract<double>(math.attr("copysign")(1.0, data));
182 double inf;
183 if (inf_sign > 0) {
184 inf = std::numeric_limits<double>::infinity();
185 } else {
186 inf = -1 * std::numeric_limits<double>::infinity();
187 }
188 return std::unique_ptr<const AbstractExpressionNode<AVariableManager>>(new DataNode<AVariableManager, double>(inf));
189 }
190 if (py::extract<bool>(math.attr("isnan")(data))) {
191 double nan = std::nan("");
192 return std::unique_ptr<const AbstractExpressionNode<AVariableManager>>(new DataNode<AVariableManager, double>(nan));
193 }
194 double d = py::extract<double>(tuple[1]);
195 return std::unique_ptr<const AbstractExpressionNode<AVariableManager>>(new DataNode<AVariableManager, double>(d));
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]);
199 return std::unique_ptr<const AbstractExpressionNode<AVariableManager>>(new DataNode<AVariableManager, bool>(b));
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]);
203 return std::unique_ptr<const AbstractExpressionNode<AVariableManager>>(new IdentifierNode<AVariableManager>(identifier));
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)));
206
207
208 std::string functionName = py::extract<std::string>(tuple[1]);
209
210
211 std::string argument = py::extract<std::string>(tuple[2]);
212 boost::algorithm::trim(argument);
213
215 for (auto& str : functionArguments) {
216 boost::algorithm::trim(str);
217 if (str.empty()) {
218 B2WARNING("Empty parameter for metavariable '" << functionName << "' in cut.");
219 }
220 }
221
222 return std::unique_ptr<const AbstractExpressionNode<AVariableManager>>(new FunctionNode<AVariableManager>(functionName,
223 functionArguments));
224 } else {
225 throw std::runtime_error("error NodeFactory::compile_expression_node: got invalid expression NodeType.");
226 }
227 }
std::vector< std::string > splitOnDelimiterAndConserveParenthesis(std::string str, char delimiter, char open, char close)
Split into std::vector on delimiter ignoring delimiters between parenthesis.
ArithmeticOperation
Enum for decoding the comparison operator type.