{"id":949,"date":"2010-01-31T15:16:59","date_gmt":"2010-01-31T23:16:59","guid":{"rendered":"http:\/\/boost-spirit.com\/home\/?p=949"},"modified":"2010-03-11T19:39:25","modified_gmt":"2010-03-12T03:39:25","slug":"what-is-the-attribute-type-exposed-by-a-parser","status":"publish","type":"post","link":"http:\/\/boost-spirit.com\/home\/2010\/01\/31\/what-is-the-attribute-type-exposed-by-a-parser\/","title":{"rendered":"What is the Attribute Type Exposed by a Parser?"},"content":{"rendered":"<p>Most questions on the <a href=\"http:\/\/boost-spirit.com\/home\/info\/mailing-list\/\">main Spirit mailing list<\/a> are centered around attributes and how to correctly utilize <em>Spirit&#8217;s<\/em> attribute propagation rules. We discussed the related\u00a0basics in several posts already, but many people still have problems to understand the rules. Somebody recently asked on the mailing list whether it would be possible to print the attribute type exposed by an arbitrary parser expression. I answered by posting a sketchy code snippet (see <a href=\"http:\/\/article.gmane.org\/gmane.comp.parsers.spirit.general\/18387\">here<\/a>), but afterwards I realized it might be a good topic for yet another &#8216;Tip of the Day&#8217;.<\/p>\n<p><!--more--><\/p>\n<p>Before you read on, please be aware that the interfaces described in this post are not set in stone and may change in the future without attempting to be backwards compatible. I&#8217;ll write about the current implementation anyway as I think those are important. Generally, understanding attribute handling is crucial to understanding <em>Spirit<\/em>. Nuff said.<\/p>\n<p>Naturally, <em>Spirit<\/em> internally implements the means of retrieving the attribute type of any parser expression. So all we need to do is to invoke those and wrap them into a nicely reusable tool.<\/p>\n<p>Let us start by briefly describing some implementation details related to parser construction and attribute composition. As you might already know, any parser expression provided by the user (such as for instance\u00a0<span style=\"font-family: Courier New;\">qi::int_ &gt;&gt; qi::double_<\/span>) is not something you could directly\u00a0use to parse input. The <span style=\"font-family: Courier New;\">qi::int_<\/span>, <span style=\"font-family: Courier New;\">qi::double_<\/span>, etc. are just placeholder symbols denoting the type of the parser component required to match the input. These parser expressions have to be compiled into real parser instances responsible for the actual matching of the input. Spirit has a built in facility <span style=\"font-family: Courier New;\">boost::spirit::compile<\/span> which performs the conversion of the parser expression into the corresponding parser instance. Here is the (simplified) prototype:<\/p>\n<pre class=\"brush: cpp; title: ; notranslate\" title=\"\">\r\nnamespace boost { namespace spirit\r\n{\r\n    template &lt;typename Domain, typename Expr&gt;\r\n    typename result_of::compile&lt;Domain, Expr&gt;::type\r\n    compile(Expr const&amp; expr);\r\n}}\r\n<\/pre>\n<p>where <span style=\"font-family: Courier New;\">Domain<\/span> is a tag type which in our case is <span style=\"font-family: Courier New;\">qi::domain<\/span>, thus identifying <em>Qi<\/em> (i.e. telling the function we want to create a parser), and <span style=\"font-family: Courier New;\">Expr<\/span> is the parser expression to compile. As most (meta-) template facilities in Spirit the <span style=\"font-family: Courier New;\">compile<\/span> construct consists out of two parts: the meta-calculation of the resulting type of the parser instance (<span style=\"font-family: Courier New;\">result_of::compile<\/span>) and the actual function doing the runtime compilation. For the purpose of this post we are interested in the resulting type of the parser instance only.<\/p>\n<p>Among other things, after compiling the parser expression, the member function <span style=\"font-family: Courier New;\">parse()<\/span> is called on the returned parser instance. In the article about <a href=\"http:\/\/boost-spirit.com\/home\/articles\/qi-example\/creating-your-own-parser-component-for-spirit-qi\/\">Creating Your Own Parser Component for Spirit.Qi<\/a> we saw that the parser instance additionally exposes its attribute type. <em>Spirit<\/em> implements another facility we can invoke to extract this attribute type for a given parser instance type:<\/p>\n<pre class=\"brush: cpp; title: ; notranslate\" title=\"\">\r\nnamespace boost { namespace spirit { namespace traits\r\n{\r\n    template &lt;typename Component, typename Context = unused_type\r\n      , typename Iterator = unused_type&gt;\r\n    struct attribute_of;\r\n}}}\r\n<\/pre>\n<p>where <span style=\"font-family: Courier New;\">Component<\/span> is the type of the parser expression to query for its attribute type, the <span style=\"font-family: Courier New;\">Context<\/span> is not relevant in our case and <span style=\"font-family: Courier New;\">Iterator<\/span> is the iterator type used to do the actual matching. Most parser components are independent of any iterator type, but components as the <span style=\"font-family: Courier New;\">raw[]<\/span> directives are. So most of the time we can leave out supplying an iterator type.<\/p>\n<p>These two Spirit facilities are all what we need! Let us combine the two in order to get the type of the attribute exposed by a parser created from a given parser expression.<\/p>\n<pre class=\"brush: cpp; title: ; notranslate\" title=\"\">\r\ntemplate &lt;typename Expr, typename Iterator = spirit::unused_type&gt;\r\nstruct attribute_of_parser\r\n{\r\n    typedef typename spirit::result_of::compile&lt;\r\n        spirit::qi::domain, Expr\r\n    &gt;::type parser_expression_type;\r\n\r\n    typedef typename spirit::traits::attribute_of&lt;\r\n        parser_expression_type, spirit::unused_type, Iterator\r\n    &gt;::type type;\r\n};\r\n<\/pre>\n<p>Now as we have a tool to get the attribute type, we can use a simple utility function to print it out to the console (in this example we ignore the iterator type):<\/p>\n<pre class=\"brush: cpp; title: ; notranslate\" title=\"\">\r\ntemplate &lt;typename T&gt;\r\nvoid display_attribute_of_parser(T const&amp;)\r\n{\r\n    typedef typename attribute_of_parser&lt;T&gt;::type attribute_type;\r\n    std::cout &lt;&lt; typeid(attribute_type).name() &lt;&lt; std::endl;\r\n}\r\n\r\n\/\/ this will print something like: boost::fusion::vector2&lt;int, double&gt;\r\ndisplay_attribute_of_parser(qi::int_ &gt;&gt; qi::double_);\r\n<\/pre>\n<p>That&#8217;s it! We created a nice, reusable function printing the attribute type of an arbitrary parser expression. I added this as an example to the Boost SVN <a href=\"http:\/\/svn.boost.org\/svn\/boost\/trunk\/libs\/spirit\/example\/qi\/display_attribute_type.hpp\">here<\/a> and <a href=\"http:\/\/svn.boost.org\/svn\/boost\/trunk\/libs\/spirit\/example\/qi\/display_attribute_type.cpp\">here<\/a>, allowing you to reuse it for your needs. The last thing to mention is that a similar utility can be easily written for <em>Karma<\/em> generators. The only thing to change is the passed <span style=\"font-family: Courier New;\">Domain<\/span> which needs to be <span style=\"font-family: Courier New;\">spirit::karma::domain<\/span>.<\/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-949\" class=\"share-facebook sd-button share-icon\" href=\"http:\/\/boost-spirit.com\/home\/2010\/01\/31\/what-is-the-attribute-type-exposed-by-a-parser\/?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-949\" class=\"share-twitter sd-button share-icon\" href=\"http:\/\/boost-spirit.com\/home\/2010\/01\/31\/what-is-the-attribute-type-exposed-by-a-parser\/?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-949\" class=\"share-pinterest sd-button share-icon\" href=\"http:\/\/boost-spirit.com\/home\/2010\/01\/31\/what-is-the-attribute-type-exposed-by-a-parser\/?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-949\" class=\"share-linkedin sd-button share-icon\" href=\"http:\/\/boost-spirit.com\/home\/2010\/01\/31\/what-is-the-attribute-type-exposed-by-a-parser\/?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\/31\/what-is-the-attribute-type-exposed-by-a-parser\/?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\/31\/what-is-the-attribute-type-exposed-by-a-parser\/?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>Most questions on the main Spirit mailing list are centered around attributes and how to correctly utilize Spirit&#8217;s attribute propagation rules. We discussed the related\u00a0basics in several posts already, but many people still have problems to understand the rules. Somebody recently asked on the mailing list whether it would be possible to print the attribute [&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-949\" class=\"share-facebook sd-button share-icon\" href=\"http:\/\/boost-spirit.com\/home\/2010\/01\/31\/what-is-the-attribute-type-exposed-by-a-parser\/?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-949\" class=\"share-twitter sd-button share-icon\" href=\"http:\/\/boost-spirit.com\/home\/2010\/01\/31\/what-is-the-attribute-type-exposed-by-a-parser\/?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-949\" class=\"share-pinterest sd-button share-icon\" href=\"http:\/\/boost-spirit.com\/home\/2010\/01\/31\/what-is-the-attribute-type-exposed-by-a-parser\/?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-949\" class=\"share-linkedin sd-button share-icon\" href=\"http:\/\/boost-spirit.com\/home\/2010\/01\/31\/what-is-the-attribute-type-exposed-by-a-parser\/?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\/31\/what-is-the-attribute-type-exposed-by-a-parser\/?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\/31\/what-is-the-attribute-type-exposed-by-a-parser\/?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":[20,5,18],"tags":[8],"jetpack_publicize_connections":[],"jetpack_featured_media_url":"","jetpack_shortlink":"https:\/\/wp.me\/pIHdZ-fj","jetpack_sharing_enabled":true,"_links":{"self":[{"href":"http:\/\/boost-spirit.com\/home\/wp-json\/wp\/v2\/posts\/949"}],"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=949"}],"version-history":[{"count":10,"href":"http:\/\/boost-spirit.com\/home\/wp-json\/wp\/v2\/posts\/949\/revisions"}],"predecessor-version":[{"id":1050,"href":"http:\/\/boost-spirit.com\/home\/wp-json\/wp\/v2\/posts\/949\/revisions\/1050"}],"wp:attachment":[{"href":"http:\/\/boost-spirit.com\/home\/wp-json\/wp\/v2\/media?parent=949"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"http:\/\/boost-spirit.com\/home\/wp-json\/wp\/v2\/categories?post=949"},{"taxonomy":"post_tag","embeddable":true,"href":"http:\/\/boost-spirit.com\/home\/wp-json\/wp\/v2\/tags?post=949"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}