Boost logo

Boost-Commit :

From: eric_at_[hidden]
Date: 2007-10-10 22:12:07


Author: eric_niebler
Date: 2007-10-10 22:12:07 EDT (Wed, 10 Oct 2007)
New Revision: 39915
URL: http://svn.boost.org/trac/boost/changeset/39915

Log:
document placeholder<> and match_results<>::let()
Text files modified:
   trunk/libs/xpressive/doc/actions.qbk | 208 +++++++++++++++++++++++++--------------
   1 files changed, 134 insertions(+), 74 deletions(-)

Modified: trunk/libs/xpressive/doc/actions.qbk
==============================================================================
--- trunk/libs/xpressive/doc/actions.qbk (original)
+++ trunk/libs/xpressive/doc/actions.qbk 2007-10-10 22:12:07 EDT (Wed, 10 Oct 2007)
@@ -128,6 +128,82 @@
 character. When the `'?'` character is encountered, the match algorithm
 backtracks, removing the final action from the queue.
 
+[h3 Lazy Functions]
+
+So far, we've seen how to write semantic actions consisting of variables and
+operators. But what if you want to be able to call a function from a semantic
+action? Xpressive provides a mechanism to do this.
+
+The first step is to define a function object type. Here, for instance, is a
+function object type that calls `push()` on its argument:
+
+ struct push_impl
+ {
+ // Result type, needed for tr1::result_of
+ typedef void result_type;
+
+ template<typename Sequence, typename Value>
+ void operator()(Sequence &seq, Value const &val) const
+ {
+ seq.push(val);
+ }
+ };
+
+The next step is to use xpressive's `function<>` template to define a function
+object named `push`:
+
+ // Global "push" function object.
+ function<push_impl>::type const push = {{}};
+
+The initialization looks a bit odd, but this is because `push` is being
+statically initialized. That means it doesn't need to be constructed
+at runtime. We can use `push` in semantic actions as follows:
+
+ std::stack<int> ints;
+ // Match digits, cast them to an int
+ // and push it on the stack.
+ sregex rex = (+_d)[push(ref(ints), as<int>(_))];
+
+You'll notice that doing it this way causes member function invocations
+to look like ordinary function invocations. You can choose to write your
+semantic action in a different way that makes it look a bit more like
+a member function call:
+
+ sregex rex = (+_d)[ref(ints)->*push(as<int>(_))];
+
+Xpressive recognizes the use of the `->*` and treats this expression
+exactly the same as the one above.
+
+When your function object must return a type that depends on its
+arguments, you can use a `result<>` member template instead of the
+`result_type` typedef. Here, for example, is a `first` function object
+that returns the `first` member of a `std::pair<>` or _sub_match_:
+
+ // Function object that returns the
+ // first element of a pair.
+ struct first_impl
+ {
+ template<typename Sig> struct result {};
+
+ template<typename This, typename Pair>
+ struct result<This(Pair)>
+ {
+ typedef typename remove_reference<Pair>
+ ::type::first_type type;
+ };
+
+ template<typename Pair>
+ typename Pair::first_type
+ operator()(Pair const &p) const
+ {
+ return p.first;
+ }
+ };
+
+ // OK, use as first(s1) to get the begin iterator
+ // of the sub-match referred to by s1.
+ function<first_impl> const first = {{}};
+
 [h3 Referring to Local Variables]
 
 As we've seen in the examples above, we can refer to local variables within
@@ -206,88 +282,72 @@
     assert( i.get() == 2 );
 
 Notice that we use `local<>::get()` to access the value of the local
-variable. Also, beware that `local<>` can be uses to create a dangling
+variable. Also, beware that `local<>` can be used to create a dangling
 reference, just as `reference<>` can.
 
-[h3 Lazy Functions]
-
-So far, we've seen how to write semantic actions consisting of variables and
-operators. But what if you want to be able to call a function from a semantic
-action? Xpressive provides a mechanism to do this.
-
-The first step is to define a function object type. Here, for instance, is a
-function object type that calls `push()` on its argument:
-
- struct push_impl
- {
- // Result type, needed for tr1::result_of
- typedef void result_type;
-
- template<typename Sequence, typename Value>
- void operator()(Sequence &seq, Value const &val) const
- {
- seq.push(val);
- }
- };
-
-The next step is to use xpressive's `function<>` template to define a function
-object named `push`:
-
- // Global "push" function object.
- function<push_impl>::type const push = {{}};
+[h3 Referring to Non-Local Variables]
 
