c++ - 解析字符串对失败。恶灵 x3 语法

标签 c++ boost-spirit-x3

我想解析键值对,将字符串映射到字符串。因为我想支持右侧的 { ... } block ,所以我想出了一个简单的语法来开始

#include <boost/spirit/home/x3.hpp>
#include <boost/fusion/include/std_pair.hpp>

namespace grammar::map
{
  using namespace boost::spirit::x3;
  auto expression = rule<class expression, std::pair<std::string, std::string>>{"expression"};

  auto lhs   =  *(~char_('='));
  auto rest  =  *(~char_(';'));
  auto block = '{' >> *expression >> '}';

  auto expression_def = lhs >> '=' >> (block | rest) >> ';';
  BOOST_SPIRIT_DEFINE(expression)
}

但是它无法组合编译,除非我将表达式的属性更改为std::string

//! Transform a string into a key-value map of strings.
template <class M, class R>
  requires InputRange<R>() && _ContainerLike<M>
           && Same<value_type_t<M>, std::pair<const std::string, std::string>>()
           // && Assignable<std::pair<std::string, std::string>, value_type_t<M>>()
M parse(R&& range)
{
  auto begin = rng::begin(range);
  auto end = rng::end(range);
  auto map = M{};
  auto ret = x3::phrase_parse(begin, end, *grammar::map::expression, x3::space, map);
  if (!ret)
    throw std::runtime_error{"parse error"};
  return map;
}

我收到错误

boost/spirit/home/x3/support/traits/move_to.hpp:62:18: error: cannot convert ‘std::remove_reference<std::pair<std::__cxx11::basic_string<char>, std::__cxx11::basic_string<char> >&>::type {aka std::pair<std::__cxx11::basic_string<char>, std::__cxx11::basic_string<char> >}’ to ‘char’ in assignment
             dest = std::move(src);

位于

boost/spirit/home/x3/support/traits/move_to.hpp: In instantiation of ‘void boost::spirit::x3::traits::detail::move_to_plain(Source&&, Dest&, mpl_::false_) [with Source = std::pair<std::__cxx11::basic_string<char>, std::__cxx11::basic_string<char> >; Dest = char; mpl_::false_ = mpl_::bool_<false>]’:

如果尝试以下表达式,也会发生同样的情况

auto pair = std::pair<std::string, std::string>{};
auto ret = x3::phrase_parse(begin, end, grammar::map::expression, x3::space, map);

我几天来就开始关注它,但不知道如何正确地做到这一点。我感谢任何帮助...:^)

使用 boost-1.60{-62} 和 gcc 6.1.1、6.2 以及更新的主干版本对其进行了测试。

最佳答案

你的问题是你已经定义了 expression具有属性 pair<string,string> ,但是 lhs >> '=' >> (block|rest) >> ';' 的综合属性是 synt_attr=tuple<string,variant<vector<synt_attr>,string>>这基本上是 synt_attr=pair<string,variant<map_of_value_type_synt_attr,string>> 。因此,根据您想要的结果,您至少有两个选择:

  • 将合成属性更改为 pair<string,string> 。使用 x3::raw 非常容易指令(running on WandBox) :

    auto expression_def = lhs >> '=' >> (raw[block] | rest) >> ';';
    
  • 更改 expression 的定义具有与合成属性兼容的属性。这需要使用递归变体,并使您访问解析映射中的数据的方式变得复杂,因为您需要创建一个访问者 (running on WandBox)

    //A value is either a `string` or a `map<string,Value>`
    using Value = boost::make_recursive_variant<std::string,std::map<std::string,boost::recursive_variant_>>::type;
    
    ...
    
    struct printer : boost::static_visitor<void>
    {
        printer(int indent) :indent(indent) {}
    
        void operator()(const std::string& val) const
        {
            std::cout << std::string(indent, ' ') << val << std::endl;
        }
    
        void operator()(const std::map<std::string,Value>& val) const
        {
            for (const auto& pair : val)
            {
                std::cout << std::string(indent, ' ') << pair.first << ':' << std::endl;
                boost::apply_visitor(printer(indent + 4), pair.second);
                std::cout << std::string(indent, ' ') << std::endl;
            }
        }
    
    
        int indent;
    };
    
    void print_map(const Value& val)
    {
        boost::apply_visitor(printer(0), val);
    }
    

关于c++ - 解析字符串对失败。恶灵 x3 语法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39780633/

相关文章:

c++ - 重载运算符以将我自己的类作为标准类处理是一种好习惯吗?

c++ - 编译时检测不应该抛出但仍然抛出的函数(noexcept 或替代方法)

c++ - 在类中封装 Spirit X3 解析器

c++ - Boost Spirit X3 跳过解析器实现?

c++ - 用boost spirit X3高效解析琐碎文件

c++ - CLion 和 Qt5 : tuning qmake

c++ - 使用 C++ 创建 HTML 报告

c++ - 如何使用具有相对路径的 fstream 对象?

c++ - 使用spirit x3 解析字符串列表,后跟字符串列表

c++ - X3,什么是attr_gen?