用于解析Spirit Qi中双括号修饰的字符串的规则语法

时间:2017-11-03 23:49:43

标签: c++ boost-spirit boost-spirit-qi

我尝试解析包含以下模式的多行内容:{{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>

它试图解析多行内容中的第一行,这恰好包含了模式本身。规则有什么问题?我是否需要从序列中的第二项中排除{{}}?如果是这样,我该怎么做?

2 个答案:

答案 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_ - "}}")];