我尝试解析包含以下模式的多行内容:{{some_dynamic_string}}
我尝试按如下方式定义规则,但解析失败了:
token_rule = qi::lit("{{") >> +qi::char_ >> qi::lit("}}");
用于解析的调试输出显示以下内容:
<start_rule>
<try>{{foo|bar}}\n</try>
<token_rule>
<try>{{foo|bar}}\n</try>
<fail/>
</token_rule>
<fail/>
</start_rule>
它试图解析多行内容中的第一行,这恰好包含了模式本身。规则有什么问题?我是否需要从序列中的第二项中排除{{
和}}
?如果是这样,我该怎么做?
答案 0 :(得分:2)
您必须阻止char_
匹配}}
匹配的位置。
最简单的方法:
token_rule = "{{" >> +(qi::char_ - "}}") >> "}}";
带有用于比较的调试信息的完整演示:
<强> Live On Coliru 强>
#define BOOST_SPIRIT_DEBUG
#include <boost/spirit/include/qi.hpp>
namespace qi = boost::spirit::qi;
using string = std::string;
using strings = std::vector<std::string>;
template <typename It>
struct Grammar: qi::grammar<It, strings()>
{
Grammar() : Grammar::base_type(start) {
start = qi::skip(qi::space) [tokens_rule];
tokens_rule = *token_rule;
token_rule = "{{" >> +(qi::char_ - "}}") >> "}}";
BOOST_SPIRIT_DEBUG_NODES((start)(tokens_rule)(token_rule))
}
private:
// implicit lexemes
qi::rule<It, strings()> start;
qi::rule<It, strings(), qi::space_type> tokens_rule;
qi::rule<It, string()> token_rule;
};
int main() {
using It = std::string::const_iterator;
Grammar<It> g;
for (std::string const input : { "{{a}}", " {{a b}} {{more}}\n", "{{a{b} }}" })
{
It f = input.begin(), l = input.end();
strings parsed;
if (parse(f, l, g, parsed)) {
std::cout << "Parsed '" << input << "'\n";
for(auto& tok : parsed)
std::cout << " -- '" << tok << "'\n";
} else {
std::cout << "Parse failed\n";
}
if (f != l)
std::cout << "Remaining unparsed: '" << std::string(f,l) << "'\n";
}
}
打印
Parsed '{{a}}'
-- 'a'
Parsed ' {{a b}} {{more}}
'
-- 'a b'
-- 'more'
Parsed '{{a{b} }}'
-- 'a{b} '
使用调试信息:
<start>
<try>{{a}}</try>
<tokens_rule>
<try>{{a}}</try>
<token_rule>
<try>{{a}}</try>
<success></success>
<attributes>[[a]]</attributes>
</token_rule>
<token_rule>
<try></try>
<fail/>
</token_rule>
<success></success>
<attributes>[[[a]]]</attributes>
</tokens_rule>
<success></success>
<attributes>[[[a]]]</attributes>
</start>
Parsed '{{a}}'
-- 'a'
<start>
<try> {{a b}} {{more}}\n</try>
<tokens_rule>
<try> {{a b}} {{more}}\n</try>
<token_rule>
<try>{{a b}} {{more}}\n</try>
<success> {{more}}\n</success>
<attributes>[[a, , b]]</attributes>
</token_rule>
<token_rule>
<try>{{more}}\n</try>
<success>\n</success>
<attributes>[[m, o, r, e]]</attributes>
</token_rule>
<token_rule>
<try></try>
<fail/>
</token_rule>
<success></success>
<attributes>[[[a, , b], [m, o, r, e]]]</attributes>
</tokens_rule>
<success></success>
<attributes>[[[a, , b], [m, o, r, e]]]</attributes>
</start>
Parsed ' {{a b}} {{more}}
'
-- 'a b'
-- 'more'
<start>
<try>{{a{b} }}</try>
<tokens_rule>
<try>{{a{b} }}</try>
<token_rule>
<try>{{a{b} }}</try>
<success></success>
<attributes>[[a, {, b, }, ]]</attributes>
</token_rule>
<token_rule>
<try></try>
<fail/>
</token_rule>
<success></success>
<attributes>[[[a, {, b, }, ]]]</attributes>
</tokens_rule>
<success></success>
<attributes>[[[a, {, b, }, ]]]</attributes>
</start>
Parsed '{{a{b} }}'
-- 'a{b} '
答案 1 :(得分:1)
我能够使用Qi Confix Parser Directive成功解析该行。
#include <boost/spirit/repository/include/qi_confix.hpp>
namespace qi_repo = boost::spirit::repository;
token_rule = qi_repo::confix("{{", "}}")[+(qi::char_ - "}}")];