Michael Caisse 发表了关于 Spirit X3 的演讲:https ://www.youtube.com/watch?v=xSBWklPLRvw 。我尝试将演示文稿转录为工作代码,但出现编译错误,包括“没有可行的重载 '='”和“没有对 'move_to.' 的匹配函数调用。” 我的phrase_parse(最后一行)定义正确吗?是否有任何明显的错误?
#include <boost/config/warning_disable.hpp>
#include <boost/spirit/home/x3.hpp>
#include <boost/spirit/home/x3/support/ast/variant.hpp>
#include <boost/fusion/include/adapt_struct.hpp>
#include <boost/fusion/include/std_pair.hpp>
#include <boost/fusion/include/io.hpp>
#include <boost/container/stable_vector.hpp>
#include <iostream>
#include <iterator>
#include <fstream>
#include <string>
#include <map>
namespace client { namespace ast
{
namespace x3 = boost::spirit::x3;
using string_t = std::string;
using double_t = double;
using float_t = double;
using int_t = int64_t;
using bool_t = bool;
struct null_t {};
class value;
using object_t = std::map<std::string, value>;
using object_member_t = object_t::value_type;
using array_t = boost::container::stable_vector<value>;
class value : public x3::variant<null_t, bool_t, string_t, int_t, double_t, object_t, array_t>
{
public:
using value_type = value;
using base_type::base_type;
using base_type::operator=;
value(null_t val = null_t{}) : base_type(val) {}
value(char const* val) : base_type(string_t(val)) {}
template<typename T>
value(T val, typename std::enable_if<std::is_floating_point<T>::value>::type) : base_type(double_t{val}) {}
template<typename T>
value(T val, typename std::enable_if<std::is_integral<T>::value::type>) : base_type(int_t{val}) {}
};
struct json_class;
using json_type = x3::rule<json_class, value>;
json_type const json = "json";
BOOST_SPIRIT_DECLARE(json_type);
// identifier_class id
// identifier_type type
// identifier_def rule def
// identifier the rule
struct value_class;
struct object_class;
struct member_pair_class;
struct array_class;
using value_type = x3::rule<value_class, value>;
using object_type = x3::rule<object_class, object_t>;
using member_pair_type = x3::rule<member_pair_class, object_member_t>;
using array_type = x3::rule<array_class, array_t>;
value_type const value = "value";
object_type const object = "object";
member_pair_type const member_pair = "member_pair";
array_type const array = "array";
auto const append = [](auto& ctx){ _val(ctx) += _attr(ctx); };
using uchar = unsigned char;
x3::uint_parser<uchar, 16, 4, 4> const hex4 = {};
auto push_esc = [](auto& ctx)
{
auto& utf8 = _val(ctx);
switch (_attr(ctx))
{
case '"' : utf8 += '"'; break;
case '\\': utf8 += '\\'; break;
case '/' : utf8 += '/'; break;
case 'b' : utf8 += '\b'; break;
case 'f' : utf8 += '\f'; break;
case 'n' : utf8 += '\n'; break;
case 'r' : utf8 += '\r'; break;
case 't' : utf8 += '\t'; break;
}
};
auto push_utf8 = [](auto& ctx)
{
typedef std::back_insert_iterator<std::string> insert_iter;
insert_iter out_iter(_val(ctx));
boost::utf8_output_iterator<insert_iter> utf8_iter(out_iter);
*utf8_iter++ = _attr(ctx);
};
auto const escape = ('u' > hex4) [push_utf8]
| x3::char_("\"\\/bfnrt") [push_esc];
auto const char_esc = '\\' > escape;
auto const double_quoted = x3::lexeme[ '"' > *(char_esc) | (x3::char_("\x20\x21\x23-\x5b\x5d\x7e")) [append] > '"' ];
struct unicode_string_class;
using unicode_string_type = x3::rule<unicode_string_class, std::string>;
unicode_string_type const unicode_string = "unicode_string";
auto const unicode_string_def = double_quoted;
BOOST_SPIRIT_DEFINE(unicode_string);
auto const null_value = x3::lit("null") >> x3::attr(null_t{});
x3::int_parser<int64_t> const int_ = {};
x3::ascii::bool_type const bool_value = {};
auto const object_def = x3::lit('{') >> -(member_pair % ',') >> x3::lit('}');
auto const member_pair_def = unicode_string >> ':' >> value;
auto const array_def = x3::lit('[') >> -(value % ',') >> x3::lit(']');
auto const value_def = null_value | bool_value | object | array | unicode_string
| x3::lexeme[!('+' | (-x3::lit('-') >> '0' >> x3::digit)) >> x3::int_ >> !x3::char_(".eE")]
| x3::lexeme[!('+' | (-x3::lit('-') >> '0' >> x3::digit)) >> x3::double_ ];
BOOST_SPIRIT_DEFINE(value, object, member_pair, array);
}
}
int main(int argc, char **argv)
{
namespace x3 = boost::spirit::x3;
std::string storage; // We will read the contents here.
using boost::spirit::x3::ascii::space;
std::string::const_iterator iter = storage.begin();
std::string::const_iterator iter_end = storage.end();
client::ast::object_t o;
auto const grammar = client::ast::value;
bool r = phrase_parse(iter, iter_end, grammar, space, o);
}