捕获含糊不清的文本片段的最佳方法是什么?
What is the best way to capture ambiguous segments of text?
在以下情况下,捕获内部文本的最佳方式是什么?
inner_text = any*;
tag_cdata = '<![CDATA[' inner_text >cdata_start %cdata_end ']]>';
问题是,由于 inner_text 可以匹配 ]
.
,因此 cdata_end
操作似乎触发了几次
我找到了解决方案。您需要处理非确定性。最初并不清楚,但正确的解决方案是这样的:
inner_text = any*;
tag_cdata = '<![CDATA[' inner_text >text_begin %text_end ']]>' %cdata_end;
action text_begin {
text_begin_at = p;
}
action text_end {
text_end_at = p;
}
action cdata_end {
delegate.cdata(data.byteslice(text_begin_at, text_end_at-text_begin_at))
}
本质上,您要等到您确定已解析完整的 CDATA 标记,然后再使用您之前捕获的信息触发回调。
此外,我发现 Ragel 中的某些形式的不确定性需要使用优先级来明确处理。虽然这看起来有点难看,但在某些情况下这是唯一的解决方案。
在处理 (a+ >a_begin %a_end | b)*
这样的模式时,您会发现事件会针对遇到的每个 a
调用,而不是针对最长的子序列调用。在某些情况下,这种歧义可以使用最长匹配 kleene 星 **
来解决。它的作用是更喜欢匹配现有模式而不是环绕。
令我惊讶的是,这实际上也修改了调用事件的方式。例如,这会产生一台在调用回调时无法一次缓冲多个字符的机器:
%%{
machine example;
action a_begin {}
action a_end {}
main := ('a'+ >a_begin %a_end | 'b')*;
}%%
产生:
您会注意到它每次都会调用 a_begin
和 a_end
。
相比之下,我们可以使内部循环和事件处理变得贪婪:
%%{
machine example;
action a_begin {}
action a_end {}
main := ('a'+ >a_begin %a_end | 'b')**;
}%%
产生:
在以下情况下,捕获内部文本的最佳方式是什么?
inner_text = any*;
tag_cdata = '<![CDATA[' inner_text >cdata_start %cdata_end ']]>';
问题是,由于 inner_text 可以匹配 ]
.
cdata_end
操作似乎触发了几次
我找到了解决方案。您需要处理非确定性。最初并不清楚,但正确的解决方案是这样的:
inner_text = any*;
tag_cdata = '<![CDATA[' inner_text >text_begin %text_end ']]>' %cdata_end;
action text_begin {
text_begin_at = p;
}
action text_end {
text_end_at = p;
}
action cdata_end {
delegate.cdata(data.byteslice(text_begin_at, text_end_at-text_begin_at))
}
本质上,您要等到您确定已解析完整的 CDATA 标记,然后再使用您之前捕获的信息触发回调。
此外,我发现 Ragel 中的某些形式的不确定性需要使用优先级来明确处理。虽然这看起来有点难看,但在某些情况下这是唯一的解决方案。
在处理 (a+ >a_begin %a_end | b)*
这样的模式时,您会发现事件会针对遇到的每个 a
调用,而不是针对最长的子序列调用。在某些情况下,这种歧义可以使用最长匹配 kleene 星 **
来解决。它的作用是更喜欢匹配现有模式而不是环绕。
令我惊讶的是,这实际上也修改了调用事件的方式。例如,这会产生一台在调用回调时无法一次缓冲多个字符的机器:
%%{
machine example;
action a_begin {}
action a_end {}
main := ('a'+ >a_begin %a_end | 'b')*;
}%%
产生:
您会注意到它每次都会调用 a_begin
和 a_end
。
相比之下,我们可以使内部循环和事件处理变得贪婪:
%%{
machine example;
action a_begin {}
action a_end {}
main := ('a'+ >a_begin %a_end | 'b')**;
}%%
产生: