问题:
软件:使用Boost 1.52提升精神之气
Platform:Windows 7(64位)
编译器 (Visual 2010)
请求
限制
代码:
#define BOOST_SPIRIT_DEBUG
#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/phoenix_core.hpp>
#include <boost/spirit/include/phoenix_container.hpp>
#include <boost/spirit/include/phoenix_statement.hpp>
#include <boost/spirit/include/phoenix_operator.hpp>
#include <boost/fusion/include/adapt_struct.hpp>
#include <boost/fusion/include/boost_tuple.hpp>
#include <boost/variant/recursive_variant.hpp>
#include <boost/make_shared.hpp>
#include <vector>
namespace signal_processing {
namespace parsing {
struct json_object;
struct json_array;
typedef boost::variant < std::string,
double,
boost::recursive_wrapper<json_object>,
boost::recursive_wrapper<json_array>,
bool > json_value;
typedef boost::tuple < std::string, json_value> json_pair;
struct json_members
{
std::vector < json_pair > items;
};
struct json_object
{
std::vector < json_members > children;
};
struct json_array
{
std::vector < json_value > list;
};
using boost::spirit::qi::bool_;
using boost::spirit::qi::char_;
using boost::spirit::qi::double_;
using boost::spirit::qi::eol;
using boost::spirit::qi::float_;
using boost::spirit::qi::int_;
using boost::spirit::qi::lexeme;
using boost::spirit::qi::lit;
using boost::spirit::qi::space;
using boost::spirit::qi::_val;
using boost::spirit::qi::_1;
template <typename Iterator, typename Skipper>
struct json_grammar : boost::spirit::qi::grammar < Iterator, json_object(), Skipper>
{
json_grammar() : json_grammar::base_type(object)
{
object = '{' > *members > '}';
pair = string > ':' > value;
members = pair > *( ',' > members );
element_list = '[' > *elements > ']';
elements = value > *( ',' > elements );
value = string |
number |
object |
element_list |
bool_ |
lit("null");
char const* exclude = " ();\"\n\r\t";
string = '"'
> +lexeme[char_ - char_(exclude)]
> '"';
// Return: double
number = double_ |
float_ |
int_;
BOOST_SPIRIT_DEBUG_NODE(object);
BOOST_SPIRIT_DEBUG_NODE(pair);
BOOST_SPIRIT_DEBUG_NODE(members);
BOOST_SPIRIT_DEBUG_NODE(element_list);
BOOST_SPIRIT_DEBUG_NODE(elements);
BOOST_SPIRIT_DEBUG_NODE(value);
BOOST_SPIRIT_DEBUG_NODE(string);
BOOST_SPIRIT_DEBUG_NODE(number);
}
boost::spirit::qi::rule < Iterator, json_object(), Skipper > object;
boost::spirit::qi::rule < Iterator, json_pair(), Skipper > pair;
boost::spirit::qi::rule < Iterator, json_members(), Skipper > members;
boost::spirit::qi::rule < Iterator, json_array(), Skipper > element_list;
boost::spirit::qi::rule < Iterator, json_array(), Skipper > elements;
boost::spirit::qi::rule < Iterator, json_value(), Skipper > value;
boost::spirit::qi::rule < Iterator, std::string(), Skipper > string;
boost::spirit::qi::rule < Iterator, double(), Skipper > number;
};
}
}
BOOST_FUSION_ADAPT_STRUCT(
signal_processing::parsing::json_object,
(std::vector < signal_processing::parsing::json_members >, children)
)
BOOST_FUSION_ADAPT_STRUCT(
signal_processing::parsing::json_members,
(std::vector < signal_processing::parsing::json_pair >, items)
)
BOOST_FUSION_ADAPT_STRUCT(
signal_processing::parsing::json_array,
(std::vector < signal_processing::parsing::json_value >, list)
)
void parse ( std::string const& file )
{
typedef signal_processing::parsing::json_grammar < std::string::const_iterator, boost::spirit::ascii::space_type > configuration_grammar;
configuration_grammar input; // Input grammar
signal_processing::parsing::json_object parsed_data;
std::string::const_iterator iter = file.begin();
std::string::const_iterator end = file.end();
bool r = boost::spirit::qi::phrase_parse ( iter, end, input, boost::spirit::ascii::space, parsed_data );
if ( ! r || iter != end)
{
// Report the next 30 characters
std::string::const_iterator some = iter + 30;
if ( some > end )
{
some = end;
}
std::string context(iter, some);
std::cout << "-------------------------\n";
std::cout << "Parsing failed\n";
std::cout << "stopped at: \": " << context << "...\"\n";
std::cout << "-------------------------\n";
}
}
int main(int,char**)
{
std::string input ( "{\r\n \"Event\": {\r\n \"attribute_a\": 0.0002,\r\n \"attribute_b\": 2e-005,\r\n \"attribute_c\": 0.022\r\n }\r\n}" );
parse ( input );
return 0;
}
发布于 2013-01-22 09:40:48
解析器
一般来说,你的第一个问题的答案是,可能有几种方法可以实现你想要的。具体来说,我可以向你展示一种似乎可行的方法。
关键是正确设置与给定短语或令牌的一个或多个实例相匹配的规则的属性类型,方法是确保声明的实际上是容器,而不是具有容器成员的结构。
一旦您这样做了,您就需要编写规则,以便齐知道您正在处理的是一个容器,并且它应该在适当的情况下返回fill。
首先查看成员规则:您提供了以下规则:
members = pair > *( ',' > members );
我不相信这本身就足以告诉齐,您希望它用pair
来填充一个pair
容器,特别是因为pair
s和member
s不具有相同的属性类型。所以我建议你把这条规则改为:
members = pair > *( ',' > pair );
甚至:
members = pair % ',';
你需要确定这些规则是否是同一件事,但你明白了。
关于json_members
类型:我更改了结构定义,使结构派生自容器,而不是将容器作为结构的属性:
struct json_members : std::vector < json_pair > {};
你不需要做结构的融合化。
在我看来,下面是您代码的一个工作版本:
#define BOOST_SPIRIT_DEBUG
#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/phoenix_core.hpp>
#include <boost/spirit/include/phoenix_container.hpp>
#include <boost/spirit/include/phoenix_statement.hpp>
#include <boost/spirit/include/phoenix_operator.hpp>
#include <boost/fusion/include/adapt_struct.hpp>
#include <boost/fusion/include/boost_tuple.hpp>
#include <boost/variant/recursive_variant.hpp>
#include <boost/make_shared.hpp>
#include <vector>
namespace signal_processing {
namespace parsing {
struct json_object;
struct json_array;
typedef boost::variant < std::string,
double,
boost::recursive_wrapper<json_object>,
boost::recursive_wrapper<json_array>,
bool > json_value;
typedef boost::tuple < std::string, json_value> json_pair;
// struct json_members
// {
// std::vector < json_pair > items;
// };
//
// struct json_object
// {
// std::vector < json_members > children;
// };
//
// struct json_array
// {
// std::vector < json_value > list;
// };
struct json_members : std::vector < json_pair > {};
struct json_object : std::vector < json_members > {};
struct json_array : std::vector < json_value > {};
using boost::spirit::qi::bool_;
using boost::spirit::qi::char_;
using boost::spirit::qi::double_;
using boost::spirit::qi::eol;
using boost::spirit::qi::float_;
using boost::spirit::qi::int_;
using boost::spirit::qi::lexeme;
using boost::spirit::qi::lit;
using boost::spirit::qi::space;
using boost::spirit::qi::_val;
using boost::spirit::qi::_1;
template <typename Iterator, typename Skipper>
struct json_grammar : boost::spirit::qi::grammar < Iterator, json_object(), Skipper>
{
json_grammar() : json_grammar::base_type(object)
{
object = '{' > *members > '}';
pair = string > ':' > value;
members = pair > *( ',' > pair );
element_list = '[' > *elements > ']';
elements = value > *( ',' > value );
value = string |
number |
object |
element_list |
bool_ |
lit("null");
char const* exclude = " ();\"\n\r\t";
string = '"'
> +lexeme[char_ - char_(exclude)]
> '"';
// Return: double
number = double_ |
float_ |
int_;
BOOST_SPIRIT_DEBUG_NODE(object);
BOOST_SPIRIT_DEBUG_NODE(pair);
BOOST_SPIRIT_DEBUG_NODE(members);
BOOST_SPIRIT_DEBUG_NODE(element_list);
BOOST_SPIRIT_DEBUG_NODE(elements);
BOOST_SPIRIT_DEBUG_NODE(value);
BOOST_SPIRIT_DEBUG_NODE(string);
BOOST_SPIRIT_DEBUG_NODE(number);
}
boost::spirit::qi::rule < Iterator, json_object(), Skipper > object;
boost::spirit::qi::rule < Iterator, json_pair(), Skipper > pair;
boost::spirit::qi::rule < Iterator, json_members(), Skipper > members;
boost::spirit::qi::rule < Iterator, json_array(), Skipper > element_list;
boost::spirit::qi::rule < Iterator, json_array(), Skipper > elements;
boost::spirit::qi::rule < Iterator, json_value(), Skipper > value;
boost::spirit::qi::rule < Iterator, std::string(), Skipper > string;
boost::spirit::qi::rule < Iterator, double(), Skipper > number;
};
}
}
// BOOST_FUSION_ADAPT_STRUCT(
// signal_processing::parsing::json_object,
// (std::vector < signal_processing::parsing::json_members >, children)
// )
//
// BOOST_FUSION_ADAPT_STRUCT(
// signal_processing::parsing::json_members,
// (std::vector < signal_processing::parsing::json_pair >, items)
// )
//
// BOOST_FUSION_ADAPT_STRUCT(
// signal_processing::parsing::json_array,
// (std::vector < signal_processing::parsing::json_value >, list)
// )
void parse ( std::string const& file )
{
typedef signal_processing::parsing::json_grammar < std::string::const_iterator, boost::spirit::ascii::space_type > configuration_grammar;
configuration_grammar input; // Input grammar
signal_processing::parsing::json_object parsed_data;
std::string::const_iterator iter = file.begin();
std::string::const_iterator end = file.end();
bool r = boost::spirit::qi::phrase_parse ( iter, end, input, boost::spirit::ascii::space, parsed_data );
if ( ! r || iter != end)
{
// Report the next 30 characters
std::string::const_iterator some = iter + 30;
if ( some > end )
{
some = end;
}
std::string context(iter, some);
std::cout << "-------------------------\n";
std::cout << "Parsing failed\n";
std::cout << "stopped at: \": " << context << "...\"\n";
std::cout << "-------------------------\n";
}
}
int main(int,char**)
{
std::string input ( "{\r\n \"Event\": {\r\n \"attribute_a\": 0.0002,\r\n \"attribute_b\": 2e-005,\r\n \"attribute_c\": 0.022\r\n }\r\n}" );
parse ( input );
return 0;
}
其中产出:
localhost stov # ./stov
<object>
<try>{\r\n "Event": {</try>
<members>
<try>\r\n "Event": {\r</try>
<pair>
<try>\r\n "Event": {\r</try>
<string>
<try>\r\n "Event": {\r</try>
<success>: {\r\n </success>
<attributes>[[E, v, e, n, t]]</attributes>
</string>
<value>
<try> {\r\n </try>
<string>
<try> {\r\n </try>
<fail/>
</string>
<number>
<try> {\r\n </try>
<fail/>
</number>
<object>
<try>{\r\n "</try>
<members>
<try>\r\n "a</try>
<pair>
<try>\r\n "a</try>
<string>
<try>\r\n "a</try>
<success>: 0.0002,\r\n </success>
<attributes>[[a, t, t, r, i, b, u, t, e, _, a]]</attributes>
</string>
<value>
<try> 0.0002,\r\n </try>
<string>
<try> 0.0002,\r\n </try>
<fail/>
</string>
<number>
<try> 0.0002,\r\n </try>
<success>,\r\n "</success>
<attributes>[0.0002]</attributes>
</number>
<success>,\r\n "</success>
<attributes>[0.0002]</attributes>
</value>
<success>,\r\n "</success>
<attributes>[[[a, t, t, r, i, b, u, t, e, _, a], 0.0002]]</attributes>
</pair>
<pair>
<try>\r\n "a</try>
<string>
<try>\r\n "a</try>
<success>: 2e-005,\r\n </success>
<attributes>[[a, t, t, r, i, b, u, t, e, _, b]]</attributes>
</string>
<value>
<try> 2e-005,\r\n </try>
<string>
<try> 2e-005,\r\n </try>
<fail/>
</string>
<number>
<try> 2e-005,\r\n </try>
<success>,\r\n "</success>
<attributes>[2e-05]</attributes>
</number>
<success>,\r\n "</success>
<attributes>[2e-05]</attributes>
</value>
<success>,\r\n "</success>
<attributes>[[[a, t, t, r, i, b, u, t, e, _, b], 2e-05]]</attributes>
</pair>
<pair>
<try>\r\n "a</try>
<string>
<try>\r\n "a</try>
<success>: 0.022\r\n }\r\n</success>
<attributes>[[a, t, t, r, i, b, u, t, e, _, c]]</attributes>
</string>
<value>
<try> 0.022\r\n }\r\n}</try>
<string>
<try> 0.022\r\n }\r\n}</try>
<fail/>
</string>
<number>
<try> 0.022\r\n }\r\n}</try>
<success>\r\n }\r\n}</success>
<attributes>[0.022]</attributes>
</number>
<success>\r\n }\r\n}</success>
<attributes>[0.022]</attributes>
</value>
<success>\r\n }\r\n}</success>
<attributes>[[[a, t, t, r, i, b, u, t, e, _, c], 0.022]]</attributes>
</pair>
<success>\r\n }\r\n}</success>
<attributes>[[[[a, t, t, r, i, b, u, t, e, _, a], 0.0002], [[a, t, t, r, i, b, u, t, e, _, b], 2e-05], [[a, t, t, r, i, b, u, t, e, _, c], 0.022]]]</attributes>
</members>
<members>
<try>\r\n }\r\n}</try>
<pair>
<try>\r\n }\r\n}</try>
<string>
<try>\r\n }\r\n}</try>
<fail/>
</string>
<fail/>
</pair>
<fail/>
</members>
<success>\r\n}</success>
<attributes>[[[[[a, t, t, r, i, b, u, t, e, _, a], 0.0002], [[a, t, t, r, i, b, u, t, e, _, b], 2e-05], [[a, t, t, r, i, b, u, t, e, _, c], 0.022]]]]</attributes>
</object>
<success>\r\n}</success>
<attributes>[[[[[a, t, t, r, i, b, u, t, e, _, a], 0.0002], [[a, t, t, r, i, b, u, t, e, _, b], 2e-05], [[a, t, t, r, i, b, u, t, e, _, c], 0.022]]]]</attributes>
</value>
<success>\r\n}</success>
<attributes>[[[E, v, e, n, t], [[[[a, t, t, r, i, b, u, t, e, _, a], 0.0002], [[a, t, t, r, i, b, u, t, e, _, b], 2e-05], [[a, t, t, r, i, b, u, t, e, _, c], 0.022]]]]]</attributes>
</pair>
<success>\r\n}</success>
<attributes>[[[[E, v, e, n, t], [[[[a, t, t, r, i, b, u, t, e, _, a], 0.0002], [[a, t, t, r, i, b, u, t, e, _, b], 2e-05], [[a, t, t, r, i, b, u, t, e, _, c], 0.022]]]]]]</attributes>
</members>
<members>
<try>\r\n}</try>
<pair>
<try>\r\n}</try>
<string>
<try>\r\n}</try>
<fail/>
</string>
<fail/>
</pair>
<fail/>
</members>
<success></success>
<attributes>[[[[[E, v, e, n, t], [[[[a, t, t, r, i, b, u, t, e, _, a], 0.0002], [[a, t, t, r, i, b, u, t, e, _, b], 2e-05], [[a, t, t, r, i, b, u, t, e, _, c], 0.022]]]]]]]</attributes>
</object>
Unicode
我理解SVN构建的boost::spirit现在支持UTF8;尝试搜索BOOST_SPIRIT_UNICODE
。您现在可以使用库中的宽字符串支持来支持'unicode‘(微软称之为unicode)。
免责声明
我正在做Linux的工作。YMMV
发布于 2013-04-25 18:43:13
我碰巧写了精神v2中的一种支持UNICODE的JSON解析器,下面是一个解析您的示例的试验案例:
#include <sstream>
#include "JSON.hpp"
// util
static JSON::Value roundtrip(JSON::Value const& given) {
return JSON::parse(to_wstring(given));
}
void roundtrip_test()
{
auto
document = JSON::readFrom(std::istringstream(
"{\r\n"
" \"Event\": {\r\n"
" \"attribute_a\": 0.0002,\r\n"
"\"attribute_b\": 2e-005,\r\n"
"\"attribute_c\": 0.022\r\n"
"}\r\n}")),
verify = roundtrip(document);
std::cout << verify << "\n";
std::cout << "document <=> verify equal: \t" << std::boolalpha << (document == verify) << "\n";
std::cout << "document <=> verify text match:\t" << std::boolalpha << (to_string(document) == to_string(verify)) << "\n";
}
这些指纹:
{"Event":{"attribute_a":0.0002,"attribute_b":2e-05,"attribute_c":0.022}}
document <=> verify equal: true
document <=> verify text match: true
一些更多的API示例:
https://stackoverflow.com/questions/14462098
复制