mavtables  0.2.1
MAVLink router and firewall.
config_grammar.hpp
Go to the documentation of this file.
1 // MAVLink router and firewall.
2 // Copyright (C) 2018 Michael R. Shannon <mrshannon.aerospace@gmail.com>
3 //
4 // This program is free software; you can redistribute it and/or modify
5 // it under the terms of the GNU General Public License as published by
6 // the Free Software Foundation; either version 2 of the License, or
7 // (at your option) any later version.
8 //
9 // This program is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 // GNU General Public License for more details.
13 //
14 // You should have received a copy of the GNU General Public License
15 // along with this program. If not, see <http://www.gnu.org/licenses/>.
16 
17 
18 #ifndef CONFIG_GRAMMAR_HPP_
19 #define CONFIG_GRAMMAR_HPP_
20 
21 
22 #include <iterator>
23 #include <memory>
24 #include <optional>
25 #include <string>
26 #include <type_traits>
27 #include <utility>
28 #include <vector>
29 
30 #include <pegtl.hpp>
31 
32 #include "parse_tree.hpp"
33 
34 
35 namespace config
36 {
37 
38  /// @cond INTERNAL
39 
40  using namespace tao::pegtl;
41  using namespace tao::pegtl::ascii;
42 
43 
44  // Error message mixin.
45  template<typename>
46  struct error
47  {
48  static const std::string error_message;
49  };
50 
51 
52  // Store node mixin.
53  template<typename T>
54  struct yes : std::true_type, error<T> {};
55 
56  // Do not store node mixin.
57  template<typename T>
58  struct no : std::false_type, error<T> {};
59 
60  // Remove content mixin for store object's.
61  template<typename T>
62  struct yes_without_content : std::true_type, error<T>
63  {
64  static void transform(std::unique_ptr<config::parse_tree::node> &node)
65  {
66  node->remove_content();
67  }
68  };
69 
70  // Replace with first child storage mixin. Removes any children of the
71  // first child.
72  template <typename T>
73  struct replace_with_first_child : std::true_type, error<T>
74  {
75  static void transform(std::unique_ptr<config::parse_tree::node> &node)
76  {
77  auto children = std::move(node->children);
78  node = std::move(children.front());
79  children.erase(children.begin());
80  node->children = std::move(children);
81  }
82  };
83 
84  // Do not store AST node content by default
85  template<typename T> struct store : no<T> {};
86 
87 
88  // Comments and ignored components.
89  struct comment : seq<one<'#'>, star<not_at<eol>, not_at<eof>, any>> {};
90  struct ignored : sor<space, comment> {};
91 
92  // Pad a rule.
93  template <typename N>
94  struct p : pad<N, ignored> {};
95 
96  // End of statement terminator.
97  struct eos : one<';'> {};
98 
99  // Generic statement with 0 or 1 values.
100  template <typename K>
101  struct a0_statement : seq<K, p<must<eos>>> {};
102  template <typename K, typename V = success>
103  struct a1_statement : seq<K, p<must<V>>, p<must<eos>>> {};
104 
105  // Generic block.
106  struct opening_brace : one<'{'> {};
107  struct closing_brace : one<'}'> {};
108  template <typename K, typename... Statements>
109  struct t_block : seq<K,
110  p<must<opening_brace>>,
111  star<p<sor<Statements...>>>,
112  p<must<closing_brace>>> {};
113 
114  // Generic named block.
115  template <typename K, typename N, typename... Statements>
116  struct t_named_block
117  : seq<K, p<must<N>>, p<must<opening_brace>>,
118  star<p<sor<Statements...>>>, p<must<closing_brace>>> {};
119 
120  // Yes/No (boolean) value.
121  struct yesno
122  : sor<TAO_PEGTL_STRING("yes"), TAO_PEGTL_STRING("no")> {};
123 
124  // Unsigned integer value.
125  struct integer : plus<digit> {};
126 
127  // Signed integer value.
128  struct signed_integer : seq<opt<one<'+', '-'>>, integer> {};
129 
130  // MAVLink addresses and masks.
131  struct mavaddr : seq<integer, one<'.'>, integer> {};
132  struct full_mask : if_must<one<':'>, mavaddr> {};
133  struct forward_mask : if_must<one<'/'>, integer> {};
134  struct backward_mask : if_must<one<'\\'>, integer> {};
135  struct mavmask
136  : seq<mavaddr, opt<sor<full_mask, forward_mask, backward_mask>>> {};
137 
138  // Port number.
139  struct port : integer {};
140  template<> struct store<port> : yes<port> {};
141 
142  // IP address.
143  struct address : seq<integer, rep<3, seq<one<'.'>, integer>>> {};
144  template<> struct store<address> : yes<address> {};
145 
146  // Maximum bitrate number.
147  struct max_bitrate : integer {};
148  template<> struct store<max_bitrate> : yes<max_bitrate> {};
149 
150  // Serial port device name.
151  struct device : plus<sor<alnum, one<'.', '_', '/'>>> {};
152  template<> struct store<device> : yes<device> {};
153 
154  // Serial port baud rate.
155  struct baudrate : integer {};
156  template<> struct store<baudrate> : yes<baudrate> {};
157 
158  // Serial port flow control.
159  struct flow_control : yesno {};
160  template<> struct store<flow_control> : yes<flow_control> {};
161 
162  // Serial port address preload.
163  struct preload : mavaddr {};
164  template<> struct store<preload> : yes<preload> {};
165 
166  // Chain name.
167  struct chain_name : identifier {};
168  template<> struct store<chain_name> : yes<chain_name> {};
169 
170  // Rule actions.
171  // accept
172  struct accept : TAO_PEGTL_STRING("accept") {};
173  template<> struct store<accept> : yes_without_content<accept> {};
174  // reject
175  struct reject : TAO_PEGTL_STRING("reject") {};
176  template<> struct store<reject> : yes_without_content<reject> {};
177  // call
178  struct call : chain_name {};
179  template<> struct store<call> : yes<call> {};
180  struct call_container : seq<TAO_PEGTL_STRING("call"), p<must<call>>> {};
181  template<> struct store<call_container>
182  : replace_with_first_child<call_container> {};
183  // goto
184  struct goto_ : chain_name {};
185  template<> struct store<goto_> : yes<goto_> {};
186  struct goto_container : seq<TAO_PEGTL_STRING("goto"), p<must<goto_>>> {};
187  template<> struct store<goto_container>
188  : replace_with_first_child<goto_container> {};
189  // generic action
190  struct action : sor<accept, reject, call_container, goto_container> {};
191 
192  // Conditional.
193  struct packet_type : plus<sor<upper, digit, one<'_'>>> {};
194  template<> struct store<packet_type> : yes<packet_type> {};
195  struct source : mavmask {};
196  template<> struct store<source> : yes<source> {};
197  struct source_command
198  : seq<TAO_PEGTL_STRING("from"), p<must<source>>> {};
199  struct dest : mavmask {};
200  template<> struct store<dest> : yes<dest> {};
201  struct dest_command
202  : seq<TAO_PEGTL_STRING("to"), p<must<dest>>> {};
203  struct start_with_packet_type
204  : seq<packet_type, opt<p<source_command>>, opt<p<dest_command>>> {};
205  struct start_with_source : seq<source_command, opt<p<dest_command>>> {};
206  struct start_with_dest : dest_command {};
207  struct condition_value
208  : p<sor<start_with_packet_type, start_with_source, start_with_dest>> {};
209  struct condition : if_must<TAO_PEGTL_STRING("if"), condition_value> {};
210  template<> struct store<condition> : yes_without_content<condition> {};
211 
212  // Priority.
213  struct priority : signed_integer {};
214  template<> struct store<priority> : yes<priority> {};
215  struct priority_keyword : TAO_PEGTL_STRING("priority") {};
216  struct priority_command
217  : seq<TAO_PEGTL_STRING("with"), p<must<priority_keyword>>,
218  p<must<priority>>> {};
219 
220  // Catch unsuported statements.
221  struct unsupported_statement : failure {};
222  struct sa0_catch
223  : if_must<a0_statement<identifier>, unsupported_statement> {};
224  struct sa1_catch
225  : if_must<a1_statement<identifier,
226  star<not_one<';'>>>, unsupported_statement> {};
227  struct s_catch : sor<sa0_catch, sa1_catch> {};
228 
229  // Catch unsuported rules.
230  struct invalid_rule : failure {};
231  struct sa0_rule_catch : if_must<a0_statement<identifier>, invalid_rule> {};
232  struct sa1_rule_catch
233  : if_must<a1_statement<identifier,
234  star<not_one<';'>>>, invalid_rule> {};
235  struct rule_catch : sor<sa0_rule_catch, sa1_rule_catch> {};
236 
237  // Filter chain.
238  struct rule
239  : if_must<sor<action, rule_catch>, opt<p<priority_command>>,
240  opt<p<condition>>, eos> {};
241  template<> struct store<rule> : replace_with_first_child<rule> {};
242  struct chain : chain_name {};
243  template<> struct store<chain> : yes<chain> {};
244  struct chain_container
245  : t_named_block<TAO_PEGTL_STRING("chain"), chain, rule> {};
246  template<> struct store<chain_container>
247  : replace_with_first_child<chain_container> {};
248 
249  // Default filter action (keep node, no content).
250  struct default_action_option : sor<accept, reject> {};
251  struct default_action
252  : a1_statement<TAO_PEGTL_STRING("default_action"),
253  default_action_option> {};
254  template<> struct store<default_action>
255  : yes_without_content<default_action> {};
256 
257  // UDP connection block.
258  struct s_port : a1_statement<TAO_PEGTL_STRING("port"), port> {};
259  struct s_address : a1_statement<TAO_PEGTL_STRING("address"), address> {};
260  struct s_max_bitrate
261  : a1_statement<TAO_PEGTL_STRING("max_bitrate"), max_bitrate> {};
262  struct udp
263  : t_block<TAO_PEGTL_STRING("udp"),
264  s_port, s_address, s_max_bitrate, s_catch> {};
265  template<> struct store<udp> : yes_without_content<udp> {};
266 
267  // Serial port block.
268  struct s_device : a1_statement<TAO_PEGTL_STRING("device"), device> {};
269  struct s_baudrate : a1_statement<TAO_PEGTL_STRING("baudrate"), baudrate> {};
270  struct s_flow_control
271  : a1_statement<TAO_PEGTL_STRING("flow_control"), flow_control> {};
272  struct s_preload : a1_statement<TAO_PEGTL_STRING("preload"), preload> {};
273  struct serial
274  : t_block<TAO_PEGTL_STRING("serial"),
275  s_device, s_baudrate, s_flow_control, s_preload, s_catch> {};
276  template<> struct store<serial> : yes_without_content<serial> {};
277 
278  // Combine grammar.
279  struct block : sor<udp, serial, chain_container> {};
280  struct statement : sor<default_action, s_catch> {};
281  struct element : sor<comment, block, statement> {};
282  struct elements : plus<pad<element, ignored>> {};
283  struct grammar : seq<must<elements>, eof> {};
284 
285 #ifdef __clang__
286  #pragma clang diagnostic push
287  #pragma clang diagnostic ignored "-Wglobal-constructors"
288  #pragma clang diagnostic ignored "-Wexit-time-destructors"
289 #endif
290 
291  // Error messages
292 
293  template<>
294  const std::string error<eos>::error_message;
295 
296  template<>
297  const std::string error<opening_brace>::error_message;
298 
299  template<>
300  const std::string error<closing_brace>::error_message;
301 
302  template<>
303  const std::string error<unsupported_statement>::error_message;
304 
305  template<>
306  const std::string error<default_action_option>::error_message;
307 
308  template<>
309  const std::string error<port>::error_message;
310 
311  template<>
312  const std::string error<address>::error_message;
313 
314  template<>
315  const std::string error<max_bitrate>::error_message;
316 
317  template<>
318  const std::string error<device>::error_message;
319 
320  template<>
321  const std::string error<baudrate>::error_message;
322 
323  template<>
324  const std::string error<flow_control>::error_message;
325 
326  template<>
327  const std::string error<preload>::error_message;
328 
329  template<>
330  const std::string error<chain_name>::error_message;
331 
332  template<>
333  const std::string error<chain>::error_message;
334 
335  template<>
336  const std::string error<call>::error_message;
337 
338  template<>
339  const std::string error<goto_>::error_message;
340 
341  template<>
342  const std::string error<invalid_rule>::error_message;
343 
344  template<>
345  const std::string error<condition_value>::error_message;
346 
347  template<>
348  const std::string error<dest>::error_message;
349 
350  template<>
351  const std::string error<source>::error_message;
352 
353  template<>
354  const std::string error<mavaddr>::error_message;
355 
356  template<>
357  const std::string error<integer>::error_message;
358 
359  template<>
360  const std::string error<priority>::error_message;
361 
362  template<>
363  const std::string error<priority_keyword>::error_message;
364 
365  template<>
366  const std::string error<elements>::error_message;
367 
368  // Default error message.
369  template<typename T>
370  const std::string error<T>::error_message =
371  "parse error matching " + internal::demangle<T>();
372 
373 #ifdef __clang__
374  #pragma clang diagnostic pop
375 #endif
376 
377  /// @endcond
378 
379 
380  /** Parses given input into an abstract syntax tree.
381  *
382  * \note The returned AST is only valid while the input exists. Therefore,
383  * the input should be kept until the AST passes out of scope.
384  *
385  * \tparam Input The type of input, usually either read_input or
386  * string_input (see PEGTL).
387  * \param in The input, from read_input etc, to parse.
388  * \returns The abstract syntax tree parsed from the input.
389  */
390  template <typename Input>
391  std::unique_ptr<config::parse_tree::node> parse(Input &in)
392  {
393  return parse_tree::parse<grammar, config::store>(in);
394  }
395 
396  std::ostream &print_node(
397  std::ostream &os, const config::parse_tree::node &n,
398  bool print_location, const std::string &s = "");
399 }
400 
401 
402 std::ostream &operator<<(
403  std::ostream &os, const config::parse_tree::node &node);
404 
405 
406 #endif // CONFIG_GRAMMAR_HPP_
std::ostream & print_node(std::ostream &os, const config::parse_tree::node &node, bool print_location, const std::string &prefix)
std::unique_ptr< config::parse_tree::node > parse(Input &in)
Reject reject
Call call(chain)
GoTo goto_(chain)
std::ostream & operator<<(std::ostream &os, const config::parse_tree::node &node)
Rule & rule
Definition: test_Call.cpp:231