 <p>After some experimentation, I have found a way to specify a custom skipper and will outline it here:</p> <pre><code>template&lt;typename Iterator&gt; struct pl0_skipper : public qi::grammar&lt;Iterator&gt; { pl0_skipper() : pl0_skipper::base_type(skip, "PL/0") { skip = ascii::space | ('{' &gt;&gt; *(qi::char_ - '}') &gt;&gt; '}'); } qi::rule&lt;Iterator&gt; skip; }; template&lt;typename Iterator, typename Skipper = pl0_skipper&lt;Iterator&gt;&gt; struct pl0_grammar : public qi::grammar&lt;Iterator, Skipper&gt; { /* The rules use our skipper */ qi::rule&lt;Iterator, Skipper&gt; start; qi::rule&lt;Iterator, Skipper&gt; block; qi::rule&lt;Iterator, Skipper&gt; statement; }; </code></pre> <p>The secret lies in the call of the parser. For some reason, when you want to parse this using <code>parse_phrase</code>, you have to give a skipper grammar object. I was not aware of this:</p> <pre><code>typedef std::string::const_iterator iterator_t; typedef parser::pl0_grammar&lt;iterator_t&gt; grammar; typedef parser::pl0_skipper&lt;iterator_t&gt; skipper; grammar g; skipper ws; iterator_t iter = str.begin(); iterator_t end = str.end(); bool r = phrase_parse(iter, end, g, ws); </code></pre> <p>This works.</p>