我一直在尝试使用 Boost Spirit 解析字符串,如下所示:
integer_count int1 int2 int3 ... intN
其中 N 是整数计数。例如,
5 1 2 3 4 5
代码如下:
#define BOOST_SPIRIT_USE_PHOENIX_V3
#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/phoenix.hpp>
#include <string>
namespace qi = boost::spirit::qi;
namespace spirit = boost::spirit;
namespace ascii = boost::spirit::ascii;
using boost::phoenix::ref;
template <typename Iterator>
struct x_grammar : public qi::grammar<Iterator, std::string(), ascii::space_type>
{
public:
x_grammar() : x_grammar::base_type(start_rule, "x_grammar")
{
using namespace qi;
int repeat_count = 0;
start_rule = int_[ref(repeat_count) = _1] > repeater > *char_;
std::cout << "repeat_count == " << repeat_count << std::endl;
repeater = repeat(repeat_count)[int_[std::cout << _1 << ".\n"]];
}
private:
qi::rule<Iterator, std::string(), ascii::space_type> start_rule;
qi::rule<Iterator, std::string(), ascii::space_type> repeater;
};
int main()
{
typedef std::string::const_iterator iter;
std::string storage("5 1 2 3 4 5 garbage");
iter it_begin(storage.begin());
iter it_end(storage.end());
std::string read_data;
using boost::spirit::ascii::space;
x_grammar<iter> g;
try {
bool r = qi::phrase_parse(it_begin, it_end, g, space, read_data);
if(r) {
std::cout << "Pass!\n";
} else {
std::cout << "Fail!\n";
}
} catch (const qi::expectation_failure<iter>& x) {
std::cout << "Fail!\n";
}
}
输出为:
repeat_count == 0
Pass!
这意味着
ref(repeat_count) = _1
从未被调用过。 那么有没有办法将整数运行时读入局部变量并使用该值进行进一步解析?
最佳答案
我想你的意思是
repeat(boost::phoenix::ref(repeat_count))
此外,当存在语义操作时,规则的自动属性传播将被禁用。您可以使用%=
强制属性传播
这是一个简单的固定版本 Live On Coliru
#define BOOST_SPIRIT_USE_PHOENIX_V3
#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/phoenix.hpp>
#include <string>
namespace qi = boost::spirit::qi;
namespace spirit = boost::spirit;
namespace ascii = boost::spirit::ascii;
using boost::phoenix::ref;
template <typename Iterator>
struct x_grammar : public qi::grammar<Iterator, ascii::space_type>
{
public:
x_grammar() : x_grammar::base_type(start_rule, "x_grammar")
{
using namespace qi;
int repeat_count = 0;
start_rule = int_[ref(repeat_count) = _1] > repeater > *char_;
std::cout << "repeat_count == " << repeat_count << std::endl;
repeater = repeat(ref(repeat_count))[int_[std::cout << _1 << ".\n"]];
}
private:
qi::rule<Iterator, ascii::space_type> start_rule;
qi::rule<Iterator, ascii::space_type> repeater;
};
int main()
{
typedef std::string::const_iterator iter;
std::string storage("5 1 2 3 4 5 garbage");
iter it_begin(storage.begin());
iter it_end(storage.end());
using boost::spirit::ascii::space;
x_grammar<iter> g;
try {
bool r = qi::phrase_parse(it_begin, it_end, g, space);
if(r) {
std::cout << "Pass!\n";
} else {
std::cout << "Fail!\n";
}
} catch (const qi::expectation_failure<iter>& x) {
std::cout << "Fail!\n";
}
}
打印
repeat_count == 0
1.
2.
3.
4.
5.
Pass!
注意显然,repeat_count == 0
是如何始终打印的,因为它是在语法构造期间执行的,而不是解析期间执行的。
关于c++ - 未调用 boost spirit 语义 Action ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23757504/