confix.qbk 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137
  1. [/==============================================================================
  2. Copyright (C) 2001-2011 Hartmut Kaiser
  3. Copyright (C) 2001-2011 Joel de Guzman
  4. Copyright (C) 2009 Chris Hoeppler
  5. Distributed under the Boost Software License, Version 1.0. (See accompanying
  6. file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
  7. ===============================================================================/]
  8. [section:confix Qi Confix Parser Directive]
  9. [heading Description]
  10. The __qi__ `confix` directive is a unary parser component allowing to embed a
  11. parser (the subject) inside an opening (the prefix) and a closing (the suffix):
  12. confix(prefix, suffix)[subject]
  13. This results in a parser that is equivalent to the sequence
  14. omit[prefix] >> subject >> omit[suffix]
  15. A simple example is a parser for non-nested comments which can now be written
  16. as:
  17. confix("/*", "*/")[*(char_ - "*/")] // C style comment
  18. confix("//", eol)[*(char_ - eol)] // C++ style comment
  19. Using the `confix` directive instead of the explicit sequence has the advantage
  20. of being able to encapsulate the prefix and the suffix into a separate construct.
  21. The following code snippet illustrates the idea:
  22. namespace spirit = boost::spirit;
  23. namespace repo = boost::spirit::repository;
  24. // Define a metafunction allowing to compute the type
  25. // of the confix() construct
  26. template <typename Prefix, typename Suffix = Prefix>
  27. struct confix_spec
  28. {
  29. typedef typename spirit::result_of::terminal<
  30. repo::tag::confix(Prefix, Suffix)
  31. >::type type;
  32. };
  33. confix_spec<std::string>::type const c_comment = repo::confix("/*", "*/");
  34. confix_spec<std::string>::type const cpp_comment = repo::confix("//", "\n");
  35. Now, the comment parsers can be written as
  36. c_comment[*(char_ - "*/")] // C style comment
  37. cpp_comment[*(char_ - eol)] // C++ style comment
  38. [note While the `confix_p(prefix, subject, suffix)` parser in __classic__
  39. was equivalent to the sequence `prefix >> *(subject - suffix) >> suffix,
  40. the __qi__ `confix` directive will not perform this refactoring any more.
  41. This simplifies the code and makes things more explicit.]
  42. [heading Header]
  43. // forwards to <boost/spirit/repository/home/qi/directive/confix.hpp>
  44. #include <boost/spirit/repository/include/qi_confix.hpp>
  45. [heading Synopsis]
  46. confix(prefix, suffix)[subject]
  47. [heading Parameters]
  48. [table
  49. [[Parameter] [Description]]
  50. [[`prefix`] [The parser for the opening (the prefix).]]
  51. [[`suffix`] [The parser for the ending (the suffix).]]
  52. [[`subject`] [The parser for the input sequence between the
  53. `prefix` and `suffix` parts.]]
  54. ]
  55. All three parameters can be arbitrarily complex parsers themselves.
  56. [heading Attribute]
  57. The `confix` directive exposes the attribute type of its subject as its own
  58. attribute type. If the `subject` does not expose any attribute (the type is
  59. `unused_type`), then the `confix` does not expose any attribute either.
  60. a: A, p: P, s: S: --> confix(p, s)[a]: A
  61. [note This notation is used all over the Spirit documentation and reads as:
  62. Given, `a`, `p`, and `s` are parsers, and `A`, `P`, and `S` are the types
  63. of their attributes, then the type of the attribute exposed by
  64. `confix(p, s)[a]` will be `A`.]
  65. [heading Example]
  66. The following example shows simple use cases of the `confix` directive. We will
  67. illustrate its usage by generating parsers for different comment styles and
  68. for some simple tagged data (for the full example code see
  69. [@../../example/qi/confix.cpp confix.cpp])
  70. [import ../../example/qi/confix.cpp]
  71. [heading Prerequisites]
  72. In addition to the main header file needed to include the core components
  73. implemented in __qi__ we add the header file needed for the new `confix`
  74. directive.
  75. [qi_confix_includes]
  76. In order to make the examples below more readable we import a number of
  77. elements into the current namespace:
  78. [qi_confix_using]
  79. [heading Parsing Different Comment Styles]
  80. We will show how to parse different comment styles. First we will parse
  81. a C++ comment:
  82. [qi_confix_cpp_comment]
  83. This function will obviously parse input such as "`// This is a comment \n `".
  84. Similarily parsing a 'C'-style comment proves to be straightforward:
  85. [qi_confix_c_comment]
  86. which again will be able to parse e.g. "`/* This is a comment */ `".
  87. [heading Parsing Tagged Data]
  88. Generating a parser that extracts the body from the HTML snippet "`<b>The Body</b>`"
  89. is not very hard, either:
  90. [qi_confix_tagged_data]
  91. [endsect]