roman.qbk 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170
  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 Roman Numerals]
  8. This example demonstrates:
  9. * symbol table
  10. * rule
  11. * grammar
  12. [heading Symbol Table]
  13. The symbol table holds a dictionary of symbols where each symbol is a sequence
  14. of characters (a `char`, `wchar_t`, `int`, enumeration etc.) . The template
  15. class, parameterized by the character type, can work efficiently with 8, 16, 32
  16. and even 64 bit characters. Mutable data of type T are associated with each
  17. symbol.
  18. Traditionally, symbol table management is maintained separately outside the BNF
  19. grammar through semantic actions. Contrary to standard practice, the Spirit
  20. symbol table class `symbols` is a parser. An object of which may be used
  21. anywhere in the EBNF grammar specification. It is an example of a dynamic
  22. parser. A dynamic parser is characterized by its ability to modify its behavior
  23. at run time. Initially, an empty symbols object matches nothing. At any time,
  24. symbols may be added or removed, thus, dynamically altering its behavior.
  25. Each entry in a symbol table has an associated mutable data slot. In this
  26. regard, one can view the symbol table as an associative container (or map) of
  27. key-value pairs where the keys are strings.
  28. The symbols class expects two template parameters. The first parameter specifies
  29. the character type of the symbols. The second specifies the data type associated
  30. with each symbol: its attribute.
  31. Here's a parser for roman hundreds (100..900) using the symbol table. Keep in
  32. mind that the data associated with each slot is the parser's attribute (which is
  33. passed to attached semantic actions).
  34. [import ../../example/qi/roman.cpp]
  35. [tutorial_roman_hundreds]
  36. Here's a parser for roman tens (10..90):
  37. [tutorial_roman_tens]
  38. and, finally, for ones (1..9):
  39. [tutorial_roman_ones]
  40. Now we can use `hundreds`, `tens` and `ones` anywhere in our parser expressions.
  41. They are all parsers.
  42. [heading Rules]
  43. Up until now, we've been inlining our parser expressions, passing them directly
  44. to the `phrase_parse` function. The expression evaluates into a temporary,
  45. unnamed parser which is passed into the `phrase_parse` function, used, and then
  46. destroyed. This is fine for small parsers. When the expressions get complicated,
  47. you'd want to break the expressions into smaller easier-to-understand pieces,
  48. name them, and refer to them from other parser expressions by name.
  49. A parser expression can be assigned to what is called a "rule". There are
  50. various ways to declare rules. The simplest form is:
  51. rule<Iterator> r;
  52. At the very least, the rule needs to know the iterator type it will be working
  53. on. This rule cannot be used with `phrase_parse`. It can only be used with the
  54. `parse` function -- a version that does not do white space skipping (does not
  55. have the skipper argument). If you want to have it skip white spaces, you need
  56. to pass in the type skip parser, as in the next form:
  57. rule<Iterator, Skipper> r;
  58. Example:
  59. rule<std::string::iterator, space_type> r;
  60. This type of rule can be used for both `phrase_parse` and `parse`.
  61. For our next example, there's one more rule form you should know about:
  62. rule<Iterator, Signature> r;
  63. or
  64. rule<Iterator, Signature, Skipper> r;
  65. [tip All rule template arguments after Iterator can be supplied in any order.]
  66. The Signature specifies the attributes of the rule. You've seen that our parsers
  67. can have an attribute. Recall that the `double_` parser has an attribute of
  68. `double`. To be precise, these are /synthesized/ attributes. The parser
  69. "synthesizes" the attribute value. Think of them as function return values.
  70. There's another type of attribute called "inherited" attribute. We won't need
  71. them for now, but it's good that you be aware of such attributes. You can think
  72. of them as function arguments. And, rightly so, the rule signature is a function
  73. signature of the form:
  74. result(argN, argN,..., argN)
  75. After having declared a rule, you can now assign any parser expression to it.
  76. Example:
  77. r = double_ >> *(',' >> double_);
  78. [heading Grammars]
  79. A grammar encapsulates one or more rules. It has the same template parameters as
  80. the rule. You declare a grammar by:
  81. # deriving a struct (or class) from the `grammar` class template
  82. # declare one or more rules as member variables
  83. # initialize the base grammar class by giving it the start rule (its the first
  84. rule that gets called when the grammar starts parsing)
  85. # initialize your rules in your constructor
  86. The roman numeral grammar is a very nice and simple example of a grammar:
  87. [tutorial_roman_grammar]
  88. Things to take notice of:
  89. * The grammar and start rule signature is `unsigned()`. It has a synthesized
  90. attribute (return value) of type `unsigned` with no inherited attributes
  91. (arguments).
  92. * We did not specify a skip-parser. We don't want to skip in between the
  93. numerals.
  94. * `roman::base_type` is a typedef for `grammar<Iterator, unsigned()>`. If
  95. `roman` was not a template, you could simply write: base_type(start)
  96. * It's best to make your grammar templates such that they can be reused
  97. for different iterator types.
  98. * `_val` is another __phoenix__ placeholder representing the rule's synthesized
  99. attribute.
  100. * `eps` is a special spirit parser that consumes no input but is always
  101. successful. We use it to initialize `_val`, the rule's synthesized
  102. attribute, to zero before anything else. The actual parser starts at
  103. `+lit('M')`, parsing roman thousands. Using `eps` this way is good
  104. for doing pre and post initializations.
  105. * The expression `a || b` reads: match a or b and in sequence. That is, if both
  106. `a` and `b` match, it must be in sequence; this is equivalent to `a >> -b | b`,
  107. but more efficient.
  108. [heading Let's Parse!]
  109. [tutorial_roman_grammar_parse]
  110. `roman_parser` is an object of type `roman`, our roman numeral parser. This time
  111. around we are using the no-skipping version of the parse functions. We do not
  112. want to skip any spaces! We are also passing in an attribute, `unsigned result`,
  113. which will receive the parsed value.
  114. The full cpp file for this example can be found here: [@../../example/qi/roman.cpp]
  115. [endsect]