这是my previous question的后续行动。
假设我想生成与给定(简化)正则表达式匹配的所有字符串。
这只是一个编码练习,我没有任何其他要求(例如生成了多少个字符串实际上)。所以主要的要求是生成漂亮,干净,简单的代码。
我考虑过使用Stream
,但在阅读this question后,我正在考虑Iterator
。你会用什么?
答案 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代码点?),你也可能希望限制它们。
无论如何,这虽然耗费时间,但却会产生一个正常工作的发电机。而且,顺便说一下,如果你为每个被解析的树写一个匹配例程,你也会有一个正常的正则表达式匹配器。