如何在提升精神业力中将属性传递给子规则
How is it possible to pass attributes to child rules in boost spirit karma
我正在通过 qi 将文本解析为 AST,然后通过 karma 再次生成文本。这按预期工作,但需要某种方法将属性从一个规则传递到另一个规则。
转自评论:
#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/karma.hpp>
#include <boost/fusion/include/adapt_struct.hpp>
#include <boost/fusion/include/adapt_adt.hpp>
#include <fstream>
struct c_struct
{
int value1;
};
struct b_struct
{
std::string value1;
std::vector< c_struct > value2;
};
struct a_struct
{
std::string value1;
std::vector< b_struct > value2;
};
BOOST_FUSION_ADAPT_STRUCT( c_struct,
(int, value1)
)
BOOST_FUSION_ADAPT_STRUCT( b_struct,
(std::string, value1)
(std::vector< c_struct >, value2)
)
BOOST_FUSION_ADAPT_STRUCT( a_struct,
(std::string, value1)
(std::vector< b_struct >, value2)
)
using namespace boost::spirit;
using namespace boost::spirit::qi;
using namespace boost::spirit::karma;
using namespace boost::spirit::ascii;
template <typename Iterator>
struct grammarB : karma::grammar<Iterator, a_struct()>
{
grammarB() : grammarB::base_type(ruleA)
{
ruleA %= karma::string << karma::lit(' ') << +ruleB << eps;
ruleB %= karma::string << +ruleC << karma::lit(' ') << eps;
ruleC %= lit(" -> ") << karma::int_;
}
karma::rule<Iterator, a_struct()> ruleA;
karma::rule<Iterator, b_struct()> ruleB;
karma::rule<Iterator, c_struct()> ruleC;
};
template <typename Iterator>
struct grammarA : qi::grammar<Iterator, a_struct(), boost::spirit::ascii::space_type>
{
grammarA() : grammarA::base_type(ruleA)
{
ruleA %= ruleString >> omit[+qi::char_('.')] >> +ruleB;
ruleB %= ruleString >> omit[qi::char_(',')] >> (ruleC % qi::char_(',')) >> omit[qi::char_(';')];
ruleC %= qi::int_;
ruleString %= +qi::char_("a-z");
}
qi::rule<Iterator, a_struct(), boost::spirit::ascii::space_type> ruleA;
qi::rule<Iterator, b_struct(), boost::spirit::ascii::space_type> ruleB;
qi::rule<Iterator, c_struct(), boost::spirit::ascii::space_type> ruleC;
qi::rule<Iterator, std::string(), boost::spirit::ascii::space_type> ruleString;
};
int main(int argc, char **argv)
{
std::string storage("parent ... whee,4,5,6;ahhhh,5,6;"); // We will read the contents here.
typedef grammarA<std::string::const_iterator> grammarA_t;
grammarA_t grammar;
a_struct ast;
std::string::const_iterator iter = storage.begin();
std::string::const_iterator end = storage.end();
bool r = phrase_parse(iter, end, grammar, boost::spirit::ascii::space, ast);
if (r && iter == end)
{
std::cout << "Parsing succeeded" << std::endl;
typedef std::back_insert_iterator<std::string> output_iterator_type;
std::string generated;
output_iterator_type sink(generated);
typedef grammarB<output_iterator_type> grammarB_t;
grammarB_t generator;
if ( generate(sink, generator, ast) )
std::cout << generated << std::endl;
else
std::cout << "fail" << std::endl;
}
return 0;
}
它打印
Parsing succeeded
parent whee -> 4 -> 5 -> 6 ahhhh -> 5 -> 6
但我更喜欢打印出来
Parsing succeeded
parent parent whee -> parent 4 -> parent 5 -> parent 6 ahhhh -> parent 5 -> parent 6
这可能吗?如何实现?
好的。输出样本 "parent parent whee -> parent 4 -> parent 5 -> parent 6 ahhhh -> parent 5 -> parent 6"
实际上/几乎/清楚了。
我认为存在不一致,因为 要么 你会期望
parent parent whee -> parent 4 -> parent 5 -> parent 6 parent ahhhh -> parent 5 -> parent 6
或你会期望
parent whee -> parent 4 -> parent 5 -> parent 6 ahhhh -> parent 5 -> parent 6
我会告诉你们两个。
ruleA %= string [ _pass_along = _1 ] << +ruleB(_pass_along);
ruleB = string << +ruleC(_inherited);
//ruleB = lit(_inherited) << string << +ruleC(_inherited); // alternative interpretation
ruleC = "->" << lit(_inherited) << karma::int_;
这同时使用了 karma::locals<>
and inherited attributes.
备注:
- 我已经简化了 Qi 和 Karma 规则
- 支持 Karma 规则中的分隔符
- 在 Qi 规则中适当使用
lexeme
(Boost spirit skipper issues)
- 如果你不想合成属性,请使用
lit("x")
而不是 string("x")
- 删除
lit()
除非选择非精神域表达式模板运算符重载
- 使用
BOOST_SPIRIT_DEBUG_NODES
- 不要不要混合
using namespace
。没必要,会出事。
//#define BOOST_SPIRIT_DEBUG
#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/karma.hpp>
#include <boost/spirit/include/phoenix.hpp>
#include <boost/fusion/adapted.hpp>
#include <iostream>
#include <fstream>
struct c_struct {
int value1;
};
struct b_struct {
std::string value1;
std::vector<c_struct> value2;
};
struct a_struct {
std::string value1;
std::vector<b_struct> value2;
};
BOOST_FUSION_ADAPT_STRUCT(c_struct, (int, value1))
BOOST_FUSION_ADAPT_STRUCT(b_struct, (std::string, value1)(std::vector<c_struct>, value2))
BOOST_FUSION_ADAPT_STRUCT(a_struct, (std::string, value1)(std::vector<b_struct>, value2))
namespace qi = boost::spirit::qi;
namespace karma = boost::spirit::karma;
namespace ascii = boost::spirit::ascii;
template <typename Iterator> struct generator : karma::grammar<Iterator, a_struct(), karma::space_type> {
generator() : generator::base_type(start) {
using namespace karma;
_a_type _pass_along;
_r1_type _inherited;
start = ruleA;
ruleA %= string [ _pass_along = _1 ] << +ruleB(_pass_along);
ruleB = string << +ruleC(_inherited);
//ruleB = lit(_inherited) << string << +ruleC(_inherited); // alternative interpretation
ruleC = "->" << lit(_inherited) << karma::int_;
BOOST_SPIRIT_DEBUG_NODES((start)(ruleA)(ruleB)(ruleC))
}
karma::rule<Iterator, a_struct(), karma::space_type> start;
karma::rule<Iterator, a_struct(), qi::locals<std::string>, karma::space_type> ruleA;
karma::rule<Iterator, b_struct(std::string const&), karma::space_type> ruleB;
karma::rule<Iterator, c_struct(std::string const&), karma::space_type> ruleC;
};
template <typename Iterator> struct grammar : qi::grammar<Iterator, a_struct(), boost::spirit::ascii::space_type> {
grammar() : grammar::base_type(ruleA) {
using namespace qi;
ruleA = ruleString >> lexeme[+qi::lit('.')] >> +ruleB;
ruleB = ruleString >> ',' >> (ruleC % ',') >> ';';
ruleC = qi::int_;
ruleString = +qi::char_("a-z");
BOOST_SPIRIT_DEBUG_NODES((ruleA)(ruleB)(ruleC)(ruleString))
}
qi::rule<Iterator, a_struct(), boost::spirit::ascii::space_type> ruleA;
qi::rule<Iterator, b_struct(), boost::spirit::ascii::space_type> ruleB;
qi::rule<Iterator, c_struct(), boost::spirit::ascii::space_type> ruleC;
qi::rule<Iterator, std::string()/*, boost::spirit::ascii::space_type*/> ruleString;
};
int main() {
typedef std::string::const_iterator It;
std::string const storage("parent ... whee,4,5,6;ahhhh,5,6;"); // We will read the contents here.
grammar<It> grammar;
a_struct ast;
It iter = storage.begin(), end = storage.end();
bool r = phrase_parse(iter, end, grammar, ascii::space, ast);
if (r && iter == end) {
std::cout << "Parsing succeeded" << std::endl;
generator<boost::spirit::ostream_iterator> generator;
std::cout << "'parent whee -> 4 -> 5 -> 6 ahhhh -> 5 -> 6 ' // ORIGINAL\n";
std::cout << "'parent parent whee -> parent 4 -> parent 5 -> parent 6 ahhhh -> parent 5 -> parent 6 ' // DESIRED/EXPECTED\n";
std::cout << "'" << karma::format_delimited(generator, karma::space, ast) << "' // ACTUAL\n";
}
}
输出:
Parsing succeeded
'parent whee -> 4 -> 5 -> 6 ahhhh -> 5 -> 6 ' // ORIGINAL
'parent parent whee -> parent 4 -> parent 5 -> parent 6 ahhhh -> parent 5 -> parent 6 ' // DESIRED/EXPECTED
'parent whee -> parent 4 -> parent 5 -> parent 6 ahhhh -> parent 5 -> parent 6 ' // ACTUAL
如果您取消注释备用 ruleB
生成器:
输出:
Parsing succeeded
'parent whee -> 4 -> 5 -> 6 ahhhh -> 5 -> 6 ' // ORIGINAL
'parent parent whee -> parent 4 -> parent 5 -> parent 6 ahhhh -> parent 5 -> parent 6 ' // DESIRED/EXPECTED
'parent parent whee -> parent 4 -> parent 5 -> parent 6 parent ahhhh -> parent 5 -> parent 6 ' // ACTUAL
我正在通过 qi 将文本解析为 AST,然后通过 karma 再次生成文本。这按预期工作,但需要某种方法将属性从一个规则传递到另一个规则。
转自评论:
#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/karma.hpp>
#include <boost/fusion/include/adapt_struct.hpp>
#include <boost/fusion/include/adapt_adt.hpp>
#include <fstream>
struct c_struct
{
int value1;
};
struct b_struct
{
std::string value1;
std::vector< c_struct > value2;
};
struct a_struct
{
std::string value1;
std::vector< b_struct > value2;
};
BOOST_FUSION_ADAPT_STRUCT( c_struct,
(int, value1)
)
BOOST_FUSION_ADAPT_STRUCT( b_struct,
(std::string, value1)
(std::vector< c_struct >, value2)
)
BOOST_FUSION_ADAPT_STRUCT( a_struct,
(std::string, value1)
(std::vector< b_struct >, value2)
)
using namespace boost::spirit;
using namespace boost::spirit::qi;
using namespace boost::spirit::karma;
using namespace boost::spirit::ascii;
template <typename Iterator>
struct grammarB : karma::grammar<Iterator, a_struct()>
{
grammarB() : grammarB::base_type(ruleA)
{
ruleA %= karma::string << karma::lit(' ') << +ruleB << eps;
ruleB %= karma::string << +ruleC << karma::lit(' ') << eps;
ruleC %= lit(" -> ") << karma::int_;
}
karma::rule<Iterator, a_struct()> ruleA;
karma::rule<Iterator, b_struct()> ruleB;
karma::rule<Iterator, c_struct()> ruleC;
};
template <typename Iterator>
struct grammarA : qi::grammar<Iterator, a_struct(), boost::spirit::ascii::space_type>
{
grammarA() : grammarA::base_type(ruleA)
{
ruleA %= ruleString >> omit[+qi::char_('.')] >> +ruleB;
ruleB %= ruleString >> omit[qi::char_(',')] >> (ruleC % qi::char_(',')) >> omit[qi::char_(';')];
ruleC %= qi::int_;
ruleString %= +qi::char_("a-z");
}
qi::rule<Iterator, a_struct(), boost::spirit::ascii::space_type> ruleA;
qi::rule<Iterator, b_struct(), boost::spirit::ascii::space_type> ruleB;
qi::rule<Iterator, c_struct(), boost::spirit::ascii::space_type> ruleC;
qi::rule<Iterator, std::string(), boost::spirit::ascii::space_type> ruleString;
};
int main(int argc, char **argv)
{
std::string storage("parent ... whee,4,5,6;ahhhh,5,6;"); // We will read the contents here.
typedef grammarA<std::string::const_iterator> grammarA_t;
grammarA_t grammar;
a_struct ast;
std::string::const_iterator iter = storage.begin();
std::string::const_iterator end = storage.end();
bool r = phrase_parse(iter, end, grammar, boost::spirit::ascii::space, ast);
if (r && iter == end)
{
std::cout << "Parsing succeeded" << std::endl;
typedef std::back_insert_iterator<std::string> output_iterator_type;
std::string generated;
output_iterator_type sink(generated);
typedef grammarB<output_iterator_type> grammarB_t;
grammarB_t generator;
if ( generate(sink, generator, ast) )
std::cout << generated << std::endl;
else
std::cout << "fail" << std::endl;
}
return 0;
}
它打印
Parsing succeeded
parent whee -> 4 -> 5 -> 6 ahhhh -> 5 -> 6
但我更喜欢打印出来
Parsing succeeded
parent parent whee -> parent 4 -> parent 5 -> parent 6 ahhhh -> parent 5 -> parent 6
这可能吗?如何实现?
好的。输出样本 "parent parent whee -> parent 4 -> parent 5 -> parent 6 ahhhh -> parent 5 -> parent 6"
实际上/几乎/清楚了。
我认为存在不一致,因为 要么 你会期望
parent parent whee -> parent 4 -> parent 5 -> parent 6 parent ahhhh -> parent 5 -> parent 6
或你会期望
parent whee -> parent 4 -> parent 5 -> parent 6 ahhhh -> parent 5 -> parent 6
我会告诉你们两个。
ruleA %= string [ _pass_along = _1 ] << +ruleB(_pass_along);
ruleB = string << +ruleC(_inherited);
//ruleB = lit(_inherited) << string << +ruleC(_inherited); // alternative interpretation
ruleC = "->" << lit(_inherited) << karma::int_;
这同时使用了 karma::locals<>
and inherited attributes.
备注:
- 我已经简化了 Qi 和 Karma 规则
- 支持 Karma 规则中的分隔符
- 在 Qi 规则中适当使用
lexeme
(Boost spirit skipper issues) - 如果你不想合成属性,请使用
lit("x")
而不是string("x")
- 删除
lit()
除非选择非精神域表达式模板运算符重载 - 使用
BOOST_SPIRIT_DEBUG_NODES
- 不要不要混合
using namespace
。没必要,会出事。
//#define BOOST_SPIRIT_DEBUG
#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/karma.hpp>
#include <boost/spirit/include/phoenix.hpp>
#include <boost/fusion/adapted.hpp>
#include <iostream>
#include <fstream>
struct c_struct {
int value1;
};
struct b_struct {
std::string value1;
std::vector<c_struct> value2;
};
struct a_struct {
std::string value1;
std::vector<b_struct> value2;
};
BOOST_FUSION_ADAPT_STRUCT(c_struct, (int, value1))
BOOST_FUSION_ADAPT_STRUCT(b_struct, (std::string, value1)(std::vector<c_struct>, value2))
BOOST_FUSION_ADAPT_STRUCT(a_struct, (std::string, value1)(std::vector<b_struct>, value2))
namespace qi = boost::spirit::qi;
namespace karma = boost::spirit::karma;
namespace ascii = boost::spirit::ascii;
template <typename Iterator> struct generator : karma::grammar<Iterator, a_struct(), karma::space_type> {
generator() : generator::base_type(start) {
using namespace karma;
_a_type _pass_along;
_r1_type _inherited;
start = ruleA;
ruleA %= string [ _pass_along = _1 ] << +ruleB(_pass_along);
ruleB = string << +ruleC(_inherited);
//ruleB = lit(_inherited) << string << +ruleC(_inherited); // alternative interpretation
ruleC = "->" << lit(_inherited) << karma::int_;
BOOST_SPIRIT_DEBUG_NODES((start)(ruleA)(ruleB)(ruleC))
}
karma::rule<Iterator, a_struct(), karma::space_type> start;
karma::rule<Iterator, a_struct(), qi::locals<std::string>, karma::space_type> ruleA;
karma::rule<Iterator, b_struct(std::string const&), karma::space_type> ruleB;
karma::rule<Iterator, c_struct(std::string const&), karma::space_type> ruleC;
};
template <typename Iterator> struct grammar : qi::grammar<Iterator, a_struct(), boost::spirit::ascii::space_type> {
grammar() : grammar::base_type(ruleA) {
using namespace qi;
ruleA = ruleString >> lexeme[+qi::lit('.')] >> +ruleB;
ruleB = ruleString >> ',' >> (ruleC % ',') >> ';';
ruleC = qi::int_;
ruleString = +qi::char_("a-z");
BOOST_SPIRIT_DEBUG_NODES((ruleA)(ruleB)(ruleC)(ruleString))
}
qi::rule<Iterator, a_struct(), boost::spirit::ascii::space_type> ruleA;
qi::rule<Iterator, b_struct(), boost::spirit::ascii::space_type> ruleB;
qi::rule<Iterator, c_struct(), boost::spirit::ascii::space_type> ruleC;
qi::rule<Iterator, std::string()/*, boost::spirit::ascii::space_type*/> ruleString;
};
int main() {
typedef std::string::const_iterator It;
std::string const storage("parent ... whee,4,5,6;ahhhh,5,6;"); // We will read the contents here.
grammar<It> grammar;
a_struct ast;
It iter = storage.begin(), end = storage.end();
bool r = phrase_parse(iter, end, grammar, ascii::space, ast);
if (r && iter == end) {
std::cout << "Parsing succeeded" << std::endl;
generator<boost::spirit::ostream_iterator> generator;
std::cout << "'parent whee -> 4 -> 5 -> 6 ahhhh -> 5 -> 6 ' // ORIGINAL\n";
std::cout << "'parent parent whee -> parent 4 -> parent 5 -> parent 6 ahhhh -> parent 5 -> parent 6 ' // DESIRED/EXPECTED\n";
std::cout << "'" << karma::format_delimited(generator, karma::space, ast) << "' // ACTUAL\n";
}
}
输出:
Parsing succeeded
'parent whee -> 4 -> 5 -> 6 ahhhh -> 5 -> 6 ' // ORIGINAL
'parent parent whee -> parent 4 -> parent 5 -> parent 6 ahhhh -> parent 5 -> parent 6 ' // DESIRED/EXPECTED
'parent whee -> parent 4 -> parent 5 -> parent 6 ahhhh -> parent 5 -> parent 6 ' // ACTUAL
如果您取消注释备用 ruleB
生成器:
输出:
Parsing succeeded
'parent whee -> 4 -> 5 -> 6 ahhhh -> 5 -> 6 ' // ORIGINAL
'parent parent whee -> parent 4 -> parent 5 -> parent 6 ahhhh -> parent 5 -> parent 6 ' // DESIRED/EXPECTED
'parent parent whee -> parent 4 -> parent 5 -> parent 6 parent ahhhh -> parent 5 -> parent 6 ' // ACTUAL