2 * This file is part of the GROMACS molecular simulation package.
4 * Copyright (c) 2009-2018, The GROMACS development team.
5 * Copyright (c) 2019, by the GROMACS development team, led by
6 * Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
7 * and including many others, as listed in the AUTHORS file in the
8 * top-level source directory and at http://www.gromacs.org.
10 * GROMACS is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU Lesser General Public License
12 * as published by the Free Software Foundation; either version 2.1
13 * of the License, or (at your option) any later version.
15 * GROMACS is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 * Lesser General Public License for more details.
20 * You should have received a copy of the GNU Lesser General Public
21 * License along with GROMACS; if not, see
22 * http://www.gnu.org/licenses, or write to the Free Software Foundation,
23 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
25 * If you want to redistribute modifications to GROMACS, please
26 * consider that scientific software is very special. Version
27 * control is crucial - bugs must be traceable. We will be happy to
28 * consider code for inclusion in the official distribution, but
29 * derived work must not be called official GROMACS. Details are found
30 * in the README & COPYING files - if they are missing, get the
31 * official version at http://www.gromacs.org.
33 * To help us fund GROMACS development, we humbly ask that you cite
34 * the research papers on the package. Check out http://www.gromacs.org.
38 * Handling of intermediate selection parser data.
40 * The data types declared in this header are used by the parser to store
41 * intermediate data when constructing method expressions.
42 * In particular, the parameters for the method are stored.
43 * The intermediate data is freed once a gmx::SelectionTreeElement object can
46 * This is an implementation header: there should be no need to use it outside
49 * \author Teemu Murtola <teemu.murtola@gmail.com>
50 * \ingroup module_selection
52 #ifndef GMX_SELECTION_PARSETREE_H
53 #define GMX_SELECTION_PARSETREE_H
60 #include "gromacs/math/vec.h"
61 #include "gromacs/math/vectypes.h"
62 #include "gromacs/utility/gmxassert.h"
63 #include "gromacs/utility/real.h"
68 struct gmx_ana_indexgrps_t;
69 struct gmx_ana_selmethod_t;
70 struct gmx_ana_selparam_t;
77 * String matching mode for string keyword expressions.
79 * \ingroup module_selection
81 enum SelectionStringMatchType
83 eStringMatchType_Auto, //!< Deduce from the string.
84 eStringMatchType_Exact, //!< Match as a literal string.
85 eStringMatchType_Wildcard, //!< Match using ? and * as wildcards.
86 eStringMatchType_RegularExpression //!< Match using regular expressions.
90 class SelectionParserValue;
92 //! Container for a list of SelectionParserValue objects.
93 typedef std::list<SelectionParserValue> SelectionParserValueList;
94 //! Smart pointer type for managing a SelectionParserValueList.
95 typedef std::unique_ptr<SelectionParserValueList> SelectionParserValueListPointer;
99 * Describes a parsed value, possibly resulting from expression evaluation.
101 * All factory methods and the constructors may throw an std::bad_alloc if
104 * \ingroup module_selection
106 class SelectionParserValue
109 //! Allocates and initializes an empty value list.
110 static SelectionParserValueListPointer createList()
112 return std::make_unique<SelectionParserValueList>();
115 * Allocates and initializes a value list with a single value.
117 * \param[in] value Initial value to put in the list.
118 * \returns Pointer to a new value list that contains \p value.
120 static SelectionParserValueListPointer createList(const SelectionParserValue& value)
122 SelectionParserValueListPointer list(new SelectionParserValueList);
123 list->push_back(value);
127 * Allocates and initializes an expression value.
129 * \param[in] expr Root of the expression tree to assign to the value.
130 * \returns The newly created value.
132 static SelectionParserValue createExpr(const gmx::SelectionTreeElementPointer& expr)
134 return SelectionParserValue(expr);
137 * Allocates and initializes a constant integer value.
139 * \param[in] value Integer value to assign to the value.
140 * \param[in] location Location of the value.
141 * \returns The newly created value.
143 static SelectionParserValue createInteger(int value, const SelectionLocation& location)
145 SelectionParserValue result(INT_VALUE, location);
146 result.u.i.i1 = result.u.i.i2 = value;
150 * Allocates and initializes a constant integer range value.
152 * \param[in] from Beginning of the range to assign to the value.
153 * \param[in] to End of the range to assign to the value.
154 * \param[in] location Location of the value.
155 * \returns The newly created value.
157 static SelectionParserValue createIntegerRange(int from, int to, const SelectionLocation& location)
159 SelectionParserValue result(INT_VALUE, location);
160 result.u.i.i1 = from;
165 * Allocates and initializes a constant floating-point value.
167 * \param[in] value Floating-point value to assign to the value.
168 * \param[in] location Location of the value.
169 * \returns The newly created value.
171 static SelectionParserValue createReal(real value, const SelectionLocation& location)
173 SelectionParserValue result(REAL_VALUE, location);
174 result.u.r.r1 = result.u.r.r2 = value;
178 * Allocates and initializes a constant floating-point range value.
180 * \param[in] from Beginning of the range to assign to the value.
181 * \param[in] to End of the range to assign to the value.
182 * \param[in] location Location of the value.
183 * \returns The newly created value.
185 static SelectionParserValue createRealRange(real from, real to, const SelectionLocation& location)
187 SelectionParserValue result(REAL_VALUE, location);
188 result.u.r.r1 = from;
193 * Allocates and initializes a constant string value.
195 * \param[in] value String to assign to the value.
196 * \param[in] location Location of the value.
197 * \returns The newly created value.
199 static SelectionParserValue createString(const char* value, const SelectionLocation& location)
201 SelectionParserValue result(STR_VALUE, location);
206 * Allocates and initializes a constant position value.
208 * \param[in] value Position vector to assign to the value.
209 * \param[in] location Location of the value.
210 * \returns The newly created value.
212 static SelectionParserValue createPosition(rvec value, const SelectionLocation& location)
214 SelectionParserValue result(POS_VALUE, location);
215 copy_rvec(value, result.u.x);
219 //! Returns the location of this value in the parsed selection text.
220 const SelectionLocation& location() const { return location_; }
221 //! Returns true if the value comes from expression evaluation.
222 bool hasExpressionValue() const { return static_cast<bool>(expr); }
224 //! Returns the string value (\a type must be ::STR_VALUE).
225 const std::string& stringValue() const
227 GMX_ASSERT(type == STR_VALUE && !hasExpressionValue(),
228 "Attempted to retrieve string value from a non-string value");
232 // TODO: boost::any or similar could be nicer for the implementation.
233 //! Type of the value.
235 //! Expression pointer if the value is the result of an expression.
236 gmx::SelectionTreeElementPointer expr;
237 //! String value for \a type ::STR_VALUE.
239 //! The actual value if \a expr is NULL and \a type is not ::STR_VALUE.
241 //! The integer value/range (\a type ::INT_VALUE).
244 //! Beginning of the range.
246 //! End of the range; equals \a i1 for a single integer.
249 //! The real value/range (\a type ::REAL_VALUE).
252 //! Beginning of the range.
254 //! End of the range; equals \a r1 for a single number.
257 //! The position value (\a type ::POS_VALUE).
263 * Initializes a new value.
265 * \param[in] type Type for the new value.
266 * \param[in] location Location for the value.
268 SelectionParserValue(e_selvalue_t type, const SelectionLocation& location);
270 * Initializes a new expression value.
272 * \param[in] expr Expression for the value.
274 explicit SelectionParserValue(const gmx::SelectionTreeElementPointer& expr);
276 //! Location of the value in the parsed text.
277 SelectionLocation location_;
280 class SelectionParserParameter;
282 //! Container for a list of SelectionParserParameter objects.
283 typedef std::list<SelectionParserParameter> SelectionParserParameterList;
284 //! Smart pointer type for managing a SelectionParserParameterList.
285 typedef std::unique_ptr<SelectionParserParameterList> SelectionParserParameterListPointer;
288 * Describes a parsed method parameter.
290 * \ingroup module_selection
292 class SelectionParserParameter
295 // Default move constructor and assignment. Only needed for old compilers.
297 SelectionParserParameter(SelectionParserParameter&& o) noexcept :
298 name_(std::move(o.name_)),
299 location_(o.location_),
300 values_(std::move(o.values_))
304 SelectionParserParameter& operator=(SelectionParserParameter&& o) noexcept
306 name_ = std::move(o.name_);
307 location_ = o.location_;
308 values_ = std::move(o.values_);
313 //! Allocates and initializes an empty parameter list.
314 static SelectionParserParameterListPointer createList()
316 return std::make_unique<SelectionParserParameterList>();
319 * Allocates and initializes a parsed method parameter.
321 * \param[in] name Name for the new parameter (can be NULL).
322 * \param[in] values List of values for the parameter.
323 * \param[in] location Location of the parameter.
324 * \returns Pointer to the newly allocated parameter.
325 * \throws std::bad_alloc if out of memory.
327 static SelectionParserParameter create(const char* name,
328 SelectionParserValueListPointer values,
329 const SelectionLocation& location)
331 return SelectionParserParameter(name, std::move(values), location);
333 //! \copydoc create(const char *, SelectionParserValueListPointer, const SelectionLocation &)
334 static SelectionParserParameter create(const std::string& name,
335 SelectionParserValueListPointer values,
336 const SelectionLocation& location)
338 return SelectionParserParameter(name.c_str(), std::move(values), location);
341 * Allocates and initializes a parsed method parameter.
343 * \param[in] name Name for the new parameter (can be NULL).
344 * \param[in] value Value for the parameter.
345 * \param[in] location Location of the parameter.
346 * \returns Pointer to the newly allocated parameter.
347 * \throws std::bad_alloc if out of memory.
349 * This overload is a convenience wrapper for the case when creating
350 * parameters outside the actual Bison parser and only a single value
353 static SelectionParserParameter create(const char* name,
354 const SelectionParserValue& value,
355 const SelectionLocation& location)
357 return create(name, SelectionParserValue::createList(value), location);
360 * Allocates and initializes a parsed method parameter.
362 * \param[in] name Name for the new parameter (can be NULL).
363 * \param[in] expr Expression value for the parameter.
364 * \returns Pointer to the newly allocated parameter.
365 * \throws std::bad_alloc if out of memory.
367 * This overload is a convenience wrapper for the case when creating
368 * parameters outside the actual Bison parser and only a single
369 * expression value is necessary.
371 static SelectionParserParameter createFromExpression(const char* name,
372 const SelectionTreeElementPointer& expr)
374 return create(name, SelectionParserValue::createExpr(expr), expr->location());
376 //! \copydoc createFromExpression(const char *, const SelectionTreeElementPointer &)
377 static SelectionParserParameter createFromExpression(const std::string& name,
378 const SelectionTreeElementPointer& expr)
380 return create(name.c_str(), SelectionParserValue::createExpr(expr), expr->location());
383 //! Returns the name of the parameter (may be empty).
384 const std::string& name() const { return name_; }
385 //! Returns the location of this parameter in the parsed selection text.
386 const SelectionLocation& location() const { return location_; }
387 //! Returns the values for the parameter.
388 const SelectionParserValueList& values() const { return *values_; }
392 * Initializes a parsed method parameter.
394 * \param[in] name Name for the new parameter (can be NULL).
395 * \param[in] values List of values for the parameter.
396 * \param[in] location Location of the parameter.
397 * \throws std::bad_alloc if out of memory.
399 SelectionParserParameter(const char* name,
400 SelectionParserValueListPointer values,
401 const SelectionLocation& location);
403 //! Name of the parameter.
405 //! Location of the parameter in the parsed text.
406 SelectionLocation location_;
408 // TODO: Make private, there is only one direct user.
410 //! Values for this parameter.
411 SelectionParserValueListPointer values_;
417 * Handles exceptions caught within the Bison code.
419 * \retval `true` if the parser should attempt error recovery.
420 * \retval `false` if the parser should immediately abort.
422 * This function is called whenever an exception is caught within Bison
423 * actions. Since exceptions cannot propagate through Bison code, the
424 * exception is saved (potentially with some extra context information) so that
425 * the caller of the parser can rethrow the exception.
427 * If it is possible to recover from the exception, then the function returns
428 * `true`, and Bison enters error recovery state. At the end of the recovery,
429 * _gmx_selparser_handle_error() is called.
430 * If this function returns false, then Bison immediately aborts the parsing
431 * so that the caller can rethrow the exception.
433 bool _gmx_selparser_handle_exception(void* scanner, std::exception* ex);
435 * Handles errors in the selection parser.
437 * \returns `true` if parsing can continue with the next selection.
438 * \throws std::bad_alloc if out of memory during the error processing.
439 * \throws unspecified Can throw the stored exception if recovery from that
440 * exception is not possible.
442 * This function is called during error recovery, after Bison has discarded all
443 * the symbols for the erroneous selection.
444 * At this point, the full selection that caused the error is known, and can be
445 * added to the error context.
447 * For an interactive parser, this function returns `true` to let the parsing
448 * continue with the next selection, or to let the user enter the next
449 * selection, if it was possible to recover from the exception.
450 * For other cases, this will either rethrow the original exception with added
451 * context, or return `false` after adding the context to the error reporter.
452 * Any exceptions thrown from this method are again caught by Bison and result
453 * in termination of the parsing; the caller can then rethrow them.
455 bool _gmx_selparser_handle_error(void* scanner);
457 /** Propagates the flags for selection elements. */
458 void _gmx_selelem_update_flags(const gmx::SelectionTreeElementPointer& sel);
460 /** Initializes the method parameter data of \ref SEL_EXPRESSION and
461 * \ref SEL_MODIFIER elements. */
462 void _gmx_selelem_init_method_params(const gmx::SelectionTreeElementPointer& sel, void* scanner);
463 /** Initializes the method for a \ref SEL_EXPRESSION selection element. */
464 void _gmx_selelem_set_method(const gmx::SelectionTreeElementPointer& sel,
465 struct gmx_ana_selmethod_t* method,
468 /* An opaque pointer. */
469 #ifndef YY_TYPEDEF_YY_SCANNER_T
470 # define YY_TYPEDEF_YY_SCANNER_T
471 typedef void* yyscan_t;
473 /** \brief Creates a gmx::SelectionTreeElement for arithmetic expression evaluation.
475 * \param[in] left Selection element for the left hand side.
476 * \param[in] right Selection element for the right hand side.
477 * \param[in] op String representation of the operator.
478 * \param[in] scanner Scanner data structure.
479 * \returns The created selection element.
481 * This function handles the creation of a gmx::SelectionTreeElement object for
482 * arithmetic expressions.
484 gmx::SelectionTreeElementPointer _gmx_sel_init_arithmetic(const gmx::SelectionTreeElementPointer& left,
485 const gmx::SelectionTreeElementPointer& right,
488 /** Creates a gmx::SelectionTreeElement for comparsion expression evaluation. */
489 gmx::SelectionTreeElementPointer _gmx_sel_init_comparison(const gmx::SelectionTreeElementPointer& left,
490 const gmx::SelectionTreeElementPointer& right,
493 /** Creates a gmx::SelectionTreeElement for a keyword expression from the parsed data. */
494 gmx::SelectionTreeElementPointer _gmx_sel_init_keyword(struct gmx_ana_selmethod_t* method,
495 gmx::SelectionParserValueListPointer args,
498 /** Creates a gmx::SelectionTreeElement for string-matching keyword expression. */
499 gmx::SelectionTreeElementPointer _gmx_sel_init_keyword_strmatch(struct gmx_ana_selmethod_t* method,
500 gmx::SelectionStringMatchType matchType,
501 gmx::SelectionParserValueListPointer args,
504 /** Creates a gmx::SelectionTreeElement for "keyword of" expression. */
505 gmx::SelectionTreeElementPointer _gmx_sel_init_keyword_of(struct gmx_ana_selmethod_t* method,
506 const gmx::SelectionTreeElementPointer& group,
509 /** Creates a gmx::SelectionTreeElement for a method expression from the parsed data. */
510 gmx::SelectionTreeElementPointer _gmx_sel_init_method(struct gmx_ana_selmethod_t* method,
511 gmx::SelectionParserParameterListPointer params,
514 /** Creates a gmx::SelectionTreeElement for a modifier expression from the parsed data. */
515 gmx::SelectionTreeElementPointer _gmx_sel_init_modifier(struct gmx_ana_selmethod_t* mod,
516 gmx::SelectionParserParameterListPointer params,
517 const gmx::SelectionTreeElementPointer& sel,
519 /** Creates a gmx::SelectionTreeElement for evaluation of reference positions. */
520 gmx::SelectionTreeElementPointer _gmx_sel_init_position(const gmx::SelectionTreeElementPointer& expr,
524 /** Creates a gmx::SelectionTreeElement for a constant position. */
525 gmx::SelectionTreeElementPointer _gmx_sel_init_const_position(real x, real y, real z, void* scanner);
526 /** Creates a gmx::SelectionTreeElement for a index group expression using group name. */
527 gmx::SelectionTreeElementPointer _gmx_sel_init_group_by_name(const char* name, void* scanner);
528 /** Creates a gmx::SelectionTreeElement for a index group expression using group index. */
529 gmx::SelectionTreeElementPointer _gmx_sel_init_group_by_id(int id, void* scanner);
530 /** Creates a gmx::SelectionTreeElement for a variable reference */
531 gmx::SelectionTreeElementPointer _gmx_sel_init_variable_ref(const gmx::SelectionTreeElementPointer& sel,
534 /** Creates a root gmx::SelectionTreeElement for a selection. */
535 gmx::SelectionTreeElementPointer _gmx_sel_init_selection(const char* name,
536 const gmx::SelectionTreeElementPointer& sel,
538 /** Creates a root gmx::SelectionTreeElement elements for a variable assignment. */
539 gmx::SelectionTreeElementPointer _gmx_sel_assign_variable(const char* name,
540 const gmx::SelectionTreeElementPointer& expr,
542 /** Appends a root gmx::SelectionTreeElement to a selection collection. */
543 gmx::SelectionTreeElementPointer _gmx_sel_append_selection(const gmx::SelectionTreeElementPointer& sel,
544 gmx::SelectionTreeElementPointer last,
546 /** Check whether the parser should finish. */
547 bool _gmx_sel_parser_should_finish(void* scanner);
550 /** Initializes an array of parameters based on input from the selection parser. */
551 void _gmx_sel_parse_params(const gmx::SelectionParserParameterList& params,
553 struct gmx_ana_selparam_t* param,
554 const gmx::SelectionTreeElementPointer& root,