Apply clang-format-11
[alexxy/gromacs.git] / src / gromacs / selection / parsetree.h
1 /*
2  * This file is part of the GROMACS molecular simulation package.
3  *
4  * Copyright (c) 2009-2018, The GROMACS development team.
5  * Copyright (c) 2019,2021, 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.
9  *
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.
14  *
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.
19  *
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.
24  *
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.
32  *
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.
35  */
36 /*! \internal \file
37  * \brief
38  * Handling of intermediate selection parser data.
39  *
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
44  * be constructed.
45  *
46  * This is an implementation header: there should be no need to use it outside
47  * this directory.
48  *
49  * \author Teemu Murtola <teemu.murtola@gmail.com>
50  * \ingroup module_selection
51  */
52 #ifndef GMX_SELECTION_PARSETREE_H
53 #define GMX_SELECTION_PARSETREE_H
54
55 #include <exception>
56 #include <list>
57 #include <memory>
58 #include <string>
59
60 #include "gromacs/math/vec.h"
61 #include "gromacs/math/vectypes.h"
62 #include "gromacs/utility/gmxassert.h"
63 #include "gromacs/utility/real.h"
64
65 #include "selelem.h"
66 #include "selvalue.h"
67
68 struct gmx_ana_indexgrps_t;
69 struct gmx_ana_selmethod_t;
70 struct gmx_ana_selparam_t;
71
72 namespace gmx
73 {
74
75 //! \cond internal
76 /*! \internal \brief
77  * String matching mode for string keyword expressions.
78  *
79  * \ingroup module_selection
80  */
81 enum SelectionStringMatchType
82 {
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.
87 };
88 /*! \endcond */
89
90 class SelectionParserValue;
91
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;
96
97 /*! \internal
98  * \brief
99  * Describes a parsed value, possibly resulting from expression evaluation.
100  *
101  * All factory methods and the constructors may throw an std::bad_alloc if
102  * out of memory.
103  *
104  * \ingroup module_selection
105  */
106 class SelectionParserValue
107 {
108 public:
109     //! Allocates and initializes an empty value list.
110     static SelectionParserValueListPointer createList()
111     {
112         return std::make_unique<SelectionParserValueList>();
113     }
114     /*! \brief
115      * Allocates and initializes a value list with a single value.
116      *
117      * \param[in] value  Initial value to put in the list.
118      * \returns   Pointer to a new value list that contains \p value.
119      */
120     static SelectionParserValueListPointer createList(const SelectionParserValue& value)
121     {
122         SelectionParserValueListPointer list(new SelectionParserValueList);
123         list->push_back(value);
124         return list;
125     }
126     /*! \brief
127      * Allocates and initializes an expression value.
128      *
129      * \param[in] expr  Root of the expression tree to assign to the value.
130      * \returns   The newly created value.
131      */
132     static SelectionParserValue createExpr(const gmx::SelectionTreeElementPointer& expr)
133     {
134         return SelectionParserValue(expr);
135     }
136     /*! \brief
137      * Allocates and initializes a constant integer value.
138      *
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.
142      */
143     static SelectionParserValue createInteger(int value, const SelectionLocation& location)
144     {
145         SelectionParserValue result(INT_VALUE, location);
146         result.u.i.i1 = result.u.i.i2 = value;
147         return result;
148     }
149     /*! \brief
150      * Allocates and initializes a constant integer range value.
151      *
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.
156      */
157     static SelectionParserValue createIntegerRange(int from, int to, const SelectionLocation& location)
158     {
159         SelectionParserValue result(INT_VALUE, location);
160         result.u.i.i1 = from;
161         result.u.i.i2 = to;
162         return result;
163     }
164     /*! \brief
165      * Allocates and initializes a constant floating-point value.
166      *
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.
170      */
171     static SelectionParserValue createReal(real value, const SelectionLocation& location)
172     {
173         SelectionParserValue result(REAL_VALUE, location);
174         result.u.r.r1 = result.u.r.r2 = value;
175         return result;
176     }
177     /*! \brief
178      * Allocates and initializes a constant floating-point range value.
179      *
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.
184      */
185     static SelectionParserValue createRealRange(real from, real to, const SelectionLocation& location)
186     {
187         SelectionParserValue result(REAL_VALUE, location);
188         result.u.r.r1 = from;
189         result.u.r.r2 = to;
190         return result;
191     }
192     /*! \brief
193      * Allocates and initializes a constant string value.
194      *
195      * \param[in] value    String to assign to the value.
196      * \param[in] location Location of the value.
197      * \returns   The newly created value.
198      */
199     static SelectionParserValue createString(const char* value, const SelectionLocation& location)
200     {
201         SelectionParserValue result(STR_VALUE, location);
202         result.str = value;
203         return result;
204     }
205     /*! \brief
206      * Allocates and initializes a constant position value.
207      *
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.
211      */
212     static SelectionParserValue createPosition(rvec value, const SelectionLocation& location)
213     {
214         SelectionParserValue result(POS_VALUE, location);
215         copy_rvec(value, result.u.x);
216         return result;
217     }
218
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); }
223
224     //! Returns the string value (\a type must be ::STR_VALUE).
225     const std::string& stringValue() const
226     {
227         GMX_ASSERT(type == STR_VALUE && !hasExpressionValue(),
228                    "Attempted to retrieve string value from a non-string value");
229         return str;
230     }
231
232     // TODO: boost::any or similar could be nicer for the implementation.
233     //! Type of the value.
234     e_selvalue_t type;
235     //! Expression pointer if the value is the result of an expression.
236     gmx::SelectionTreeElementPointer expr;
237     //! String value for \a type ::STR_VALUE.
238     std::string str;
239     //! The actual value if \a expr is NULL and \a type is not ::STR_VALUE.
240     union
241     {
242         //! The integer value/range (\a type ::INT_VALUE).
243         struct
244         {
245             //! Beginning of the range.
246             int i1;
247             //! End of the range; equals \a i1 for a single integer.
248             int i2;
249         } i;
250         //! The real value/range (\a type ::REAL_VALUE).
251         struct
252         {
253             //! Beginning of the range.
254             real r1;
255             //! End of the range; equals \a r1 for a single number.
256             real r2;
257         } r;
258         //! The position value (\a type ::POS_VALUE).
259         rvec x;
260     } u;
261
262 private:
263     /*! \brief
264      * Initializes a new value.
265      *
266      * \param[in] type     Type for the new value.
267      * \param[in] location Location for the value.
268      */
269     SelectionParserValue(e_selvalue_t type, const SelectionLocation& location);
270     /*! \brief
271      * Initializes a new expression value.
272      *
273      * \param[in] expr  Expression for the value.
274      */
275     explicit SelectionParserValue(const gmx::SelectionTreeElementPointer& expr);
276
277     //! Location of the value in the parsed text.
278     SelectionLocation location_;
279 };
280
281 class SelectionParserParameter;
282
283 //! Container for a list of SelectionParserParameter objects.
284 typedef std::list<SelectionParserParameter> SelectionParserParameterList;
285 //! Smart pointer type for managing a SelectionParserParameterList.
286 typedef std::unique_ptr<SelectionParserParameterList> SelectionParserParameterListPointer;
287
288 /*! \internal \brief
289  * Describes a parsed method parameter.
290  *
291  * \ingroup module_selection
292  */
293 class SelectionParserParameter
294 {
295 public:
296     // Default move constructor and assignment. Only needed for old compilers.
297     //! \cond
298     SelectionParserParameter(SelectionParserParameter&& o) noexcept :
299         name_(std::move(o.name_)), location_(o.location_), values_(std::move(o.values_))
300     {
301     }
302
303     SelectionParserParameter& operator=(SelectionParserParameter&& o) noexcept
304     {
305         name_     = std::move(o.name_);
306         location_ = o.location_;
307         values_   = std::move(o.values_);
308         return *this;
309     }
310     //! \endcond
311
312     //! Allocates and initializes an empty parameter list.
313     static SelectionParserParameterListPointer createList()
314     {
315         return std::make_unique<SelectionParserParameterList>();
316     }
317     /*! \brief
318      * Allocates and initializes a parsed method parameter.
319      *
320      * \param[in] name     Name for the new parameter (can be NULL).
321      * \param[in] values   List of values for the parameter.
322      * \param[in] location Location of the parameter.
323      * \returns   Pointer to the newly allocated parameter.
324      * \throws    std::bad_alloc if out of memory.
325      */
326     static SelectionParserParameter create(const char*                     name,
327                                            SelectionParserValueListPointer values,
328                                            const SelectionLocation&        location)
329     {
330         return SelectionParserParameter(name, std::move(values), location);
331     }
332     //! \copydoc create(const char *, SelectionParserValueListPointer, const SelectionLocation &)
333     static SelectionParserParameter create(const std::string&              name,
334                                            SelectionParserValueListPointer values,
335                                            const SelectionLocation&        location)
336     {
337         return SelectionParserParameter(name.c_str(), std::move(values), location);
338     }
339     /*! \brief
340      * Allocates and initializes a parsed method parameter.
341      *
342      * \param[in] name     Name for the new parameter (can be NULL).
343      * \param[in] value    Value for the parameter.
344      * \param[in] location Location of the parameter.
345      * \returns   Pointer to the newly allocated parameter.
346      * \throws    std::bad_alloc if out of memory.
347      *
348      * This overload is a convenience wrapper for the case when creating
349      * parameters outside the actual Bison parser and only a single value
350      * is necessary.
351      */
352     static SelectionParserParameter create(const char*                 name,
353                                            const SelectionParserValue& value,
354                                            const SelectionLocation&    location)
355     {
356         return create(name, SelectionParserValue::createList(value), location);
357     }
358     /*! \brief
359      * Allocates and initializes a parsed method parameter.
360      *
361      * \param[in] name    Name for the new parameter (can be NULL).
362      * \param[in] expr    Expression value for the parameter.
363      * \returns   Pointer to the newly allocated parameter.
364      * \throws    std::bad_alloc if out of memory.
365      *
366      * This overload is a convenience wrapper for the case when creating
367      * parameters outside the actual Bison parser and only a single
368      * expression value is necessary.
369      */
370     static SelectionParserParameter createFromExpression(const char*                        name,
371                                                          const SelectionTreeElementPointer& expr)
372     {
373         return create(name, SelectionParserValue::createExpr(expr), expr->location());
374     }
375     //! \copydoc createFromExpression(const char *, const SelectionTreeElementPointer &)
376     static SelectionParserParameter createFromExpression(const std::string&                 name,
377                                                          const SelectionTreeElementPointer& expr)
378     {
379         return create(name.c_str(), SelectionParserValue::createExpr(expr), expr->location());
380     }
381
382     //! Returns the name of the parameter (may be empty).
383     const std::string& name() const { return name_; }
384     //! Returns the location of this parameter in the parsed selection text.
385     const SelectionLocation& location() const { return location_; }
386     //! Returns the values for the parameter.
387     const SelectionParserValueList& values() const { return *values_; }
388
389 private:
390     /*! \brief
391      * Initializes a parsed method parameter.
392      *
393      * \param[in] name     Name for the new parameter (can be NULL).
394      * \param[in] values   List of values for the parameter.
395      * \param[in] location Location of the parameter.
396      * \throws    std::bad_alloc if out of memory.
397      */
398     SelectionParserParameter(const char*                     name,
399                              SelectionParserValueListPointer values,
400                              const SelectionLocation&        location);
401
402     //! Name of the parameter.
403     std::string name_;
404     //! Location of the parameter in the parsed text.
405     SelectionLocation location_;
406
407     // TODO: Make private, there is only one direct user.
408 public:
409     //! Values for this parameter.
410     SelectionParserValueListPointer values_;
411 };
412
413 } // namespace gmx
414
415 /*! \brief
416  * Handles exceptions caught within the Bison code.
417  *
418  * \retval `true`  if the parser should attempt error recovery.
419  * \retval `false` if the parser should immediately abort.
420  *
421  * This function is called whenever an exception is caught within Bison
422  * actions.  Since exceptions cannot propagate through Bison code, the
423  * exception is saved (potentially with some extra context information) so that
424  * the caller of the parser can rethrow the exception.
425  *
426  * If it is possible to recover from the exception, then the function returns
427  * `true`, and Bison enters error recovery state.  At the end of the recovery,
428  * _gmx_selparser_handle_error() is called.
429  * If this function returns false, then Bison immediately aborts the parsing
430  * so that the caller can rethrow the exception.
431  */
432 bool _gmx_selparser_handle_exception(void* scanner, std::exception* ex);
433 /*! \brief
434  * Handles errors in the selection parser.
435  *
436  * \returns `true` if parsing can continue with the next selection.
437  * \throws  std::bad_alloc if out of memory during the error processing.
438  * \throws  unspecified    Can throw the stored exception if recovery from that
439  *     exception is not possible.
440  *
441  * This function is called during error recovery, after Bison has discarded all
442  * the symbols for the erroneous selection.
443  * At this point, the full selection that caused the error is known, and can be
444  * added to the error context.
445  *
446  * For an interactive parser, this function returns `true` to let the parsing
447  * continue with the next selection, or to let the user enter the next
448  * selection, if it was possible to recover from the exception.
449  * For other cases, this will either rethrow the original exception with added
450  * context, or return `false` after adding the context to the error reporter.
451  * Any exceptions thrown from this method are again caught by Bison and result
452  * in termination of the parsing; the caller can then rethrow them.
453  */
454 bool _gmx_selparser_handle_error(void* scanner);
455
456 /** Propagates the flags for selection elements. */
457 void _gmx_selelem_update_flags(const gmx::SelectionTreeElementPointer& sel);
458
459 /** Initializes the method parameter data of \ref SEL_EXPRESSION and
460  * \ref SEL_MODIFIER elements. */
461 void _gmx_selelem_init_method_params(const gmx::SelectionTreeElementPointer& sel, void* scanner);
462 /** Initializes the method for a \ref SEL_EXPRESSION selection element. */
463 void _gmx_selelem_set_method(const gmx::SelectionTreeElementPointer& sel,
464                              struct gmx_ana_selmethod_t*             method,
465                              void*                                   scanner);
466
467 /* An opaque pointer. */
468 #ifndef YY_TYPEDEF_YY_SCANNER_T
469 #    define YY_TYPEDEF_YY_SCANNER_T
470 typedef void* yyscan_t;
471 #endif
472 /** \brief Creates a gmx::SelectionTreeElement for arithmetic expression evaluation.
473  *
474  * \param[in]  left    Selection element for the left hand side.
475  * \param[in]  right   Selection element for the right hand side.
476  * \param[in]  op      String representation of the operator.
477  * \param[in]  scanner Scanner data structure.
478  * \returns    The created selection element.
479  *
480  * This function handles the creation of a gmx::SelectionTreeElement object for
481  * arithmetic expressions.
482  */
483 gmx::SelectionTreeElementPointer _gmx_sel_init_arithmetic(const gmx::SelectionTreeElementPointer& left,
484                                                           const gmx::SelectionTreeElementPointer& right,
485                                                           char     op,
486                                                           yyscan_t scanner);
487 /** Creates a gmx::SelectionTreeElement for comparsion expression evaluation. */
488 gmx::SelectionTreeElementPointer _gmx_sel_init_comparison(const gmx::SelectionTreeElementPointer& left,
489                                                           const gmx::SelectionTreeElementPointer& right,
490                                                           const char* cmpop,
491                                                           void*       scanner);
492 /** Creates a gmx::SelectionTreeElement for a keyword expression from the parsed data. */
493 gmx::SelectionTreeElementPointer _gmx_sel_init_keyword(struct gmx_ana_selmethod_t*          method,
494                                                        gmx::SelectionParserValueListPointer args,
495                                                        const char*                          rpost,
496                                                        void* scanner);
497 /** Creates a gmx::SelectionTreeElement for string-matching keyword expression. */
498 gmx::SelectionTreeElementPointer _gmx_sel_init_keyword_strmatch(struct gmx_ana_selmethod_t* method,
499                                                                 gmx::SelectionStringMatchType matchType,
500                                                                 gmx::SelectionParserValueListPointer args,
501                                                                 const char* rpost,
502                                                                 void*       scanner);
503 /** Creates a gmx::SelectionTreeElement for "keyword of" expression. */
504 gmx::SelectionTreeElementPointer _gmx_sel_init_keyword_of(struct gmx_ana_selmethod_t* method,
505                                                           const gmx::SelectionTreeElementPointer& group,
506                                                           const char* rpost,
507                                                           void*       scanner);
508 /** Creates a gmx::SelectionTreeElement for a method expression from the parsed data. */
509 gmx::SelectionTreeElementPointer _gmx_sel_init_method(struct gmx_ana_selmethod_t* method,
510                                                       gmx::SelectionParserParameterListPointer params,
511                                                       const char* rpost,
512                                                       void*       scanner);
513 /** Creates a gmx::SelectionTreeElement for a modifier expression from the parsed data. */
514 gmx::SelectionTreeElementPointer _gmx_sel_init_modifier(struct gmx_ana_selmethod_t* mod,
515                                                         gmx::SelectionParserParameterListPointer params,
516                                                         const gmx::SelectionTreeElementPointer& sel,
517                                                         void* scanner);
518 /** Creates a gmx::SelectionTreeElement for evaluation of reference positions. */
519 gmx::SelectionTreeElementPointer _gmx_sel_init_position(const gmx::SelectionTreeElementPointer& expr,
520                                                         const char* type,
521                                                         void*       scanner);
522
523 /** Creates a gmx::SelectionTreeElement for a constant position. */
524 gmx::SelectionTreeElementPointer _gmx_sel_init_const_position(real x, real y, real z, void* scanner);
525 /** Creates a gmx::SelectionTreeElement for a index group expression using group name. */
526 gmx::SelectionTreeElementPointer _gmx_sel_init_group_by_name(const char* name, void* scanner);
527 /** Creates a gmx::SelectionTreeElement for a index group expression using group index. */
528 gmx::SelectionTreeElementPointer _gmx_sel_init_group_by_id(int id, void* scanner);
529 /** Creates a gmx::SelectionTreeElement for a variable reference */
530 gmx::SelectionTreeElementPointer _gmx_sel_init_variable_ref(const gmx::SelectionTreeElementPointer& sel,
531                                                             void* scanner);
532
533 /** Creates a root gmx::SelectionTreeElement for a selection. */
534 gmx::SelectionTreeElementPointer _gmx_sel_init_selection(const char* name,
535                                                          const gmx::SelectionTreeElementPointer& sel,
536                                                          void* scanner);
537 /** Creates a root gmx::SelectionTreeElement elements for a variable assignment. */
538 gmx::SelectionTreeElementPointer _gmx_sel_assign_variable(const char* name,
539                                                           const gmx::SelectionTreeElementPointer& expr,
540                                                           void* scanner);
541 /** Appends a root gmx::SelectionTreeElement to a selection collection. */
542 gmx::SelectionTreeElementPointer _gmx_sel_append_selection(const gmx::SelectionTreeElementPointer& sel,
543                                                            gmx::SelectionTreeElementPointer last,
544                                                            void* scanner);
545 /** Check whether the parser should finish. */
546 bool _gmx_sel_parser_should_finish(void* scanner);
547
548 /* In params.c */
549 /** Initializes an array of parameters based on input from the selection parser. */
550 void _gmx_sel_parse_params(const gmx::SelectionParserParameterList& params,
551                            int                                      nparam,
552                            struct gmx_ana_selparam_t*               param,
553                            const gmx::SelectionTreeElementPointer&  root,
554                            void*                                    scanner);
555
556 #endif