【发布时间】:2011-07-23 01:59:02
【问题描述】:
我正在尝试设置一个解析器,给定一个值,它可以将它分配给向量的某个元素,但我不完全确定如何实现它。
假设以下代码解析字符串(0){**+*+}。它应该为每个+ 增加一次bar.a[0],为每个* 增加一次bar.b[0]。我遇到的问题是我不确定如何使用_a 获取对向量元素的引用:
#include <boost/spirit/include/qi.hpp>
#include <boost/fusion/include/adapt_struct.hpp>
#include <boost/spirit/include/phoenix_fusion.hpp>
#include <boost/spirit/include/phoenix_operator.hpp>
#include <vector>
//The struct containing the vector.
struct testStruct {
std::vector<int> a, b;
};
BOOST_FUSION_ADAPT_STRUCT (
testStruct,
(std::vector<int>, a)
(std::vector<int>, b)
)
namespace qi = boost::spirit::qi;
namespace phoenix = boost::phoenix;
namespace ascii = boost::spirit::ascii;
template<typename Iterator>
struct foo : qi::grammar<Iterator, testStruct(), qi::locals<unsigned>, ascii::space_type> {
foo() : foo::base_type(start) {
using namespace qi::labels;
using qi::eps;
using qi::lit;
using qi::uint_;
using phoenix::at_c;
start = lit('(')
>> uint_ [_a = _1]
>> ')'
>> '{'
>> starsOrPlus(
at_c<_a>(at_c<0>(_val)), //This is where I'm not sure what to do.
at_c<_a>(at_c<1>(_val))
)
>> '}'
;
starsOrPlus = eps [_r1 = 0]
[_r2 = 0]
>> (
* (
(
+lit('+') [_r1 += 1]
)
^ (
+lit('*') [_r2 += 1]
)
)
)
;
}
qi::rule<Iterator, testStruct(), qi::locals<unsigned>, ascii::space_type> start;
//Parses stars and pluses. Sets the first uint8_t to the number of *, and the
//second to the number of +.
qi::rule<Iterator, void(int&, int&), ascii::space_type> starsOrPlus;
};
//Main program
int main() {
std::string testString = "(2){**++*+}";
typedef foo<std::string::const_iterator> foo;
foo grammar;
testStruct bar;
std::string::const_iterator iter = testString.begin();
std::string::const_iterator end = testString.end();
bool parsed = phrase_parse(iter, end, grammar, ascii::space, bar);
if (parsed) {
//Do something with the data...
}
return 0;
}
编译失败,出现以下错误:
main.cpp||In constructor 'foo<Iterator>::foo()':|
main.cpp|36|error: 'boost::spirit::_a' cannot appear in a constant-expression|
main.cpp|36|error: no matching function for call to 'at_c(boost::phoenix::actor<boost::phoenix::composite<boost::phoenix::at_eval<0>, boost::fusion::vector<boost::spirit::attribute<0>, boost::fusion::void_, boost::fusion::void_, boost::fusion::void_, boost::fusion::void_, boost::fusion::void_, boost::fusion::void_, boost::fusion::void_, boost::fusion::void_, boost::fusion::void_> > >&)'|
main.cpp|37|error: 'boost::spirit::_a' cannot appear in a constant-expression|
main.cpp|37|error: no matching function for call to 'at_c(boost::phoenix::actor<boost::phoenix::composite<boost::phoenix::at_eval<1>, boost::fusion::vector<boost::spirit::attribute<0>, boost::fusion::void_, boost::fusion::void_, boost::fusion::void_, boost::fusion::void_, boost::fusion::void_, boost::fusion::void_, boost::fusion::void_, boost::fusion::void_, boost::fusion::void_> > >&)'|
所以,很明显,我不能在at_c 中使用占位符值。我也知道,即使可以,如果给定位置超出范围,也会出现重新调整矢量大小的问题。
我将如何实现这样的事情?我是不是走错了路?
【问题讨论】:
标签: boost boost-spirit boost-spirit-qi