使用凤凰绑定到结构的提升精神规则 - 编译失败
boost spirit rule with phoenix bind to structure - compile failure
我想解析以下字符串:id=1;entry1=[A,B,D];entry2=[bla,blubb];factor=[1,5]!
我的解析器:
struct Entry
{
uint32_t id;
std::vector< std::string > entry1;
std::vector< std::string > entry2;
bool useFactor;
std::pair<int, int> factor;
};
BOOST_FUSION_ADAPT_STRUCT( Entry, id, entry1, entry2, useFactor, factor)
template<typename It>
struct testParser : qi::grammar<It, Entry()>
{
testParser : testParser::base_type(start)
{
using namespace qi;
id_ %= lit("id=") >> int_ ;
entry1_ %= lit("entry1=") >> char_('[') >> +(char_ -char_(']') % ',') >> char_(']');
entry2_ %= lit("entry1=") >> char_('[') >> +(char_ -char_(']') % ',') >> char_(']');
factor %= lit("factor=") >> char_('[') >> int_ >> char_(',') >> int_ >> char_(']');
start = id >> ';' >> entry1 >> ';' >> entry2 >> (( ';' >> factor[ phx::bind(&Entry::useFactor,_1) = true;] ) >> '!') | '!';
qi::rule<It, Entry()> start;
qi::rule<It, int()> id;
qi::rule<It, std::vector<std::string>()> entry1_, entry2_;
qi::rule<It, std::pair<int,int>()> factor;
}
};
我收到非常大的编译错误消息。我认为这是因为 entry1 和 entry2 规则(字符串插入向量)
正如您在直播中看到的那样,我逐步修正了语法。
其中有相当多的 "are-you-drunk" 时刻,所以我不确定我是否能够在这里抓住散文的基本步骤。一定要a look at the recorded stream¹.
一些重要的注释(忽略随机错别字和明显混淆的代码):
- 使用
attr(v)
来简单地公开一个属性(如本例中的 attr(true)
)
- 使用
lit('c')
、lit("abc")
或仅'c'
和"abc"
来匹配文字字符(字符串)没有捕获他们的内容
- 仅在存在语义动作时使用
%=
语义 运行s after 它的主题解析器成功了(只有 iff 它成功了) .
因此,即使您 should/should 从语义操作中设置了 useFactor
成员,如果 factor
部分存在(并且否则将留下不确定的值)。
格式化很重要。
- 调试很重要。
可选:
- 使用
BOOST_SPIRIT_DEBUG*
调试规则
- 使用
as_vector
破解快速打印结果的方法
- 我已经展示了使用 inherited arguments 的技术,因此您可以将
entry
规则重复用于 entry1
和 entry2
未显示:
- 使用 skipper 来防止空格不敏感
- 将
no_case
用于...不区分大小写
- 使用船长:注意
lexeme
以避免在跳过的输入字符中匹配关键字
工作代码,作为SSCCE:
#define BOOST_SPIRIT_DEBUG
#include <iostream>
#include <vector>
namespace std {
template <typename T>
static ostream& operator<<(ostream& os, vector<T> const& v) {
os << "vector{ ";
for(auto& e : v)
os << "'" << e << "', ";
return os << "}";
}
template <typename T, typename U>
static ostream& operator<<(ostream& os, pair<T,U> const& p) {
return os << "pair{ '" << p.first << "', '" << p.second << "' }";
}
}
#include <boost/fusion/adapted/struct.hpp>
#include <boost/fusion/adapted/std_pair.hpp>
#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/phoenix.hpp>
namespace qi = boost::spirit::qi;
namespace phx = boost::phoenix;
struct Entry
{
uint32_t id;
std::vector<std::string> entry1;
std::vector<std::string> entry2;
bool useFactor;
std::pair<int, int> factor;
};
BOOST_FUSION_ADAPT_STRUCT(Entry, id, entry1, entry2, useFactor, factor)
template<typename It>
struct testParser : qi::grammar<It, Entry()>
{
testParser() : testParser::base_type(start)
{
using namespace qi;
id = "id=" >> int_;
entry = lit(_r1) >> ('[' >> +~char_("],") % ',' >> ']');
factor = "factor=" >> ('[' >> int_ >> ',' >> int_ >> ']');
start =
id >> ';'
>> entry(+"entry1=") >> ';'
>> entry(+"entry2=") >> ';'
>> attr(true)
>> (factor | attr(std::pair<int,int>{1,1}))
>> '!';
BOOST_SPIRIT_DEBUG_NODES((start)(entry)(id)(factor))
#if 0
#endif
}
private:
qi::rule<It, Entry()> start;
qi::rule<It, int()> id;
qi::rule<It, std::vector<std::string>(std::string)> entry;
qi::rule<It, std::pair<int,int>()> factor;
};
int main() {
std::string const input = "id=1;entry1=[A,B,D];entry2=[bla,blubb];factor=[1,5]!";
using It = std::string::const_iterator;
testParser<It> g;
It f = input.begin(), l = input.end();
Entry entry;
bool ok = qi::parse(f, l, g, entry);
std::cout << std::boolalpha;
if (ok) {
std::cout << "Parsed: " << boost::fusion::as_vector(entry) << "\n";
} else {
std::cout << "Parse failed\n";
}
if (f!=l)
std::cout << "Remaining unparsed: '" << std::string(f,l) << "'\n";
}
打印:
<start>
<try>id=1;entry1=[A,B,D];</try>
<id>
<try>id=1;entry1=[A,B,D];</try>
<success>;entry1=[A,B,D];entr</success>
<attributes>[1]</attributes>
</id>
<entry>
<try>entry1=[A,B,D];entry</try>
<success>;entry2=[bla,blubb];</success>
<attributes>[[[A], [B], [D]], [e, n, t, r, y, 1, =]]</attributes>
</entry>
<entry>
<try>entry2=[bla,blubb];f</try>
<success>;factor=[1,5]!</success>
<attributes>[[[b, l, a], [b, l, u, b, b]], [e, n, t, r, y, 2, =]]</attributes>
</entry>
<factor>
<try>factor=[1,5]!</try>
<success>!</success>
<attributes>[[1, 5]]</attributes>
</factor>
<success></success>
<attributes>[[1, [[A], [B], [D]], [[b, l, a], [b, l, u, b, b]], 1, [1, 5]]]</attributes>
</start>
Parsed: (1 vector{ 'A', 'B', 'D', } vector{ 'bla', 'blubb', } true pair{ '1', '5' })
¹(我错过了修复 headers、平衡括号和向构造函数添加 parens 等的第一部分……o.O)。
我想解析以下字符串:id=1;entry1=[A,B,D];entry2=[bla,blubb];factor=[1,5]!
我的解析器:
struct Entry
{
uint32_t id;
std::vector< std::string > entry1;
std::vector< std::string > entry2;
bool useFactor;
std::pair<int, int> factor;
};
BOOST_FUSION_ADAPT_STRUCT( Entry, id, entry1, entry2, useFactor, factor)
template<typename It>
struct testParser : qi::grammar<It, Entry()>
{
testParser : testParser::base_type(start)
{
using namespace qi;
id_ %= lit("id=") >> int_ ;
entry1_ %= lit("entry1=") >> char_('[') >> +(char_ -char_(']') % ',') >> char_(']');
entry2_ %= lit("entry1=") >> char_('[') >> +(char_ -char_(']') % ',') >> char_(']');
factor %= lit("factor=") >> char_('[') >> int_ >> char_(',') >> int_ >> char_(']');
start = id >> ';' >> entry1 >> ';' >> entry2 >> (( ';' >> factor[ phx::bind(&Entry::useFactor,_1) = true;] ) >> '!') | '!';
qi::rule<It, Entry()> start;
qi::rule<It, int()> id;
qi::rule<It, std::vector<std::string>()> entry1_, entry2_;
qi::rule<It, std::pair<int,int>()> factor;
}
};
我收到非常大的编译错误消息。我认为这是因为 entry1 和 entry2 规则(字符串插入向量)
正如您在直播中看到的那样,我逐步修正了语法。
其中有相当多的 "are-you-drunk" 时刻,所以我不确定我是否能够在这里抓住散文的基本步骤。一定要a look at the recorded stream¹.
一些重要的注释(忽略随机错别字和明显混淆的代码):
- 使用
attr(v)
来简单地公开一个属性(如本例中的attr(true)
) - 使用
lit('c')
、lit("abc")
或仅'c'
和"abc"
来匹配文字字符(字符串)没有捕获他们的内容 - 仅在存在语义动作时使用
%=
语义 运行s after 它的主题解析器成功了(只有 iff 它成功了) .
因此,即使您 should/should 从语义操作中设置了
useFactor
成员,如果factor
部分存在(并且否则将留下不确定的值)。格式化很重要。
- 调试很重要。
可选:
- 使用
BOOST_SPIRIT_DEBUG*
调试规则 - 使用
as_vector
破解快速打印结果的方法 - 我已经展示了使用 inherited arguments 的技术,因此您可以将
entry
规则重复用于entry1
和entry2
未显示:
- 使用 skipper 来防止空格不敏感
- 将
no_case
用于...不区分大小写 - 使用船长:注意
lexeme
以避免在跳过的输入字符中匹配关键字
工作代码,作为SSCCE:
#define BOOST_SPIRIT_DEBUG
#include <iostream>
#include <vector>
namespace std {
template <typename T>
static ostream& operator<<(ostream& os, vector<T> const& v) {
os << "vector{ ";
for(auto& e : v)
os << "'" << e << "', ";
return os << "}";
}
template <typename T, typename U>
static ostream& operator<<(ostream& os, pair<T,U> const& p) {
return os << "pair{ '" << p.first << "', '" << p.second << "' }";
}
}
#include <boost/fusion/adapted/struct.hpp>
#include <boost/fusion/adapted/std_pair.hpp>
#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/phoenix.hpp>
namespace qi = boost::spirit::qi;
namespace phx = boost::phoenix;
struct Entry
{
uint32_t id;
std::vector<std::string> entry1;
std::vector<std::string> entry2;
bool useFactor;
std::pair<int, int> factor;
};
BOOST_FUSION_ADAPT_STRUCT(Entry, id, entry1, entry2, useFactor, factor)
template<typename It>
struct testParser : qi::grammar<It, Entry()>
{
testParser() : testParser::base_type(start)
{
using namespace qi;
id = "id=" >> int_;
entry = lit(_r1) >> ('[' >> +~char_("],") % ',' >> ']');
factor = "factor=" >> ('[' >> int_ >> ',' >> int_ >> ']');
start =
id >> ';'
>> entry(+"entry1=") >> ';'
>> entry(+"entry2=") >> ';'
>> attr(true)
>> (factor | attr(std::pair<int,int>{1,1}))
>> '!';
BOOST_SPIRIT_DEBUG_NODES((start)(entry)(id)(factor))
#if 0
#endif
}
private:
qi::rule<It, Entry()> start;
qi::rule<It, int()> id;
qi::rule<It, std::vector<std::string>(std::string)> entry;
qi::rule<It, std::pair<int,int>()> factor;
};
int main() {
std::string const input = "id=1;entry1=[A,B,D];entry2=[bla,blubb];factor=[1,5]!";
using It = std::string::const_iterator;
testParser<It> g;
It f = input.begin(), l = input.end();
Entry entry;
bool ok = qi::parse(f, l, g, entry);
std::cout << std::boolalpha;
if (ok) {
std::cout << "Parsed: " << boost::fusion::as_vector(entry) << "\n";
} else {
std::cout << "Parse failed\n";
}
if (f!=l)
std::cout << "Remaining unparsed: '" << std::string(f,l) << "'\n";
}
打印:
<start>
<try>id=1;entry1=[A,B,D];</try>
<id>
<try>id=1;entry1=[A,B,D];</try>
<success>;entry1=[A,B,D];entr</success>
<attributes>[1]</attributes>
</id>
<entry>
<try>entry1=[A,B,D];entry</try>
<success>;entry2=[bla,blubb];</success>
<attributes>[[[A], [B], [D]], [e, n, t, r, y, 1, =]]</attributes>
</entry>
<entry>
<try>entry2=[bla,blubb];f</try>
<success>;factor=[1,5]!</success>
<attributes>[[[b, l, a], [b, l, u, b, b]], [e, n, t, r, y, 2, =]]</attributes>
</entry>
<factor>
<try>factor=[1,5]!</try>
<success>!</success>
<attributes>[[1, 5]]</attributes>
</factor>
<success></success>
<attributes>[[1, [[A], [B], [D]], [[b, l, a], [b, l, u, b, b]], 1, [1, 5]]]</attributes>
</start>
Parsed: (1 vector{ 'A', 'B', 'D', } vector{ 'bla', 'blubb', } true pair{ '1', '5' })
¹(我错过了修复 headers、平衡括号和向构造函数添加 parens 等的第一部分……o.O)。