mavtables  0.2.1
MAVLink router and firewall.
parse_tree.hpp
Go to the documentation of this file.
1 // Copyright (c) 2007-2018 Dr. Colin Hirsch and Daniel Frey
2 //
3 // Permission is hereby granted, free of charge, to any person obtaining a copy
4 // of this software and associated documentation files (the "Software"), to deal
5 // in the Software without restriction, including without limitation the rights
6 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7 // copies of the Software, and to permit persons to whom the Software is
8 // furnished to do so, subject to the following conditions:
9 //
10 // The above copyright notice and this permission notice shall be included in
11 // all copies or substantial portions of the Software.
12 //
13 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
19 // SOFTWARE.
20 
21 
22 // Modified by Michael R. Shannon for use in mavtables.
23 
24 
25 #ifndef PARSE_TREE_HPP_
26 #define PARSE_TREE_HPP_
27 
28 
29 #include <cassert>
30 #include <memory>
31 #include <typeinfo>
32 #include <type_traits>
33 #include <utility>
34 #include <vector>
35 
36 #include <pegtl/config.hpp>
37 #include <pegtl/internal/demangle.hpp>
38 #include <pegtl/internal/iterator.hpp>
39 #include <pegtl/normal.hpp>
40 #include <pegtl/nothing.hpp>
41 #include <pegtl/parse.hpp>
42 
43 
44 // Not included in documentation because it is mostly copied from PEGTL.
45 
46 /// @cond INTERNAL
47 namespace config
48 {
49  namespace parse_tree
50  {
51  namespace pegtl = tao::pegtl;
52 
53  template<typename T>
54  struct default_node_children
55  {
56  using node_t = T;
57  using children_t = std::vector< std::unique_ptr< node_t > >;
58  children_t children;
59 
60  // each node will be default constructed
61  default_node_children() = default;
62 
63  // no copy/move is necessary
64  // (nodes are always owned/handled by a std::unique_ptr)
65  default_node_children(const default_node_children &) = delete;
66  default_node_children(default_node_children &&) = delete;
67 
68  ~default_node_children() = default;
69 
70  // no assignment either
71  default_node_children &operator=(
72  const default_node_children &) = delete;
73  default_node_children &operator=(
74  default_node_children &&) = delete;
75 
76  typename children_t::reference at(
77  const typename children_t::size_type pos)
78  {
79  return children.at(pos);
80  }
81 
82  typename children_t::const_reference at(
83  const typename children_t::size_type pos) const
84  {
85  return children.at(pos);
86  }
87 
88  typename children_t::reference front()
89  {
90  return children.front();
91  }
92 
93  typename children_t::const_reference front() const
94  {
95  return children.front();
96  }
97 
98  typename children_t::reference back()
99  {
100  return children.back();
101  }
102 
103  typename children_t::const_reference back() const
104  {
105  return children.back();
106  }
107 
108  bool empty() const noexcept
109  {
110  return children.empty();
111  }
112 
113  typename children_t::size_type size() const noexcept
114  {
115  return children.size();
116  }
117 
118  // if parsing succeeded and the (optional) transform call
119  // did not discard the node, it is appended to its parent.
120  // note that "child" is the node whose Rule just succeeded
121  // and "*this" is the parent where the node should be appended.
122  template<typename... States>
123  void emplace_back(
124  std::unique_ptr< node_t > child, States &&... /*unused*/)
125  {
126  assert(child);
127  children.emplace_back(std::move(child));
128  }
129  };
130 
131  struct default_node_content
132  {
133  const std::type_info *id_ = nullptr;
134  pegtl::internal::iterator begin_;
135  pegtl::internal::iterator end_;
136  std::string source_;
137 
138  bool is_root() const noexcept
139  {
140  return id_ == nullptr;
141  }
142 
143  template<typename T>
144  bool is() const noexcept
145  {
146  return id_ == &typeid(T);
147  }
148 
149  std::string name() const
150  {
151  assert(!is_root());
152  return pegtl::internal::demangle(id_->name());
153  }
154 
155  pegtl::position begin() const
156  {
157  return pegtl::position(begin_, source_);
158  }
159 
160  pegtl::position end() const
161  {
162  return pegtl::position(end_, source_);
163  }
164 
165  const std::string &source() const noexcept
166  {
167  return source_;
168  }
169 
170  bool has_content() const noexcept
171  {
172  return end_.data != nullptr;
173  }
174 
175  std::string content() const
176  {
177  assert(has_content());
178  return std::string(begin_.data, end_.data);
179  }
180 
181  template< typename... States >
182  void remove_content(States &&... /*unused*/) noexcept
183  {
184  end_.reset();
185  }
186 
187  // all non-root nodes are initialized by calling this method
188  template<typename Rule, typename Input, typename... States>
189  void start(const Input &in, States &&... /*unused*/)
190  {
191  id_ = &typeid(Rule);
192  begin_ = in.iterator();
193  source_ = in.source();
194  }
195 
196  // if parsing of the rule succeeded, this method is called
197  template<typename Rule, typename Input, typename... States>
198  void success(const Input &in, States &&... /*unused*/) noexcept
199  {
200  end_ = in.iterator();
201  }
202 
203  // if parsing of the rule failed, this method is called
204  template<typename Rule, typename Input, typename... States>
205  void failure(
206  const Input & /*unused*/, States &&... /*unused*/) noexcept
207  {
208  }
209  };
210 
211  template<typename T>
212  struct basic_node
213  : default_node_children<T>, default_node_content
214  {
215  };
216 
217  struct node
218  : basic_node< node >
219  {
220  };
221 
222  namespace internal
223  {
224  template<typename Node>
225  struct state
226  {
227  std::vector<std::unique_ptr<Node>> stack;
228 
229  state()
230  {
231  emplace_back();
232  }
233 
234  void emplace_back()
235  {
236  stack.emplace_back(std::unique_ptr< Node >(new Node));
237  }
238 
239  std::unique_ptr<Node> &back() noexcept
240  {
241  return stack.back();
242  }
243 
244  void pop_back() noexcept
245  {
246  return stack.pop_back();
247  }
248  };
249 
250  template<typename Node, typename S, typename = void>
251  struct transform
252  {
253  template<typename... States>
254  static void call(std::unique_ptr< Node > & /*unused*/,
255  States &&... /*unused*/) noexcept
256  {
257  }
258  };
259 
260  template<typename Node, typename S>
261  struct transform <
262  Node, S, decltype(
263  S::transform(std::declval<std::unique_ptr<Node>& >()), void()) >
264  {
265  template<typename... States>
266  static void call(
267  std::unique_ptr<Node> &n, States &&... st)
268  noexcept(noexcept(S::transform(n)))
269  {
270  S::transform(n, st...);
271  }
272  };
273 
274  // https://stackoverflow.com/a/16000226
275  template <typename T, typename = int>
276  struct has_error_message : std::false_type {};
277 
278  // https://stackoverflow.com/a/16000226
279  template <typename T>
280  struct has_error_message <T, decltype((void) T::error_message, 0)>
281 : std::true_type {};
282 
283  template<template<typename> class S>
284  struct make_control
285  {
286  template<typename Rule, bool = S<Rule>::value>
287  struct control;
288 
289  template<typename Rule>
290  using type = control<Rule>;
291  };
292 
293  template<template<typename> class S>
294  template<typename Rule>
295  struct make_control< S >::control< Rule, false >
296  : pegtl::normal< Rule >
297  {
298 
299  // custom error message
300  template< typename Input, typename... States >
301  static void raise(const Input &in, States &&...)
302  {
303  if constexpr(has_error_message<S<Rule>>::value)
304  {
305  throw pegtl::parse_error(S<Rule>::error_message, in);
306  }
307  else
308  {
309  throw pegtl::parse_error(
310  "Parse error matching " +
311  pegtl::internal::demangle<Rule>(), in);
312  }
313  }
314 
315  };
316 
317  template<template<typename> class S>
318  template<typename Rule>
319  struct make_control<S>::control< Rule, true >
320  : pegtl::normal<Rule>
321  {
322 
323  // custom error message
324  template< typename Input, typename... States >
325  static void raise(const Input &in, States &&...)
326  {
327  if constexpr(has_error_message<S<Rule>>::value)
328  {
329  throw pegtl::parse_error(S<Rule>::error_message, in);
330  }
331  else
332  {
333  throw pegtl::parse_error(
334  "Parse error matching " +
335  pegtl::internal::demangle<Rule>(), in);
336  }
337  }
338 
339  template<typename Input, typename Node, typename... States>
340  static void start(
341  const Input &in, state< Node > &state, States &&... st)
342  {
343  state.emplace_back();
344  state.back()->template start<Rule>(in, st...);
345  }
346 
347  template< typename Input, typename Node, typename... States >
348  static void success(
349  const Input &in, state<Node> &state, States &&... st)
350  {
351  auto n = std::move(state.back());
352  state.pop_back();
353  n->template success<Rule>(in, st...);
354  transform<Node, S<Rule>>::call(n, st...);
355 
356  if (n)
357  {
358  state.back()->emplace_back(std::move(n), st...);
359  }
360  }
361 
362  template<typename Input, typename Node, typename... States>
363  static void failure(
364  const Input &in, state< Node > &state, States &&... st)
365  noexcept(noexcept(std::declval<node &>().template
366  failure<Rule>(in, st...)))
367  {
368  state.back()->template failure< Rule >(in, st...);
369  state.pop_back();
370  }
371  };
372 
373  template<typename>
374  struct store_all : std::true_type
375  {
376  };
377 
378  } // namespace internal
379 
380  template <
381  typename Rule,
382  typename Node,
383  template<typename> class S = internal::store_all,
384  typename Input,
385  typename... States >
386  std::unique_ptr<Node> parse(Input &in, States && ... st)
387  {
388  internal::state< Node > state;
389 
390  if (!pegtl::parse <
391  Rule, pegtl::nothing,
392  internal::make_control<S>::template type >
393  (in, state, st...))
394  {
395  return nullptr;
396  }
397 
398  assert(state.stack.size() == 1);
399  return std::move(state.back());
400  }
401 
402  template <
403  typename Rule,
404  template<typename> class S = internal::store_all,
405  typename Input,
406  typename... States >
407  std::unique_ptr<node> parse(Input &in, States && ... st)
408  {
409  return parse<Rule, node, S>(in, st...);
410  }
411 
412  } // namespace parse_tree
413 
414 } // namespace config
415 /// @endcond
416 
417 #endif
std::unique_ptr< config::parse_tree::node > parse(Input &in)
Call call(chain)
Definition: Rule.hpp:38