{"id":929,"date":"2010-01-28T03:27:29","date_gmt":"2010-01-28T11:27:29","guid":{"rendered":"http:\/\/boost-spirit.com\/home\/?p=929"},"modified":"2010-01-28T04:09:23","modified_gmt":"2010-01-28T12:09:23","slug":"can-the-classic-dynamic-parsers-be-ported-to-qi","status":"publish","type":"post","link":"https:\/\/boost-spirit.com\/home\/2010\/01\/28\/can-the-classic-dynamic-parsers-be-ported-to-qi\/","title":{"rendered":"Can the Classic Dynamic Parsers be Ported to Qi?"},"content":{"rendered":"<p>After writing about local variables for rules <a href=\"http:\/\/boost-spirit.com\/home\/2010\/01\/21\/what-are-rule-bound-semantic-actions\/\">here<\/a> I would like to get back to some information I have had lying around for some time already. Today&#8217;s topic seems to be a nice fit as porting the dynamic parsers from <em>Spirit.Classic<\/em> requires to utilize local variables. This allows me to give you some more examples for this facility.<\/p>\n<p>Previous versions of <em>Spirit<\/em>, which are the versions we refer to as <em>Spirit.Classic<\/em> today, implemented special dynamic parsers allowing to insert control statements into the parsing process (such as <span style=\"font-family: Courier New;\">if_p<\/span>, <span style=\"font-family: Courier New;\">while_p<\/span>, and <span style=\"font-family: Courier New;\">for_p<\/span>). These dynamic parsers are not available anymore in <em>Qi<\/em>. But it is easy enough to achieve the same behavior using existing <em>Qi<\/em> components. This &#8216;Tip of the Day&#8217; describes those techniques, which have been developed and contributed by Carl Barron. Thanks Carl!<\/p>\n<p><!--more--><\/p>\n<p>Generally, <em>Spirit.Classic<\/em> allowed to employ the dynamic parser in two ways. The condition to check could be either a function or function object, or a parser expression. Functions or function objects are expected to return values convertible to <span style=\"font-family: Courier New;\">bool<\/span>. When the evaluation of the function or function object yields true it will be considered as meeting the condition. When the parser matches the condition is met as well.<\/p>\n<h5>General Notation<\/h5>\n<p>In the tables below we use the following notation:<\/p>\n<ul>\n<li><span style=\"font-family: Courier New;\">c<\/span>: A nullary function or function object evaluating to <span style=\"font-family: Courier New;\">bool<\/span><\/li>\n<li><span style=\"font-family: Courier New;\">p, p1, p2, \u2026<\/span>: Arbitrary parser expressions<\/li>\n<li><span style=\"font-family: Courier New;\">init, step<\/span>: Arbitrary <a href=\"http:\/\/www.boost.org\/doc\/libs\/1_41_0\/libs\/spirit\/phoenix\/doc\/html\/index.html\">Phoenix<\/a> nullary functions or function objects<\/li>\n<li><span style=\"font-family: Courier New;\">_a<\/span>: a local variable of the rule the expression is assigned to (the type of the local variable should be <span style=\"font-family: Courier New;\">bool<\/span>)<\/li>\n<\/ul>\n<p>All symbols are assumed to be referenced from their respective namespaces (i.e. <span style=\"font-family: Courier New;\">boost::spirit::classic<\/span> or <span style=\"font-family: Courier New;\">boost::spirit::qi<\/span>).<\/p>\n<h5>Conditional Parsing (<span style=\"font-family: Courier New;\">if_p<\/span>)<\/h5>\n<table border=\"1\" cellspacing=\"0\" cellpadding=\"2\" width=\"600\">\n<tbody>\n<tr>\n<td width=\"220\" valign=\"top\">Spirit.Classic Expression<\/td>\n<td width=\"380\" valign=\"top\">Equivalent Spirit.Qi Expression<\/td>\n<\/tr>\n<tr>\n<td width=\"220\" valign=\"top\"><span style=\"font-family: Courier New;\">if_p(p)[p1]<\/span><\/td>\n<td width=\"380\" valign=\"top\"><span style=\"font-family: Courier New;\">p &gt;&gt; p1 | eps<\/span><\/td>\n<\/tr>\n<tr>\n<td width=\"220\" valign=\"top\"><span style=\"font-family: Courier New;\">if_p(p)[p1].else_p[p2]<\/span><\/td>\n<td width=\"380\" valign=\"top\"><span style=\"font-family: Courier New;\">p &gt;&gt; p1 | p2 <\/span><\/td>\n<\/tr>\n<tr>\n<td width=\"220\" valign=\"top\">\u00a0<\/td>\n<td width=\"380\" valign=\"top\">\u00a0<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>The <em>Qi<\/em> constructs as shown exactly reproduce the behavior if the <span style=\"font-family: Courier New;\">if_p<\/span> construct: if the condition <span style=\"font-family: Courier New;\">&#8216;p&#8217;<\/span> is a parser it will consume input\u00a0in case\u00a0it matches. If this is not required you may utilize\u00a0predicates instead (see the post about <a href=\"http:\/\/boost-spirit.com\/home\/2010\/01\/17\/whats-the-difference-between-qis-and\/\">What\u2019s the Difference Between Qi\u2019s \u2018!\u2019 and \u2018~\u2019?<\/a>\u00a0for more details).<\/p>\n<h5>Parsing With Loops (<span style=\"font-family: Courier New;\">while_p<\/span>, <span style=\"font-family: Courier New;\">do_p<\/span>, and <span style=\"font-family: Courier New;\">for_p<\/span>)<\/h5>\n<p>All looping constructs require a local Boolean variable to be defined in the rule the expression is assigned to. It does not necessarily have to be the local variable <span style=\"font-family: Courier New;\">_a<\/span>, which in the expressions below is used as a placeholder for any local variable (<span style=\"font-family: Courier New;\">_a<\/span>, <span style=\"font-family: Courier New;\">_b<\/span>, \u2026<span style=\"font-family: Courier New;\">_j<\/span>). At the same time this restricts the function objects <span style=\"font-family: Courier New;\">&#8216;init&#8217;<\/span> and <span style=\"font-family: Courier New;\">&#8216;step&#8217;<\/span> to be <a href=\"http:\/\/www.boost.org\/doc\/libs\/1_41_0\/libs\/spirit\/phoenix\/doc\/html\/index.html\">Phoenix<\/a> function objects (remember, Phoenix expressions do not mix well with non-Phoenix function objects).<\/p>\n<table border=\"1\" cellspacing=\"0\" cellpadding=\"2\" width=\"600\">\n<tbody>\n<tr>\n<td width=\"220\" valign=\"top\">Spirit.Classic Expression<\/td>\n<td width=\"380\" valign=\"top\">Equivalent Spirit.Qi Expression<\/td>\n<\/tr>\n<tr>\n<td width=\"220\" valign=\"top\"><span style=\"font-family: Courier New;\">while_p(p)[p1]<\/span><\/td>\n<td width=\"380\" valign=\"top\"><span style=\"font-family: Courier New;\">\u00a0\u00a0\u00a0 eps[_a = true]<br \/>\n&gt;&gt; *(p &gt;&gt; (p1 | eps[_a = false]))<br \/>\n&gt;&gt;\u00a0 eps(_a) <\/span><\/td>\n<\/tr>\n<tr>\n<td width=\"220\" valign=\"top\">\u00a0<\/td>\n<td width=\"380\" valign=\"top\">\u00a0<\/td>\n<\/tr>\n<tr>\n<td width=\"220\" valign=\"top\"><span style=\"font-family: Courier New;\">do_p[p1].while_p(p)<\/span><\/td>\n<td width=\"380\" valign=\"top\"><span style=\"font-family: Courier New;\">\u00a0\u00a0\u00a0 eps[_a = true]<br \/>\n&gt;&gt; *((p1 | eps[_a = false]) &gt;&gt; p)<br \/>\n&gt;&gt;\u00a0 eps(_a)<\/span><\/td>\n<\/tr>\n<tr>\n<td width=\"220\" valign=\"top\">\u00a0<\/td>\n<td width=\"380\" valign=\"top\">\u00a0<\/td>\n<\/tr>\n<tr>\n<td width=\"220\" valign=\"top\"><span style=\"font-family: Courier New;\">for_p(init, p, step)[p1]<\/span><\/td>\n<td width=\"380\" valign=\"top\"><span style=\"font-family: Courier New;\">\u00a0\u00a0\u00a0 eps[init, _a = true]<br \/>\n&gt;&gt; *(p &gt;&gt; (p1 | eps[_a = false]) &gt;&gt; eps[step])<br \/>\n<span style=\"font-family: Courier New;\">&gt;&gt;\u00a0 eps(_a)<\/span> <\/span><\/td>\n<\/tr>\n<tr>\n<td width=\"220\" valign=\"top\">\u00a0<\/td>\n<td width=\"380\" valign=\"top\">\u00a0<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>All Qi constructs in the table above\u00a0employ the same trick as shown in the last installment about local variables (<a href=\"http:\/\/boost-spirit.com\/home\/2010\/01\/21\/what-are-rule-bound-semantic-actions\/\">What are Rule Bound Semantic Actions?<\/a>). By\u00a0using the <span style=\"font-family: Courier New;\">eps<\/span> component we inject arbitrary semantic actions into the parser execution. But please don&#8217;t confuse this with the <span style=\"font-family: Courier New;\">eps(_a)<\/span> component, which will propagate the current value of <span style=\"font-family: Courier New;\">_a<\/span> to its own return code. It will succeed parsing unless the current value of <span style=\"font-family: Courier New;\">_a<\/span> is <span style=\"font-family: Courier New;\">false<\/span>. In our case this forces the whole loop construct to fail parsing if the body parser <span style=\"font-family: Courier New;\">&#8216;p1&#8217;<\/span> failed.<\/p>\n<p>If you replace the <span style=\"font-family: Courier New;\">&#8216;p&#8217;<\/span> with <span style=\"font-family: Courier New;\">&#8216;c&#8217;<\/span> in any of the <em>Classic<\/em> expressions above (i.e. you want to use a function object as the condition instead of a parser), the <span style=\"font-family: Courier New;\">&#8216;p&#8217;<\/span> in the equivalent <em>Qi<\/em> expression needs to be replaced by <span style=\"font-family: Courier New;\">&#8216;eps(c)&#8217;<\/span>.<\/p>\n<p>Needless to say, all of the above expressions require you to add the proper <span style=\"font-family: Courier New;\">#include<\/span> statements to your code. Please consult the related documentation to see what&#8217;s necessary.<\/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-929\" class=\"share-facebook sd-button share-icon\" href=\"https:\/\/boost-spirit.com\/home\/2010\/01\/28\/can-the-classic-dynamic-parsers-be-ported-to-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-929\" class=\"share-twitter sd-button share-icon\" href=\"https:\/\/boost-spirit.com\/home\/2010\/01\/28\/can-the-classic-dynamic-parsers-be-ported-to-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-929\" class=\"share-pinterest sd-button share-icon\" href=\"https:\/\/boost-spirit.com\/home\/2010\/01\/28\/can-the-classic-dynamic-parsers-be-ported-to-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-929\" class=\"share-linkedin sd-button share-icon\" href=\"https:\/\/boost-spirit.com\/home\/2010\/01\/28\/can-the-classic-dynamic-parsers-be-ported-to-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\/01\/28\/can-the-classic-dynamic-parsers-be-ported-to-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\/01\/28\/can-the-classic-dynamic-parsers-be-ported-to-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>After writing about local variables for rules here I would like to get back to some information I have had lying around for some time already. Today&#8217;s topic seems to be a nice fit as porting the dynamic parsers from Spirit.Classic requires to utilize local variables. This allows me to give you some more examples [&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-929\" class=\"share-facebook sd-button share-icon\" href=\"https:\/\/boost-spirit.com\/home\/2010\/01\/28\/can-the-classic-dynamic-parsers-be-ported-to-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-929\" class=\"share-twitter sd-button share-icon\" href=\"https:\/\/boost-spirit.com\/home\/2010\/01\/28\/can-the-classic-dynamic-parsers-be-ported-to-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-929\" class=\"share-pinterest sd-button share-icon\" href=\"https:\/\/boost-spirit.com\/home\/2010\/01\/28\/can-the-classic-dynamic-parsers-be-ported-to-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-929\" class=\"share-linkedin sd-button share-icon\" href=\"https:\/\/boost-spirit.com\/home\/2010\/01\/28\/can-the-classic-dynamic-parsers-be-ported-to-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\/01\/28\/can-the-classic-dynamic-parsers-be-ported-to-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\/01\/28\/can-the-classic-dynamic-parsers-be-ported-to-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":[20,18],"tags":[8],"jetpack_publicize_connections":[],"jetpack_featured_media_url":"","jetpack_shortlink":"https:\/\/wp.me\/pIHdZ-eZ","jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/boost-spirit.com\/home\/wp-json\/wp\/v2\/posts\/929"}],"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=929"}],"version-history":[{"count":3,"href":"https:\/\/boost-spirit.com\/home\/wp-json\/wp\/v2\/posts\/929\/revisions"}],"predecessor-version":[{"id":947,"href":"https:\/\/boost-spirit.com\/home\/wp-json\/wp\/v2\/posts\/929\/revisions\/947"}],"wp:attachment":[{"href":"https:\/\/boost-spirit.com\/home\/wp-json\/wp\/v2\/media?parent=929"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/boost-spirit.com\/home\/wp-json\/wp\/v2\/categories?post=929"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/boost-spirit.com\/home\/wp-json\/wp\/v2\/tags?post=929"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}