【问题标题】:convert/compile regular expressions to C code将正则表达式转换/编译为 C 代码
【发布时间】:2012-09-20 02:02:02
【问题描述】:

我在内存有限的系统上,boost::regex 太大。有哪些选项可以将我的正则表达式直接编译为 C/C++ 以及我应该排除多少 KB 的代码大小?以尽可能减少内存和代码大小为目标。

我正在寻找小于 100kb 的代码大小和相同的内存使用量。 Boost 正则表达式似乎约为 470kb,太大了。

【问题讨论】:

  • 无论如何,boost::regex 是 C++,而不是 C。
  • 您的正则表达式需要有多复杂?在“Beautiful Code”一书中,有一些简单的正则表达式函数,可能相当于几百字节的代码和堆栈空间量,主要由正则表达式中出现的星号 (*) 控制。但这些都是非常简单的正则表达式。
  • 正则表达式将匹配 HTTP 协议的不同部分,因此不仅仅是基本的 *+
  • 匹配 HTTP 什么?网址?要求?标头?身体?
  • (GET|POST|HEAD)[[:blank:]]+(?:([[:alpha:]]{1,6})://([^/[:blank:]]+))?(/[^[:blank:]]*)(?:[[:blank:]]+HTTP/([[:digit:]]{1,3})\\.([[:digit:]]{1,4}))? 例如。

标签: c++ regex compiler-construction


【解决方案1】:

lex(和flex)生成的表驱动词法分析器通常很小;他们回到了 100kB 被认为是超级计算机的时代 :) 基本的 flex 代码骨架很小(几 kB),表格取决于您拥有多少令牌类型以及正则表达式的复杂程度,但是一个简单的flex 扫描仪表通常也只有几 kB。

但是,如果您不使用它们来构建解释器/编译器,它们确实有一些令人讨厌的特性:首先,它们坚持为您进行输入和缓冲,如果您一直在阅读,那就太好了来自文件,但如果您的输入来自套接字或终端(或者,更糟糕的是,被某种翻译器预处理),则可能不太酷,其次它们是为您拥有一些简单令牌类型的环境而设计的,并且你有一个解析器负责解释排序。 (因此yaccbison。)当然,您可以使用这些工具来解析HTTP,您甚至可能会发现您已经学到了一些有用的新技能。

有一个名为 re2c 的工具(即 C 的正则表达式),您可能会觉得它更舒服一些。与lex 不同,它生成定制的 C 代码,这有点笨重,但可以说运行速度稍快一些。我不认为它得到了积极的维护,但几年前我已经取得了相当大的成功。你应该可以找到它on SourceForge

祝你好运。

【讨论】:

    【解决方案2】:

    人们似乎忘记了这个问题早就被lex and yacc解决了。

    【讨论】:

    • 类似于lex,但不是真的。您使用lex 编译了一组可能的正则表达式,但您无法在运行时使用lex 适应新的正则表达式。
    • @Jonathan,是的,是的,但是谁说过运行时? C代码在运行时有什么用?
    • 因此您需要按照以下方式限定您的答案:如果在编译程序时要管理的正则表达式集是固定的,那么您可以使用lex来识别这些表达。
    • 我不想构建一个编译器来解析 HTTP。我查看了 lex 和 yacc 并无法弄清楚它们。编译器也不会使用大量内存(相对而言)?
    • 嗯,不这么认为。问题的标题是“将正则表达式转换/编译为 C 代码”,然后说“存在哪些选项可以将我的正则表达式直接编译为 C/C++ ...”。我在这里没有看到任何歧义。
    【解决方案3】:

    re2c 是一个专门为此而设计的应用程序

    http://sourceforge.net/projects/re2c/

    (也可作为 debian 包等提供)

    许可:公共领域

    或者,可以将正则表达式编译为字节码并仅链接 pcre2 的解释器部分(或您想要的任何正则表达式样式) 例如:

    https://www.pcre.org/current/doc/html/pcre2api.html#SEC25

    可以将编译后的模式保存在磁盘或其他地方,并在以后重新加载它们,但有一些限制。重新加载模式的主机必须运行相同版本的 PCRE2,具有相同的代码单元宽度,并且还必须具有相同的字节序、指针宽度和 PCRE2_SIZE 类型。在保存已编译的模式之前,必须将它们转换为“序列化”形式,在 PCRE2 的情况下实际上只是一个字节码转储。名称以 pcre2_serialize_ 开头的函数用于在序列化形式之间进行转换。它们在 pcre2serialize 文档中进行了描述。请注意,PCRE2 序列化不会将编译模式转换为抽象格式,如 Java 或 .NET 序列化。

    因此,要包含 RCRE2 的预编译正则表达式,您可能需要在目标系统上或在仿真下运行编译。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-07-02
      • 2011-10-02
      • 1970-01-01
      • 2023-03-09
      • 2015-01-15
      • 2016-09-13
      • 1970-01-01
      相关资源
      最近更新 更多