我如何用精神正确解析这个?
我的情况:我是 Spirit 的新手,我必须使用 VC6,因此使用 Spirit 1.6.4。
我有一行看起来像这样:
//The Description;DESCRIPTION;;
如果该行以 //The Description;
开头,我想将文本 DESCRIPTION
放入字符串中。
我有一些可行的东西,但对我来说看起来不太优雅:
vector<char> vDescription; // std::string doesn't work due to missing ::clear() in VC6's STL implementation
if(parse(chars,
// Begin grammar
(
as_lower_d["//the description;"]
>> (+~ch_p(';'))[assign(vDescription)]
),
// End grammar
space_p).hit)
{
const string desc(vDescription.begin(), vDescription.end());
}
我更想将所有可打印字符分配给下一个 ';'
但以下内容不起作用,因为 parse( ...).hit == false
parse(chars,
// Begin grammar
(
as_lower_d["//the description;"]
>> (+print_p)[assign(vDescription)]
>> ';'
),
// End grammar
space_p).hit)
如何让它命中?
My situation: I'm new to Spirit, I have to use VC6 and am thus using Spirit 1.6.4.
I have a line that looks like this:
//The Description;DESCRIPTION;;
I want to put the text DESCRIPTION
in a string if the line starts with //The Description;
.
I have something that works but looks not that elegant to me:
vector<char> vDescription; // std::string doesn't work due to missing ::clear() in VC6's STL implementation
if(parse(chars,
// Begin grammar
(
as_lower_d["//the description;"]
>> (+~ch_p(';'))[assign(vDescription)]
),
// End grammar
space_p).hit)
{
const string desc(vDescription.begin(), vDescription.end());
}
I would much more like to assign all printable characters up to the next ';'
but the following won't work because parse(...).hit == false
parse(chars,
// Begin grammar
(
as_lower_d["//the description;"]
>> (+print_p)[assign(vDescription)]
>> ';'
),
// End grammar
space_p).hit)
How do I make it hit?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
您可以尝试使用
confix_p
:
它应该相当于Fred的响应。
您的代码失败的原因是
print_p
是贪婪。 +print_p 解析器将消耗字符,直到遇到输入结尾或不可打印的字符。 分号是可打印的,因此print_p
声明它。 您的输入耗尽,变量被分配,并且匹配失败 - 解析器的最后一个分号没有任何内容可以匹配。Fred 的答案构造了一个新的解析器
(print_p - ';')
,它匹配print_p
所做的一切,除了分号。 “匹配除 X 之外的所有内容,然后匹配 X”是一种常见模式,因此提供了confix_p
作为构建此类解析器的快捷方式。 文档建议使用它来解析 C 或 Pascal 风格的注释,但这不是必需的。为了使您的代码正常工作,Spirit 需要识别出贪婪的
print_p
匹配太多,然后回溯以允许更少的匹配。 但是,尽管 Spirit 会回溯,但它不会回溯到子解析器贪婪匹配的“中间”。 它将回溯到下一个“选择点”,但你的语法没有任何选择。 请参阅详尽的回溯和贪婪Spirit 文档中的 RD。You might try using
confix_p
:It should be equivalent to Fred's response.
The reason your code fails is because
print_p
is greedy. The+print_p
parser will consume characters until it encounters the end of the input or a non-printable character. Semicolon is printable, soprint_p
claims it. Your input gets exhausted, the variable is assigned, and the match fails — there's nothing left for the last semicolon of your parser to match.Fred's answer constructs a new parser,
(print_p - ';')
, which matches everythingprint_p
does, except for semicolons. "Match everything except X, and then match X" is a common pattern, soconfix_p
is provided as a shortcut for constructing that kind of parser. The documentation suggests using it for parsing C- or Pascal-style comments, but that's not required.For your code to work, Spirit would need to recognize that the greedy
print_p
matched too much and then backtrack to allow matching less. But although Spirit will backtrack, it won't backtrack to the "middle" of what a sub-parser would otherwise greedily match. It will backtrack to the next "choice point," but your grammar doesn't have any. See Exhaustive backtracking and greedy RD in the Spirit documentation.你没有受到打击,因为 ';' 与 print_p 匹配。 尝试这个:
You're not getting a hit because ';' is matched by print_p. Try this: