{"id":857,"date":"2010-01-15T07:41:35","date_gmt":"2010-01-15T15:41:35","guid":{"rendered":"http:\/\/boost-spirit.com\/home\/?p=857"},"modified":"2010-06-24T06:19:26","modified_gmt":"2010-06-24T13:19:26","slug":"how-do-rules-propagate-attributes","status":"publish","type":"post","link":"http:\/\/boost-spirit.com\/home\/2010\/01\/15\/how-do-rules-propagate-attributes\/","title":{"rendered":"How Do Rules Propagate Their Attributes?"},"content":{"rendered":"<p>If you read the article about attribute handling for non-terminals (<a href=\"http:\/\/boost-spirit.com\/home\/articles\/basics\/the-magical-power-of-attributes-in-spirit-directives-and-non-terminals\/\">The Magical Power of Attributes in Spirit &#8211; Directives and Non-terminals<\/a>) you might remember that <em>Spirit&#8217;s<\/em> non-terminals (rules and grammars) are somewhat special with regard to their attribute handling. In today&#8217;s &#8216;Tip of the Day&#8217; I would like to revisit this topic as it still seems to be difficult to understand.<\/p>\n<p><!--more--><\/p>\n<p><em>Spirit&#8217;s<\/em> non-terminals can expose any attribute type, and the required type needs to be explicitly specified while declaring them. This is true for <em>Qi<\/em> parsers and <em>Karma<\/em> generators. The following example declares a rule exposing an (synthesized) attribute of type <span style=\"font-family: Courier New;\">double<\/span> (if you wonder why it uses the unusual function declaration syntax, i.e. <span style=\"font-family: Courier New;\">double()<\/span>, please read the article mentioned above):<\/p>\n<pre class=\"brush: cpp; title: ; notranslate\" title=\"\">\r\nnamespace qi = boost::spirit::qi;\r\nstd::string input(&quot;1.0&quot;);\r\nstd::string::const_iterator b = input.begin();\r\ndouble result = 0;\r\nqi::rule&lt;std::string::const_iterator, double()&gt; r = qi::double_;\r\nqi::parse(b, input.end(), r, result);\r\n<\/pre>\n<p>The left hand side&#8217;s attribute (the <span style=\"font-family: Courier New;\">result<\/span> passed in by the user) is directly handed over to the right hand side of the rule. The parser created by <span style=\"font-family: Courier New;\">qi::double_<\/span> will put its result into the very same <span style=\"font-family: Courier New;\">double<\/span> instance as passed in from the outside. No additional copies are created. We call this behavior <em>auto attribute propagation<\/em>. For rules it is enabled by default as long as no semantic actions are attached to the right hand side&#8217;s expression.<\/p>\n<p>If you want to enforce auto attribute propagation even if the right hand side has semantic actions, you need to employ the &#8216;%=&#8217; syntax as shown in the next Karma example:<\/p>\n<pre class=\"brush: cpp; title: ; notranslate\" title=\"\">\r\nnamespace karma = boost::spirit::karma;\r\ntypedef std::back_insert_iterator&lt;std::string&gt; output_iterator;\r\nstd::string output;\r\noutput_iterator sink(output);\r\nkarma::rule&lt;output_iterator, double()&gt; r;\r\nr %= karma::double_[++karma::_1];\r\nkarma::generate(sink, r, 1.0);    \/\/ will emit: 2.0\r\n<\/pre>\n<p>This code will increment the attribute (the <span style=\"font-family: Courier New;\">1.0<\/span>)\u00a0 before emitting the result to the output iterator (remember, semantic actions in <em>Karma<\/em> are called before invoking the related generator). Note, we incremented the attribute of the generator <span style=\"font-family: Courier New;\">karma::double_<\/span>, not the left hand side&#8217;s attribute (which would have been <span style=\"font-family: Courier New;\">++karma::_val<\/span>). This works as we enforced the auto attribute propagation using the &#8216;%=&#8217;.<\/p>\n<p>There is one more important thing to remember: regardless of how the auto attribute propagation is enabled, either based on the default behavior of <span style=\"font-family: Courier New;\">&#8216;=&#8217;<\/span> or by enforcing it using <span style=\"font-family: Courier New;\">&#8216;%=&#8217;<\/span>, the attribute types of the rule and the right hand side must be compatible. It is not possible to define <em>Spirit&#8217;s<\/em> &#8216;attribute compatibility&#8217; in a short sentence, so we leave the topic for another day. But in the simplest case it means the attributes have to be convertible. In <em>Qi<\/em> the right hand side&#8217;s attribute must at least be convertible to the rule&#8217;s attribute, while in <em>Karma<\/em> the opposite needs to be true: the rule&#8217;s attribute should at least be convertible to the right hand side&#8217;s attribute.<\/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-857\" class=\"share-facebook sd-button share-icon\" href=\"http:\/\/boost-spirit.com\/home\/2010\/01\/15\/how-do-rules-propagate-attributes\/?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-857\" class=\"share-twitter sd-button share-icon\" href=\"http:\/\/boost-spirit.com\/home\/2010\/01\/15\/how-do-rules-propagate-attributes\/?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-857\" class=\"share-pinterest sd-button share-icon\" href=\"http:\/\/boost-spirit.com\/home\/2010\/01\/15\/how-do-rules-propagate-attributes\/?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-857\" class=\"share-linkedin sd-button share-icon\" href=\"http:\/\/boost-spirit.com\/home\/2010\/01\/15\/how-do-rules-propagate-attributes\/?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=\"http:\/\/boost-spirit.com\/home\/2010\/01\/15\/how-do-rules-propagate-attributes\/?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=\"http:\/\/boost-spirit.com\/home\/2010\/01\/15\/how-do-rules-propagate-attributes\/?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>If you read the article about attribute handling for non-terminals (The Magical Power of Attributes in Spirit &#8211; Directives and Non-terminals) you might remember that Spirit&#8217;s non-terminals (rules and grammars) are somewhat special with regard to their attribute handling. In today&#8217;s &#8216;Tip of the Day&#8217; I would like to revisit this topic as it still [&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-857\" class=\"share-facebook sd-button share-icon\" href=\"http:\/\/boost-spirit.com\/home\/2010\/01\/15\/how-do-rules-propagate-attributes\/?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-857\" class=\"share-twitter sd-button share-icon\" href=\"http:\/\/boost-spirit.com\/home\/2010\/01\/15\/how-do-rules-propagate-attributes\/?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-857\" class=\"share-pinterest sd-button share-icon\" href=\"http:\/\/boost-spirit.com\/home\/2010\/01\/15\/how-do-rules-propagate-attributes\/?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-857\" class=\"share-linkedin sd-button share-icon\" href=\"http:\/\/boost-spirit.com\/home\/2010\/01\/15\/how-do-rules-propagate-attributes\/?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=\"http:\/\/boost-spirit.com\/home\/2010\/01\/15\/how-do-rules-propagate-attributes\/?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=\"http:\/\/boost-spirit.com\/home\/2010\/01\/15\/how-do-rules-propagate-attributes\/?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,18],"tags":[7,8],"jetpack_publicize_connections":[],"jetpack_featured_media_url":"","jetpack_shortlink":"https:\/\/wp.me\/pIHdZ-dP","jetpack_sharing_enabled":true,"_links":{"self":[{"href":"http:\/\/boost-spirit.com\/home\/wp-json\/wp\/v2\/posts\/857"}],"collection":[{"href":"http:\/\/boost-spirit.com\/home\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"http:\/\/boost-spirit.com\/home\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"http:\/\/boost-spirit.com\/home\/wp-json\/wp\/v2\/users\/3"}],"replies":[{"embeddable":true,"href":"http:\/\/boost-spirit.com\/home\/wp-json\/wp\/v2\/comments?post=857"}],"version-history":[{"count":9,"href":"http:\/\/boost-spirit.com\/home\/wp-json\/wp\/v2\/posts\/857\/revisions"}],"predecessor-version":[{"id":1129,"href":"http:\/\/boost-spirit.com\/home\/wp-json\/wp\/v2\/posts\/857\/revisions\/1129"}],"wp:attachment":[{"href":"http:\/\/boost-spirit.com\/home\/wp-json\/wp\/v2\/media?parent=857"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"http:\/\/boost-spirit.com\/home\/wp-json\/wp\/v2\/categories?post=857"},{"taxonomy":"post_tag","embeddable":true,"href":"http:\/\/boost-spirit.com\/home\/wp-json\/wp\/v2\/tags?post=857"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}