title: How to get error position using the spirit parser
body: <p>I wrote a simple parser with spirit, akin to json (but simpler and more specialised). By following the advice in <a href="http://boost-spirit.com/home/articles/qi-example/tracking-the-input-position-while-parsing/" rel="nofollow">here</a>, I tried to implement error handling by tracking the error position. In particular, my parsing function is as follows</p>
  
  <pre><code>bool parse_properties(std::istream&amp; is, const std::string &amp;filename, PropertyList &amp;pset)
  {
      namespace qi = boost::spirit::qi;
      namespace ascii = boost::spirit::ascii;
      namespace classic = boost::spirit::classic;
  
      typedef std::istreambuf_iterator&lt;char&gt; base_iterator_type;
      base_iterator_type in_begin(is);
  
      // convert input iterator to forward iterator, usable by spirit parser
      typedef boost::spirit::multi_pass&lt;base_iterator_type&gt; forward_iterator_type;
      forward_iterator_type fwd_begin = boost::spirit::make_default_multi_pass(in_begin);
      forward_iterator_type fwd_end;
  
      // wrap forward iterator with position iterator, to record the position
      typedef classic::position_iterator2&lt;forward_iterator_type&gt; pos_iterator_type;
      pos_iterator_type position_begin(fwd_begin, fwd_end, filename);
      pos_iterator_type position_end;
  
      qi::rule&lt;pos_iterator_type&gt; skipper = ascii::space | 
      '#' &gt;&gt; *(ascii::char_ - qi::eol) &gt;&gt; qi::eol; 
  
      property_set_grammar&lt;pos_iterator_type, qi::rule&lt;pos_iterator_type&gt; &gt; g;
      bool r = false;
      try {
          r = phrase_parse(position_begin, 
                           position_end, 
               g, skipper, pset);
      }
      catch(const qi::expectation_failure&lt;pos_iterator_type&gt;&amp; e) {
          const classic::file_position_base&lt;std::string&gt;&amp; pos = e.first.get_position();
          std::stringstream msg;
          msg &lt;&lt;
              "parse error at file " &lt;&lt; pos.file &lt;&lt;
              " line " &lt;&lt; pos.line &lt;&lt; " column " &lt;&lt; pos.column &lt;&lt; std::endl &lt;&lt;
              "'" &lt;&lt; e.first.get_currentline() &lt;&lt; "'" &lt;&lt; std::endl &lt;&lt;
              std::setw(pos.column) &lt;&lt; " " &lt;&lt; "^- here";
          throw std::runtime_error(msg.str());
      }
  
      return r;
  }
  </code></pre>
  
  <p>Unfortunately, it does not work. Function <code>phrase_parse</code> always returns false immediately, both for correct and for incorrect files, and never raises any exception. </p>
  
  <p>However, when I modify the above code to use a simple <code>forward_iterator</code> instead of the <code>classic::position_iterator2</code> it works fine, but of course it does not track the error position. The very strange thing is that the original example in <a href="http://boost-spirit.com/home/articles/qi-example/tracking-the-input-position-while-parsing/" rel="nofollow">here</a> works fine. So maybe the problem is related to my grammar. Here it follows:</p>
  
  <pre><code>template &lt;typename Iterator, typename Skipper&gt;
  struct property_set_grammar : qi::grammar&lt;Iterator, PropertyList(),
                                            Skipper&gt;
  {
      qi::rule&lt;Iterator, Property(), Skipper&gt; prop;
      qi::rule&lt;Iterator, std::string(), Skipper&gt; name;
      qi::rule&lt;Iterator, std::string(), Skipper&gt; type;
      qi::rule&lt;Iterator, std::string(), Skipper&gt; value;
      qi::rule&lt;Iterator, std::string(), Skipper&gt; value_simple;
      qi::rule&lt;Iterator, std::string(), Skipper&gt; value_quoted;
      qi::rule&lt;Iterator, PropertyList(), Skipper&gt; plist;
  
      property_set_grammar() : 
          property_set_grammar::base_type(plist, "Set of Properties") {
          using qi::lit;
          using qi::alpha;
          using qi::alnum;
          using qi::lexeme;
          using qi::char_;
  
          name = lexeme[alpha &gt;&gt; *alnum];
          type = lexeme[alpha &gt;&gt; *alnum];
          value_simple = lexeme[*(alnum - lit('"'))];
          value_quoted = lit('"') &gt; lexeme[*(char_ - lit('"'))] &gt; lit('"');
          value = (value_quoted | value_simple);
  
          prop = name &gt;&gt; '=' &gt; value &gt; ';';
          plist = type &gt;&gt; '(' &gt; name &gt; ')' &gt; '{' &gt;&gt; *(prop | plist) &gt; '}' &gt; ';';
      }
  };   
  </code></pre>
  
  <p>I am using g++ (Ubuntu/Linaro 4.7.2-2ubuntu1) 4.7.2 and version 1.50 of the boost libraries.</p>
  
  <p>Is there anything stupid that I am overlooking? If needed, I can provide the complete code (it's just a few files).</p>