Update instructions in containers.rst
[gromacs.git] / src / gromacs / selection / parser_internal.h
blobbc2f63bf56a609a6ebd0f0f1dc5cd088f827cc3c
1 /*
2 * This file is part of the GROMACS molecular simulation package.
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.
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.
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.
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.
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.
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.
36 /*! \internal \file
37 * \brief Helper functions for the selection parser.
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.
44 * \author Teemu Murtola <teemu.murtola@gmail.com>
45 * \ingroup module_selection
47 #ifndef GMX_SELECTION_PARSER_INTERNAL_H
48 #define GMX_SELECTION_PARSER_INTERNAL_H
50 #include <exception>
51 #include <memory>
53 #include "gromacs/utility/exceptions.h"
54 #include "gromacs/utility/gmxassert.h"
55 #include "gromacs/utility/stringutil.h"
57 #include "parsetree.h"
58 #include "scanner.h"
59 #include "selelem.h"
61 //! Error handler needed by Bison.
62 static void yyerror(YYLTYPE* location, yyscan_t scanner, char const* s)
64 try
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())
71 context = gmx::formatString("Near '%s'", context.c_str());
72 ex.prependContext(context);
74 _gmx_sel_lexer_set_exception(scanner, std::make_exception_ptr(ex));
76 catch (const std::exception&)
78 _gmx_sel_lexer_set_exception(scanner, std::current_exception());
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)
98 /*! \brief
99 * Custom macro to influence Bison behavior.
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.
109 #define GMX_YYFORCE_C_STACK_EXTENSION 1
111 /*! \name Exception handling macros for actions
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 * \{
123 //! Starts an action that may throw exceptions.
124 #define BEGIN_ACTION \
125 try \
127 //! Finishes an action that may throw exceptions.
128 #define END_ACTION \
130 catch (std::exception & ex) \
132 if (_gmx_selparser_handle_exception(scanner, &ex)) \
134 YYERROR; \
136 else \
138 YYABORT; \
141 //! Finishes an action that may throw exceptions and does not support resuming.
142 #define END_ACTION_TOPLEVEL \
144 catch (const std::exception&) \
146 _gmx_sel_lexer_set_exception(scanner, std::current_exception()); \
147 YYABORT; \
149 //!\}
151 /*! \brief
152 * Retrieves a semantic value.
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.
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.
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.
168 template<typename ValueType>
169 static ValueType get(ValueType* src)
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));
175 /*! \brief
176 * Sets a semantic value.
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.
185 * This should be the last statement before ::END_ACTION, except for a
186 * possible ::CHECK_SEL.
188 template<typename ValueType>
189 static void set(ValueType*& dest, ValueType value)
191 dest = new ValueType(std::move(value));
193 /*! \brief
194 * Sets an empty semantic value.
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.
202 * This should be the last statement before ::END_ACTION, except for a
203 * possible ::CHECK_SEL.
205 template<typename ValueType>
206 static void set_empty(ValueType*& dest)
208 dest = new ValueType;
210 /*! \brief
211 * Checks that a valid tree was set.
213 * Should be called after set() if it was used to set a value where NULL
214 * pointer indicates an error.
216 * \todo
217 * Get rid of this macro. It should now be possible to handle all errors using
218 * exceptions.
220 #define CHECK_SEL(sel) \
221 if (!*(sel)) \
223 delete (sel); \
224 YYERROR; \
227 #endif