{"id":540,"date":"2009-11-19T21:31:17","date_gmt":"2009-11-20T05:31:17","guid":{"rendered":"http:\/\/boost-spirit.com\/home\/?page_id=540"},"modified":"2010-01-16T11:03:25","modified_gmt":"2010-01-16T19:03:25","slug":"debugging","status":"publish","type":"page","link":"http:\/\/boost-spirit.com\/home\/articles\/doc-addendum\/debugging\/","title":{"rendered":"Debugging"},"content":{"rendered":"<p>Preliminary documentation for Spirit2 debugging support.<\/p>\n<p><!-- BODY { FONT-FAMILY:Tahoma; FONT-SIZE:10pt } P { FONT-FAMILY:Tahoma; FONT-SIZE:10pt } DIV { FONT-FAMILY:Tahoma; FONT-SIZE:10pt } TD { FONT-FAMILY:Tahoma; FONT-SIZE:10pt } --><\/p>\n<h4>Requirements:<\/h4>\n<ol>\n<li>It should provide info on rule attributes and locals.<\/li>\n<li>It should be easy to set a breakpoint for conditional debugging in the IDE.<\/li>\n<li>The user should be able to easily supply her own debug handler.<\/li>\n<li>The output should be valid xml (snippet) that can be read by any xml editor.<\/li>\n<\/ol>\n<blockquote><p><!-- BODY { FONT-FAMILY:Tahoma; FONT-SIZE:10pt } P { FONT-FAMILY:Tahoma; FONT-SIZE:10pt } DIV { FONT-FAMILY:Tahoma; FONT-SIZE:10pt } TD { FONT-FAMILY:Tahoma; FONT-SIZE:10pt } -->One thing that&#8217;s nice about having an xml format for debugging is that you can use an xml editor or viewer to inspect the results. A good debugging strategy is to collect the debug result into a text editor and inspect it with an XML editor. Some (most?) editors have display filter capabilities to make it easy to spot the piece of XML you are looking for.<\/p><\/blockquote>\n<p>Here&#8217;s how to add debugging to a rule in Spirit 2.1:<\/p>\n<pre class=\"brush: cpp; title: ; notranslate\" title=\"\">\r\ndebug(my_rule)\r\n<\/pre>\n<p>Yep, that was easy. That one uses Spirit 2.1&#8217;s simple_trace class which provides simple tracing capabilities (similar to Classic&#8217;s). Be aware that:<\/p>\n<ol>\n<li>Your attributes and local variables need to have a streaming operator defined, otherwise you&#8217;ll be getting a compiler error.<\/li>\n<li>That your rule is named. Check the docs on how to do this. Otherwise, you will get a printout with &#8216;unamed-rule&#8217;. If you want to have the rule named and enable debugging at the same time, you can use the convenience macro: BOOST_SPIRIT_DEBUG_NODE(my_rule).<\/li>\n<\/ol>\n<p>The example <a href=\"http:\/\/www.boost.org\/doc\/libs\/1_41_0\/libs\/spirit\/example\/qi\/calc4_debug.cpp\">calc4_debug.cpp<\/a> highlights the debugger. Here&#8217;s a sample session:<\/p>\n<pre class=\"brush: xml; title: ; notranslate\" title=\"\">\r\n1+1\r\n&lt;expression&gt;\r\n   &lt;try&gt;1+1&lt;\/try&gt;\r\n   &lt;term&gt;\r\n     &lt;try&gt;1+1&lt;\/try&gt;\r\n     &lt;factor&gt;\r\n       &lt;try&gt;1+1&lt;\/try&gt;\r\n       &lt;success&gt;+1&lt;\/success&gt;\r\n       &lt;attributes&gt;(1)&lt;\/attributes&gt;\r\n     &lt;\/factor&gt;\r\n     &lt;success&gt;+1&lt;\/success&gt;\r\n     &lt;attributes&gt;(1)&lt;\/attributes&gt;\r\n   &lt;\/term&gt;\r\n   &lt;term&gt;\r\n     &lt;try&gt;1&lt;\/try&gt;\r\n     &lt;factor&gt;\r\n       &lt;try&gt;1&lt;\/try&gt;\r\n       &lt;success&gt;&lt;\/success&gt;\r\n       &lt;attributes&gt;(1)&lt;\/attributes&gt;\r\n     &lt;\/factor&gt;\r\n     &lt;success&gt;&lt;\/success&gt;\r\n     &lt;attributes&gt;(1)&lt;\/attributes&gt;\r\n   &lt;\/term&gt;\r\n   &lt;success&gt;&lt;\/success&gt;\r\n   &lt;attributes&gt;(2)&lt;\/attributes&gt;\r\n&lt;\/expression&gt;\r\n-------------------------\r\nParsing succeeded\r\nresult = 2\r\n-------------------------\r\n<\/pre>\n<p>Things to note:<\/p>\n<ul>\n<li>The printout is more xml-ish than before. There is no wierd &lt;#tag&gt;to signal failure. You can use an xml editor to analyze the result.<\/li>\n<li>The attributes are printed. It is a tuple printed inside the (). What you see is the synthesized attribute of the rule. If there are inherited attributes, they are also printed. If there are local variables, those are also printed (a line after &#8220;Attributes&#8221;). The format is:\n<pre class=\"brush: xml; title: ; notranslate\" title=\"\">\r\n&lt;attributes&gt;(Synth, Inh1, Inh2 ... InhN)&lt;\/attributes&gt;\r\n&lt;locals&gt;(Loc1, Loc2 ... LocN)&lt;\/locals&gt;\r\n<\/pre>\n<\/li>\n<li>The markup\n<pre class=\"brush: xml; title: ; notranslate\" title=\"\">&lt;try&gt;...&lt;\/try&gt; and &lt;success&gt;...&lt;\/success&gt;<\/pre>\n<p>show some of the inputs prior and after parsing. As before, the number of chars printed is controlled by: BOOST_SPIRIT_DEBUG_PRINT_SOME<\/li>\n<li>As before the output is controlled by: BOOST_SPIRIT_DEBUG_OUT<\/li>\n<li>The number of indents os controlled by: BOOST_SPIRIT_DEBUG_INDENT<\/li>\n<\/ul>\n<p>Here&#8217;s a sample with syntax error:<\/p>\n<pre class=\"brush: xml; title: ; notranslate\" title=\"\">\r\n1+a\r\n&lt;expression&gt;\r\n   &lt;try&gt;1+a&lt;\/try&gt;\r\n   &lt;term&gt;\r\n     &lt;try&gt;1+a&lt;\/try&gt;\r\n     &lt;factor&gt;\r\n       &lt;try&gt;1+a&lt;\/try&gt;\r\n       &lt;success&gt;+a&lt;\/success&gt;\r\n       &lt;attributes&gt;(1)&lt;\/attributes&gt;\r\n     &lt;\/factor&gt;\r\n     &lt;success&gt;+a&lt;\/success&gt;\r\n     &lt;attributes&gt;(1)&lt;\/attributes&gt;\r\n   &lt;\/term&gt;\r\n   &lt;term&gt;\r\n     &lt;try&gt;a&lt;\/try&gt;\r\n     &lt;factor&gt;\r\n       &lt;try&gt;a&lt;\/try&gt;\r\n       &lt;fail\/&gt;\r\n     &lt;\/factor&gt;\r\n     &lt;fail\/&gt;\r\n   &lt;\/term&gt;\r\nError! Expecting &lt;term&gt; here: &quot;a&quot;\r\n   &lt;fail\/&gt;\r\n&lt;\/expression&gt;\r\n-------------------------\r\nParsing failed\r\n-------------------------\r\n<\/pre>\n<p>Notes:<\/p>\n<ol>\n<li>Error! Expecting &lt;term&gt; here: &#8220;a&#8221; was printed by the error_handler (same one in calc4.cpp). It shows in context where the exception was caught<\/li>\n<li>&lt;fail\/&gt; signals parse failure.<\/li>\n<\/ol>\n<p>As mentioned, the calc4_debug.cpp example utilizes the Spirit supplied simple_trace class. It is a simple function object. You can set a breakpoint in its operator(). The class is very simple:<\/p>\n<pre class=\"brush: cpp; title: ; notranslate\" title=\"\">\r\nstruct simple_trace\r\n{\r\n    void print_indent(int n) const\r\n    {\r\n        n *= BOOST_SPIRIT_DEBUG_INDENT;\r\n        for (int i = 0; i != n; ++i)\r\n            BOOST_SPIRIT_DEBUG_OUT &lt;&lt; ' ';\r\n    }\r\n\r\n    template &lt;typename Iterator&gt;\r\n    void print_some(\r\n        char const* tag\r\n      , int indent\r\n      , Iterator first, Iterator const&amp; last) const\r\n    {\r\n        print_indent(indent);\r\n        BOOST_SPIRIT_DEBUG_OUT &lt;&lt; '&lt;' &lt;&lt; tag &lt;&lt; '&gt;';\r\n        int const n = BOOST_SPIRIT_DEBUG_PRINT_SOME;\r\n        for (int i = 0; first != last &amp;&amp; i != n; ++i)\r\n            BOOST_SPIRIT_DEBUG_OUT &lt;&lt; *first++;\r\n        BOOST_SPIRIT_DEBUG_OUT &lt;&lt; &quot;&lt;\/&quot; &lt;&lt; tag &lt;&lt; '&gt;' &lt;&lt; std::endl;\r\n    }\r\n\r\n    template &lt;typename Iterator, typename Context, typename State&gt;\r\n    void operator()(\r\n        Iterator const&amp; first\r\n      , Iterator const&amp; last\r\n      , Context const&amp; context\r\n      , State state\r\n      , std::string const&amp; rule_name) const\r\n    {\r\n        int static indent = 0;\r\n\r\n        switch (state)\r\n        {\r\n            case pre_parse:\r\n                print_indent(indent++);\r\n                BOOST_SPIRIT_DEBUG_OUT\r\n                    &lt;&lt; '&lt;' &lt;&lt; rule_name &lt;&lt; '&gt;'\r\n                    &lt;&lt; std::endl;\r\n                print_some(&quot;try&quot;, indent, first, last);\r\n                break;\r\n            case successful_parse:\r\n                print_some(&quot;success&quot;, indent, first, last);\r\n                print_indent(indent);\r\n                BOOST_SPIRIT_DEBUG_OUT\r\n                    &lt;&lt; &quot;&lt;attributes&gt;&quot; &lt;&lt;\r\n                        context.attributes &lt;&lt; &quot;&lt;\/attributes&gt;&quot;;\r\n                if (!fusion::empty(context.locals))\r\n                    BOOST_SPIRIT_DEBUG_OUT &lt;&lt; &quot;&lt;locals&gt;&quot;\r\n                        &lt;&lt; context.locals &lt;&lt; &quot;&lt;\/locals&gt;&quot;;\r\n                BOOST_SPIRIT_DEBUG_OUT &lt;&lt; std::endl;\r\n                print_indent(--indent);\r\n                BOOST_SPIRIT_DEBUG_OUT &lt;&lt; &quot;&lt;\/&quot; &lt;&lt; rule_name &lt;&lt; '&gt;'\r\n                    &lt;&lt; std::endl;\r\n                break;\r\n            case failed_parse:\r\n                print_indent(indent);\r\n                BOOST_SPIRIT_DEBUG_OUT\r\n                    &lt;&lt; &quot;&lt;fail\/&gt;&quot; &lt;&lt; std::endl;\r\n                print_indent(--indent);\r\n                BOOST_SPIRIT_DEBUG_OUT &lt;&lt; &quot;&lt;\/&quot; &lt;&lt; rule_name &lt;&lt; '&gt;'\r\n                    &lt;&lt; std::endl;\r\n                break;\r\n        }\r\n    }\r\n};\r\n<\/pre>\n<p>State is:<\/p>\n<pre class=\"brush: cpp; title: ; notranslate\" title=\"\">\r\nenum debug_handler_state\r\n{\r\n    pre_parse\r\n  , successful_parse\r\n  , failed_parse\r\n};\r\n<\/pre>\n<p>Context is the rule&#8217;s context where the attributes and locals reside. There is a public API in support\/context.hpp. The actual class is quite simply a struct with 2 elements:<\/p>\n<pre class=\"brush: cpp; title: ; notranslate\" title=\"\">\r\ntemplate &lt;typename Attributes, typename Locals&gt;\r\nstruct context\r\n{\r\n    \/*...*\/\r\n\r\n    Attributes attributes;  \/\/ The attributes\r\n    Locals locals;          \/\/ Local variables\r\n};\r\n<\/pre>\n<p>Both are tuples.<\/p>\n<p>simple_trace exemplifies a debug-handler. You can specify your own if needed:<\/p>\n<pre class=\"brush: cpp; title: ; notranslate\" title=\"\">\r\ndebug(my_rule, my_handler);\r\n<\/pre>\n<p>The only requiremenmt is for the debug-handler to have an operator() with the signature:<\/p>\n<pre class=\"brush: cpp; title: ; notranslate\" title=\"\">\r\ntemplate &lt;typename Iterator, typename Context, typename State&gt;\r\nvoid operator()(\r\n    Iterator const&amp; first\r\n  , Iterator const&amp; last\r\n  , Context const&amp; context\r\n  , State state\r\n  , std::string const&amp; rule_name) const;\r\n<\/pre>\n<hr \/>\n<p>Ok, there you go&#8230; As usual, comments and suggestionsare very welcome. Have fun debugging!<\/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-540\" class=\"share-facebook sd-button share-icon\" href=\"http:\/\/boost-spirit.com\/home\/articles\/doc-addendum\/debugging\/?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-540\" class=\"share-twitter sd-button share-icon\" href=\"http:\/\/boost-spirit.com\/home\/articles\/doc-addendum\/debugging\/?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-540\" class=\"share-pinterest sd-button share-icon\" href=\"http:\/\/boost-spirit.com\/home\/articles\/doc-addendum\/debugging\/?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-540\" class=\"share-linkedin sd-button share-icon\" href=\"http:\/\/boost-spirit.com\/home\/articles\/doc-addendum\/debugging\/?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\/articles\/doc-addendum\/debugging\/?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\/articles\/doc-addendum\/debugging\/?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>Preliminary documentation for Spirit2 debugging support. Requirements: It should provide info on rule attributes and locals. It should be easy to set a breakpoint for conditional debugging in the IDE. The user should be able to easily supply her own debug handler. The output should be valid xml (snippet) that can be read by any [&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-540\" class=\"share-facebook sd-button share-icon\" href=\"http:\/\/boost-spirit.com\/home\/articles\/doc-addendum\/debugging\/?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-540\" class=\"share-twitter sd-button share-icon\" href=\"http:\/\/boost-spirit.com\/home\/articles\/doc-addendum\/debugging\/?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-540\" class=\"share-pinterest sd-button share-icon\" href=\"http:\/\/boost-spirit.com\/home\/articles\/doc-addendum\/debugging\/?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-540\" class=\"share-linkedin sd-button share-icon\" href=\"http:\/\/boost-spirit.com\/home\/articles\/doc-addendum\/debugging\/?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\/articles\/doc-addendum\/debugging\/?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\/articles\/doc-addendum\/debugging\/?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":2,"featured_media":0,"parent":538,"menu_order":3,"comment_status":"open","ping_status":"open","template":"article-page.php","meta":{"_s2mail":"","spay_email":""},"jetpack_shortlink":"https:\/\/wp.me\/PIHdZ-8I","jetpack_sharing_enabled":true,"_links":{"self":[{"href":"http:\/\/boost-spirit.com\/home\/wp-json\/wp\/v2\/pages\/540"}],"collection":[{"href":"http:\/\/boost-spirit.com\/home\/wp-json\/wp\/v2\/pages"}],"about":[{"href":"http:\/\/boost-spirit.com\/home\/wp-json\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"http:\/\/boost-spirit.com\/home\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"http:\/\/boost-spirit.com\/home\/wp-json\/wp\/v2\/comments?post=540"}],"version-history":[{"count":9,"href":"http:\/\/boost-spirit.com\/home\/wp-json\/wp\/v2\/pages\/540\/revisions"}],"predecessor-version":[{"id":542,"href":"http:\/\/boost-spirit.com\/home\/wp-json\/wp\/v2\/pages\/540\/revisions\/542"}],"up":[{"embeddable":true,"href":"http:\/\/boost-spirit.com\/home\/wp-json\/wp\/v2\/pages\/538"}],"wp:attachment":[{"href":"http:\/\/boost-spirit.com\/home\/wp-json\/wp\/v2\/media?parent=540"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}