-The initialization looks a bit odd, but this is because `push` is being
-statically initialized. That means it doesn't need to be constructed
-at runtime. We can use `push` in semantic actions as follows:
-
- std::stack<int> ints;
- // Match digits, cast them to an int
- // and push it on the stack.
- sregex rex = (+_d)[push(ref(ints), as<int>(_))];
-
-You'll notice that doing it this way causes member function invocations
-to look like ordinary function invocations. You can choose to write your
-semantic action in a different way that makes it look a bit more like
-a member function call:
-
- sregex rex = (+_d)[ref(ints)->*push(as<int>(_))];
-
-Xpressive recognizes the use of the `->*` and treats this expression
-exactly the same as the one above.
-
-When your function object must return a type that depends on its
-arguments, you can use a `result<>` member template instead of the
-`result_type` typedef. Here, for example, is a `first` function object
-that returns the `first` member of a `std::pair<>` or _sub_match_:
+In the beginning of this
+section, we used a regex with a semantic action to parse a string of
+word/integer pairs and stuff them into a `std::map<>`. That required that
+the map and the regex be defined together and used before either could
+go out of scope. What if we wanted to define the regex once and use it
+to fill lots of different maps? We would rather pass the map into the
+_regex_match_ algorithm rather than embed a reference to it directly in
+the regex object. What we can do instead is define a placeholder and use
+that in the semantic action instead of the map itself. Later, when we
+call one of the regex algorithms, we can bind the reference to an actual
+map object. The following code shows how.
+
+ // Define a placeholder for a map object:
+ placeholder<std::map<std::string, int> > _map;
+
+ // Match a word and an integer, separated by =>,
+ // and then stuff the result into a std::map<>
+ sregex pair = ( (s1= +_w) >> "=>" >> (s2= +_d) )
+ [ _map[s1] = as<int>(s2) ];
+
+ // Match one or more word/integer pairs, separated
+ // by whitespace.
+ sregex rx = pair >> *(+_s >> pair);
+
+ // The string to parse
+ std::string str("aaa=>1 bbb=>23 ccc=>456");
+
+ // Here is the actual map to fill in:
+ std::map<std::string, int> result;
+
+ // Bind the _map placeholder to the actual map
+ smatch what;
+ what.let( _map = result );
 
- // Function object that returns the
- // first element of a pair.
- struct first_impl
+ // Execute the match and fill in result map
+ if(regex_match(str, what, rx))
     {
- template<typename Sig> struct result {};
-
- template<typename This, typename Pair>
- struct result<This(Pair)>
- {
- typedef typename remove_reference<Pair>
- ::type::first_type type;
- };
-
- template<typename Pair>
- typename Pair::first_type
- operator()(Pair const &p) const
- {
- return p.first;
- }
- };
+ std::cout << result["aaa"] << '\n';
+ std::cout << result["bbb"] << '\n';
+ std::cout << result["ccc"] << '\n';
+ }
 
- // OK, use as first(s1) to get the begin iterator
- // of the sub-match referred to by s1.
- function<first_impl> const first = {{}};
+This program displays:
 
-[h3 Late-Bound Variables]
+[pre
+1
+23
+456
+]
 
-TODO describe placeholder<> and match_results<>::let().
+We use `placeholder<>` here to define `_map`, which stands in for a
+`std::map<>` variable. We can use the placeholder in the semantic action as if
+it were a map. Then, we define a _match_results_ struct and bind an actual map
+to the placeholder with "`what.let( _map = result );`". The _regex_match_ call
+behaves as if the placeholder in the semantic action had been replaced with a
+reference to `result`.
+
+[note Placeholders in semantic actions are not /actually/ replaced at runtime
+with references to variables. The regex object is never mutated in any way
+during any of the regex algorithms, so they are safe to use in multiple
+threads.]
 
 [h2 User-Defined Assertions]
 


Boost-Commit list run by bdawes at acm.org, david.abrahams at rcn.com, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk