boost.spiritqi中序列和列表运算符的属性?
Attributes of sequence and list operator in boost.spirit qi?
我想解析类似
的东西
"{xxxx}
{xxxx}"
由 eol 分隔成 vector<vector<wchar_t>>
: ({xxxx},{xxxx})
以便“{”和“}”与内部字符保持在一起。
我的代码是:
#define BOOST_SPIRIT_UNICODE
#include <iostream>
#include<boost/spirit/include/qi.hpp>
#include<string>
#include<vector>
using namespace std;
namespace sw=boost::spirit::standard_wide;
namespace qi= boost::spirit::qi;
using boost::spirit::standard_wide::char_;
int main()
{
wstring s = L"{\"id\":23,\"text\":\"sf\nsf\"}\n{\"id\":23,\"text\":\"sfsf\"}";
qi::rule<wstring::iterator, vector<vector<wchar_t>>(), sw::blank_type> ru;
ru = (qi::char_(L"{") >> *(char_-char_(L"}")) >> char_(L"}")) % qi::eol;
vector<vector<wchar_t>> result;
qi::phrase_parse(s.begin(), s.end(), ru, sw::blank, result);
for (auto& v : result) {
//cout << "Size of string: " << v.size() << endl;
for (auto& s : v) {
wcout << s;
};
cout << endl;
};
std::cout << "Size of result"<<result.size()<<endl ;
}
但是输出是:
{
"id":23,"text":"sf
sf"
}
{
"id":23,"text":"sfsf"
}
Size of result6
对于外部向量,“{”似乎变成了 vector<wchar_t>
类型的单个元素。
然后考虑规则:
ru = (qi::char_(L"{") >> *(char_-char_(L"}")) >> char_(L"}")) % qi::eol;
根据文档,*(char_-char_(L"}"))
应该是 vector<A>
。而因为a: A, b: vector<A> --> (a >> b): vector<A>
,那么我认为(qi::char_(L"{") >> *(char_-char_(L"}")) >> char_(L"}"))
应该是vector<wchar_t>
。这与结果矛盾。
我哪里错了?
And because a: A, b: vector --> (a >> b): vector, then I think that (qi::char_(L"{") >> *(char_-char_(L"}")) >> char_(L"}")) should be vector. This is contracdicted to the result.
事实并非如此。应用来自 Detecting the parameter types in a Spirit semantic action
的现代化技巧
struct sense_f {
template <typename T> void operator()(T&&) const {
std::cout << boost::core::demangle(typeid(T).name()) << "\n";
}
};
static const boost::phoenix::function<sense_f> sense;
我们可以打印实际的属性类型:
ru = (char_(L'{') >> *(char_ - char_(L'}')) >> char_(L'}')) [sense(qi::_0)] % qi::eol;
这将打印 Live On Coliru:
boost::fusion::vector<wchar_t, std::vector<wchar_t, std::allocator<wchar_t> >, wchar_t>
简单的解决方案
假设您不需要捕获 {},您可以将它们设为文字而不是 char_
:
ru = (L'{' >> *(char_ - L'}') >> L'}') [sense(qi::_0)] % qi::eol;
这将打印 Live On Coliru:
boost::fusion::vector<std::vector<wchar_t, std::allocator<wchar_t> >&>
的确,如果你也让它传播属性:
ru %= (L'{' >> *(char_ - L'}') >> L'}') [sense(qi::_0)] % qi::eol;
程序打印:
boost::fusion::vector<std::vector<wchar_t, std::allocator<wchar_t> >&>
boost::fusion::vector<std::vector<wchar_t, std::allocator<wchar_t> >&>
"\"id\":23,\"text\":\"sf
sf\""
"\"id\":23,\"text\":\"sfsf\""
请注意 std::vector<wchar_t>
和 std::wstring
之间存在属性兼容性,这就是我使用后者的原因。
奖金
如果您确实想要包含 {} 和任何中间空格,请使用 qi::raw
:
ru %= qi::raw [L'{' >> *(char_ - L'}') >> L'}'] [sense(qi::_0)] % qi::eol;
现在打印:
boost::fusion::vector<boost::iterator_range<__gnu_cxx::__normal_iterator<wchar_t const*, std::__cxx11::basic_string<wchar_t, std::char_traits<wchar_t>, std::allocator<wchar_t> > > >&>
boost::fusion::vector<boost::iterator_range<__gnu_cxx::__normal_iterator<wchar_t const*, std::__cxx11::basic_string<wchar_t, std::char_traits<wchar_t>, std::allocator<wchar_t> > > >&>
"{\"id\":23,\"text\":\"sf
sf\"}"
"{\"id\":23,\"text\":\"sfsf\"}"
As you can see even iterator_range<It>
has attribute compatibility with std::wstring
because the input is also a sequence of wchar_t
.
当然,除非您想要那个输出,否则请关闭 sense
操作。
完整列表
使用qi::raw
方法的最终结果:
#define BOOST_SPIRIT_UNICODE
#include <boost/spirit/include/qi.hpp>
#include <iostream>
#include <iomanip>
#include <string>
#include <vector>
namespace sw = boost::spirit::standard_wide;
namespace qi = boost::spirit::qi;
using sw::char_;
int main() {
std::wstring s = LR"({"id":23,"text":"sf
sf"}
{"id":23,"text":"sfsf"})";
using Data = std::vector<std::wstring>;
using It = std::wstring::const_iterator;
qi::rule<It, Data(), sw::blank_type> ru
= qi::raw [L'{' >> *(char_ - L'}') >> L'}'] % qi::eol;
Data result;
It f = s.begin(), l = s.end();
if (qi::phrase_parse(f, l, ru, sw::blank, result)) {
for (auto& s : result) {
std::wcout << std::quoted(s) << std::endl;
};
} else {
std::wcout << "Parse failed\n";
}
if (f!=l) {
std::wcout << L"Remaining unparsed: " << std::quoted(std::wstring(f,l)) << std::endl;
}
}
我想解析类似
的东西"{xxxx}
{xxxx}"
由 eol 分隔成 vector<vector<wchar_t>>
: ({xxxx},{xxxx})
以便“{”和“}”与内部字符保持在一起。
我的代码是:
#define BOOST_SPIRIT_UNICODE
#include <iostream>
#include<boost/spirit/include/qi.hpp>
#include<string>
#include<vector>
using namespace std;
namespace sw=boost::spirit::standard_wide;
namespace qi= boost::spirit::qi;
using boost::spirit::standard_wide::char_;
int main()
{
wstring s = L"{\"id\":23,\"text\":\"sf\nsf\"}\n{\"id\":23,\"text\":\"sfsf\"}";
qi::rule<wstring::iterator, vector<vector<wchar_t>>(), sw::blank_type> ru;
ru = (qi::char_(L"{") >> *(char_-char_(L"}")) >> char_(L"}")) % qi::eol;
vector<vector<wchar_t>> result;
qi::phrase_parse(s.begin(), s.end(), ru, sw::blank, result);
for (auto& v : result) {
//cout << "Size of string: " << v.size() << endl;
for (auto& s : v) {
wcout << s;
};
cout << endl;
};
std::cout << "Size of result"<<result.size()<<endl ;
}
但是输出是:
{
"id":23,"text":"sf
sf"
}
{
"id":23,"text":"sfsf"
}
Size of result6
对于外部向量,“{”似乎变成了 vector<wchar_t>
类型的单个元素。
然后考虑规则:
ru = (qi::char_(L"{") >> *(char_-char_(L"}")) >> char_(L"}")) % qi::eol;
根据文档,*(char_-char_(L"}"))
应该是 vector<A>
。而因为a: A, b: vector<A> --> (a >> b): vector<A>
,那么我认为(qi::char_(L"{") >> *(char_-char_(L"}")) >> char_(L"}"))
应该是vector<wchar_t>
。这与结果矛盾。
我哪里错了?
And because a: A, b: vector --> (a >> b): vector, then I think that (qi::char_(L"{") >> *(char_-char_(L"}")) >> char_(L"}")) should be vector. This is contracdicted to the result.
事实并非如此。应用来自 Detecting the parameter types in a Spirit semantic action
的现代化技巧struct sense_f {
template <typename T> void operator()(T&&) const {
std::cout << boost::core::demangle(typeid(T).name()) << "\n";
}
};
static const boost::phoenix::function<sense_f> sense;
我们可以打印实际的属性类型:
ru = (char_(L'{') >> *(char_ - char_(L'}')) >> char_(L'}')) [sense(qi::_0)] % qi::eol;
这将打印 Live On Coliru:
boost::fusion::vector<wchar_t, std::vector<wchar_t, std::allocator<wchar_t> >, wchar_t>
简单的解决方案
假设您不需要捕获 {},您可以将它们设为文字而不是 char_
:
ru = (L'{' >> *(char_ - L'}') >> L'}') [sense(qi::_0)] % qi::eol;
这将打印 Live On Coliru:
boost::fusion::vector<std::vector<wchar_t, std::allocator<wchar_t> >&>
的确,如果你也让它传播属性:
ru %= (L'{' >> *(char_ - L'}') >> L'}') [sense(qi::_0)] % qi::eol;
程序打印:
boost::fusion::vector<std::vector<wchar_t, std::allocator<wchar_t> >&>
boost::fusion::vector<std::vector<wchar_t, std::allocator<wchar_t> >&>
"\"id\":23,\"text\":\"sf
sf\""
"\"id\":23,\"text\":\"sfsf\""
请注意 std::vector<wchar_t>
和 std::wstring
之间存在属性兼容性,这就是我使用后者的原因。
奖金
如果您确实想要包含 {} 和任何中间空格,请使用 qi::raw
:
ru %= qi::raw [L'{' >> *(char_ - L'}') >> L'}'] [sense(qi::_0)] % qi::eol;
现在打印:
boost::fusion::vector<boost::iterator_range<__gnu_cxx::__normal_iterator<wchar_t const*, std::__cxx11::basic_string<wchar_t, std::char_traits<wchar_t>, std::allocator<wchar_t> > > >&>
boost::fusion::vector<boost::iterator_range<__gnu_cxx::__normal_iterator<wchar_t const*, std::__cxx11::basic_string<wchar_t, std::char_traits<wchar_t>, std::allocator<wchar_t> > > >&>
"{\"id\":23,\"text\":\"sf
sf\"}"
"{\"id\":23,\"text\":\"sfsf\"}"
As you can see even
iterator_range<It>
has attribute compatibility withstd::wstring
because the input is also a sequence ofwchar_t
.
当然,除非您想要那个输出,否则请关闭 sense
操作。
完整列表
使用qi::raw
方法的最终结果:
#define BOOST_SPIRIT_UNICODE
#include <boost/spirit/include/qi.hpp>
#include <iostream>
#include <iomanip>
#include <string>
#include <vector>
namespace sw = boost::spirit::standard_wide;
namespace qi = boost::spirit::qi;
using sw::char_;
int main() {
std::wstring s = LR"({"id":23,"text":"sf
sf"}
{"id":23,"text":"sfsf"})";
using Data = std::vector<std::wstring>;
using It = std::wstring::const_iterator;
qi::rule<It, Data(), sw::blank_type> ru
= qi::raw [L'{' >> *(char_ - L'}') >> L'}'] % qi::eol;
Data result;
It f = s.begin(), l = s.end();
if (qi::phrase_parse(f, l, ru, sw::blank, result)) {
for (auto& s : result) {
std::wcout << std::quoted(s) << std::endl;
};
} else {
std::wcout << "Parse failed\n";
}
if (f!=l) {
std::wcout << L"Remaining unparsed: " << std::quoted(std::wstring(f,l)) << std::endl;
}
}