指定不解释范围的字符集
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 不 非常适合动态生成规则。在此站点上查看我现有的一些 boost-spirit 答案。
您试过使用\- bk::char_("a-zA-Z0-9\-_.~")
吗?
当我必须在规则中定义减号时,我对解析字符串感到非常困惑,它只是一个减号字符,而不是两个端点之间的字符范围。
例如,当您编写一个规则来对一串字符进行百分比编码时,您通常会编写
*(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 不 非常适合动态生成规则。在此站点上查看我现有的一些 boost-spirit 答案。
您试过使用\- bk::char_("a-zA-Z0-9\-_.~")
吗?