在过去的几周里我对这些东西学到了很多东西,但还不够。下面的代码编译并运行,但TEST_ADAPT
中的代码不完整,我不确定如何建立连接。
该对象将解析为没有变体依赖关系的平面容器。我已经想通了我可以得到一个对我的存储器的引用元组很好的精神。 (见TEST_REF
)。 kleene运算符正在寻找单个顺序容器,但是在一组替代方案中,这看起来是不可能的。所以我想我需要提供一个代表该容器的东西,但是有一些工具可以在目标引用的元组中找到它。
我认为,即使这是一种错误的方式,写下ContainerAdaptor
对我来说也是一个很好的练习。所以我想知道我是在正确的领域还是在正确的轨道上。
我知道我能完成的最好的方法是使用TEST_VECT
方法并对向量进行传递,将数据复制到我的ALL
容器中。但那是不对的。
更新
我已经使Target::All
融合并使ContainerAdaptor
部分起作用。足以让kleene操作员接受它。我应该能够连接到Target :: All对象,也许......
#include <iostream>
#include <boost/fusion/include/as_vector.hpp>
#include <boost/fusion/adapted.hpp>
#include <boost/fusion/adapted/std_tuple.hpp>
#include <boost/fusion/include/boost_tuple.hpp>
#include <boost/spirit/home/x3.hpp>
#include <boost/spirit/home/x3/support/ast/variant.hpp>
//parse kleene operator to a set of alternatives, adaptor? with spirit x3
#define TEST_VECT
#define TEST_REF
#define TEST_ADAPT
// l.......................................................................
namespace Target {
struct Int
{
int int_val;
};
using IntVect = std::vector<Int>;
struct Word
{
std::string word_val;
};
using WordVect = std::vector<Word>;
struct All
{
IntVect int_vect;
WordVect word_vect;
};
}
BOOST_FUSION_ADAPT_STRUCT(Target::Int, int_val)
BOOST_FUSION_ADAPT_STRUCT(Target::Word, word_val)
BOOST_FUSION_ADAPT_STRUCT(Target::All, int_vect, word_vect)
std::ostream& operator << (std::ostream& o, const Target::Int& in) { o << in.int_val; return o; }
std::ostream& operator << (std::ostream& o, const Target::Word& in) { o << in.word_val; return o; }
std::ostream& operator << (std::ostream& o, const Target::IntVect& in) { for( auto& i : in ) o << i << " "; return o; }
std::ostream& operator << (std::ostream& o, const Target::WordVect& in) { for (auto& i : in) o << i << " "; return o; }
#define DEF_RULE( RuleName, Attr ) static auto const RuleName = rule<struct Attr##_def, Attr>( #RuleName )
namespace Target {
using namespace boost::spirit::x3;
auto const bare_word = lexeme[+char_("a-z")];
DEF_RULE(int_rule, Int) = int_;
DEF_RULE(word_rule, Word) = bare_word;
auto const int_vect_rule= "int" >> *int_rule;
auto const word_vect_rule= "word" >> *(word_rule - "int");
//another test
DEF_RULE(f_int_vect_rule, IntVect) = int_vect_rule;
DEF_RULE(f_word_vect_rule, IntVect) = word_vect_rule;
}//namespace Target
namespace Target {
struct Printer {
Printer(std::ostream& out) : out(out) {};
using result_type = void;
void operator()(const IntVect& expression) {
out << "IntVect: ";
for (auto& t : expression)
out << t << " ";
out << std::endl;
}
void operator()(const WordVect& expression) {
out << "Word: ";
for (auto& t : expression)
out << t << " ";
out << std::endl;
}
private:
std::ostream& out;
};
}//namespace Target
template<class Arg>
class ContainerAdaptor
{
public:
ContainerAdaptor(Arg& arg) :arg(arg) { }
typedef boost::spirit::x3::variant<Target::IntVect,Target::WordVect> value_type;
typedef size_t size_type;
struct Vis : public boost::static_visitor<>
{
void operator()(const Target::IntVect & i) const
{
std::cout << i << std::endl;
}
void operator()(const Target::WordVect & i) const
{
std::cout << i << std::endl;
}
};
void insert(value_type* e, const value_type& v) {
std::cout << "haha! ";
boost::apply_visitor(Vis(), v);
}
value_type* end() { return nullptr; }
value_type* begin() { return nullptr; }
size_t size;
private:
Arg & arg;
};
int main()
{
using namespace Target;
std::string thestr("word test more int 1 2 3 4 word this and that int 5 4 int 99 22");
std::string::iterator end = thestr.end();
#if defined(TEST_ADAPT)
{
std::cout << "\nTEST_ADAPT\n";
std::string::iterator begin = thestr.begin();
All all;
auto fwd = std::forward_as_tuple(all.word_vect, all.int_vect);
ContainerAdaptor<All>attr( all );
phrase_parse(begin, end, *( int_vect_rule | word_vect_rule), space, attr);
Printer printer(std::cout);
}
#endif
#if defined(TEST_VECT)
{
std::cout << "TEST_VECT\n";
std::string::iterator begin = thestr.begin();
using Vars = variant<Target::IntVect, Target::WordVect>;
std::vector< Vars > a_vect;
bool r = phrase_parse(begin, end, *( int_vect_rule | word_vect_rule), space, a_vect);
Printer printer(std::cout);
for (auto& i : a_vect)
i.apply_visitor(printer);
}
#endif
#if defined(TEST_REF)
{
std::cout << "\nTEST_REF\n";
std::string::iterator begin = thestr.begin();
All all;
auto fwd = std::forward_as_tuple(all.word_vect,all.int_vect);
phrase_parse(begin, end, word_vect_rule >> int_vect_rule, space, fwd);
Printer printer(std::cout);
std::_For_each_tuple_element(fwd, printer);
}
#endif
return 0;
}
答案 0 :(得分:1)
充分简化,它有效:
<强> Live On Coliru 强>
#include <iostream>
#include <boost/fusion/adapted.hpp>
#include <boost/spirit/home/x3.hpp>
#include <boost/spirit/home/x3/support/ast/variant.hpp>
namespace Target {
struct Int { int int_val; };
struct Word { std::string word_val; };
using IntVect = std::vector<Int>;
using WordVect = std::vector<Word>;
struct All {
IntVect int_vect;
WordVect word_vect;
};
}
BOOST_FUSION_ADAPT_STRUCT(Target::Int, int_val)
BOOST_FUSION_ADAPT_STRUCT(Target::Word, word_val)
std::ostream& operator << (std::ostream& o, const Target::Int& in) { o << in.int_val; return o; }
std::ostream& operator << (std::ostream& o, const Target::Word& in) { o << in.word_val; return o; }
std::ostream& operator << (std::ostream& o, const Target::IntVect& in) { for( auto& i : in ) o << i << " "; return o; }
std::ostream& operator << (std::ostream& o, const Target::WordVect& in) { for (auto& i : in) o << i << " "; return o; }
namespace Target {
using namespace boost::spirit::x3;
static auto const int_rule = rule<struct Int_def, Int>("int_rule") = int_;
static auto const word_rule = rule<struct Word_def, Word>("word_rule") = lexeme[+char_("a-z")];
static auto const int_vect_rule = "int" >> *int_rule;
static auto const word_vect_rule = "word" >> *(word_rule - "int");
}
template<class Arg> struct ContainerAdaptor
{
typedef boost::spirit::x3::variant<Target::IntVect,Target::WordVect> value_type;
void insert(value_type* /*e*/, const value_type& v) {
std::cout << "haha! ";
struct Vis {
//using result_type = void;
void operator()(const Target::IntVect & i) const { std::cout << i << std::endl; }
void operator()(const Target::WordVect & i) const { std::cout << i << std::endl; }
};
boost::apply_visitor(Vis(), v);
}
value_type* end() { return nullptr; }
value_type* begin() { return nullptr; }
Arg & arg;
};
int main() {
using namespace Target;
std::string const thestr("word test more int 1 2 3 4 word this and that int 5 4 int 99 22");
All all;
ContainerAdaptor<All> attr { all };
if (phrase_parse(begin(thestr), end(thestr), *( int_vect_rule | word_vect_rule), space, attr)) {
std::cout << "Parsed: \n";
std::cout << all.int_vect << "\n";
std::cout << all.word_vect << "\n";
}
}
打印:
haha! test more
haha! 1 2 3 4
haha! this and that
haha! 5 4
haha! 99 22
Parsed:
<强> Live On Coliru 强>
#include <iostream>
#include <boost/fusion/adapted.hpp>
#include <boost/spirit/home/x3.hpp>
namespace Target {
struct Int { int int_val; };
struct Word { std::string word_val; };
using IntVect = std::vector<Int>;
using WordVect = std::vector<Word>;
struct All {
IntVect int_vect;
WordVect word_vect;
};
}
BOOST_FUSION_ADAPT_STRUCT(Target::Int, int_val)
BOOST_FUSION_ADAPT_STRUCT(Target::Word, word_val)
std::ostream& operator << (std::ostream& o, const Target::Int& in) { o << in.int_val; return o; }
std::ostream& operator << (std::ostream& o, const Target::Word& in) { o << in.word_val; return o; }
std::ostream& operator << (std::ostream& o, const Target::IntVect& in) { for( auto& i : in ) o << i << " "; return o; }
std::ostream& operator << (std::ostream& o, const Target::WordVect& in) { for (auto& i : in) o << i << " "; return o; }
namespace x3 = boost::spirit::x3;
namespace Target {
using namespace x3;
static auto const int_rule = rule<struct Int_def, Int>("int_rule") = int_;
static auto const word_rule = rule<struct Word_def, Word>("word_rule") = lexeme[+char_("a-z")];
static auto const int_vect_rule = "int" >> *int_rule;
static auto const word_vect_rule = "word" >> *(word_rule - "int");
}
int main() {
std::string const thestr("word test more int 1 2 3 4 word this and that int 5 4 int 99 22");
Target::All all;
struct {
Target::All& _r;
void operator()(Target::IntVect const&v) const { _r.int_vect.insert(_r.int_vect.end(), v.begin(), v.end()); }
void operator()(Target::WordVect const&v) const { _r.word_vect.insert(_r.word_vect.end(), v.begin(), v.end()); }
} push_back { all };
auto unary = [](auto f) { return [f](auto& ctx) { return f(x3::_attr(ctx)); }; };
auto action = unary(push_back);
if (phrase_parse(begin(thestr), end(thestr), *(Target::int_vect_rule[action] | Target::word_vect_rule[action]), x3::space)) {
std::cout << "Parsed: \n";
std::cout << all.int_vect << "\n";
std::cout << all.word_vect << "\n";
}
}
打印
Parsed:
1 2 3 4 5 4 99 22
test more this and that
重新引入变体“value_type”:
<强> Live On Coliru 强>
#include <iostream>
#include <boost/fusion/adapted.hpp>
#include <boost/spirit/home/x3.hpp>
namespace Target {
struct Int { int int_val; };
struct Word { std::string word_val; };
using IntVect = std::vector<Int>;
using WordVect = std::vector<Word>;
struct All {
IntVect int_vect;
WordVect word_vect;
};
}
BOOST_FUSION_ADAPT_STRUCT(Target::Int, int_val)
BOOST_FUSION_ADAPT_STRUCT(Target::Word, word_val)
std::ostream& operator << (std::ostream& o, const Target::Int& in) { o << in.int_val; return o; }
std::ostream& operator << (std::ostream& o, const Target::Word& in) { o << in.word_val; return o; }
std::ostream& operator << (std::ostream& o, const Target::IntVect& in) { for( auto& i : in ) o << i << " "; return o; }
std::ostream& operator << (std::ostream& o, const Target::WordVect& in) { for (auto& i : in) o << i << " "; return o; }
namespace boost { namespace spirit { namespace x3 { namespace traits {
template<>
struct container_value<Target::All> {
using type = boost::variant<Target::IntVect, Target::WordVect>;
};
template<>
struct push_back_container<Target::All> {
template <typename V>
static bool call(Target::All& c, V&& v) {
struct {
Target::All& _r;
void operator()(Target::IntVect const&v) const { _r.int_vect.insert(_r.int_vect.end(), v.begin(), v.end()); }
void operator()(Target::WordVect const&v) const { _r.word_vect.insert(_r.word_vect.end(), v.begin(), v.end()); }
} vis {c};
boost::apply_visitor(vis, v);
return true;
}
};
} } } }
namespace x3 = boost::spirit::x3;
namespace Target {
using namespace x3;
static auto const int_rule = rule<struct Int_def, Int>("int_rule") = int_;
static auto const word_rule = rule<struct Word_def, Word>("word_rule") = lexeme[+char_("a-z")];
static auto const int_vect_rule = "int" >> *int_rule;
static auto const word_vect_rule = "word" >> *(word_rule - "int");
}
int main() {
std::string const thestr("word test more int 1 2 3 4 word this and that int 5 4 int 99 22");
Target::All all;
if (phrase_parse(begin(thestr), end(thestr), *(Target::int_vect_rule | Target::word_vect_rule), x3::space, all)) {
std::cout << "Parsed: \n";
std::cout << all.int_vect << "\n";
std::cout << all.word_vect << "\n";
}
}
打印
Parsed:
1 2 3 4 5 4 99 22
test more this and that