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