Line data Source code
1 : // Author(s): Wieger Wesselink
2 : // Copyright: see the accompanying file COPYING or copy at
3 : // https://github.com/mCRL2org/mCRL2/blob/master/COPYING
4 : //
5 : // Distributed under the Boost Software License, Version 1.0.
6 : // (See accompanying file LICENSE_1_0.txt or copy at
7 : // http://www.boost.org/LICENSE_1_0.txt)
8 : //
9 : /// \file mcrl2/core/parse.h
10 : ///
11 : /// \brief Parse mCRL2 specifications and expressions.
12 :
13 : #ifndef MCRL2_CORE_PARSE_H
14 : #define MCRL2_CORE_PARSE_H
15 :
16 : #include "mcrl2/atermpp/aterm_io.h"
17 : #include "mcrl2/core/detail/dparser_functions.h"
18 : #include "mcrl2/core/identifier_string.h"
19 :
20 : struct D_ParserTables; // prototype
21 :
22 : extern "C"
23 : {
24 : extern D_ParserTables parser_tables_mcrl2;
25 : extern D_ParserTables parser_tables_fsm;
26 : extern D_ParserTables parser_tables_dot;
27 : }
28 :
29 : namespace mcrl2
30 : {
31 : namespace core
32 : {
33 :
34 : class parse_node_exception : public mcrl2::runtime_error
35 : {
36 : protected:
37 4 : static std::string get_error_message(const parse_node& node, const std::string& user_message)
38 : {
39 : try
40 : {
41 4 : return node.add_context(user_message);
42 : }
43 0 : catch (...)
44 : {
45 0 : return user_message;
46 0 : }
47 : }
48 :
49 0 : parse_node_exception(const std::string& message)
50 0 : : mcrl2::runtime_error(message)
51 0 : { }
52 :
53 : public:
54 4 : parse_node_exception(const parse_node& node, const std::string& message)
55 4 : : mcrl2::runtime_error(get_error_message(node, message))
56 4 : { }
57 : };
58 :
59 : class parse_node_unexpected_exception : public parse_node_exception
60 : {
61 : private:
62 0 : static std::string get_error_message(const parser& p, const parse_node& node)
63 : {
64 0 : std::string inherited = parse_node_exception::get_error_message(node, "unexpected parse node!");
65 : try
66 : {
67 0 : std::ostringstream out;
68 0 : out << inherited << std::endl;
69 0 : p.print_node(out, node);
70 0 : return out.str();
71 0 : }
72 0 : catch (...)
73 : {
74 0 : return inherited;
75 0 : }
76 0 : }
77 : public:
78 0 : parse_node_unexpected_exception(const parser& p, const parse_node& node)
79 0 : : parse_node_exception(get_error_message(p, node))
80 0 : { }
81 : };
82 :
83 : struct parser_actions
84 : {
85 : const parser& m_parser;
86 :
87 3153 : parser_actions(const parser& parser_)
88 3153 : : m_parser(parser_)
89 3153 : {}
90 :
91 : // starts a traversal in node, and calls the function f to each subnode of the given type
92 : template <typename Function>
93 188768 : void traverse(const parse_node& node, const Function& f) const
94 : {
95 188768 : if (!node)
96 : {
97 0 : return;
98 : }
99 188768 : if (!f(node))
100 : {
101 300631 : for (int i = 0; i < node.child_count(); i++)
102 : {
103 155311 : traverse(node.child(i), f);
104 : }
105 : }
106 : }
107 :
108 : // callback function that applies a function to nodes of a given type
109 : template <typename Function>
110 : struct visitor
111 : {
112 : const parser_table& table;
113 : const std::string& type;
114 : const Function& f;
115 :
116 4 : visitor(const parser_table& table_, const std::string& type_, const Function& f_)
117 4 : : table(table_),
118 4 : type(type_),
119 4 : f(f_)
120 4 : {}
121 :
122 136 : bool operator()(const parse_node& node) const
123 : {
124 136 : if (table.symbol_name(node) == type)
125 : {
126 128 : f(node);
127 128 : return true;
128 : }
129 8 : return false;
130 : }
131 : };
132 :
133 : template <typename Function>
134 4 : visitor<Function> make_visitor(const parser_table& table, const std::string& type, const Function& f) const
135 : {
136 4 : return visitor<Function>(table, type, f);
137 : }
138 :
139 : // callback function that applies a function to a node, and adds the result to a container
140 : template <typename Container, typename Function>
141 : struct collector
142 : {
143 : const parser_table& table;
144 : const std::string& type;
145 : Container& container;
146 : const Function& f;
147 :
148 23387 : collector(const parser_table& table_, const std::string& type_, Container& container_, const Function& f_)
149 23387 : : table(table_),
150 23387 : type(type_),
151 23387 : container(container_),
152 23387 : f(f_)
153 23387 : {}
154 :
155 99019 : bool operator()(const parse_node& node) const
156 : {
157 99019 : if (table.symbol_name(node) == type)
158 : {
159 28889 : container.push_back(f(node));
160 28889 : return true;
161 : }
162 70130 : return false;
163 : }
164 : };
165 :
166 : template <typename Container, typename Function>
167 23387 : collector<Container, Function> make_collector(const parser_table& table, const std::string& type, Container& container, const Function& f) const
168 : {
169 23387 : return collector<Container, Function>(table, type, container, f);
170 : }
171 :
172 : // callback function that applies a function to a node, and adds the result to a set container
173 : template <typename SetContainer, typename Function>
174 : struct set_collector
175 : {
176 : const parser_table& table;
177 : const std::string& type;
178 : SetContainer& container;
179 : const Function& f;
180 :
181 128 : set_collector(const parser_table& table_, const std::string& type_, SetContainer& container_, const Function& f_)
182 128 : : table(table_),
183 128 : type(type_),
184 128 : container(container_),
185 128 : f(f_)
186 128 : {}
187 :
188 672 : bool operator()(const parse_node& node) const
189 : {
190 672 : if (table.symbol_name(node) == type)
191 : {
192 224 : container.insert(f(node));
193 224 : return true;
194 : }
195 448 : return false;
196 : }
197 : };
198 :
199 : template <typename SetContainer, typename Function>
200 128 : set_collector<SetContainer, Function> make_set_collector(const parser_table& table, const std::string& type, SetContainer& container, const Function& f) const
201 : {
202 128 : return set_collector<SetContainer, Function>(table, type, container, f);
203 : }
204 :
205 613173 : std::string symbol_name(const parse_node& node) const
206 : {
207 613173 : return m_parser.symbol_table().symbol_name(node.symbol());
208 : }
209 : };
210 :
211 : struct default_parser_actions: public parser_actions
212 : {
213 3153 : default_parser_actions(const parser& parser_)
214 3153 : : parser_actions(parser_)
215 3153 : {}
216 :
217 : template <typename T, typename Function>
218 21966 : atermpp::term_list<T> parse_list(const parse_node& node, const std::string& type, const Function& f) const
219 : {
220 21966 : std::vector<T> result;
221 21966 : traverse(node, make_collector(m_parser.symbol_table(), type, result, f));
222 43932 : return atermpp::term_list<T>(result.begin(), result.end());
223 21966 : }
224 :
225 : template <typename T, typename Function>
226 1421 : std::vector<T> parse_vector(const parse_node& node, const std::string& type, const Function& f) const
227 : {
228 1421 : std::vector<T> result;
229 1421 : traverse(node, make_collector(m_parser.symbol_table(), type, result, f));
230 1421 : return result;
231 0 : }
232 :
233 45652 : core::identifier_string parse_Id(const parse_node& node) const
234 : {
235 91304 : return core::identifier_string(node.string());
236 : }
237 :
238 5562 : core::identifier_string parse_Number(const parse_node& node) const
239 : {
240 11124 : return core::identifier_string(node.string());
241 : }
242 :
243 10682 : core::identifier_string_list parse_IdList(const parse_node& node) const
244 : {
245 23294 : return parse_list<core::identifier_string>(node, "Id", [&](const core::parse_node& node) { return parse_Id(node); });
246 : }
247 : };
248 :
249 : template <typename T>
250 : void print_aterm(const T&)
251 : {
252 : }
253 :
254 : template<>
255 : inline
256 : void print_aterm(const atermpp::aterm_appl& x)
257 : {
258 : std::clog << "aterm: " << x << std::endl;
259 : }
260 :
261 : /// \brief Parse an identifier.
262 : inline
263 : identifier_string parse_identifier(const std::string& text)
264 : {
265 : core::parser p(parser_tables_mcrl2, core::detail::ambiguity_fn, core::detail::syntax_error_fn);
266 : unsigned int start_symbol_index = p.start_symbol_index("Id");
267 : bool partial_parses = false;
268 : core::parse_node node = p.parse(text, start_symbol_index, partial_parses);
269 : identifier_string result = default_parser_actions(p).parse_Id(node);
270 : return result;
271 : }
272 :
273 : inline
274 : bool is_user_identifier(std::string const& s)
275 : {
276 : try
277 : {
278 : parse_identifier(s);
279 : }
280 : catch (...)
281 : {
282 : return false;
283 : }
284 : return true;
285 : }
286 :
287 : } // namespace core
288 : } // namespace mcrl2
289 :
290 : #endif // MCRL2_CORE_PARSE_H
|