Moved selection parser helpers into separate file.
[alexxy/gromacs.git] / src / gromacs / selection / parser_internal.h
1 /*
2  *
3  *                This source code is part of
4  *
5  *                 G   R   O   M   A   C   S
6  *
7  *          GROningen MAchine for Chemical Simulations
8  *
9  * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
10  * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
11  * Copyright (c) 2001-2009, The GROMACS development team,
12  * check out http://www.gromacs.org for more information.
13
14  * This program is free software; you can redistribute it and/or
15  * modify it under the terms of the GNU General Public License
16  * as published by the Free Software Foundation; either version 2
17  * of the License, or (at your option) any later version.
18  *
19  * If you want to redistribute modifications, please consider that
20  * scientific software is very special. Version control is crucial -
21  * bugs must be traceable. We will be happy to consider code for
22  * inclusion in the official distribution, but derived work must not
23  * be called official GROMACS. Details are found in the README & COPYING
24  * files - if they are missing, get the official version at www.gromacs.org.
25  *
26  * To help us fund GROMACS development, we humbly ask that you cite
27  * the papers on the package - you can find them in the top README file.
28  *
29  * For more info, check our website at http://www.gromacs.org
30  */
31 /*! \internal \file
32  * \brief Helper functions for the selection parser.
33  *
34  * This header is includes only from parser.cpp (generated from parser.y), and
35  * it includes functions and macros used internally by the parser.
36  * They are in a separate file to make then easier to edit (no need to
37  * regenerate the parser), and to keep parser.y as simple as possible.
38  *
39  * \author Teemu Murtola <teemu.murtola@cbr.su.se>
40  * \ingroup module_selection
41  */
42 #ifndef GMX_SELECTION_PARSER_INTERNAL_H
43 #define GMX_SELECTION_PARSER_INTERNAL_H
44
45 #include <exception>
46
47 #include "parsetree.h"
48 #include "selelem.h"
49
50 #include "scanner.h"
51
52 //! Helper method to reorder a list of parameter values and to count the values.
53 static t_selexpr_value *
54 process_value_list(t_selexpr_value *values, int *nr)
55 {
56     t_selexpr_value *val, *pval, *nval;
57
58     /* Count values (if needed) and reverse list */
59     if (nr)
60     {
61         *nr  = 0;
62     }
63     pval = NULL;
64     val  = values;
65     while (val)
66     {
67         if (nr)
68         {
69             ++*nr;
70         }
71         nval = val->next;
72         val->next = pval;
73         pval = val;
74         val = nval;
75     }
76     values = pval;
77
78     return values;
79 }
80
81 //! Helper method to reorder a list of parameters.
82 static t_selexpr_param *
83 process_param_list(t_selexpr_param *params)
84 {
85     t_selexpr_param *par, *ppar, *npar;
86
87     /* Reverse list */
88     ppar = NULL;
89     par  = params;
90     while (par)
91     {
92         npar = par->next;
93         par->next = ppar;
94         ppar = par;
95         par = npar;
96     }
97     params = ppar;
98
99     return params;
100 }
101
102 //! Error handler needed by Bison.
103 static void
104 yyerror(yyscan_t scanner, char const *s)
105 {
106     _gmx_selparser_error(scanner, "%s", s);
107 }
108
109 /*! \name Exception handling macros for actions
110  *
111  * These macros should be used at the beginning and end of each semantic action
112  * that may throw an exception. For robustness, it's best to wrap all actions
113  * that call functions declared outside parser.y should be wrapped.
114  * These macros take care to catch any exceptions, store the exception (or
115  * handle it and allow the parser to continue), and terminate the parser
116  * cleanly if necessary.
117  * The code calling the parser should use
118  * _gmx_sel_lexer_rethrow_exception_if_occurred() to rethrow any exceptions.
119  * \{
120  */
121 //! Starts an action that may throw exceptions.
122 #define BEGIN_ACTION \
123     try {
124 //! Finishes an action that may throw exceptions.
125 #define END_ACTION \
126     } \
127     catch(const std::exception &ex) \
128     { \
129         if (_gmx_selparser_handle_exception(scanner, ex)) \
130             YYERROR; \
131         else \
132             YYABORT; \
133     }
134 //!\}
135
136 /*! \brief
137  * Retrieves a selection tree pointer from a semantic value.
138  *
139  * \param[in] src  Semantic value to get the tree from.
140  * \returns   Pointer to the selection tree.
141  *
142  * There should be no statements that may throw exceptions in actions before
143  * this function has been called for all semantic values that have a tree
144  * argument.  Together with set(), this function abstracts away exception
145  * safety issues that arise from the use of a plain pointer for storing the
146  * selection tree semantic values.
147  *
148  * Does not throw.
149  */
150 static gmx::SelectionTreeElementPointer
151 get(gmx::SelectionTreeElementPointer *src)
152 {
153     gmx::SelectionTreeElementPointer result;
154     if (src != NULL)
155     {
156         result.swap(*src);
157         delete src;
158     }
159     return result;
160 }
161 /*! \brief
162  * Sets a selection tree pointer to a semantic value.
163  *
164  * \param[out] dest  Semantic value to set the tree to.
165  * \param[in]  value Pointer to the selection tree to set.
166  * \throws     std::bad_alloc if out of memory.
167  *
168  * This should be the last statement before ::END_ACTION, except for a
169  * possible ::CHECK_SEL.
170  */
171 static void
172 set(gmx::SelectionTreeElementPointer *&dest,
173         const gmx::SelectionTreeElementPointer &value)
174 {
175     dest = new gmx::SelectionTreeElementPointer(value);
176 }
177 /*! \brief
178  * Checks that a valid tree was set.
179  *
180  * Should be called after set() if it was used to set a value where NULL
181  * pointer indicates an error.
182  *
183  * \todo
184  * Get rid of this macro.  It should now be possible to handle all errors using
185  * exceptions.
186  */
187 #define CHECK_SEL(sel) \
188     if (!*(sel)) { \
189         delete sel; \
190         YYERROR; \
191     }
192
193 #endif