actions.qbk 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125
  1. [/==============================================================================
  2. Copyright (C) 2001-2011 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 C++ functions or function objects that are called whenever a
  15. part of the parser successfully recognizes a portion of the input. Say you have
  16. a parser `P`, and a C++ function `F`. You can make the parser call `F` whenever
  17. it matches an input by attaching `F`:
  18. P[F]
  19. The expression above links `F` to the parser, `P`.
  20. The function/function object signature depends on the type of the parser to
  21. which it is attached. The parser `double_` passes the parsed number. Thus, if we
  22. were to attach a function `F` to `double_`, we need `F` to be declared as:
  23. void F(double n);
  24. There are actually 2 more arguments being passed (the parser context and a
  25. reference to a boolean 'hit' parameter). We don't need these, for now, but we'll
  26. see more on these other arguments later. Spirit.Qi allows us to bind a single
  27. argument function, like above. The other arguments are simply ignored.
  28. [heading Examples of Semantic Actions]
  29. Presented are various ways to attach semantic actions:
  30. * Using plain function pointer
  31. * Using simple function object
  32. * Using __boost_bind__ with a plain function
  33. * Using __boost_bind__ with a member function
  34. * Using __boost_lambda__
  35. [import ../../example/qi/actions.cpp]
  36. Given:
  37. [tutorial_semantic_action_functions]
  38. Take note that with function objects, we need to have an `operator()` with 3
  39. arguments. Since we don't care about the other two, we can use `unused_type` for
  40. these. We'll see more of `unused_type` elsewhere. `unused_type` is a Spirit
  41. supplied support class.
  42. All examples parse inputs of the form:
  43. "{integer}"
  44. An integer inside the curly braces.
  45. The first example shows how to attach a plain function:
  46. [tutorial_attach_actions1]
  47. What's new? Well `int_` is the sibling of `double_`. I'm sure you can guess
  48. what this parser does.
  49. The next example shows how to attach a simple function object:
  50. [tutorial_attach_actions2]
  51. We can use __boost_bind__ to 'bind' member functions:
  52. [tutorial_attach_actions4]
  53. Likewise, we can also use __boost_bind__ to 'bind' plain functions:
  54. [tutorial_attach_actions3]
  55. Yep, we can also use __boost_lambda__:
  56. [tutorial_attach_actions5]
  57. There are more ways to bind semantic action functions, but the examples above
  58. are the most common. Attaching semantic actions is the first hurdle one has
  59. to tackle when getting started with parsing with Spirit. Familiarize yourself
  60. with this task and get intimate with the tools behind it such as __boost_bind__
  61. and __boost_lambda__.
  62. The examples above can be found here: [@../../example/qi/actions.cpp]
  63. [heading Phoenix]
  64. __phoenix__, a companion library bundled with Spirit, is specifically suited
  65. for binding semantic actions. It is like __boost_lambda__ on steroids, with
  66. special custom features that make it easy to integrate semantic actions with
  67. Spirit. If your requirements go beyond simple to moderate parsing, it is
  68. suggested that you use this library. All the following examples in this tutorial
  69. will use __phoenix__ for semantic actions.
  70. [important There are different ways to write semantic actions for __qi__:
  71. using plain functions, __boost_bind__, __boost_lambda__, or
  72. __phoenix__. The latter three allow you to use special placeholders
  73. to control parameter placement (`_1`, `_2`, etc.). Each of those
  74. libraries has it's own implementation of the placeholders, all
  75. in different namespaces. You have to make sure not to mix
  76. placeholders with a library they don't belong to and not to
  77. use different libraries while writing a semantic action.
  78. Generally, for __boost_bind__, use `::_1`, `::_2`, etc. (yes, these
  79. placeholders are defined in the global namespace).
  80. For __boost_lambda__ use the placeholders defined in the namespace
  81. `boost::lambda`.
  82. For semantic actions written using __phoenix__ use the placeholders
  83. defined in the namespace `boost::spirit`. Please note that all
  84. existing placeholders for your convenience are also available from
  85. the namespace `boost::spirit::qi`.]
  86. [endsect]