百科问答小站 logo
百科问答小站 font logo



如何从零写一个正则表达式引擎? 第1页

  

user avatar   luikore 网友的相关建议: 
      

是的, 首先要确定实现的目标, 有几个关键目标是会影响你的实现的

- 要不要支持完整的正则文法? (如果不支持 "|", 几十行就能搞定, 如果要支持完整的正则文法, 就需要一个能力超越正则的解析器, 如果要编写一个高效的 one-pass 正则编译器, 还是要学不少编译技术的...)

- 要不要支持 unicode 及 unicode character class? (扫描 UTF-8/16 码点会比较蛋疼, 容易一点的做法是转换成 UTF-32 做), 要对 unicode 做完整支持的话, 很多传统正则引擎里基于字节的匹配方式就不能做了, 一些 DFA 节点的表示方式和压缩手段也会受限制.

- 要不要支持 back reference? (如果你要实现 back reference 的话, 你不能用

Implementing Regular Expressions

里描述的 ThompsonVM/PikeVM 的, thread list 占有的内存会随着状态数指数增长而爆裂) 支持 back reference 的正则基本很多会退回去扩展最原始那个 Henry Spencer VM...

- 要做成 NFA based, DFA based, 还是一个字节码虚拟机? 对虚拟机的解决方案, 你要学习字节码解释器的基本构造, 可能会用 direct threading 等技术去做优化. 字节码可以看作线性化的 NFA, 相比构造 NFA 节点会减少一些 cache miss 但是相应的就不能使用很多节点压缩和优化的手段了.

- 要不要做一个 JIT 引擎? 这个更令人兴奋, 可以参考

ytljit/regexp.rb at master · miura1729/ytljit · GitHub

)

- 要不要兼容 POSIX 标准里的正则部分? (估摸至少 4000 行代码, 自己考虑工作量咯)

- 要不要做 extended 正则?

所谓 extended 正则, 就是还支持补集和交集运算, 正则语言这么搞完结果还是个正则语言, 就是实现 grep -v 之类的可以简单一些, 可以尝试

这个方法

- 要不要做 Online Parsing?

online parsing 常用于语法高亮和大文件解析中. 其意思是输入一部分内容就匹配一部分, 有新内容输入的时候你不该重头匹配一遍 (每敲一个字符重新着色一遍太慢了), 而是做最低限度的回溯. 如果要做 online parsing, 那么怎么暂停你的 VM, 怎么缓存回溯都是要考虑的问题. 而且正则的语法会有限制.

- 要不要支持超巨大的正则表达式?

有些 network filter 例如联邦的防火墙, 会有几十万条规则, 你会发现普通的办法在 20G 内存的机器上都编译不了这个正则... 不过用小内存支持 DFA 千万节点的方法已经有人研究出来了: D^2FA... 为了编译出这么大的 D^2FA, 其编译期算法也有人研究过了:

D^2FA

- 要不要支持以下各种正则引擎的 fancy feature?

-- X 匹配字素

-- 递归 named group

-- capture history

-- nested capture

-- atomic group

-- greedy vs reluctant vs possessive

...

每一项都相当有难度... 尤其是 greedy/reluctant/possessive 的区别有可能从根本上颠覆你这个正则引擎的实现, 很多人的正则引擎做完 DFA/NFA 就停下来了, 也是因为搞不动这些 feature.

---

OK, 目标明确了, 开始代码之前要先夹沟夹沟哦, 建议: 不要一开始就想把它做得很高效率, 要把问题拆得足够小足够简单的来做, 只要决定好大方向不错, 就不用推倒重来很多次了...

现在的正则引擎的构造比各种 parser generator 都要复杂, good luck!

推荐书籍: Parsing Techniques - A Practical Guide 2008 (讲得比较全了, 就是缺少 coroutine based parser 的构建)

推荐课程:

Parsing Beyond Context-Free Grammars

(为什么要 beyond CFG 呢? 因为现在正则引擎的能力已经 beyond CFG 啦)

推荐代码: Henry Spencer's regexp engine

regexp.old/regexp.c at master · garyhouston/regexp.old · GitHub

是很多现代流行的正则引擎的始祖, 解释器实现, 很多新 feature 能扩展得得进去, 也有混合 DFA 的优化

Onigmo

k-takata/Onigmo · GitHub

是 Ruby 的正则引擎, 特点是 encoding aware 兼容多种语法和 feature, 如果要做 unicode character class 可以抄它的...




  

相关话题

  Windows 上最小的「HelloWorld.exe」能有多小? 
  编程语言用let等关键字声明变量有什么好处? 
  有什么行为习惯昭示着你是个编程大佬? 
  有没有什么程序库使得我们可以比较方便的在windows下使用比较新版本的opengl的? 
  .NET 会翻身吗? 
  在编程中有没有巧妙运用数学知识解决过问题? 
  中国计算机专业的大学生相比于美国差在哪里? 
  教授说没有写过一千行以上代码的程序就别想上大公司,这种说法对吗? 
  VS 2015 的跨平台特性对 Qt 会带来多大的冲击呢? 
  有没有简单一点的 Python 小例子或小项目? 

前一个讨论
计科学生能成为b站稚晖君这样软硬兼通能diy电子产品的人吗?
下一个讨论
CPU的功耗和什么相关?为什么一个while(1);就可占满CPU的功耗?





© 2025-04-04 - tinynew.org. All Rights Reserved.
© 2025-04-04 - tinynew.org. 保留所有权利