Boost Spirit Qi - 字符串解析的C++语法

Boost Spirit Qi - C++ Grammar for string parsing

C++ Spirit 专家,我正在为以下用例寻找通用解析器。任何帮助将不胜感激

KEY = alphanumeric value 
Value = alphanumeric value 
    Array of values alphanumeric  separated by ()
    List of Array – 2D

例如:

Key1 = “my name”  key2= 10 key3=(1 2 3) key4=((1 2 3) (4 5 6))

我希望将键和值存储在 std::map 中。

因为我写解析器已经很久了,所以我 运行 用它:

Live On Coliru

// #define BOOST_SPIRIT_DEBUG
#include <boost/fusion/include/std_pair.hpp>
#include <boost/spirit/include/qi.hpp>
#include <iomanip> // std::quoted
#include <map>

namespace qi = boost::spirit::qi;

using Value = boost::make_recursive_variant<std::string, double, std::vector<boost::recursive_variant_> >::type;
using Map = std::map<std::string, Value>;

template <typename It>
struct Parser : qi::grammar<It, Map()> {
    Parser() : Parser::base_type(start) {
        using namespace qi;

        start     = skip(space) [*key_value];
        key_value = key >> '=' >> value;
        value     = v_string | v_array | v_num;

        // lexemes
        key = alpha >> *alnum;
        v_string  = "“" >> *('\' >> char_ | ~char_("”")) >> "”";
        v_array   = '(' >> *value >> ')';
        v_num     = double_;

        BOOST_SPIRIT_DEBUG_NODES((start)(key_value)(value)(key)(v_string)(v_array)(v_num))
    }
  private:
    qi::rule<It, Map()> start;
    qi::rule<It, std::pair<std::string, Value>(), qi::space_type> key_value;
    qi::rule<It, Value(), qi::space_type> value;
    qi::rule<It, std::vector<Value>(), qi::space_type> v_array;

    qi::rule<It, std::string()> key, v_string;
    qi::rule<It, double()> v_num;
    // lexemes
};

static inline std::ostream& operator<<(std::ostream& os, Value const& v) {
    struct {
        std::ostream& _os;
        void operator()(Value const& v) const { boost::apply_visitor(*this, v); }
        void operator()(std::string const& v) const { _os << std::quoted(v); }
        void operator()(double v) const { _os << v; }
        void operator()(std::vector<Value> const& v) const {
            _os << "( ";
            for (auto& el:v) {
                operator()(el);
                _os << " ";
            }
            _os << ")";
        }
    } vis{os};
    vis(v);
    return os;
}

int main() {
    using It = std::string::const_iterator;
    Parser<It> const p;

    for (std::string const& input : {
            "Key1 = “my name”  key2= 10 key3=(1 2 3) key4=((1 2 3) (4 5 6))"
        })
    {
        It f = input.begin(), l = input.end();
        Map data;
        bool ok = parse(f, l, p, data);

        if (ok) {
            std::cout << "Parsed " << data.size() << " unique keys\n";

            for (auto& entry : data) {
                std::cout << entry.first << " = " << entry.second << "\n";
            }
        } else {
            std::cout << "Parse failed\n";
        }

        if (f != l)
            std::cout << "Remaining unparsed: " << std::quoted(std::string(f,l)) << "\n";
    }
}

正在打印:

Parsed 4 unique keys
Key1 = "my name"
key2 = 10
key3 = ( 1 2 3 )
key4 = ( ( 1 2 3 ) ( 4 5 6 ) )

Note: I hope the tricky Unicode quotes are on purpose

启用BOOST_SPIRIT_DEBUG:

<start>
  <try>Key1 = “my name”</try>
  <key_value>
    <try>Key1 = “my name”</try>
    <key>
      <try>Key1 = “my name”</try>
      <success> = “my name”  ke</success>
      <attributes>[[K, e, y, 1]]</attributes>
    </key>
    <value>
      <try> “my name”  key2</try>
      <v_string>
        <try>“my name”  key2=</try>
        <success>  key2= 10 key3=(1 2</success>
        <attributes>[[m, y,  , n, a, m, e]]</attributes>
      </v_string>
      <success>  key2= 10 key3=(1 2</success>
      <attributes>[[m, y,  , n, a, m, e]]</attributes>
    </value>
    <success>  key2= 10 key3=(1 2</success>
    <attributes>[[[K, e, y, 1], [m, y,  , n, a, m, e]]]</attributes>
  </key_value>
  <key_value>
    <try>  key2= 10 key3=(1 2</try>
    <key>
      <try>key2= 10 key3=(1 2 3</try>
      <success>= 10 key3=(1 2 3) ke</success>
      <attributes>[[k, e, y, 2]]</attributes>
    </key>
    <value>
      <try> 10 key3=(1 2 3) key</try>
      <v_string>
        <try>10 key3=(1 2 3) key4</try>
        <fail/>
      </v_string>
      <v_array>
        <try>10 key3=(1 2 3) key4</try>
        <fail/>
      </v_array>
      <v_num>
        <try>10 key3=(1 2 3) key4</try>
        <success> key3=(1 2 3) key4=(</success>
        <attributes>[10]</attributes>
      </v_num>
      <success> key3=(1 2 3) key4=(</success>
      <attributes>[10]</attributes>
    </value>
    <success> key3=(1 2 3) key4=(</success>
    <attributes>[[[k, e, y, 2], 10]]</attributes>
  </key_value>
  <key_value>
    <try> key3=(1 2 3) key4=(</try>
    <key>
      <try>key3=(1 2 3) key4=((</try>
      <success>=(1 2 3) key4=((1 2 </success>
      <attributes>[[k, e, y, 3]]</attributes>
    </key>
    <value>
      <try>(1 2 3) key4=((1 2 3</try>
      <v_string>
        <try>(1 2 3) key4=((1 2 3</try>
        <fail/>
      </v_string>
      <v_array>
        <try>(1 2 3) key4=((1 2 3</try>
        <value>
          <try>1 2 3) key4=((1 2 3)</try>
          <v_string>
            <try>1 2 3) key4=((1 2 3)</try>
            <fail/>
          </v_string>
          <v_array>
            <try>1 2 3) key4=((1 2 3)</try>
            <fail/>
          </v_array>
          <v_num>
            <try>1 2 3) key4=((1 2 3)</try>
            <success> 2 3) key4=((1 2 3) </success>
            <attributes>[1]</attributes>
          </v_num>
          <success> 2 3) key4=((1 2 3) </success>
          <attributes>[1]</attributes>
        </value>
        <value>
          <try> 2 3) key4=((1 2 3) </try>
          <v_string>
            <try>2 3) key4=((1 2 3) (</try>
            <fail/>
          </v_string>
          <v_array>
            <try>2 3) key4=((1 2 3) (</try>
            <fail/>
          </v_array>
          <v_num>
            <try>2 3) key4=((1 2 3) (</try>
            <success> 3) key4=((1 2 3) (4</success>
            <attributes>[2]</attributes>
          </v_num>
          <success> 3) key4=((1 2 3) (4</success>
          <attributes>[2]</attributes>
        </value>
        <value>
          <try> 3) key4=((1 2 3) (4</try>
          <v_string>
            <try>3) key4=((1 2 3) (4 </try>
            <fail/>
          </v_string>
          <v_array>
            <try>3) key4=((1 2 3) (4 </try>
            <fail/>
          </v_array>
          <v_num>
            <try>3) key4=((1 2 3) (4 </try>
            <success>) key4=((1 2 3) (4 5</success>
            <attributes>[3]</attributes>
          </v_num>
          <success>) key4=((1 2 3) (4 5</success>
          <attributes>[3]</attributes>
        </value>
        <value>
          <try>) key4=((1 2 3) (4 5</try>
          <v_string>
            <try>) key4=((1 2 3) (4 5</try>
            <fail/>
          </v_string>
          <v_array>
            <try>) key4=((1 2 3) (4 5</try>
            <fail/>
          </v_array>
          <v_num>
            <try>) key4=((1 2 3) (4 5</try>
            <fail/>
          </v_num>
          <fail/>
        </value>
        <success> key4=((1 2 3) (4 5 </success>
        <attributes>[[1, 2, 3]]</attributes>
      </v_array>
      <success> key4=((1 2 3) (4 5 </success>
      <attributes>[[1, 2, 3]]</attributes>
    </value>
    <success> key4=((1 2 3) (4 5 </success>
    <attributes>[[[k, e, y, 3], [1, 2, 3]]]</attributes>
  </key_value>
  <key_value>
    <try> key4=((1 2 3) (4 5 </try>
    <key>
      <try>key4=((1 2 3) (4 5 6</try>
      <success>=((1 2 3) (4 5 6))</success>
      <attributes>[[k, e, y, 4]]</attributes>
    </key>
    <value>
      <try>((1 2 3) (4 5 6))</try>
      <v_string>
        <try>((1 2 3) (4 5 6))</try>
        <fail/>
      </v_string>
      <v_array>
        <try>((1 2 3) (4 5 6))</try>
        <value>
          <try>(1 2 3) (4 5 6))</try>
          <v_string>
            <try>(1 2 3) (4 5 6))</try>
            <fail/>
          </v_string>
          <v_array>
            <try>(1 2 3) (4 5 6))</try>
            <value>
              <try>1 2 3) (4 5 6))</try>
              <v_string>
                <try>1 2 3) (4 5 6))</try>
                <fail/>
              </v_string>
              <v_array>
                <try>1 2 3) (4 5 6))</try>
                <fail/>
              </v_array>
              <v_num>
                <try>1 2 3) (4 5 6))</try>
                <success> 2 3) (4 5 6))</success>
                <attributes>[1]</attributes>
              </v_num>
              <success> 2 3) (4 5 6))</success>
              <attributes>[1]</attributes>
            </value>
            <value>
              <try> 2 3) (4 5 6))</try>
              <v_string>
                <try>2 3) (4 5 6))</try>
                <fail/>
              </v_string>
              <v_array>
                <try>2 3) (4 5 6))</try>
                <fail/>
              </v_array>
              <v_num>
                <try>2 3) (4 5 6))</try>
                <success> 3) (4 5 6))</success>
                <attributes>[2]</attributes>
              </v_num>
              <success> 3) (4 5 6))</success>
              <attributes>[2]</attributes>
            </value>
            <value>
              <try> 3) (4 5 6))</try>
              <v_string>
                <try>3) (4 5 6))</try>
                <fail/>
              </v_string>
              <v_array>
                <try>3) (4 5 6))</try>
                <fail/>
              </v_array>
              <v_num>
                <try>3) (4 5 6))</try>
                <success>) (4 5 6))</success>
                <attributes>[3]</attributes>
              </v_num>
              <success>) (4 5 6))</success>
              <attributes>[3]</attributes>
            </value>
            <value>
              <try>) (4 5 6))</try>
              <v_string>
                <try>) (4 5 6))</try>
                <fail/>
              </v_string>
              <v_array>
                <try>) (4 5 6))</try>
                <fail/>
              </v_array>
              <v_num>
                <try>) (4 5 6))</try>
                <fail/>
              </v_num>
              <fail/>
            </value>
            <success> (4 5 6))</success>
            <attributes>[[1, 2, 3]]</attributes>
          </v_array>
          <success> (4 5 6))</success>
          <attributes>[[1, 2, 3]]</attributes>
        </value>
        <value>
          <try> (4 5 6))</try>
          <v_string>
            <try>(4 5 6))</try>
            <fail/>
          </v_string>
          <v_array>
            <try>(4 5 6))</try>
            <value>
              <try>4 5 6))</try>
              <v_string>
                <try>4 5 6))</try>
                <fail/>
              </v_string>
              <v_array>
                <try>4 5 6))</try>
                <fail/>
              </v_array>
              <v_num>
                <try>4 5 6))</try>
                <success> 5 6))</success>
                <attributes>[4]</attributes>
              </v_num>
              <success> 5 6))</success>
              <attributes>[4]</attributes>
            </value>
            <value>
              <try> 5 6))</try>
              <v_string>
                <try>5 6))</try>
                <fail/>
              </v_string>
              <v_array>
                <try>5 6))</try>
                <fail/>
              </v_array>
              <v_num>
                <try>5 6))</try>
                <success> 6))</success>
                <attributes>[5]</attributes>
              </v_num>
              <success> 6))</success>
              <attributes>[5]</attributes>
            </value>
            <value>
              <try> 6))</try>
              <v_string>
                <try>6))</try>
                <fail/>
              </v_string>
              <v_array>
                <try>6))</try>
                <fail/>
              </v_array>
              <v_num>
                <try>6))</try>
                <success>))</success>
                <attributes>[6]</attributes>
              </v_num>
              <success>))</success>
              <attributes>[6]</attributes>
            </value>
            <value>
              <try>))</try>
              <v_string>
                <try>))</try>
                <fail/>
              </v_string>
              <v_array>
                <try>))</try>
                <fail/>
              </v_array>
              <v_num>
                <try>))</try>
                <fail/>
              </v_num>
              <fail/>
            </value>
            <success>)</success>
            <attributes>[[4, 5, 6]]</attributes>
          </v_array>
          <success>)</success>
          <attributes>[[4, 5, 6]]</attributes>
        </value>
        <value>
          <try>)</try>
          <v_string>
            <try>)</try>
            <fail/>
          </v_string>
          <v_array>
            <try>)</try>
            <fail/>
          </v_array>
          <v_num>
            <try>)</try>
            <fail/>
          </v_num>
          <fail/>
        </value>
        <success></success>
        <attributes>[[[1, 2, 3], [4, 5, 6]]]</attributes>
      </v_array>
      <success></success>
      <attributes>[[[1, 2, 3], [4, 5, 6]]]</attributes>
    </value>
    <success></success>
    <attributes>[[[k, e, y, 4], [[1, 2, 3], [4, 5, 6]]]]</attributes>
  </key_value>
  <key_value>
    <try></try>
    <key>
      <try></try>
      <fail/>
    </key>
    <fail/>
  </key_value>
  <success></success>
  <attributes>[[[[K, e, y, 1], [m, y,  , n, a, m, e]], [[k, e, y, 2], 10], [[k, e, y, 3], [1, 2, 3]], [[k, e, y, 4], [[1, 2, 3], [4, 5, 6]]]]]</attributes>
</start>