distinct.qbk 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125
  1. [/==============================================================================
  2. Copyright (C) 2001-2011 Hartmut Kaiser
  3. Copyright (C) 2001-2011 Joel de Guzman
  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:distinct Qi Distinct Parser Directive]
  8. [heading Description]
  9. The __qi__ `distinct` parser is a directive component allowing to avoid partial
  10. matches while parsing using a skipper. A simple example is the common task of
  11. matching a C keyword.
  12. Consider:
  13. "description" >> -lit(":") >> *(char_ - eol)
  14. intended to match a line in a configuration file. Let's assume further, that
  15. this rule is used with a `space` skipper and that we have the following strings
  16. in the input:
  17. "description: ident\n"
  18. "description ident\n"
  19. "descriptionident\n"
  20. It might seem unexpected, but the parser above matches all three inputs just
  21. fine, even if the third input should not match at all! In order to avoid the
  22. unwanted match we are forced to make our rule more complicated:
  23. lexeme["description" >> !char_("a-zA-Z_0-9")] >> -lit(":") >> *(char_ - eol)
  24. (the rule reads as: match `"description"` as long as it's not /directly/
  25. followed by a valid identifier).
  26. The `distinct[]` directive is meant to simplify the rule above:
  27. distinct(char_("a-zA-Z_0-9"))["description"] >> -lit(":") >> *(char_ - eol)
  28. Using the `distinct[]` component instead of the explicit sequence has the
  29. advantage of being able to encapsulate the tail (i.e the `char_("a-zA-Z_0-9")`)
  30. as a separate parser construct. The following code snippet illustrates the idea
  31. (for the full code of this example please see
  32. [@../../test/qi/distinct.cpp distinct.cpp]):
  33. [import ../../test/qi/distinct.cpp]
  34. [qi_distinct_encapsulation]
  35. These definitions define a new Qi parser recognizing keywords! This allows to
  36. rewrite our declaration parser expression as:
  37. keyword["description"] >> -lit(":") >> *(char_ - eol)
  38. which is much more readable and concise if compared to the original parser
  39. expression. In addition the new `keyword[]` directive has the advantage to be
  40. usable for wrapping any parser expression, not only strings as in the example
  41. above.
  42. [heading Header]
  43. // forwards to <boost/spirit/repository/home/qi/directive/distinct.hpp>
  44. #include <boost/spirit/repository/include/qi_distinct.hpp>
  45. [heading Synopsis]
  46. distinct(tail)[subject]
  47. [heading Parameters]
  48. [table
  49. [[Parameter] [Description]]
  50. [[`tail`] [The parser construct specifying what whould not
  51. follow the subject in order to match the overall
  52. expression.]]
  53. [[`subject`] [The parser construct to use to match the current
  54. input. The distinct directive makes sure that no
  55. unexpected partial matches occur.]]
  56. ]
  57. All two parameters can be arbitrary complex parsers themselves.
  58. [heading Attribute]
  59. The `distinct` component exposes the attribute type of its subject as its own
  60. attribute type. If the `subject` does not expose any attribute (the type is
  61. `unused_type`), then the `distinct` does not expose any attribute either.
  62. a: A, b: B --> distinct(b)[a]: A
  63. [heading Example]
  64. The following example shows simple use cases of the `distinct` parser.
  65. [@../../example/qi/distinct.cpp distinct.cpp])
  66. [import ../../example/qi/distinct.cpp]
  67. [heading Prerequisites]
  68. In addition to the main header file needed to include the core components
  69. implemented in __qi__ we add the header file needed for the new `distinct`
  70. generator.
  71. [qi_distinct_includes]
  72. To make all the code below more readable we introduce the following namespaces.
  73. [qi_distinct_namespace]
  74. [heading Using The Distinct Directive to Match keywords]
  75. We show several examples of how the `distinct[]` directive can be used to force
  76. correct behavior while matching keywords. The first two code snippets show
  77. the correct matching of the `description` keyword (in this hypothetical example
  78. we allow keywords to be directly followed by an optional `"--"`):
  79. [qi_distinct_description_ident]
  80. [qi_distinct_description__ident]
  81. The last example shows that the `distinct[]` parser component correctly refuses
  82. to match "description-ident":
  83. [qi_distinct_description_ident_error]
  84. [endsect]