{"id":1010,"date":"2010-03-03T10:04:35","date_gmt":"2010-03-03T18:04:35","guid":{"rendered":"http:\/\/boost-spirit.com\/home\/?p=1010"},"modified":"2010-08-24T06:25:24","modified_gmt":"2010-08-24T13:25:24","slug":"the-anatomy-of-semantic-actions-in-qi","status":"publish","type":"post","link":"https:\/\/boost-spirit.com\/home\/2010\/03\/03\/the-anatomy-of-semantic-actions-in-qi\/","title":{"rendered":"The Anatomy of Semantic Actions in Qi"},"content":{"rendered":"<p>The concept of <em>Spirit&#8217;s<\/em> semantic actions seems to be easy enough to understand as most people new to the library prefer their usage over applying the built-in attribute propagation rules. That is not surprising. The idea of attaching a function to any point of a grammar which is called whenever the corresponding parser matched is straighforward to grasp. Earlier versions of <em>Spirit<\/em> required a semantic action to conform to a very specific interface. Today&#8217;s semantic actions are more flexible and more powerful. Recently, a couple of people asked questions about them. So I decided dedicating this Tip of the Day to the specifics and the usage model of semantic actions in <em>Spirit Qi<\/em>.<\/p>\n<p><!--more--><\/p>\n<p>All three of <em>Spirit&#8217;s<\/em> sub-libraries &#8211; <em>Qi<\/em>, <em>Karma<\/em>, and <em>Lex<\/em> \u2013 support semantic actions. In each case they are different and have some specifics. Today I will highlight semantic actions in <em>Qi<\/em>. But I will dedicate later Tips of the Day to semantic actions in <em>Karma<\/em> and\u00a0 <em>Lex<\/em>.<\/p>\n<p>Semantic actions are functions or function objects attached to some specific part of a grammar. In <em>Qi<\/em> they are invoked <em>after<\/em> the corresponding parser successfully recognizes a portion of the input. Here the semantic action receives the attribute value of the matching parser.<\/p>\n<h5>Semantic Actions \u2013 a General View<\/h5>\n<p>A semantic action <span style=\"font-family: Courier New;\">f<\/span> are attached to a <em>Qi<\/em> parser <span style=\"font-family: Courier New;\">p<\/span> by simply writing:<\/p>\n<pre class=\"brush: cpp; title: ; notranslate\" title=\"\">\r\np[f]\r\n<\/pre>\n<p>The function (or function object) <span style=\"font-family: Courier New;\">f<\/span> has to expose a certain interface allowing <em>Spirit<\/em> to pass the proper argument types. In the simplest case this can be a global function taking no arguments at all.<\/p>\n<pre class=\"brush: cpp; title: ; notranslate\" title=\"\">\r\nvoid func()\r\n{\r\n    std::cout &lt;&lt; &quot;Matched an integer!\\n&quot;;\r\n}\r\n\r\nstd::string input(&quot;1234&quot;);\r\nstd::string::const_iterator begin = input.begin();\r\nstd::string::const_iterator end = input.end();\r\nqi::parse(begin, end, qi::int_[func]);     \/\/ this will call func\r\n<\/pre>\n<p>Most of the time this is not sufficient as a semantic action is expected to receive the matched attribute value. This is possible by writing:<\/p>\n<pre class=\"brush: cpp; title: ; notranslate\" title=\"\">\r\nvoid func(int attribute)\r\n{\r\n    std::cout &lt;&lt; &quot;Matched integer: &quot; &lt;&lt; attribute &lt;&lt; &quot;\\n&quot;;\r\n}\r\n<\/pre>\n<p>The type of the expected parameter (in this case the <span style=\"font-family: Courier New;\">int<\/span>) depends on the parser the semantic action is attached to. The attribute type exposed by the parser has to be convertible to the argument type.<\/p>\n<p>There are actually 2 more arguments being passed: the parser context and a reference to a boolean &#8216;hit&#8217; parameter. The parser context is meaningful only if the semantic action is attached somewhere to the right hand side of a rule. We will see more information about this shortly. The boolean value can be set to false inside the semantic action invalidating the match in retrospective, making the parser fail. <em>Qi<\/em> allows us to bind a nullary or a single argument function, like above. The other arguments are simply ignored.<\/p>\n<p>It is feasible to bind any function object (such as generated by <a href=\"http:\/\/www.boost.org\/doc\/libs\/1_42_0\/libs\/bind\/index.html\">Boost.Bind<\/a> or <a href=\"http:\/\/www.boost.org\/doc\/libs\/1_42_0\/libs\/lambda\/index.html\">Boost.Lambda<\/a>) as an semantic action. Even if the documentation shows a couple of examples (see <a href=\"http:\/\/www.boost.org\/doc\/libs\/1_42_0\/libs\/spirit\/doc\/html\/spirit\/qi\/tutorials\/semantic_actions.html#spirit.qi.tutorials.semantic_actions.examples_of_semantic_actions\">here<\/a>), I would not recommend using those libraries in this context. For me the preferred method of writing semantic actions is to employ <a href=\"http:\/\/www.boost.org\/doc\/libs\/1_42_0\/libs\/spirit\/phoenix\/doc\/html\/index.html\">Boost.Phoenix<\/a> &#8211; a companion library bundled with <em>Spirit<\/em>. It is like <a href=\"http:\/\/www.boost.org\/libs\/lambda\/index.html\">Boost.Lambda<\/a> on steroids, with special custom features that make it easy to integrate semantic actions with Spirit. If your requirements go beyond simple parsing, I suggest that you use this library. All the following examples in this article will use <a href=\"http:\/\/www.boost.org\/phoenix\/doc\/html\/index.html\">Boost.Phoenix<\/a> for semantic actions. But whatever method you use, please let me highlight the following:<\/p>\n<blockquote><p>The three libraries allow you to utilize special placeholders to control parameter placement (<code>_1<\/code>, <code>_2<\/code>, etc.). Unfortunately, each of those libraries has it&#8217;s own implementation of the placeholders, all in different namespaces. You have to make sure not to mix placeholders with a library they don&#8217;t belong to and not to use different libraries while writing a semantic action.<\/p>\n<p>Generally, for <a href=\"http:\/\/www.boost.org\/libs\/bind\/index.html\">Boost.Bind<\/a>, use <code>::_1<\/code>, <code>::_2<\/code>, etc. (yes, these placeholders are defined in the global namespace).<\/p>\n<p>For <a href=\"http:\/\/www.boost.org\/libs\/lambda\/index.html\">Boost.Lambda<\/a> use the placeholders defined in the namespace <code>boost::lambda<\/code>.<\/p>\n<p>For semantic actions written using <a href=\"http:\/\/www.boost.org\/phoenix\/doc\/html\/index.html\">Boost.Phoenix<\/a> use the placeholders defined in the namespace <code>boost::spirit<\/code>. Please note that all existing placeholders for your convenience are also available from the namespace <code>boost::spirit::qi<\/code>.<\/p><\/blockquote>\n<p>The current version of Spirit (V2.2) does not yet support binding a native C++0x lambda function as a semantic action, but this is something we are currently working on. You can expect this to be possible in the near future.<\/p>\n<h5>Writing Phoenix based Semantic Actions<\/h5>\n<p>Writing a semantic action with Phoenix is beneficial as <em>Spirit<\/em>\u00a0 &#8216;knows&#8217; about Phoenix. If you write them with the help of Phoenix you can utilize special placeholders <em>Spirit<\/em> provides you with. Those placeholders refer to elements in the context of the current parser execution such as attributes, local variables and inherited attributes of rules, etc. None of the other means of writing semantic actions (using Bind, Lambda, or hand written function objects) gives you direct access to those elements. The following table lists all available placeholders exposed by Spirit (as mentioned earlier, all are defined in the namespace <span style=\"font-family: Courier New;\">boost::spirit::qi<\/span>). Again, please note, these are only available inside a semantic action and only if the semantic action is written utilizing Phoenix.<\/p>\n<table border=\"1\" cellspacing=\"0\" cellpadding=\"2\" width=\"600\">\n<tbody>\n<tr>\n<td width=\"206\" valign=\"top\"><strong>Placeholder<\/strong><\/td>\n<td width=\"394\" valign=\"top\"><strong>Description<\/strong><\/td>\n<\/tr>\n<tr>\n<td width=\"206\" valign=\"top\"><code>_1, _2, ... , _N<\/code><\/td>\n<td width=\"394\" valign=\"top\">Nth attribute of the parser <code>p<\/code><\/td>\n<\/tr>\n<tr>\n<td width=\"206\" valign=\"top\">\n<dt><code>_pass<\/code><\/dt>\n<\/td>\n<td width=\"394\" valign=\"top\">Assign <code>false<\/code> to <code>_pass<\/code> to force a generator failure.<\/td>\n<\/tr>\n<tr>\n<td width=\"206\" valign=\"top\">\n<dt><code>_val<\/code><\/dt>\n<\/td>\n<td width=\"394\" valign=\"top\">The enclosing rule&#8217;s synthesized attribute.<\/td>\n<\/tr>\n<tr>\n<td width=\"206\" valign=\"top\">\n<dt><code>_r1, _r2, ... , _rN<\/code><\/dt>\n<\/td>\n<td width=\"394\" valign=\"top\">The enclosing rule&#8217;s Nth inherited attribute.<\/td>\n<\/tr>\n<tr>\n<td width=\"206\" valign=\"top\">\n<dt><code>_a, _b, ... , _j<\/code><\/dt>\n<\/td>\n<td width=\"394\" valign=\"top\">The enclosing rule&#8217;s local variables (<code>_a<\/code> refers to the first).<\/td>\n<\/tr>\n<tr>\n<td width=\"206\" valign=\"top\">\u00a0<\/td>\n<td width=\"394\" valign=\"top\">\u00a0<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>Obviously, the placeholders listed in the last three rows of the table are meaningful only if used in a rule definition. As an example, let us rewrite the semantic action from above with Phoenix:<\/p>\n<pre class=\"brush: cpp; title: ; notranslate\" title=\"\">\r\nstd::string input(&quot;1234&quot;);\r\nstd::string::const_iterator begin = input.begin();\r\nstd::string::const_iterator end = input.end();\r\nqi::parse(begin, end,\r\n    qi::int_\r\n    [\r\n        std::cout &lt;&lt; &quot;Matched integer: &quot; &lt;&lt; qi::_1 &lt;&lt; &quot;\\n&quot;;\r\n    ]\r\n);\r\n<\/pre>\n<p>One problem with earlier versions of Spirit (i.e. <em>Spirit.Classic<\/em>) was that while parsing sequences of things it was difficult to avoid calling a semantic action prematurely. For instance, in a parser sequence of two integer parsers (<span style=\"font-family: Courier New;\">int_[f1] &gt;&gt; &#8216;,&#8217; &gt;&gt; int_[f2]<\/span>) the function <span style=\"font-family: Courier New;\">f1<\/span> got called immediately after the first integer matched, and even if the second integer parser would fail later on. In the current version of Spirit this is not an issue anymore as it is possible to attach a semantic action to the whole sequence while still referring to the single attributes of the different sequence elements:<\/p>\n<pre class=\"brush: cpp; title: ; notranslate\" title=\"\">\r\nstd::string input(&quot;1234,2345&quot;);\r\nstd::string::const_iterator begin = input.begin();\r\nstd::string::const_iterator end = input.end();\r\nqi::parse(begin, end,\r\n    (qi::int_ &gt;&gt; ',' &gt;&gt; qi::int_)\r\n    [\r\n        std::cout &lt;&lt; &quot;Matched integers: &quot;\r\n              &lt;&lt; qi::_1 &lt;&lt; &quot; and &quot; &lt;&lt; qi::_2 &lt;&lt; &quot;\\n&quot;;\r\n    ]\r\n);\r\n<\/pre>\n<p>Here, <span style=\"font-family: Courier New;\">qi::_1<\/span> refers to the attribute matched by the first integer parser, and <span style=\"font-family: Courier New;\">qi::_2<\/span> to the second one.<\/p>\n<p>Initially I was planning to additionally describe the internal interface of a semantic action. Utilizing this interface allows you to write your own function objects and still to get access to the elements of the parser context mentioned above (attributes, the rule&#8217;s local variables and inherited attributes, etc.). But this post already got longer as anticipated, which is why I defer this discussion to a second Tip of the Day. Stay tuned!<\/p>\n<div class=\"sharedaddy sd-sharing-enabled\"><div class=\"robots-nocontent sd-block sd-social sd-social-icon-text sd-sharing\"><h3 class=\"sd-title\">Share this:<\/h3><div class=\"sd-content\"><ul><li><a href=\"#\" class=\"sharing-anchor sd-button share-more\"><span>Share<\/span><\/a><\/li><li class=\"share-end\"><\/li><\/ul><div class=\"sharing-hidden\"><div class=\"inner\" style=\"display: none;\"><ul><li class=\"share-facebook\"><a rel=\"nofollow noopener noreferrer\" data-shared=\"sharing-facebook-1010\" class=\"share-facebook sd-button share-icon\" href=\"https:\/\/boost-spirit.com\/home\/2010\/03\/03\/the-anatomy-of-semantic-actions-in-qi\/?share=facebook\" target=\"_blank\" title=\"Click to share on Facebook\" ><span>Facebook<\/span><\/a><\/li><li class=\"share-twitter\"><a rel=\"nofollow noopener noreferrer\" data-shared=\"sharing-twitter-1010\" class=\"share-twitter sd-button share-icon\" href=\"https:\/\/boost-spirit.com\/home\/2010\/03\/03\/the-anatomy-of-semantic-actions-in-qi\/?share=twitter\" target=\"_blank\" title=\"Click to share on Twitter\" ><span>Twitter<\/span><\/a><\/li><li class=\"share-end\"><\/li><li class=\"share-pinterest\"><a rel=\"nofollow noopener noreferrer\" data-shared=\"sharing-pinterest-1010\" class=\"share-pinterest sd-button share-icon\" href=\"https:\/\/boost-spirit.com\/home\/2010\/03\/03\/the-anatomy-of-semantic-actions-in-qi\/?share=pinterest\" target=\"_blank\" title=\"Click to share on Pinterest\" ><span>Pinterest<\/span><\/a><\/li><li class=\"share-linkedin\"><a rel=\"nofollow noopener noreferrer\" data-shared=\"sharing-linkedin-1010\" class=\"share-linkedin sd-button share-icon\" href=\"https:\/\/boost-spirit.com\/home\/2010\/03\/03\/the-anatomy-of-semantic-actions-in-qi\/?share=linkedin\" target=\"_blank\" title=\"Click to share on LinkedIn\" ><span>LinkedIn<\/span><\/a><\/li><li class=\"share-end\"><\/li><li class=\"share-reddit\"><a rel=\"nofollow noopener noreferrer\" data-shared=\"\" class=\"share-reddit sd-button share-icon\" href=\"https:\/\/boost-spirit.com\/home\/2010\/03\/03\/the-anatomy-of-semantic-actions-in-qi\/?share=reddit\" target=\"_blank\" title=\"Click to share on Reddit\" ><span>Reddit<\/span><\/a><\/li><li class=\"share-tumblr\"><a rel=\"nofollow noopener noreferrer\" data-shared=\"\" class=\"share-tumblr sd-button share-icon\" href=\"https:\/\/boost-spirit.com\/home\/2010\/03\/03\/the-anatomy-of-semantic-actions-in-qi\/?share=tumblr\" target=\"_blank\" title=\"Click to share on Tumblr\" ><span>Tumblr<\/span><\/a><\/li><li class=\"share-end\"><\/li><li class=\"share-end\"><\/li><\/ul><\/div><\/div><\/div><\/div><\/div>","protected":false},"excerpt":{"rendered":"<p>The concept of Spirit&#8217;s semantic actions seems to be easy enough to understand as most people new to the library prefer their usage over applying the built-in attribute propagation rules. That is not surprising. The idea of attaching a function to any point of a grammar which is called whenever the corresponding parser matched is [&hellip;]<\/p>\n<div class=\"sharedaddy sd-sharing-enabled\"><div class=\"robots-nocontent sd-block sd-social sd-social-icon-text sd-sharing\"><h3 class=\"sd-title\">Share this:<\/h3><div class=\"sd-content\"><ul><li><a href=\"#\" class=\"sharing-anchor sd-button share-more\"><span>Share<\/span><\/a><\/li><li class=\"share-end\"><\/li><\/ul><div class=\"sharing-hidden\"><div class=\"inner\" style=\"display: none;\"><ul><li class=\"share-facebook\"><a rel=\"nofollow noopener noreferrer\" data-shared=\"sharing-facebook-1010\" class=\"share-facebook sd-button share-icon\" href=\"https:\/\/boost-spirit.com\/home\/2010\/03\/03\/the-anatomy-of-semantic-actions-in-qi\/?share=facebook\" target=\"_blank\" title=\"Click to share on Facebook\" ><span>Facebook<\/span><\/a><\/li><li class=\"share-twitter\"><a rel=\"nofollow noopener noreferrer\" data-shared=\"sharing-twitter-1010\" class=\"share-twitter sd-button share-icon\" href=\"https:\/\/boost-spirit.com\/home\/2010\/03\/03\/the-anatomy-of-semantic-actions-in-qi\/?share=twitter\" target=\"_blank\" title=\"Click to share on Twitter\" ><span>Twitter<\/span><\/a><\/li><li class=\"share-end\"><\/li><li class=\"share-pinterest\"><a rel=\"nofollow noopener noreferrer\" data-shared=\"sharing-pinterest-1010\" class=\"share-pinterest sd-button share-icon\" href=\"https:\/\/boost-spirit.com\/home\/2010\/03\/03\/the-anatomy-of-semantic-actions-in-qi\/?share=pinterest\" target=\"_blank\" title=\"Click to share on Pinterest\" ><span>Pinterest<\/span><\/a><\/li><li class=\"share-linkedin\"><a rel=\"nofollow noopener noreferrer\" data-shared=\"sharing-linkedin-1010\" class=\"share-linkedin sd-button share-icon\" href=\"https:\/\/boost-spirit.com\/home\/2010\/03\/03\/the-anatomy-of-semantic-actions-in-qi\/?share=linkedin\" target=\"_blank\" title=\"Click to share on LinkedIn\" ><span>LinkedIn<\/span><\/a><\/li><li class=\"share-end\"><\/li><li class=\"share-reddit\"><a rel=\"nofollow noopener noreferrer\" data-shared=\"\" class=\"share-reddit sd-button share-icon\" href=\"https:\/\/boost-spirit.com\/home\/2010\/03\/03\/the-anatomy-of-semantic-actions-in-qi\/?share=reddit\" target=\"_blank\" title=\"Click to share on Reddit\" ><span>Reddit<\/span><\/a><\/li><li class=\"share-tumblr\"><a rel=\"nofollow noopener noreferrer\" data-shared=\"\" class=\"share-tumblr sd-button share-icon\" href=\"https:\/\/boost-spirit.com\/home\/2010\/03\/03\/the-anatomy-of-semantic-actions-in-qi\/?share=tumblr\" target=\"_blank\" title=\"Click to share on Tumblr\" ><span>Tumblr<\/span><\/a><\/li><li class=\"share-end\"><\/li><li class=\"share-end\"><\/li><\/ul><\/div><\/div><\/div><\/div><\/div>","protected":false},"author":3,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_s2mail":"","spay_email":"","jetpack_publicize_message":"","jetpack_is_tweetstorm":false,"jetpack_publicize_feature_enabled":true},"categories":[19,10,18],"tags":[7,8],"jetpack_publicize_connections":[],"jetpack_featured_media_url":"","jetpack_shortlink":"https:\/\/wp.me\/pIHdZ-gi","jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/boost-spirit.com\/home\/wp-json\/wp\/v2\/posts\/1010"}],"collection":[{"href":"https:\/\/boost-spirit.com\/home\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/boost-spirit.com\/home\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/boost-spirit.com\/home\/wp-json\/wp\/v2\/users\/3"}],"replies":[{"embeddable":true,"href":"https:\/\/boost-spirit.com\/home\/wp-json\/wp\/v2\/comments?post=1010"}],"version-history":[{"count":7,"href":"https:\/\/boost-spirit.com\/home\/wp-json\/wp\/v2\/posts\/1010\/revisions"}],"predecessor-version":[{"id":1148,"href":"https:\/\/boost-spirit.com\/home\/wp-json\/wp\/v2\/posts\/1010\/revisions\/1148"}],"wp:attachment":[{"href":"https:\/\/boost-spirit.com\/home\/wp-json\/wp\/v2\/media?parent=1010"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/boost-spirit.com\/home\/wp-json\/wp\/v2\/categories?post=1010"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/boost-spirit.com\/home\/wp-json\/wp\/v2\/tags?post=1010"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}