a313c2ecde34b1b75061397a5330da7edf36e554
[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,2010,2011,2012, by the GROMACS development team, led by
5  * David van der Spoel, Berk Hess, Erik Lindahl, and including many
6  * others, as listed in the AUTHORS file in the top-level source
7  * directory and at http://www.gromacs.org.
8  *
9  * GROMACS is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU Lesser General Public License
11  * as published by the Free Software Foundation; either version 2.1
12  * of the License, or (at your option) any later version.
13  *
14  * GROMACS is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17  * Lesser General Public License for more details.
18  *
19  * You should have received a copy of the GNU Lesser General Public
20  * License along with GROMACS; if not, see
21  * http://www.gnu.org/licenses, or write to the Free Software Foundation,
22  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA.
23  *
24  * If you want to redistribute modifications to GROMACS, please
25  * consider that scientific software is very special. Version
26  * control is crucial - bugs must be traceable. We will be happy to
27  * consider code for inclusion in the official distribution, but
28  * derived work must not be called official GROMACS. Details are found
29  * in the README & COPYING files - if they are missing, get the
30  * official version at http://www.gromacs.org.
31  *
32  * To help us fund GROMACS development, we humbly ask that you cite
33  * the research papers on the package. Check out http://www.gromacs.org.
34  */
35 /*! \internal \file
36  * \brief
37  * Handling of intermediate selection parser data.
38  *
39  * The data types declared in this header are used by the parser to store
40  * intermediate data when constructing method expressions.
41  * In particular, the parameters for the method are stored.
42  * The intermediate data is freed once a gmx::SelectionTreeElement object can
43  * be constructed.
44  *
45  * This is an implementation header: there should be no need to use it outside
46  * this directory.
47  *
48  * \author Teemu Murtola <teemu.murtola@gmail.com>
49  * \ingroup module_selection
50  */
51 #ifndef GMX_SELECTION_PARSETREE_H
52 #define GMX_SELECTION_PARSETREE_H
53
54 #include <exception>
55 #include <list>
56 #include <string>
57
58 #include "gromacs/legacyheaders/types/simple.h"
59 #include "gromacs/legacyheaders/vec.h"
60
61 #include "gromacs/utility/gmxassert.h"
62 #include "gromacs/utility/uniqueptr.h"
63
64 #include "selelem.h"
65 #include "selvalue.h"
66
67 struct gmx_ana_indexgrps_t;
68 struct gmx_ana_selmethod_t;
69 struct gmx_ana_selparam_t;
70
71 namespace gmx
72 {
73
74 //! \cond internal
75 /*! \internal \brief
76  * String matching mode for string keyword expressions.
77  *
78  * \ingroup module_selection
79  */
80 enum SelectionStringMatchType
81 {
82     eStringMatchType_Auto,              //!< Deduce from the string.
83     eStringMatchType_Exact,             //!< Match as a literal string.
84     eStringMatchType_Wildcard,          //!< Match using ? and * as wildcards.
85     eStringMatchType_RegularExpression  //!< Match using regular expressions.
86 };
87 /*! \endcond */
88
89 class SelectionParserValue;
90
91 //! Container for a list of SelectionParserValue objects.
92 typedef std::list<SelectionParserValue>
93     SelectionParserValueList;
94 //! Smart pointer type for managing a SelectionParserValueList.
95 typedef gmx::gmx_unique_ptr<SelectionParserValueList>::type
96     SelectionParserValueListPointer;
97
98 /*! \internal \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 SelectionParserValueListPointer(new 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
121         createList(const SelectionParserValue &value)
122         {
123             SelectionParserValueListPointer list(new SelectionParserValueList);
124             list->push_back(value);
125             return move(list);
126         }
127         /*! \brief
128          * Allocates and initializes an expression value.
129          *
130          * \param[in] expr  Root of the expression tree to assign to the value.
131          * \returns   The newly created value.
132          */
133         static SelectionParserValue
134         createExpr(const gmx::SelectionTreeElementPointer &expr)
135         {
136             return SelectionParserValue(expr);
137         }
138         /*! \brief
139          * Allocates and initializes a constant integer value.
140          *
141          * \param[in] value  Integer value to assign to the value.
142          * \returns   The newly created value.
143          */
144         static SelectionParserValue createInteger(int value)
145         {
146             SelectionParserValue result(INT_VALUE);
147             result.u.i.i1 = result.u.i.i2 = value;
148             return result;
149         }
150         /*! \brief
151          * Allocates and initializes a constant integer range value.
152          *
153          * \param[in] from  Beginning of the range to assign to the value.
154          * \param[in] to    End of the range to assign to the value.
155          * \returns   The newly created value.
156          */
157         static SelectionParserValue createIntegerRange(int from, int to)
158         {
159             SelectionParserValue result(INT_VALUE);
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          * \returns   The newly created value.
169          */
170         static SelectionParserValue createReal(real value)
171         {
172             SelectionParserValue result(REAL_VALUE);
173             result.u.r.r1 = result.u.r.r2 = value;
174             return result;
175         }
176         /*! \brief
177          * Allocates and initializes a constant floating-point range value.
178          *
179          * \param[in] from  Beginning of the range to assign to the value.
180          * \param[in] to    End of the range to assign to the value.
181          * \returns   The newly created value.
182          */
183         static SelectionParserValue createRealRange(real from, real to)
184         {
185             SelectionParserValue result(REAL_VALUE);
186             result.u.r.r1 = from;
187             result.u.r.r2 = to;
188             return result;
189         }
190         /*! \brief
191          * Allocates and initializes a constant string value.
192          *
193          * \param[in] value  String to assign to the value.
194          * \returns   The newly created value.
195          */
196         static SelectionParserValue createString(const char *value)
197         {
198             SelectionParserValue result(STR_VALUE);
199             result.str = value;
200             return result;
201         }
202         /*! \brief
203          * Allocates and initializes a constant position value.
204          *
205          * \param[in] value  Position vector to assign to the value.
206          * \returns   The newly created value.
207          */
208         static SelectionParserValue createPosition(rvec value)
209         {
210             SelectionParserValue result(POS_VALUE);
211             copy_rvec(value, result.u.x);
212             return result;
213         }
214
215         //! Returns true if the value comes from expression evaluation.
216         bool hasExpressionValue() const { return expr; }
217
218         //! Returns the string value (\a type must be ::STR_VALUE).
219         const std::string &stringValue() const
220         {
221             GMX_ASSERT(type == STR_VALUE && !hasExpressionValue(),
222                        "Attempted to retrieve string value from a non-string value");
223             return str;
224         }
225
226         // TODO: boost::any or similar could be nicer for the implementation.
227         //! Type of the value.
228         e_selvalue_t                     type;
229         //! Expression pointer if the value is the result of an expression.
230         gmx::SelectionTreeElementPointer expr;
231         //! String value for \a type ::STR_VALUE.
232         std::string                      str;
233         //! The actual value if \a expr is NULL and \a type is not ::STR_VALUE.
234         union {
235             //! The integer value/range (\a type ::INT_VALUE).
236             struct {
237                 //! Beginning of the range.
238                 int             i1;
239                 //! End of the range; equals \a i1 for a single integer.
240                 int             i2;
241             }                   i;
242             //! The real value/range (\a type ::REAL_VALUE).
243             struct {
244                 //! Beginning of the range.
245                 real            r1;
246                 //! End of the range; equals \a r1 for a single number.
247                 real            r2;
248             }                   r;
249             //! The position value (\a type ::POS_VALUE).
250             rvec                x;
251         }                       u;
252
253     private:
254         /*! \brief
255          * Initializes a new value.
256          *
257          * \param[in] type  Type for the new value.
258          */
259         explicit SelectionParserValue(e_selvalue_t type);
260         /*! \brief
261          * Initializes a new expression value.
262          *
263          * \param[in] expr  Expression for the value.
264          */
265         explicit SelectionParserValue(const gmx::SelectionTreeElementPointer &expr);
266 };
267
268 class SelectionParserParameter;
269
270 //! Container for a list of SelectionParserParameter objects.
271 typedef std::list<SelectionParserParameter>
272     SelectionParserParameterList;
273 //! Smart pointer type for managing a SelectionParserParameterList.
274 typedef gmx::gmx_unique_ptr<SelectionParserParameterList>::type
275     SelectionParserParameterListPointer;
276
277 /*! \internal \brief
278  * Describes a parsed method parameter.
279  *
280  * \ingroup module_selection
281  */
282 class SelectionParserParameter
283 {
284     public:
285         //! Allocates and initializes an empty parameter list.
286         static SelectionParserParameterListPointer createList()
287         {
288             return SelectionParserParameterListPointer(
289                     new SelectionParserParameterList);
290         }
291         /*! \brief
292          * Allocates and initializes a parsed method parameter.
293          *
294          * \param[in] name    Name for the new parameter (can be NULL).
295          * \param[in] values  List of values for the parameter.
296          * \returns   Pointer to the newly allocated parameter.
297          * \throws    std::bad_alloc if out of memory.
298          */
299         static SelectionParserParameter
300         create(const char *name, SelectionParserValueListPointer values)
301         {
302             return SelectionParserParameter(name, move(values));
303         }
304         //! \copydoc create(const char *, SelectionParserValueListPointer)
305         static SelectionParserParameter
306         create(const std::string &name, SelectionParserValueListPointer values)
307         {
308             return SelectionParserParameter(name.c_str(), move(values));
309         }
310         /*! \brief
311          * Allocates and initializes a parsed method parameter.
312          *
313          * \param[in] name    Name for the new parameter (can be NULL).
314          * \param[in] value   Value for the parameter.
315          * \returns   Pointer to the newly allocated parameter.
316          * \throws    std::bad_alloc if out of memory.
317          *
318          * This overload is a convenience wrapper for the case when creating
319          * parameters outside the actual Bison parser and only a single value
320          * is necessary.
321          */
322         static SelectionParserParameter
323         create(const char *name, const SelectionParserValue &value)
324         {
325             return create(name, SelectionParserValue::createList(value));
326         }
327         /*! \brief
328          * Allocates and initializes a parsed method parameter.
329          *
330          * \param[in] name    Name for the new parameter (can be NULL).
331          * \param[in] expr    Expression value for the parameter.
332          * \returns   Pointer to the newly allocated parameter.
333          * \throws    std::bad_alloc if out of memory.
334          *
335          * This overload is a convenience wrapper for the case when creating
336          * parameters outside the actual Bison parser and only a single
337          * expression value is necessary.
338          */
339         static SelectionParserParameter
340         createFromExpression(const char                        *name,
341                              const SelectionTreeElementPointer &expr)
342         {
343             return create(name, SelectionParserValue::createExpr(expr));
344         }
345         //! \copydoc createFromExpression(const char *, const SelectionTreeElementPointer &)
346         static SelectionParserParameter
347         createFromExpression(const std::string                 &name,
348                              const SelectionTreeElementPointer &expr)
349         {
350             return create(name.c_str(), SelectionParserValue::createExpr(expr));
351         }
352
353         /*! \brief
354          * Initializes a parsed method parameter.
355          *
356          * \param[in] name    Name for the new parameter (can be NULL).
357          * \param[in] values  List of values for the parameter.
358          * \throws    std::bad_alloc if out of memory.
359          */
360         SelectionParserParameter(const char                     *name,
361                                  SelectionParserValueListPointer values);
362
363         //! Returns the name of the parameter (may be empty).
364         const std::string &name() const { return name_; }
365         //! Returns the values for the parameter.
366         const SelectionParserValueList &values() const { return *values_; }
367
368         //! Name of the parameter.
369         std::string                     name_;
370         //! Values for this parameter.
371         SelectionParserValueListPointer values_;
372 };
373
374 } // namespace gmx
375
376 /** Error reporting function for the selection parser. */
377 void
378 _gmx_selparser_error(void *scanner, const char *fmt, ...);
379 /** Handle exceptions caught within the Bison code. */
380 bool
381 _gmx_selparser_handle_exception(void *scanner, const std::exception &ex);
382
383 /** Propagates the flags for selection elements. */
384 void
385 _gmx_selelem_update_flags(const gmx::SelectionTreeElementPointer &sel,
386                           void                                   *scanner);
387
388 /** Initializes the method parameter data of \ref SEL_EXPRESSION and
389  * \ref SEL_MODIFIER elements. */
390 void
391 _gmx_selelem_init_method_params(const gmx::SelectionTreeElementPointer &sel,
392                                 void                                   *scanner);
393 /** Initializes the method for a \ref SEL_EXPRESSION selection element. */
394 void
395 _gmx_selelem_set_method(const gmx::SelectionTreeElementPointer &sel,
396                         struct gmx_ana_selmethod_t *method, void *scanner);
397
398 /** Creates a gmx::SelectionTreeElement for arithmetic expression evaluation. */
399 gmx::SelectionTreeElementPointer
400 _gmx_sel_init_arithmetic(const gmx::SelectionTreeElementPointer &left,
401                          const gmx::SelectionTreeElementPointer &right,
402                          char op, void *scanner);
403 /** Creates a gmx::SelectionTreeElement for comparsion expression evaluation. */
404 gmx::SelectionTreeElementPointer
405 _gmx_sel_init_comparison(const gmx::SelectionTreeElementPointer &left,
406                          const gmx::SelectionTreeElementPointer &right,
407                          const char *cmpop, void *scanner);
408 /** Creates a gmx::SelectionTreeElement for a keyword expression from the parsed data. */
409 gmx::SelectionTreeElementPointer
410 _gmx_sel_init_keyword(struct gmx_ana_selmethod_t *method,
411                       gmx::SelectionParserValueListPointer args,
412                       const char *rpost, void *scanner);
413 /** Creates a gmx::SelectionTreeElement for string-matching keyword expression. */
414 gmx::SelectionTreeElementPointer
415 _gmx_sel_init_keyword_strmatch(struct gmx_ana_selmethod_t *method,
416                                gmx::SelectionStringMatchType matchType,
417                                gmx::SelectionParserValueListPointer args,
418                                const char *rpost, void *scanner);
419 /** Creates a gmx::SelectionTreeElement for a method expression from the parsed data. */
420 gmx::SelectionTreeElementPointer
421 _gmx_sel_init_method(struct gmx_ana_selmethod_t *method,
422                      gmx::SelectionParserParameterListPointer params,
423                      const char *rpost, void *scanner);
424 /** Creates a gmx::SelectionTreeElement for a modifier expression from the parsed data. */
425 gmx::SelectionTreeElementPointer
426 _gmx_sel_init_modifier(struct gmx_ana_selmethod_t              *mod,
427                        gmx::SelectionParserParameterListPointer params,
428                        const gmx::SelectionTreeElementPointer  &sel,
429                        void                                    *scanner);
430 /** Creates a gmx::SelectionTreeElement for evaluation of reference positions. */
431 gmx::SelectionTreeElementPointer
432 _gmx_sel_init_position(const gmx::SelectionTreeElementPointer &expr,
433                        const char *type, void *scanner);
434
435 /** Creates a gmx::SelectionTreeElement for a constant position. */
436 gmx::SelectionTreeElementPointer
437 _gmx_sel_init_const_position(real x, real y, real z);
438 /** Creates a gmx::SelectionTreeElement for a index group expression using group name. */
439 gmx::SelectionTreeElementPointer
440 _gmx_sel_init_group_by_name(const char *name, void *scanner);
441 /** Creates a gmx::SelectionTreeElement for a index group expression using group index. */
442 gmx::SelectionTreeElementPointer
443 _gmx_sel_init_group_by_id(int id, void *scanner);
444 /** Creates a gmx::SelectionTreeElement for a variable reference */
445 gmx::SelectionTreeElementPointer
446 _gmx_sel_init_variable_ref(const gmx::SelectionTreeElementPointer &sel);
447
448 /** Creates a root gmx::SelectionTreeElement for a selection. */
449 gmx::SelectionTreeElementPointer
450 _gmx_sel_init_selection(const char                             *name,
451                         const gmx::SelectionTreeElementPointer &sel,
452                         void                                   *scanner);
453 /** Creates a root gmx::SelectionTreeElement elements for a variable assignment. */
454 gmx::SelectionTreeElementPointer
455 _gmx_sel_assign_variable(const char                             *name,
456                          const gmx::SelectionTreeElementPointer &expr,
457                          void                                   *scanner);
458 /** Appends a root gmx::SelectionTreeElement to a selection collection. */
459 gmx::SelectionTreeElementPointer
460 _gmx_sel_append_selection(const gmx::SelectionTreeElementPointer &sel,
461                           gmx::SelectionTreeElementPointer        last,
462                           void                                   *scanner);
463 /** Check whether the parser should finish. */
464 bool
465 _gmx_sel_parser_should_finish(void *scanner);
466
467 /** Handle empty commands. */
468 void
469 _gmx_sel_handle_empty_cmd(void *scanner);
470 /** Process help commands. */
471 void
472 _gmx_sel_handle_help_cmd(const gmx::SelectionParserValueListPointer &topic,
473                          void                                       *scanner);
474
475 /* In params.c */
476 /** Initializes an array of parameters based on input from the selection parser. */
477 bool
478 _gmx_sel_parse_params(const gmx::SelectionParserParameterList &params,
479                       int nparam, struct gmx_ana_selparam_t *param,
480                       const gmx::SelectionTreeElementPointer &root,
481                       void *scanner);
482
483 #endif