Stream或Iterator生成与正则表达式匹配的所有字符串?

时间:2012-01-04 16:11:45

标签: regex algorithm scala stream iterator

这是my previous question的后续行动。

假设我想生成与给定(简化)正则表达式匹配的所有字符串。

这只是一个编码练习,我没有任何其他要求(例如生成了多少个字符串实际上)。所以主要的要求是生成漂亮,干净,简单的代码。

我考虑过使用Stream,但在阅读this question后,我正在考虑Iterator。你会用什么?

1 个答案:

答案 0 :(得分:4)

这个问题的解决方案要求太多代码才能在这里回答它,但大纲如下。

首先,您要解析正则表达式 - 例如,您可以查看解析器组合器。然后,您将拥有一个评估树,例如,

List(
  Constant("abc"),
  ZeroOrOne(Constant("d")),
  Constant("efg"),
  OneOf(Constant("h"),List(Constant("ij"),ZeroOrOne(Constant("klmnop")))),
  Constant("qrs"),
  AnyChar()
)

不是将此表达式树作为匹配器运行,而是可以通过在每个术语上定义generate方法将其作为生成器运行。对于某些术语(例如ZeroOrOne(Constant("d"))),将有多个选项,因此您可以定义迭代器。一种方法是在每个术语中存储内部状态,并传入“advance”标志或“reset”标志。在“重置”时,生成器返回第一个可能的匹配(例如"");提前,它转到下一个并返回该值(例如"d"),同时消耗提前标志(其余部分在没有标志的情况下进行评估)。如果没有其他项目,则会为其内部的所有内容生成重置,并为下一个项目保留前进标记。首先运行重置;在每次迭代中,你都会预先进入,并在你再次出局时停止。

当然,像"d+"这样的一些正则表达式构造可以产生无限多的值,所以你可能想要以某种方式限制它们(或者在某些时候返回,例如d...d意味着“很多”) ;和其他人有很多可能的值(例如.匹配任何char,但你真的想要所有64k字符,或者有多少unicode代码点?),你也可能希望限制它们。

无论如何,这虽然耗费时间,但却会产生一个正常工作的发电机。而且,顺便说一下,如果你为每个被解析的树写一个匹配例程,你也会有一个正常的正则表达式匹配器。