e99aa0375050c6c509efd914ef91ce0c11f50190
[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,2015,2017,2018,2019, 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 <exception>
50 #include <memory>
51
52 #include "gromacs/utility/exceptions.h"
53 #include "gromacs/utility/gmxassert.h"
54 #include "gromacs/utility/stringutil.h"
55
56 #include "parsetree.h"
57 #include "scanner.h"
58 #include "selelem.h"
59
60 //! Error handler needed by Bison.
61 static void yyerror(YYLTYPE* location, yyscan_t scanner, char const* s)
62 {
63     try
64     {
65         std::string            context(_gmx_sel_lexer_get_text(scanner, *location));
66         gmx::InvalidInputError ex(s);
67         // TODO: Examine how to show better context information.
68         if (!context.empty())
69         {
70             context = gmx::formatString("Near '%s'", context.c_str());
71             ex.prependContext(context);
72         }
73         _gmx_sel_lexer_set_exception(scanner, std::make_exception_ptr(ex));
74     }
75     catch (const std::exception&)
76     {
77         _gmx_sel_lexer_set_exception(scanner, std::current_exception());
78     }
79 }
80
81 //! Logic for computing the location of the output of Bison reduction.
82 #define YYLLOC_DEFAULT(Current, Rhs, N)                                            \
83     do                                                                             \
84     {                                                                              \
85         if ((N) != 0)                                                              \
86         {                                                                          \
87             (Current).startIndex = YYRHSLOC(Rhs, 1).startIndex;                    \
88             (Current).endIndex   = YYRHSLOC(Rhs, N).endIndex;                      \
89         }                                                                          \
90         else                                                                       \
91         {                                                                          \
92             (Current).startIndex = (Current).endIndex = YYRHSLOC(Rhs, 0).endIndex; \
93         }                                                                          \
94         _gmx_sel_lexer_set_current_location(scanner, (Current));                   \
95     } while (0)
96
97 /*! \brief
98  * Custom macro to influence Bison behavior.
99  *
100  * This macro added to parser.cpp through our patch to force Bison to
101  * use C-style logic for stack reallocation even though we have provided
102  * YYLTYPE and are compiling the code in C++ (our YYLTYPE can safely be copied
103  * this way).
104  * An alternative would be to provide the whole reallocation logic through an
105  * undocumented yyoverflow() macro, but that is probably also more trouble than
106  * it is worth.
107  */
108 #define GMX_YYFORCE_C_STACK_EXTENSION 1
109
110 /*! \name Exception handling macros for actions
111  *
112  * These macros should be used at the beginning and end of each semantic action
113  * that may throw an exception. For robustness, it's best to wrap all actions
114  * that call functions declared outside parser.y should be wrapped.
115  * These macros take care to catch any exceptions, store the exception (or
116  * handle it and allow the parser to continue), and terminate the parser
117  * cleanly if necessary.
118  * The code calling the parser should use
119  * _gmx_sel_lexer_rethrow_exception_if_occurred() to rethrow any exceptions.
120  * \{
121  */
122 //! Starts an action that may throw exceptions.
123 #define BEGIN_ACTION \
124     try              \
125     {
126 //! Finishes an action that may throw exceptions.
127 #define END_ACTION                                         \
128     }                                                      \
129     catch (std::exception & ex)                            \
130     {                                                      \
131         if (_gmx_selparser_handle_exception(scanner, &ex)) \
132         {                                                  \
133             YYERROR;                                       \
134         }                                                  \
135         else                                               \
136         {                                                  \
137             YYABORT;                                       \
138         }                                                  \
139     }
140 //! Finishes an action that may throw exceptions and does not support resuming.
141 #define END_ACTION_TOPLEVEL                                              \
142     }                                                                    \
143     catch (const std::exception&)                                        \
144     {                                                                    \
145         _gmx_sel_lexer_set_exception(scanner, std::current_exception()); \
146         YYABORT;                                                         \
147     }
148 //!\}
149
150 /*! \brief
151  * Retrieves a semantic value.
152  *
153  * \param[in] src  Semantic value to get the value from.
154  * \returns   Retrieved value.
155  * \throws    unspecified  Any exception thrown by the move constructor of
156  *      ValueType.
157  *
158  * There should be no statements that may throw exceptions in actions before
159  * this function has been called for all semantic values that have a C++ object
160  * stored.  Together with set(), this function abstracts away exception
161  * safety issues that arise from the use of a plain pointer for storing the
162  * semantic values.
163  *
164  * Does not throw for smart pointer types.  If used with types that may throw,
165  * the order of operations should be such that it is exception-safe.
166  */
167 template<typename ValueType>
168 static ValueType get(ValueType* src)
169 {
170     GMX_RELEASE_ASSERT(src != nullptr, "Semantic value pointers should be non-NULL");
171     const std::unique_ptr<ValueType> srcGuard(src);
172     return ValueType(std::move(*src));
173 }
174 /*! \brief
175  * Sets a semantic value.
176  *
177  * \tparam     ValueType Type of value to set.
178  * \param[out] dest  Semantic value to set (typically $$).
179  * \param[in]  value Value to put into the semantic value.
180  * \throws     std::bad_alloc if out of memory.
181  * \throws     unspecified  Any exception thrown by the move constructor of
182  *      ValueType.
183  *
184  * This should be the last statement before ::END_ACTION, except for a
185  * possible ::CHECK_SEL.
186  */
187 template<typename ValueType>
188 static void set(ValueType*& dest, ValueType value)
189 {
190     dest = new ValueType(std::move(value));
191 }
192 /*! \brief
193  * Sets an empty semantic value.
194  *
195  * \tparam     ValueType Type of value to set (must be default constructible).
196  * \param[out] dest  Semantic value to set (typically $$).
197  * \throws     std::bad_alloc if out of memory.
198  * \throws     unspecified  Any exception thrown by the default constructor of
199  *      ValueType.
200  *
201  * This should be the last statement before ::END_ACTION, except for a
202  * possible ::CHECK_SEL.
203  */
204 template<typename ValueType>
205 static void set_empty(ValueType*& dest)
206 {
207     dest = new ValueType;
208 }
209 /*! \brief
210  * Checks that a valid tree was set.
211  *
212  * Should be called after set() if it was used to set a value where NULL
213  * pointer indicates an error.
214  *
215  * \todo
216  * Get rid of this macro.  It should now be possible to handle all errors using
217  * exceptions.
218  */
219 #define CHECK_SEL(sel) \
220     if (!*(sel))       \
221     {                  \
222         delete (sel);  \
223         YYERROR;       \
224     }
225
226 #endif