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



这是我上一个问题的后续内容。

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

这只是一个编码练习,我没有任何额外的要求(例如,实际生成了多少字符串)。因此,主要需求是生成漂亮、干净、简单的代码。

我曾想过使用Stream,但看完这个问题后,我想到了Iterator。你会用什么?

这个问题的解决方案需要太多的代码,所以在这里回答起来很实用,但大纲如下。

首先,您想要解析正则表达式——例如,您可以为此查看解析器组合子。然后你会有一个评估树,看起来像

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

您可以将此表达式树作为生成器运行,而不是将其作为matcher来运行,方法是为每个项定义一个generate方法。对于某些术语(例如ZeroOrOne(Constant("d"))),将有多个选项,因此您可以定义迭代器。一种方法是在每个术语中存储内部状态,并传递"前进"标志或"重置"标志。在"重置"时,生成器返回第一个可能的匹配(例如"");在前进时,它前进到下一个并返回该值(例如"d"),同时消耗前进标志(剩下的要在没有标志的情况下进行评估)。如果没有更多的项目,它会对自身内部的所有内容进行重置,并为下一个项目保留前进标志。你从重置开始跑步;在每一次迭代中,你都会提前一步,当你再次得到它时,就会停止。

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

无论如何,这虽然很耗时,但会导致发电机工作。顺便说一句,如果您为解析的树的每一部分编写一个匹配例程,那么您还将拥有一个可工作的正则表达式匹配器。

相关内容

  • 没有找到相关文章

最新更新