Apply clang-format to source tree
[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, 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         //! The integer value/range (\a type ::INT_VALUE).
242         struct
243         {
244             //! Beginning of the range.
245             int i1;
246             //! End of the range; equals \a i1 for a single integer.
247             int i2;
248         } i;
249         //! The real value/range (\a type ::REAL_VALUE).
250         struct
251         {
252             //! Beginning of the range.
253             real r1;
254             //! End of the range; equals \a r1 for a single number.
255             real r2;
256         } r;
257         //! The position value (\a type ::POS_VALUE).
258         rvec x;
259     } u;
260
261 private:
262     /*! \brief
263      * Initializes a new value.
264      *
265      * \param[in] type     Type for the new value.
266      * \param[in] location Location for the value.
267      */
268     SelectionParserValue(e_selvalue_t type, const SelectionLocation& location);
269     /*! \brief
270      * Initializes a new expression value.
271      *
272      * \param[in] expr  Expression for the value.
273      */
274     explicit SelectionParserValue(const gmx::SelectionTreeElementPointer& expr);
275
276     //! Location of the value in the parsed text.
277     SelectionLocation location_;
278 };
279
280 class SelectionParserParameter;
281
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;
286
287 /*! \internal \brief
288  * Describes a parsed method parameter.
289  *
290  * \ingroup module_selection
291  */
292 class SelectionParserParameter
293 {
294 public:
295     // Default move constructor and assignment. Only needed for old compilers.
296     //! \cond
297     SelectionParserParameter(SelectionParserParameter&& o) noexcept :
298         name_(std::move(o.name_)),
299         location_(o.location_),
300         values_(std::move(o.values_))
301     {
302     }
303
304     SelectionParserParameter& operator=(SelectionParserParameter&& o) noexcept
305     {
306         name_     = std::move(o.name_);
307         location_ = o.location_;
308         values_   = std::move(o.values_);
309         return *this;
310     }
311     //! \endcond
312
313     //! Allocates and initializes an empty parameter list.
314     static SelectionParserParameterListPointer createList()
315     {
316         return std::make_unique<SelectionParserParameterList>();
317     }
318     /*! \brief
319      * Allocates and initializes a parsed method parameter.
320      *
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.
326      */
327     static SelectionParserParameter create(const char*                     name,
328                                            SelectionParserValueListPointer values,
329                                            const SelectionLocation&        location)
330     {
331         return SelectionParserParameter(name, std::move(values), location);
332     }
333     //! \copydoc create(const char *, SelectionParserValueListPointer, const SelectionLocation &)
334     static SelectionParserParameter create(const std::string&              name,
335                                            SelectionParserValueListPointer values,
336                                            const SelectionLocation&        location)
337     {
338         return SelectionParserParameter(name.c_str(), std::move(values), location);
339     }
340     /*! \brief
341      * Allocates and initializes a parsed method parameter.
342      *
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.
348      *
349      * This overload is a convenience wrapper for the case when creating
350      * parameters outside the actual Bison parser and only a single value
351      * is necessary.
352      */
353     static SelectionParserParameter create(const char*                 name,
354                                            const SelectionParserValue& value,
355                                            const SelectionLocation&    location)
356     {
357         return create(name, SelectionParserValue::createList(value), location);
358     }
359     /*! \brief
360      * Allocates and initializes a parsed method parameter.
361      *
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.
366      *
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.
370      */
371     static SelectionParserParameter createFromExpression(const char*                        name,
372                                                          const SelectionTreeElementPointer& expr)
373     {
374         return create(name, SelectionParserValue::createExpr(expr), expr->location());
375     }
376     //! \copydoc createFromExpression(const char *, const SelectionTreeElementPointer &)
377     static SelectionParserParameter createFromExpression(const std::string&                 name,
378                                                          const SelectionTreeElementPointer& expr)
379     {
380         return create(name.c_str(), SelectionParserValue::createExpr(expr), expr->location());
381     }
382
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_; }
389
390 private:
391     /*! \brief
392      * Initializes a parsed method parameter.
393      *
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.
398      */
399     SelectionParserParameter(const char*                     name,
400                              SelectionParserValueListPointer values,
401                              const SelectionLocation&        location);
402
403     //! Name of the parameter.
404     std::string name_;
405     //! Location of the parameter in the parsed text.
406     SelectionLocation location_;
407
408     // TODO: Make private, there is only one direct user.
409 public:
410     //! Values for this parameter.
411     SelectionParserValueListPointer values_;
412 };
413
414 } // namespace gmx
415
416 /*! \brief
417  * Handles exceptions caught within the Bison code.
418  *
419  * \retval `true`  if the parser should attempt error recovery.
420  * \retval `false` if the parser should immediately abort.
421  *
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.
426  *
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.
432  */
433 bool _gmx_selparser_handle_exception(void* scanner, std::exception* ex);
434 /*! \brief
435  * Handles errors in the selection parser.
436  *
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.
441  *
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.
446  *
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.
454  */
455 bool _gmx_selparser_handle_error(void* scanner);
456
457 /** Propagates the flags for selection elements. */
458 void _gmx_selelem_update_flags(const gmx::SelectionTreeElementPointer& sel);
459
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,
466                              void*                                   scanner);
467
468 /* An opaque pointer. */
469 #ifndef YY_TYPEDEF_YY_SCANNER_T
470 #    define YY_TYPEDEF_YY_SCANNER_T
471 typedef void* yyscan_t;
472 #endif
473 /** \brief Creates a gmx::SelectionTreeElement for arithmetic expression evaluation.
474  *
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.
480  *
481  * This function handles the creation of a gmx::SelectionTreeElement object for
482  * arithmetic expressions.
483  */
484 gmx::SelectionTreeElementPointer _gmx_sel_init_arithmetic(const gmx::SelectionTreeElementPointer& left,
485                                                           const gmx::SelectionTreeElementPointer& right,
486                                                           char     op,
487                                                           yyscan_t scanner);
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,
491                                                           const char* cmpop,
492                                                           void*       scanner);
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,
496                                                        const char*                          rpost,
497                                                        void* scanner);
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,
502                                                                 const char* rpost,
503                                                                 void*       scanner);
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,
507                                                           const char* rpost,
508                                                           void*       scanner);
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,
512                                                       const char* rpost,
513                                                       void*       scanner);
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,
518                                                         void* scanner);
519 /** Creates a gmx::SelectionTreeElement for evaluation of reference positions. */
520 gmx::SelectionTreeElementPointer _gmx_sel_init_position(const gmx::SelectionTreeElementPointer& expr,
521                                                         const char* type,
522                                                         void*       scanner);
523
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,
532                                                             void* scanner);
533
534 /** Creates a root gmx::SelectionTreeElement for a selection. */
535 gmx::SelectionTreeElementPointer _gmx_sel_init_selection(const char* name,
536                                                          const gmx::SelectionTreeElementPointer& sel,
537                                                          void* scanner);
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,
541                                                           void* scanner);
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,
545                                                            void* scanner);
546 /** Check whether the parser should finish. */
547 bool _gmx_sel_parser_should_finish(void* scanner);
548
549 /* In params.c */
550 /** Initializes an array of parameters based on input from the selection parser. */
551 void _gmx_sel_parse_params(const gmx::SelectionParserParameterList& params,
552                            int                                      nparam,
553                            struct gmx_ana_selparam_t*               param,
554                            const gmx::SelectionTreeElementPointer&  root,
555                            void*                                    scanner);
556
557 #endif