Boost C++ Libraries: Ticket #5566: Spirit.Lex converting a token to its value in a lexer semantic action fails https://svn.boost.org/trac10/ticket/5566 <p> Discussed this on #boost with heller and he said to post a bug report about the issue. Here's a test case that should apparently work fine: </p> <pre class="wiki">#include &lt;string&gt; #include &lt;vector&gt; #include &lt;boost/spirit/include/lex_lexertl.hpp&gt; #include &lt;boost/spirit/include/phoenix_core.hpp&gt; #include &lt;boost/spirit/include/phoenix_stl.hpp&gt; namespace lex = boost::spirit::lex; template &lt;typename Lexer&gt; struct text_decorator_lexer : lex::lexer&lt;Lexer&gt; { text_decorator_lexer() : tag_open("\\{\\{.+?\\}\\}") , tag_close("\\{\\{\\/.+?\\}\\}") , var("\\$\\$.+?\\$\\$") , any(".") { using boost::spirit::lex::_val; using boost::phoenix::push_back; using boost::phoenix::ref; this-&gt;self = tag_open [push_back(ref(tokens), _val)] | tag_close [push_back(ref(tokens), _val)] | var [push_back(ref(tokens), _val)] | any [push_back(ref(tokens), _val)] ; } std::vector&lt;std::string&gt; tokens; lex::token_def&lt;std::string&gt; tag_open, tag_close, var, any; }; int main() { typedef lex::lexertl::token&lt;const char*, boost::mpl::vector&lt;std::string&gt;, boost::mpl::false_&gt; token_type; typedef lex::lexertl::actor_lexer&lt;token_type&gt; lexer_type; text_decorator_lexer&lt;lexer_type&gt; text_decorator_tokenizer; std::string input = "Hello {{b}}there{{/b}}, the time is $$time$$."; char const* first = input.c_str(); char const* last = &amp;first[input.size()]; lex::tokenize(first, last, text_decorator_tokenizer); } </pre><p> And the relevant part of the error is: </p> <pre class="wiki">/opt/local/include/boost/spirit/home/phoenix/stl/container/container.hpp:492:40: error: no matching function for call to 'std::vector&lt;std::basic_string&lt;char&gt; &gt;::push_back(const boost::variant&lt;boost::detail::variant::over_sequence&lt;boost::mpl::v_item&lt;boost::iterator_range&lt;const char*&gt;, boost::mpl::v_item&lt;std::basic_string&lt;char&gt;, boost::mpl::vector0&lt;mpl_::na&gt;, 1&gt;, 1&gt; &gt;, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_&gt;&amp;)' /opt/local/include/boost/spirit/home/phoenix/stl/container/container.hpp:492:40: note: candidate is: /opt/local/include/gcc46/c++/bits/stl_vector.h:826:7: note: void std::vector&lt;_Tp, _Alloc&gt;::push_back(const value_type&amp;) [with _Tp = std::basic_string&lt;char&gt;, _Alloc = std::allocator&lt;std::basic_string&lt;char&gt; &gt;, std::vector&lt;_Tp, _Alloc&gt;::value_type = std::basic_string&lt;char&gt;] /opt/local/include/gcc46/c++/bits/stl_vector.h:826:7: note: no known conversion for argument 1 from 'const boost::variant&lt;boost::detail::variant::over_sequence&lt;boost::mpl::v_item&lt;boost::iterator_range&lt;const char*&gt;, boost::mpl::v_item&lt;std::basic_string&lt;char&gt;, boost::mpl::vector0&lt;mpl_::na&gt;, 1&gt;, 1&gt; &gt;, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_, boost::detail::variant::void_&gt;' to 'const value_type&amp;' /opt/local/include/boost/spirit/home/phoenix/stl/container/container.hpp:492:40: error: return-statement with a value, in function returning 'void' [-fpermissive] </pre><p> Tested with: </p> <p> gcc version 4.6.1 20110325 (prerelease) (GCC) gcc version 4.2.1 (Apple Inc. build 5666) (dot 3) </p> en-us Boost C++ Libraries /htdocs/site/boost.png https://svn.boost.org/trac10/ticket/5566 Trac 1.4.3 Hartmut Kaiser Fri, 27 May 2011 00:33:03 GMT owner changed https://svn.boost.org/trac10/ticket/5566#comment:1 https://svn.boost.org/trac10/ticket/5566#comment:1 <ul> <li><strong>owner</strong> changed from <span class="trac-author">Joel de Guzman</span> to <span class="trac-author">Hartmut Kaiser</span> </li> </ul> Ticket Hartmut Kaiser Fri, 27 May 2011 01:21:23 GMT <link>https://svn.boost.org/trac10/ticket/5566#comment:2 </link> <guid isPermaLink="false">https://svn.boost.org/trac10/ticket/5566#comment:2</guid> <description> <p> Replying to <a class="closed ticket" href="https://svn.boost.org/trac10/ticket/5566" title="#5566: Bugs: Spirit.Lex converting a token to its value in a lexer semantic action fails (closed: fixed)">Reko Tiira &lt;reko@…&gt;</a>: </p> <p> It does not exactly work as you expect as the type of teh token value is a variant (initially holding a pair of iterators pointing to the matched input sequence). You need to explicitly convert this iterator range into the attribute type. Normally this is done while parsing on first access to the attribute. Here is your modified code doing this: </p> <pre class="wiki">#include &lt;string&gt; #include &lt;vector&gt; #include &lt;boost/spirit/include/lex_lexertl.hpp&gt; #include &lt;boost/spirit/include/phoenix_core.hpp&gt; #include &lt;boost/spirit/include/phoenix_stl.hpp&gt; namespace lex = boost::spirit::lex; namespace phoenix = boost::phoenix; struct get_string_impl { template &lt;typename Value&gt; struct result { typedef std::string type; }; template &lt;typename Value&gt; std::string operator()(Value const&amp; val) const { // transform the token value (here a variant) into a string // at this point the variant holds a pair of iterators typedef boost::iterator_range&lt;char const*&gt; iterpair_type; iterpair_type const&amp; ip = boost::get&lt;iterpair_type&gt;(val); return std::string(ip.begin(), ip.end()); } }; boost::phoenix::function&lt;get_string_impl&gt; get_string; template &lt;typename Lexer&gt; struct text_decorator_lexer : lex::lexer&lt;Lexer&gt; { text_decorator_lexer() : tag_open("\\{\\{.+?\\}\\}") , tag_close("\\{\\{\\/.+?\\}\\}") , var("\\$\\$.+?\\$\\$") , any(".") { using boost::spirit::lex::_val; using boost::phoenix::push_back; using boost::phoenix::ref; this-&gt;self = tag_open [push_back(ref(tokens), get_string(_val))] | tag_close [push_back(ref(tokens), get_string(_val))] | var [push_back(ref(tokens), get_string(_val))] | any [push_back(ref(tokens), get_string(_val))] ; } std::vector&lt;std::string&gt; tokens; lex::token_def&lt;std::string&gt; tag_open, tag_close, var, any; }; int main() { typedef lex::lexertl::token&lt; const char*, boost::mpl::vector&lt;std::string&gt;, boost::mpl::false_ &gt; token_type; typedef lex::lexertl::actor_lexer&lt;token_type&gt; lexer_type; text_decorator_lexer&lt;lexer_type&gt; text_decorator_tokenizer; std::string input = "Hello {{b}}there{{/b}}, the time is $$time$$."; char const* first = input.c_str(); char const* last = &amp;first[input.size()]; lex::tokenize(first, last, text_decorator_tokenizer); } </pre><p> But to be honest, I needed to fix a (unrelated) problem to make this code work, therefore you'll need to update from SVN or wait for Boost V1.47. </p> </description> <category>Ticket</category> </item> <item> <dc:creator>Hartmut Kaiser</dc:creator> <pubDate>Fri, 27 May 2011 02:02:24 GMT</pubDate> <title>status changed; resolution set https://svn.boost.org/trac10/ticket/5566#comment:3 https://svn.boost.org/trac10/ticket/5566#comment:3 <ul> <li><strong>status</strong> <span class="trac-field-old">new</span> → <span class="trac-field-new">closed</span> </li> <li><strong>resolution</strong> → <span class="trac-field-new">fixed</span> </li> </ul> <p> (In <a class="changeset" href="https://svn.boost.org/trac10/changeset/72201" title="Spirit: fixed #5566: Spirit.Lex converting a token to its value in a ...">[72201]</a>) Spirit: fixed <a class="closed ticket" href="https://svn.boost.org/trac10/ticket/5566" title="#5566: Bugs: Spirit.Lex converting a token to its value in a lexer semantic action fails (closed: fixed)">#5566</a>: Spirit.Lex converting a token to its value in a lexer semantic action fails </p> Ticket Gilles <gillesb68@…> Thu, 11 Apr 2013 17:23:04 GMT <link>https://svn.boost.org/trac10/ticket/5566#comment:4 </link> <guid isPermaLink="false">https://svn.boost.org/trac10/ticket/5566#comment:4</guid> <description> <p> What I see from the token's variant is that the value replaces the pair of iterators pointing to the matched input sequence. Is there a way to store the converted value and, in the same time, keeping the pair of iterators pointing to the matched input sequence ? </p> </description> <category>Ticket</category> </item> <item> <dc:creator>Hartmut Kaiser</dc:creator> <pubDate>Thu, 11 Apr 2013 17:37:51 GMT</pubDate> <title/> <link>https://svn.boost.org/trac10/ticket/5566#comment:5 </link> <guid isPermaLink="false">https://svn.boost.org/trac10/ticket/5566#comment:5</guid> <description> <p> Replying to <a class="ticket" href="https://svn.boost.org/trac10/ticket/5566#comment:4" title="Comment 4">Gilles &lt;gillesb68@…&gt;</a>: </p> <blockquote class="citation"> <p> What I see from the token's variant is that the value replaces the pair of iterators pointing to the matched input sequence. Is there a way to store the converted value and, in the same time, keeping the pair of iterators pointing to the matched input sequence ? </p> </blockquote> <p> Yes, simply use position_token instead of the plain token class. </p> </description> <category>Ticket</category> </item> <item> <author>Gilles <gillesb68@…></author> <pubDate>Thu, 11 Apr 2013 18:37:01 GMT</pubDate> <title/> <link>https://svn.boost.org/trac10/ticket/5566#comment:6 </link> <guid isPermaLink="false">https://svn.boost.org/trac10/ticket/5566#comment:6</guid> <description> <p> Replying to <a class="ticket" href="https://svn.boost.org/trac10/ticket/5566#comment:5" title="Comment 5">hkaiser</a>: </p> <blockquote class="citation"> <p> Replying to <a class="ticket" href="https://svn.boost.org/trac10/ticket/5566#comment:4" title="Comment 4">Gilles &lt;gillesb68@…&gt;</a>: </p> <blockquote class="citation"> <p> What I see from the token's variant is that the value replaces the pair of iterators pointing to the matched input sequence. Is there a way to store the converted value and, in the same time, keeping the pair of iterators pointing to the matched input sequence ? </p> </blockquote> <p> Yes, simply use position_token instead of the plain token class. </p> </blockquote> <p> I understand this for a token enclosing the pair pointing the matched input sequence alone, but how do I declare a token enclosing together : </p> <p> 1/ the pair of iterators pointing to the matched input sequence; and </p> <p> 2/ the converted value of the same input sequence ? </p> </description> <category>Ticket</category> </item> <item> <dc:creator>Hartmut Kaiser</dc:creator> <pubDate>Thu, 11 Apr 2013 23:09:40 GMT</pubDate> <title/> <link>https://svn.boost.org/trac10/ticket/5566#comment:7 </link> <guid isPermaLink="false">https://svn.boost.org/trac10/ticket/5566#comment:7</guid> <description> <p> Replying to <a class="ticket" href="https://svn.boost.org/trac10/ticket/5566#comment:6" title="Comment 6">Gilles &lt;gillesb68@…&gt;</a>: </p> <blockquote class="citation"> <p> Replying to <a class="ticket" href="https://svn.boost.org/trac10/ticket/5566#comment:5" title="Comment 5">hkaiser</a>: </p> <blockquote class="citation"> <p> Replying to <a class="ticket" href="https://svn.boost.org/trac10/ticket/5566#comment:4" title="Comment 4">Gilles &lt;gillesb68@…&gt;</a>: </p> <blockquote class="citation"> <p> What I see from the token's variant is that the value replaces the pair of iterators pointing to the matched input sequence. Is there a way to store the converted value and, in the same time, keeping the pair of iterators pointing to the matched input sequence ? </p> </blockquote> <p> Yes, simply use position_token instead of the plain token class. </p> </blockquote> <p> I understand this for a token enclosing the pair pointing the matched input sequence alone, but how do I declare a token enclosing together : </p> <p> 1/ the pair of iterators pointing to the matched input sequence; and </p> <p> 2/ the converted value of the same input sequence ? </p> </blockquote> <p> Yes, that's what you can do with the <code>position_token</code> type. It is semantically equivalent to the <code>token</code> type, except for the additionally stored iterator pair of the matched input sequence. Please see libs/example/qi/compiler_tutorial/conjure3 for an example. </p> </description> <category>Ticket</category> </item> <item> <dc:creator>anonymous</dc:creator> <pubDate>Fri, 12 Apr 2013 14:06:59 GMT</pubDate> <title/> <link>https://svn.boost.org/trac10/ticket/5566#comment:8 </link> <guid isPermaLink="false">https://svn.boost.org/trac10/ticket/5566#comment:8</guid> <description> <p> Ah, the position_token class, of course, I should have thought. Thanks a lot, and I apologize for making you wasting time about something so obvious. </p> </description> <category>Ticket</category> </item> </channel> </rss>