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