指定不解释范围的字符集

Specify a charset without intepreting ranges

当我必须在规则中定义减号时,我对解析字符串感到非常困惑,它只是一个减号字符,而不是两个端点之间的字符范围。

例如,当您编写一个规则来对一串字符进行百分比编码时,您通常会编写

*(bk::char_("a-zA-Z0-9-_.~") | '%' << bk::right_align(2, 0)[bk::upper[bk::hex]]);

通常表示 "letters, capital letters, digits, minus sign, underscore, dot and tilde",但第三个减号会在 9 和下划线之间创建一个范围,因此您必须将减号放在末尾 bk::char_("a-zA-Z0-9_.~-")

它解决了当前的问题,但是当输入是动态的,比如用户输入,而减号只表示减号时,该怎么办?

如何防止 Spirit 为任何可能的字符分配特殊含义?

编辑001: 我求助于来自@sehe

的更具体的例子
void spirit_direct(std::vector<std::string>& result, const std::string& input, char const* delimiter)
{
    result.clear();
    using namespace bsq;
    if(!parse(input.begin(), input.end(), raw[*(char_ - char_(delimiter))] % char_(delimiter), result))
        result.push_back(input);
}

如果您想确保减号被视为减号而不是一个范围,可以按以下方式更改代码(根据下面的@sehe 建议)。

void spirit_direct(std::vector<std::string>& result, const std::string&
    input, char const* delimiter)
{
    result.clear();
    bsq::symbols<char, bsq::unused_type> sym_;
    std::string separators = delimiter;
    for(auto ch : separators)
    {
        sym_.add(std::string(1, ch));
    }
    using namespace bsq;
    if(!parse(input.begin(), input.end(), raw[*(char_ - sym_)] % sym_, result))
        result.push_back(input);
}

看起来很优雅。 在使用静态常量规则的情况下,我想我可以用'\'转义字符,方括号是需要转义的 "special" 字符之一。为什么?的意义是什么 []?是否还有其他字符需要转义?

简单。

您设计并指定用户可以提供其含义的受支持模式。

接下来,

  • 您编写将其转换为字符集的代码(例如,扩展所有范围(如果用户输入支持)并根据定义将 - 排序为第一个字符) .

  • 根本不使用字符集。

    • 为什么不用char_ [ _pass = my_match_predicate(_1) ]
    • 为什么不直接替换文字字符呢? lit('a') | 'b' | '-' | '0' | '1' | '2' | '3' | '4' | '5' | '6' | '7' | '8' | '9'
    • 为什么不使用 qi::symbols<char, char>(甚至 qi::symbols<char, qi::unused_type> sym_;raw [ sym_ ] 或类似的)

      Update The qi::symbols<> approach is surprisingly fast: Live On Coliru. I had a recent optimization job where it disappointed: see this answer (under "Spirit (Trie)") –

总的来说,我不知道您想要达到什么目的,但是 Spirit 非常适合动态生成规则。在此站点上查看我现有的一些 答案。

您试过使用\- bk::char_("a-zA-Z0-9\-_.~")吗?