title: Boost.Spirit: combining preparsing with keyword parser and with Nabialek trick
body: <p>I have the input in the json-like form </p>
  
  <pre><code>{
    type: "name",
    value: &lt;json_value&gt;,
  }
  </code></pre>
  
  <p>Type name can be one of "int1", "int2a", "int2b" (of course, I simplify the real situation to provide the minimal relevant code). </p>
  
  <p>The value always confirms to JSON syntax but also depends on type name. The possible cases are:</p>
  
  <pre><code>type: int1 =&gt; expected value: &lt;number&gt;
  type: int2a =&gt; expected value: [ &lt;number&gt;, &lt;number&gt; ]
  type: int2b =&gt; expected value: [ &lt;number&gt;, &lt;number&gt; ]
  </code></pre>
  
  <p>I need to parse input into the following data types:</p>
  
  <pre><code>struct int_1  { int i1; };
  struct int_2a { int i1, i2; };
  struct int_2b { int i1, i2; };
  
  using any_value = boost::variant&lt;int_1, int_2a, int_2b&gt;;
  
  struct data { std::string type; any_value value; };
  </code></pre>
  
  <p>I combined keyword parser with Nabialek trick. I create symbols table and store the pointers to the <strong>int_1</strong>, <strong>int_2a</strong> and <strong>int_2b</strong> parsers into it:</p>
  
  <pre><code>using value_rule_type = qi::rule&lt;It, any_value (), Skipper&gt;;
  
  qi::symbols&lt;char, value_rule_type *&gt; value_selector;
  
  qi::rule&lt;It, int_1  (), Skipper&gt; int1_parser;
  qi::rule&lt;It, int_2a (), Skipper&gt; int2a_parser;
  qi::rule&lt;It, int_2b (), Skipper&gt; int2b_parser;
  
  value_rule_type int1_rule, int2a_rule, int2b_rule;
  
  int1_parser  =        int_                      ;
  int2a_parser = '[' &gt;&gt; int_ &gt;&gt; ',' &gt;&gt; int_ &gt;&gt; ']';
  int2b_parser = '[' &gt;&gt; int_ &gt;&gt; ',' &gt;&gt; int_ &gt;&gt; ']';
  
  int1_rule  = int1_parser;
  int2a_rule = int2a_parser;
  int2b_rule = int2b_parser;
  
  value_selector.add
    ( "\"int1\"",  &amp;int1_rule  )
    ("\"int2a\"",  &amp;int2a_rule )
    ("\"int2b\"",  &amp;int2b_rule )
  ;
  </code></pre>
  
  <p>I use keyword parser to parse the outer <strong>data</strong> structure:</p>
  
  <pre><code>data_
    %= eps [ _a = px::val (nullptr) ]
    &gt; '{' &gt; (
        kwd ( lit ("\"type\"" ) ) [ ':' &gt;&gt; parsed_type_ (_a) &gt;&gt; ',' ]
      / kwd ( lit ("\"value\"") ) [ ':' &gt;&gt; value_ (_a)       &gt;&gt; ',' ]
    ) &gt; '}'
  ;
  </code></pre>
  
  <p>parsed_type_ rule here do a look up into the symbol table for the type name and sets the local variable of <strong>data</strong> rule to the found rule pointer.</p>
  
  <pre><code>parsed_type_ %=  raw[value_selector [ _r1  = _1 ]];
  </code></pre>
  
  <p>And value_ rule has the usual form for the Nabialek trick:</p>
  
  <pre><code>value_ = lazy (*_r1);
  </code></pre>
  
  <p>This parser works just fine (<a href="http://coliru.stacked-crooked.com/a/03622920a1e4f4c7" rel="nofollow">live demo</a>)... except for the case when value is passed before the type name:</p>
  
  <pre><code>{
    value: &lt;json_value&gt;,
    type: "name",
  }
  </code></pre>
  
  <p>As we have NULL in the stored pointer to the rule, and the parser for "type" field did not run yet, the program crashes during the parsing the "value" field.</p>
  
  <p>I'd like to fix this case. If the value field follows the type name field, I'd like the current parser logic applied (as in live demo). </p>
  
  <p>If value precedes the type key, I'd like to pre-parse value field with the json parser (just to find the end-boundary of that field) and to store that field in the form of iterator range into some local variable. After the parser got "type" field, I'd like to start the specific parser - int1_rule, int2a_rule or int2b_rule over stored range.</p>
  
  <p>So, the expression  </p>
  
  <pre><code>value_ = lazy (*_r1);
  </code></pre>
  
  <p>should probably be changed the something like: </p>
  
  <pre><code>if (_r1 == NULL) { 
    &lt;parse json value&gt;
    &lt;store raw range into local variable&gt; 
  } else { 
    lazy (*_r1); 
  }  
  </code></pre>
  
  <p>and expression</p>
  
  <pre><code>parsed_type_ %=  raw[value_selector [ _r1  = _1 ]];
  </code></pre>
  
  <p>should be extended with:</p>
  
  <pre><code>if (has stored range) parse it with lazy (*_r1);  
  </code></pre>
  
  <p>Unfortunately I have no idea how to implement it or it is possible at all.</p>
  
  <p>I include simplified JSON parser found on stackoverflow into my live demo for the convenience.</p>
  
  <p>The question: Is it possible at all with spirit? If yes, how it can be done? </p>
  
  <p>PS. Complete demo source:</p>
  
  <pre><code>#define BOOST_SPIRIT_USE_PHOENIX_V3
  
  #include &lt;boost/optional.hpp&gt;
  #include &lt;boost/variant.hpp&gt;
  #include &lt;boost/variant/recursive_variant.hpp&gt;
  
  #include &lt;boost/spirit/include/qi.hpp&gt;
  #include &lt;boost/spirit/include/phoenix.hpp&gt;
  
  #include &lt;boost/spirit/repository/include/qi_kwd.hpp&gt;
  #include &lt;boost/spirit/repository/include/qi_keywords.hpp&gt;
  
  #include &lt;boost/fusion/adapted.hpp&gt;
  #include &lt;boost/fusion/adapted/std_pair.hpp&gt;
  
  namespace spirit = ::boost::spirit;
  namespace qi = spirit::qi;
  namespace px = ::boost::phoenix;
  
  namespace json {
  
  struct null {
    constexpr bool operator== (null) const { return true; }
  };
  
  template&lt;typename Ch, typename Tr&gt;
  std::basic_ostream&lt;Ch, Tr&gt;&amp;
  operator&lt;&lt; (std::basic_ostream&lt;Ch, Tr&gt;&amp; os, null) { return os &lt;&lt; "null"; }
  
  using text = std::string;
  
  using value = boost::make_recursive_variant&lt;
      null
    , text                                        // string
    , double                                      // number
    , std::map&lt;text, boost::recursive_variant_&gt;   // object
    , std::vector&lt;boost::recursive_variant_&gt;      // array
    , bool
  &gt;::type;
  
  using member = std::pair&lt;text, value&gt;;
  using object = std::map&lt;text, value&gt;;
  using array = std::vector&lt;value&gt;;
  
  static auto const null_ = "null" &gt;&gt; qi::attr (null {});
  
  static auto const bool_ =
    "true" &gt;&gt; qi::attr (true) | "false" &gt;&gt; qi::attr (false);
  
  #if 0
  static auto const text_   =
    '"' &gt;&gt; qi::raw [*('\\' &gt;&gt; qi::char_ | ~qi::char_('"'))] &gt;&gt; '"';
  #endif
  
  template &lt;typename It, typename Skipper = qi::space_type&gt;
  struct grammar : qi::grammar&lt;It, value (), Skipper&gt;
  {
    grammar () : grammar::base_type (value_)
    {
      using namespace qi;
  
      text_   = '"' &gt;&gt; qi::raw [*('\\' &gt;&gt; qi::char_ | ~qi::char_('"'))] &gt;&gt; '"';
  
      value_  = null_ | bool_ | text_ | double_ | object_ | array_;
      member_ = text_ &gt;&gt; ':' &gt;&gt; value_;
      object_ = '{' &gt;&gt; -(member_ % ',') &gt;&gt; '}';
      array_  = '[' &gt;&gt; -(value_ % ',') &gt;&gt; ']';
  
      BOOST_SPIRIT_DEBUG_NODES((value_)(member_)(object_)(array_))
    }
  
  private:
    qi::rule&lt;It, std::string ()&gt; text_;
    qi::rule&lt;It, json:: value (), Skipper&gt; value_;
    qi::rule&lt;It, json::member (), Skipper&gt; member_;
    qi::rule&lt;It, json::object (), Skipper&gt; object_;
    qi::rule&lt;It, json:: array (), Skipper&gt; array_;
  };
  
  template &lt;typename Range,
    typename It = typename boost::range_iterator&lt;Range const&gt;::type&gt;
  value parse(Range const&amp; input)
  {
    grammar&lt;It&gt; g;
  
    It first(boost::begin(input)), last(boost::end(input));
    value parsed;
    bool ok = qi::phrase_parse(first, last, g, qi::space, parsed);
  
    if (ok &amp;&amp; (first == last))
      return parsed;
  
    throw std::runtime_error("Remaining unparsed: '" +
                             std::string(first, last) + "'");
  }
  
  } // namespace json
  
  namespace mine {
  
  struct int_1  { int_1 (int i) : i1 (i) {} int_1 () : i1 () {} int i1; };
  struct int_2a { int i1, i2; };
  struct int_2b { int i1, i2; };
  
  using any_value = boost::variant&lt;int_1, int_2a, int_2b&gt;;
  
  struct data { std::string type; any_value value; };
  
  template &lt;class C, class T&gt; std::basic_ostream&lt;C,T&gt;&amp;
  operator&lt;&lt; (std::basic_ostream&lt;C,T&gt;&amp; os, int_1 const&amp; i)
  {
    return os &lt;&lt; "{int1:" &lt;&lt; i.i1 &lt;&lt; '}';
  }
  
  template &lt;class C, class T&gt; std::basic_ostream&lt;C,T&gt;&amp;
  operator&lt;&lt; (std::basic_ostream&lt;C,T&gt;&amp; os, int_2a const&amp; i)
  {
    return os &lt;&lt; "{int2a:" &lt;&lt; i.i1 &lt;&lt; ',' &lt;&lt; i.i2 &lt;&lt; '}';
  }
  
  template &lt;class C, class T&gt; std::basic_ostream&lt;C,T&gt;&amp;
  operator&lt;&lt; (std::basic_ostream&lt;C,T&gt;&amp; os, int_2b const&amp; i)
  {
    return os &lt;&lt; "{int2b:" &lt;&lt; i.i1 &lt;&lt; ',' &lt;&lt; i.i2 &lt;&lt; '}';
  }
  
  template &lt;class C, class T&gt; std::basic_ostream&lt;C,T&gt;&amp;
  operator&lt;&lt; (std::basic_ostream&lt;C,T&gt;&amp; os, data const&amp; d)
  {
    return os &lt;&lt; "{type=" &lt;&lt; d.type &lt;&lt; ",value=" &lt;&lt; d.value &lt;&lt; '}';
  }
  
  }
  
  BOOST_FUSION_ADAPT_STRUCT(mine::int_1,  (int, i1) )
  BOOST_FUSION_ADAPT_STRUCT(mine::int_2a, (int, i1) (int, i2) )
  BOOST_FUSION_ADAPT_STRUCT(mine::int_2b, (int, i1) (int, i2) )
  BOOST_FUSION_ADAPT_STRUCT(mine::data,(std::string,type)(mine::any_value,value))
  
  namespace mine {
  
  template &lt;typename It, typename Skipper = qi::space_type&gt;
  struct grammar: qi::grammar&lt;It, data (), Skipper&gt;
  {
    grammar () : grammar::base_type (start)
    {
      using namespace qi;
      using spirit::repository::qi::kwd;
  
      int1_parser  =        int_                      ;
      int2a_parser = '[' &gt;&gt; int_ &gt;&gt; ',' &gt;&gt; int_ &gt;&gt; ']';
      int2b_parser = '[' &gt;&gt; int_ &gt;&gt; ',' &gt;&gt; int_ &gt;&gt; ']';
  
      int1_rule  = int1_parser;
      int2a_rule = int2a_parser;
      int2b_rule = int2b_parser;
  
      value_selector.add
        ( "\"int1\"",  &amp;int1_rule  )
        ("\"int2a\"",  &amp;int2a_rule )
        ("\"int2b\"",  &amp;int2b_rule )
      ;
  
      start = data_.alias ();
  
      parsed_type_ %=  raw[value_selector [ _r1  = _1 ]];
      value_ = lazy (*_r1);
  
      data_
        %= eps [ _a = px::val (nullptr) ]
        &gt; '{' &gt; (
            kwd ( lit ("\"type\"" ) ) [ ':' &gt;&gt; parsed_type_ (_a) &gt;&gt; ',' ]
          / kwd ( lit ("\"value\"") ) [ ':' &gt;&gt; value_ (_a)       &gt;&gt; ',' ]
        ) &gt; '}'
       ;
  
      on_error&lt;fail&gt;(start,
                     px::ref(std::cout)
                     &lt;&lt; "Error! Expecting "
                     &lt;&lt; qi::_4
                     &lt;&lt; " here: '"
                     &lt;&lt; px::construct&lt;std::string&gt;(qi::_3, qi::_2)
                     &lt;&lt; "'\n"
                     );
  
    }
  
  private:
    using value_rule_type = qi::rule&lt;It, any_value (), Skipper&gt;;
    qi::rule&lt;It, data (), Skipper&gt; start;
  
    qi::rule&lt;It, data (), qi::locals&lt;value_rule_type *&gt;, Skipper&gt; data_;
  
    qi::symbols&lt;char, value_rule_type *&gt; value_selector;
  
    qi::rule&lt;It, int_1  (), Skipper&gt; int1_parser;
    qi::rule&lt;It, int_2a (), Skipper&gt; int2a_parser;
    qi::rule&lt;It, int_2b (), Skipper&gt; int2b_parser;
  
    value_rule_type int1_rule, int2a_rule, int2b_rule;
  
    qi::rule&lt;It, std::string (value_rule_type *&amp;)         &gt; parsed_type_;
    qi::rule&lt;It, any_value   (value_rule_type *&amp;), Skipper&gt; value_;
  };
  
  template &lt;typename Range,
  typename It = typename boost::range_iterator&lt;Range const&gt;::type&gt;
  data parse(Range const&amp; input)
  {
    grammar&lt;It&gt; g;
  
    It first(boost::begin(input)), last(boost::end(input));
    data parsed;
    bool ok = qi::phrase_parse(first, last, g, qi::space, parsed);
  
    if (ok &amp;&amp; (first == last))
      return parsed;
  
    throw std::runtime_error("Remaining unparsed: '" +
                             std::string(first, last) + "'");
  }
  
  }
  
  static std::string const sample1 = R"(
  {
    "type": "int1",
    "value": 111,
  })";
  
  static std::string const sample2 = R"(
  {
    "type": "int2a",
    "value": [ 111, 222 ],
  })";
  
  static std::string const sample3 = R"(
  {
    "type": "int2b",
    "value": [ 111, 333 ],
  })";
  
  static std::string const sample4 = R"(
  {
    "value": 111,
    "type": "int1",
  })";
  
  int main()
  {
    auto mine = mine::parse(sample1); std::cout &lt;&lt; mine &lt;&lt; '\n';
         mine = mine::parse(sample2); std::cout &lt;&lt; mine &lt;&lt; '\n';
         mine = mine::parse(sample3); std::cout &lt;&lt; mine &lt;&lt; '\n';
         // mine = mine::parse(sample4); std::cout &lt;&lt; mine &lt;&lt; '\n';
    return 0;
  }
  </code></pre>