title: Is it possible to create custom Parsers in Boost.Spirit?
body: <p>I was trying to create a custom Parser class in Boost.Spirit (2.3), but it didn't work out. The code is:</p>
  
  <pre><code>template &lt;class Iter&gt;
  class crule : public boost::spirit::qi::parser&lt;crule&lt;Iter&gt; &gt;
  {
    rule&lt;Iter&gt; r_;
  public:
    crule(const rule&lt;Iter&gt;&amp; r) : r_(r) {}
    template &lt;class T&gt;
    crule(const T&amp; t) : r_(t) {}
    template&lt;class Ctx, class Skip&gt;
    bool parse(Iter&amp; f, const Iter&amp; l, Ctx&amp; context, Skip&amp; skip, typename rule&lt;Iter&gt;::template attribute&lt;Ctx, Iter&gt;::type&amp; attr) const {
      return r_.parse(f, l, context, skip, attr);
    }
    template &lt;class Ctx&gt;
    boost::spirit::info what(Ctx&amp; context) const {
      return r_.what(context);
    }
    template &lt;class Context, class It&gt;
    struct attribute {
      typedef typename rule&lt;Iter&gt;::template attribute&lt;Context, It&gt;::type type;
    };
  };
  </code></pre>
  
  <p>and although I have (at least I think I have) fulfilled all the <a href="http://www.boost.org/doc/libs/1_43_0/libs/spirit/doc/html/spirit/qi/reference/parser_concepts/parser.html" rel="nofollow noreferrer">requirements</a>, I get errors when I try to use this class in a parsing expression:</p>
  
  <pre><code>shell_grammar.h:134: error: no match for 'operator!' in '!shell_grammar&lt;Iter&gt;::token(boost::spirit::qi::rule&lt;Iter, boost::fusion::unused_type, boost::fusion::unused_type, boost::fusion::unused_type&gt;) [with Iter = __gnu_cxx::__normal_iterator&lt;const char*, std::basic_string&lt;char, std::char_traits&lt;char&gt;, std::allocator&lt;char&gt; &gt; &gt;](boost::spirit::qi::rule&lt;__gnu_cxx::__normal_iterator&lt;const char*, std::basic_string&lt;char, std::char_traits&lt;char&gt;, std::allocator&lt;char&gt; &gt; &gt;, boost::fusion::unused_type, boost::fusion::unused_type, boost::fusion::unused_type&gt;(((const boost::spirit::qi::rule&lt;__gnu_cxx::__normal_iterator&lt;const char*, std::basic_string&lt;char, std::char_traits&lt;char&gt;, std::allocator&lt;char&gt; &gt; &gt;, boost::fusion::unused_type, boost::fusion::unused_type, boost::fusion::unused_type&gt;&amp;)((const boost::spirit::qi::rule&lt;__gnu_cxx::__normal_iterator&lt;const char*, std::basic_string&lt;char, std::char_traits&lt;char&gt;, std::allocator&lt;char&gt; &gt; &gt;, boost::fusion::unused_type, boost::fusion::unused_type, boost::fusion::unused_type&gt;*)(&amp;((shell_grammar&lt;__gnu_cxx::__normal_iterator&lt;const char*, std::basic_string&lt;char, std::char_traits&lt;char&gt;, std::allocator&lt;char&gt; &gt; &gt; &gt;*)this)-&gt;shell_grammar&lt;__gnu_cxx::__normal_iterator&lt;const char*, std::basic_string&lt;char, std::char_traits&lt;char&gt;, std::allocator&lt;char&gt; &gt; &gt; &gt;::reserved_words)))))'
  
  shell_grammar.h:134: note: candidates are: operator!(bool) &lt;built-in&gt;
  </code></pre>
  
  <p>I tried to look at the implementation of other parsets (eg. <code>not_predicate</code>), but can't figure out what is the difference that makes it work.</p>
  
  <h2>Motvation</h2>
  
  <p>The reason I do it is related to <a href="https://stackoverflow.com/questions/3470668/copy-or-reference-semantics-of-boostspirits-rule">this question</a>. I want to parse POSIX shell language, which has peculiar lexical rules. Particularly, the "skipper parser" has to be applied even in lexemes, but it has to be different from the "phrase level" skipper parser. Which is what the <code>lexeme</code> directive can't do, and <code>skip</code> doesn't pre-skip (AFAIK), which is what I need, too. So I want to create a function</p>
  
  <pre><code>something token(std::string);
  </code></pre>
  
  <p>that would return a rule matching the token. One way is creating my own <code>rule</code> wrapper that would serve as a terminal (since <code>rule</code> alone cannot be used for its reference semantics), another would be creating a new parser (that would be a nonterminal in <code>proto</code>), and implement shell's token parsing in it.</p>