【发布时间】:2017-06-07 17:18:46
【问题描述】:
我有一个更复杂的规则,但这个规则足以解决这个问题(我希望如此)。考虑规则:
result = double_ >> *(char_ > int_);
其中 result 是根据命名空间 ast 中的结构结果声明的:
qi::rule<Iterator, ast::result(), qi::space_type> result;
那么ast::result 应该是什么样子的呢?
根据 boost::spirit docs (http://www.boost.org/doc/libs/develop/libs/spirit/doc/html/spirit/abstracts/attributes/compound_attributes.html),属性
char_ > int_ 是 tuple<char, int> 或 std::pair<char, int>。
所以,我尝试了:
namespace ast
{
using second_type = std::vector<std::pair<char, int>>;
struct result
{
double first;
second_type second;
};
} // namespace ast
除了
BOOST_FUSION_ADAPT_STRUCT(
ast::result,
(double, first),
(ast::second_type, second)
)
但这给了我编译错误:
error: no matching function for call to 'std::pair<char, int>::pair(const char&)'
这个规则很简单,创建将存储结果的 AST 结构也应该很简单......但是如何?
这是我尝试的完整测试程序:
#include <boost/config/warning_disable.hpp>
#include <boost/spirit/include/qi.hpp>
#include <boost/fusion/include/adapt_struct.hpp>
#include <iostream>
#include <string>
#include <vector>
namespace ast
{
using second_type = std::vector<std::pair<char, int>>;
struct result
{
double first;
second_type second;
friend std::ostream& operator<<(std::ostream& os, result const& result);
};
std::ostream& operator<<(std::ostream& os, second_type::value_type val)
{
return os << val.first << ' ' << val.second;
}
std::ostream& operator<<(std::ostream& os, result const& result)
{
os << result.first;
for (auto& i : result.second)
os << ' ' << i;
return os;
}
} // namespace ast
BOOST_FUSION_ADAPT_STRUCT(
ast::result,
(double, first),
(ast::second_type, second)
)
namespace client
{
namespace qi = boost::spirit::qi;
namespace ascii = boost::spirit::ascii;
template <typename Iterator>
class test_grammar : public qi::grammar<Iterator, ast::result(), qi::space_type>
{
private:
qi::rule<Iterator, ast::result(), qi::space_type> result;
public:
test_grammar() : test_grammar::base_type(result, "result_grammar")
{
using qi::double_;
using qi::char_;
using qi::int_;
result = double_ >> *(char_ > int_);
}
};
} // namespace client
int main()
{
std::string const input{"3.4 a 5 b 6 c 7"};
using iterator_type = std::string::const_iterator;
using test_grammar = client::test_grammar<iterator_type>;
namespace qi = boost::spirit::qi;
test_grammar program;
iterator_type iter{input.begin()};
iterator_type const end{input.end()};
ast::result out;
bool r = qi::phrase_parse(iter, end, program, qi::space, out);
if (!r || iter != end)
{
std::cerr << "Parsing failed." << std::endl;
return 1;
}
std::cout << "Parsed: " << out << std::endl;
}
【问题讨论】:
标签: c++11 boost-spirit