Merge branch release-5-0 into release-5-1
[alexxy/gromacs.git] / src / gromacs / selection / parser_internal.h
1 /*
2  * This file is part of the GROMACS molecular simulation package.
3  *
4  * Copyright (c) 2012,2014, by the GROMACS development team, led by
5  * Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
6  * and including many others, as listed in the AUTHORS file in the
7  * top-level source 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 Helper functions for the selection parser.
37  *
38  * This header is includes only from parser.cpp (generated from parser.y), and
39  * it includes functions and macros used internally by the parser.
40  * They are in a separate file to make then easier to edit (no need to
41  * regenerate the parser), and to keep parser.y as simple as possible.
42  *
43  * \author Teemu Murtola <teemu.murtola@gmail.com>
44  * \ingroup module_selection
45  */
46 #ifndef GMX_SELECTION_PARSER_INTERNAL_H
47 #define GMX_SELECTION_PARSER_INTERNAL_H
48
49 #include "config.h"
50
51 #include <exception>
52
53 #include <boost/exception_ptr.hpp>
54 #include <boost/scoped_ptr.hpp>
55
56 #include "gromacs/utility/exceptions.h"
57 #include "gromacs/utility/gmxassert.h"
58 #include "gromacs/utility/stringutil.h"
59
60 #include "parsetree.h"
61 #include "scanner.h"
62 #include "selelem.h"
63
64 //! Error handler needed by Bison.
65 static void
66 yyerror(YYLTYPE *location, yyscan_t scanner, char const *s)
67 {
68     try
69     {
70         std::string            context(_gmx_sel_lexer_get_text(scanner, *location));
71         gmx::InvalidInputError ex(s);
72         // TODO: Examine how to show better context information.
73         if (!context.empty())
74         {
75             context = gmx::formatString("Near '%s'", context.c_str());
76             ex.prependContext(context);
77         }
78         _gmx_sel_lexer_set_exception(scanner, boost::copy_exception(ex));
79     }
80     catch (const std::exception &)
81     {
82         _gmx_sel_lexer_set_exception(scanner, boost::current_exception());
83     }
84 }
85
86 //! Logic for computing the location of the output of Bison reduction.
87 #define YYLLOC_DEFAULT(Current, Rhs, N)                          \
88     do {                                                         \
89         if (N != 0)                                              \
90         {                                                        \
91             (Current).startIndex = YYRHSLOC(Rhs, 1).startIndex;  \
92             (Current).endIndex   = YYRHSLOC(Rhs, N).endIndex;    \
93         }                                                        \
94         else                                                     \
95         {                                                        \
96             (Current).startIndex = (Current).endIndex =          \
97                     YYRHSLOC(Rhs, 0).endIndex;                   \
98         }                                                        \
99         _gmx_sel_lexer_set_current_location(scanner, (Current)); \
100     } while (0)
101
102 /*! \brief
103  * Custom macro to influence Bison behavior.
104  *
105  * This macro added to parser.cpp through our patch to force Bison to
106  * use C-style logic for stack reallocation even though we have provided
107  * YYLTYPE and are compiling the code in C++ (our YYLTYPE can safely be copied
108  * this way).
109  * An alternative would be to provide the whole reallocation logic through an
110  * undocumented yyoverflow() macro, but that is probably also more trouble than
111  * it is worth.
112  */
113 #define GMX_YYFORCE_C_STACK_EXTENSION 1
114
115 /*! \name Exception handling macros for actions
116  *
117  * These macros should be used at the beginning and end of each semantic action
118  * that may throw an exception. For robustness, it's best to wrap all actions
119  * that call functions declared outside parser.y should be wrapped.
120  * These macros take care to catch any exceptions, store the exception (or
121  * handle it and allow the parser to continue), and terminate the parser
122  * cleanly if necessary.
123  * The code calling the parser should use
124  * _gmx_sel_lexer_rethrow_exception_if_occurred() to rethrow any exceptions.
125  * \{
126  */
127 //! Starts an action that may throw exceptions.
128 #define BEGIN_ACTION \
129     try {
130 //! Finishes an action that may throw exceptions.
131 #define END_ACTION                                              \
132     }                                                           \
133     catch (std::exception &ex)                                  \
134     {                                                           \
135         if (_gmx_selparser_handle_exception(scanner, &ex))      \
136         {                                                       \
137             YYERROR;                                            \
138         }                                                       \
139         else                                                    \
140         {                                                       \
141             YYABORT;                                            \
142         }                                                       \
143     }
144 //! Finishes an action that may throw exceptions and does not support resuming.
145 #define END_ACTION_TOPLEVEL                                     \
146     }                                                           \
147     catch (const std::exception &)                              \
148     {                                                           \
149         _gmx_sel_lexer_set_exception(scanner, boost::current_exception()); \
150         YYABORT;                                                \
151     }
152 //!\}
153
154 #ifndef GMX_CXX11
155 //! No-op to enable use of same get()/set() implementation as with C++11.
156 static gmx::SelectionParserValue &move(gmx::SelectionParserValue &src)
157 {
158     return src;
159 }
160 //! No-op to enable use of same get()/set() implementation as with C++11.
161 static gmx::SelectionParserParameter &move(gmx::SelectionParserParameter &src)
162 {
163     return src;
164 }
165 #endif
166
167 /*! \brief
168  * Retrieves a semantic value.
169  *
170  * \param[in] src  Semantic value to get the value from.
171  * \returns   Retrieved value.
172  * \throws    unspecified  Any exception thrown by the move constructor of
173  *      ValueType (copy constructor if GMX_CXX11 is not set).
174  *
175  * There should be no statements that may throw exceptions in actions before
176  * this function has been called for all semantic values that have a C++ object
177  * stored.  Together with set(), this function abstracts away exception
178  * safety issues that arise from the use of a plain pointer for storing the
179  * semantic values.
180  *
181  * Does not throw for smart pointer types.  If used with types that may throw,
182  * the order of operations should be such that it is exception-safe.
183  */
184 template <typename ValueType> static
185 ValueType get(ValueType *src)
186 {
187     GMX_RELEASE_ASSERT(src != NULL, "Semantic value pointers should be non-NULL");
188     boost::scoped_ptr<ValueType> srcGuard(src);
189     return ValueType(move(*src));
190 }
191 /*! \brief
192  * Sets a semantic value.
193  *
194  * \tparam     ValueType Type of value to set.
195  * \param[out] dest  Semantic value to set (typically $$).
196  * \param[in]  value Value to put into the semantic value.
197  * \throws     std::bad_alloc if out of memory.
198  * \throws     unspecified  Any exception thrown by the move constructor of
199  *      ValueType (copy constructor if GMX_CXX11 is not set).
200  *
201  * This should be the last statement before ::END_ACTION, except for a
202  * possible ::CHECK_SEL.
203  */
204 template <typename ValueType> static
205 void set(ValueType * &dest, ValueType value)
206 {
207     dest = new ValueType(move(value));
208 }
209 /*! \brief
210  * Sets an empty semantic value.
211  *
212  * \tparam     ValueType Type of value to set (must be default constructible).
213  * \param[out] dest  Semantic value to set (typically $$).
214  * \throws     std::bad_alloc if out of memory.
215  * \throws     unspecified  Any exception thrown by the default constructor of
216  *      ValueType.
217  *
218  * This should be the last statement before ::END_ACTION, except for a
219  * possible ::CHECK_SEL.
220  */
221 template <typename ValueType> static
222 void set_empty(ValueType * &dest)
223 {
224     dest = new ValueType;
225 }
226 /*! \brief
227  * Checks that a valid tree was set.
228  *
229  * Should be called after set() if it was used to set a value where NULL
230  * pointer indicates an error.
231  *
232  * \todo
233  * Get rid of this macro.  It should now be possible to handle all errors using
234  * exceptions.
235  */
236 #define CHECK_SEL(sel) \
237     if (!*(sel)) { \
238         delete sel; \
239         YYERROR; \
240     }
241
242 #endif