symbols.qbk 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110
  1. [/
  2. / Copyright (c) 2007 David Jenkins
  3. /
  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 Symbol Tables and Attributes]
  8. [h2 Overview]
  9. Symbol tables can be built into xpressive regular expressions with just a
  10. `std::map<>`. The map keys are the strings to be matched and the map values are
  11. the data to be returned to your semantic action. Xpressive attributes, named
  12. `a1`, `a2`, through `a9`, hold the value corresponding to a matching key so
  13. that it can be used in a semantic action. A default value can be specified
  14. for an attribute if a symbol is not found.
  15. [h2 Symbol Tables]
  16. An xpressive symbol table is just a `std::map<>`, where the key is a string type
  17. and the value can be anything. For example, the following regular expression
  18. matches a key from map1 and assigns the corresponding value to the attribute
  19. `a1`. Then, in the semantic action, it assigns the value stored in attribute
  20. `a1` to an integer result.
  21. int result;
  22. std::map<std::string, int> map1;
  23. // ... (fill the map)
  24. sregex rx = ( a1 = map1 ) [ ref(result) = a1 ];
  25. Consider the following example code,
  26. which translates number names into integers. It is
  27. described below.
  28. #include <string>
  29. #include <iostream>
  30. #include <boost/xpressive/xpressive.hpp>
  31. #include <boost/xpressive/regex_actions.hpp>
  32. using namespace boost::xpressive;
  33. int main()
  34. {
  35. std::map<std::string, int> number_map;
  36. number_map["one"] = 1;
  37. number_map["two"] = 2;
  38. number_map["three"] = 3;
  39. // Match a string from number_map
  40. // and store the integer value in 'result'
  41. // if not found, store -1 in 'result'
  42. int result = 0;
  43. cregex rx = ((a1 = number_map ) | *_)
  44. [ ref(result) = (a1 | -1)];
  45. regex_match("three", rx);
  46. std::cout << result << '\n';
  47. regex_match("two", rx);
  48. std::cout << result << '\n';
  49. regex_match("stuff", rx);
  50. std::cout << result << '\n';
  51. return 0;
  52. }
  53. This program prints the following:
  54. [pre
  55. 3
  56. 2
  57. -1
  58. ]
  59. First the program builds a number map, with number names as string keys and the
  60. corresponding integers as values. Then it constructs a static regular
  61. expression using an attribute `a1` to represent the result of the symbol table
  62. lookup. In the semantic action, the attribute is assigned to an integer
  63. variable `result`. If the symbol was not found, a default value of `-1` is
  64. assigned to `result`. A wildcard, `*_`, makes sure the regex matches even if
  65. the symbol is not found.
  66. A more complete version of this example can be found in
  67. [^libs/xpressive/example/numbers.cpp][footnote Many thanks to David Jenkins,
  68. who contributed this example.]. It translates number names up to "nine hundred
  69. ninety nine million nine hundred ninety nine thousand nine hundred ninety nine"
  70. along with some special number names like "dozen".
  71. Symbol table matches are case sensitive by default, but they can be made
  72. case-insensitive by enclosing the expression in `icase()`.
  73. [h2 Attributes]
  74. [def __default_value__ '''<replaceable>default-value</replaceable>''']
  75. Up to nine attributes can be used in a regular expression. They are named
  76. `a1`, `a2`, ..., `a9` in the `boost::xpressive` namespace. The attribute type
  77. is the same as the second component of the map that is assigned to it. A
  78. default value for an attribute can be specified in a semantic action with the
  79. syntax `(a1 | __default_value__)`.
  80. Attributes are properly scoped, so you can do crazy things like:
  81. `( (a1=sym1) >> (a1=sym2)[ref(x)=a1] )[ref(y)=a1]`. The inner semantic action
  82. sees the inner `a1`, and the outer semantic action sees the outer one. They can
  83. even have different types.
  84. [note Xpressive builds a hidden ternary search trie from the map so it can
  85. search quickly. If BOOST_DISABLE_THREADS is defined,
  86. the hidden ternary search trie "self adjusts", so after each
  87. search it restructures itself to improve the efficiency of future searches
  88. based on the frequency of previous searches.]
  89. [endsect]