我正在尝试使用以下语法解析测试结果的日志文件。
template<typename Iterator>
struct test_step_parse: qi::grammar<Iterator, TestResults(), ascii::space_type> {
test_step_parse() : test_step_parse::base_type(rqmts) {
using qi::lit;
using qi::lexeme;
using qi::omit;
using qi::int_;
using qi::eol;
using qi::char_;
test_step = lit("Test Step No.") >> int_;
pass_or_fail = lit("-") >> (string("Passed") | string("Failed"));
fdor_rqmts = -lit("OID")
>> lit("FDOR")
>> -lit("OID")
>> int_
>> *(-omit[char_(",/\\")] >> -(lit("FDOR") ^ lit("OID")) >> int_)
;
sard_rqmts = -lit("OID")
>> lit("SARD")
>> -lit("OID")
>> int_
>> *(-omit[char_(",/\\")] >> -(lit("SARD") ^ -lit("OID")) >> int_)
;
comment = lit("Comment:") >> lexeme[*(char_ - eol)] ;
rqmts = test_step
>> pass_or_fail
>> omit[*(char_ - lit("REQUIREMENT VERIFIED:"))]
>> lit("REQUIREMENT VERIFIED:")
>> (fdor_rqmts ^ sard_rqmts)
>> omit[+char_("=")]
>> -comment
;
BOOST_SPIRIT_DEBUG_NODE(test_step);
BOOST_SPIRIT_DEBUG_NODE(pass_or_fail);
BOOST_SPIRIT_DEBUG_NODE(fdor_rqmts);
BOOST_SPIRIT_DEBUG_NODE(sard_rqmts);
BOOST_SPIRIT_DEBUG_NODE(comment);
BOOST_SPIRIT_DEBUG_NODE(rqmts);
}
qi::rule<Iterator, TestResults(), ascii::space_type> rqmts;
qi::rule<Iterator, int(), ascii::space_type> test_step;
qi::rule<Iterator, std::string(), ascii::space_type> pass_or_fail;
qi::rule<Iterator, std::string(), ascii::space_type> comment;
qi::rule<Iterator, std::vector<int>(), ascii::space_type> fdor_rqmts;
qi::rule<Iterator, std::vector<int>(), ascii::space_type> sard_rqmts;
};
语法解析好了。但是,在尝试自动填充用户定义的结构时,std :: string类型的规则“comment”的属性将作为ascii数字传递给向量。
这是我用户定义的结构:
struct TestResults {
int test_step_no;
std::string pass_or_fail;
std::vector<int> FDOR;
std::vector<int> SARD;
std::string comment;
};
BOOST_FUSION_ADAPT_STRUCT(
atp::TestResults,
(int, test_step_no)
(std::string, pass_or_fail)
(std::vector<int>, FDOR)
(std::vector<int>, SARD)
(std::string, comment)
)
debug out put表示规则暴露了正确的类型,但不知何故它们没有正确放置在结构中。
任何想法我做错了什么?对于任何滥用术语等感到抱歉。
使用gcc 4.6.3和boost 1-47。谢谢。
更新:澄清一下,所以我期待解析以下内容:
std::string test_test =
"Test Step No. 953-Failed\n"
"==============================================================================\n"
"STEP 7.7:\n"
"Test step, etc.\n"
"===============================================================================\n"
"REQUIREMENT VERIFIED: FDOR 12345"
" SARD 12345, 12356\n"
"===============================================================================\n"
"Comment: Didn't work.\n"
;
使用调试器,似乎所有规则都正确地公开了它们的属性:
<rqmts>
<try>Test Step No. 953-Fa</try>
<test_step>
<try>Test Step No. 953-Fa</try>
<success>-Failed\n============</success>
<attributes>[953]</attributes>
</test_step>
<pass_or_fail>
<try>-Failed\n============</try>
<success>\n===================</success>
<attributes>[[F, a, i, l, e, d]]</attributes>
</pass_or_fail>
<fdor_rqmts>
<try> FDOR 12345 </try>
<success> </success>
<attributes>[[12345]]</attributes>
</fdor_rqmts>
<sard_rqmts>
<try> </try>
<success>\n===================</success>
<attributes>[[12345, 12356]]</attributes>
</sard_rqmts>
<comment>
<try>Comment: Didn't work</try>
<success>\n</success>
<attributes>[[D, i, d, n, ', t, , w, o, r, k, .]]</attributes>
</comment>
<success>\n</success>
<attributes>[[953, [F, a, i, l, e, d], [12345], [68, 105, 100, 110, 39, 116, 32, 119, 111, 114, 107, 46], []]]</attributes>
</rqmts>
所以一切似乎都在起作用,只是“comments”属性(std :: string)被填充在“SARD”属性(向量)中,作为ascii数字的向量,即
[68, 105, 100, 110, 39, 116, 32, 119, 111, 114, 107, 46] = "Didn't work."
答案 0 :(得分:2)
问题是解析器(A ^ B)
返回的类型是A类型和B类型的元组,即在您的情况下(fdor_rqmts ^ sard_rqmts)
返回类型boost::tuple<std::vector<int>, std::vector<int> >
。
可以在Boost documentation中找到解析器组合方式的详细信息。
因此,您可以选择修改struct
以解析解析器将返回的类型(这是属性语法的唯一选择)
struct TestResults {
int test_step_no;
std::string pass_or_fail;
boost::tuple<std::vector<int>, std::vector<int> > FdorOrSard;
std::string comment;
};
或指定操作。然后你的语法就会变成:
struct TestResults {
int test_step_no;
std::string pass_or_fail;
std::vector<int> FDOR;
std::vector<int> SARD;
std::string comment;
};
test_step [ at<0>(_val) = _1]
>> pass_or_fail [ at<1>(_val) = _1 ]
>> omit[*(char_ - lit("REQUIREMENT VERIFIED:"))]
>> lit("REQUIREMENT VERIFIED:")
>> (fdor_rqmts [at<2>(_val) = _1 ] ^ sard_rqmts [at<3>(_val) = _1] )
>> omit[+char_("=")]
>> -comment [at<4>(_val) = _1];
这些操作仍然依赖于具有适应的结构,但现在它们明确地描述了如何放置解析的结果。请注意,我们对(A ^ B)
的结果一无所知,而是使用A
结果或B
结果执行某些操作。
作为旁注,我遇到了混淆>
和>>
的问题,其中spirit
决定以有趣的方式嵌套结果 - 我个人发现几乎无法确定事实上返回了什么结构,所以当我无法使基于属性的语法工作时,我倾向于坚持使用动作。在这个问题中有关于此类事情的更多信息:boost::spirit::qi Expectation Parser and parser grouping unexpected behaviour
编辑:我假设你知道行动是如何运作的,以及你需要的包含和使用声明。前两个灵魂解析器教程对此有好处,否则回答任何问题!您可能还必须使用at_c
而不是at
- 我真的无法弄清楚增强凤凰/功能的细节......