actions.qbk 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990
  1. [/==============================================================================
  2. Copyright (C) 2001-2015 Joel de Guzman
  3. Copyright (C) 2001-2011 Hartmut Kaiser
  4. Distributed under the Boost Software License, Version 1.0. (See accompanying
  5. file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
  6. ===============================================================================/]
  7. [section:semantic_actions Parser Semantic Actions]
  8. The example in the previous section was very simplistic. It only recognized
  9. data, but did nothing with it. It answered the question: "Did the input match?".
  10. Now, we want to extract information from what was parsed. For example, we would
  11. want to store the parsed number after a successful match. To do this, you will
  12. need ['semantic actions].
  13. Semantic actions may be attached to any point in the grammar specification.
  14. These actions are polymorphic function objects that are called whenever a part
  15. of the parser successfully recognizes a portion of the input. Say you have a
  16. parser `p`, and a polymorphic C++ function object `f`. You can make the parser
  17. call `f` whenever it matches an input by attaching `f`:
  18. p[f]
  19. The expression above links `f` to the parser, `p`. `f` is expected to be a
  20. polymorphic function object with the signature:
  21. template <typename Context>
  22. void operator()(Context const& ctx) const;
  23. We can also use C++14 generic lambdas of the form:
  24. [](auto& ctx) { /*...*/ }
  25. From the context, we can extract relevant information:
  26. [table Parse Context Access Functions
  27. [[Function] [Description] [Example]]
  28. [[`_val`] [A reference to the attribute of the
  29. innermost rule that directly or indirectly
  30. invokes the parser `p`] [`_val(ctx) = "Gotya!"`]]
  31. [[`_where`] [Iterator range to the input stream] [`_where(ctx).begin()`]]
  32. [[`_attr`] [A reference to the attribute of the
  33. parser `p`] [`_val(ctx) += _attr(ctx)`]]
  34. [[`_pass`] [A reference to a `bool` flag that
  35. can be used to force the `p` to fail] [`_pass(ctx) = false`]]
  36. ]
  37. [heading Examples of Semantic Actions]
  38. Given:
  39. struct print_action
  40. {
  41. template <typename Context>
  42. void operator()(Context const& ctx) const
  43. {
  44. std::cout << _attr(ctx) << std::endl;
  45. }
  46. };
  47. Take note that with function objects, we need to have an `operator()` with
  48. the Context argument. If we don't care about the context, we can use
  49. `unused_type`. We'll see more of `unused_type` elsewhere. `unused_type` is a
  50. Spirit supplied support class.
  51. All examples parse inputs of the form:
  52. "{NNN}"
  53. Where NNN is an integer inside the curly braces (e.g. {44}).
  54. The first example shows how to attach a function object:
  55. parse(first, last, '{' >> int_[print_action()] >> '}');
  56. What's new? Well `int_` is the sibling of `double_`. I'm sure you can guess
  57. what this parser does.
  58. The next example shows how use C++14 lambda:
  59. auto f = [](auto& ctx){ std::cout << _attr(ctx) << std::endl; };
  60. parse(first, last, '{' >> int_[f] >> '}');
  61. Attaching semantic actions is the first hurdle one has to tackle when getting
  62. started with parsing with Spirit. Familiarize yourself with this task.
  63. The examples above can be found here: [@../../../example/x3/actions.cpp actions.cpp]
  64. [endsect]