在编译时执行编译时编译的正则表达式

时间:2015-06-20 10:09:39

标签: regex d compile-time

当我尝试编译此代码时出现编译错误:

import std.regex;
enum truth = "baba".matchFirst(ctRegex!`[ab]+$`) ? true : false;
void main() {}

/usr/local/Cellar/dmd/2.067.1/include/d2/std/regex/package.d(671): Error: malloc cannot be interpreted at compile time, because it has no available source code

如何解决这个问题?

1 个答案:

答案 0 :(得分:2)

你不能,正则表达式可以在编译时编译,但不能运行。你必须以其他方式编写匹配,也许是indexOf或其他更简单函数的组合。 (原因不是因为正则表达式过于复杂,实际上是因为它在内部调用malloc来提高效率,这在编译时不受支持,因为它是一个外部C函数。)

理解ctRegex需要一些解释Phobos的正则表达式引擎。它分两步工作:给定一个正则表达式,它首先将其编译成一些字节码,然后在字符串上匹配它,它运行该代码。

在普通regex中,这两个步骤都在运行时发生。构造正则表达式对象时,它将其编译为字节码。然后,当您匹配字符串时,它会运行该代码。

使用ctRegex,第一部分发生在编译时,但第二部分仍然在运行时发生。因此,当编译D时,它将正则表达式编译成字节码...然后将该字节码推送到D编译器的其余部分,以优化为完全本机代码。这就是它可以提供的好处。 (BTW差异通常并不重要,你应该对你的输入字符串进行基准测试,看看哪个更好。)

通常,CTFE(编译时功能评估)意味着运行时代码也可以在编译时运行,但仅在源可用时运行。 malloc的情况并非如此,这就是错误说明的原因。

所以答案将取决于你的正则表达式是什么。您可能希望简化它并根据其他字符串和/或std.algorithm函数重写它。

...或者重写std.regex源代码以摆脱那些malloc调用。将其替换为newif(_ctfe)即可开始。我之前尝试过这样做,除非代码自那时起被重构,否则你只会遇到另一个问题:对于运行时性能,std.regex也会使用像union这样的东西,ctfe也不支持。你必须重写一堆,并注意不要在此过程中损害运行时性能。

使用其他功能处理您的特定情况可能更容易。