首页 > 解决方案 > 如何编写 SPF 记录的解析器和验证器?

问题描述

我想尝试编写解析器,特别是我想解析和验证 SPF 记录(https://www.rfc-editor.org/rfc/rfc7208)。这主要是一个学习练习,所以我想从下到上构建它,而不使用任何外部工具,如 ANTLR。

SPF 记录如下所示:

   v=spf1 a ip4:192.0.2.1 include:_spf.google.com ?exists:%{l1r+}.%{d} redirect=_spf.example.com -all

RFC 有一个语法规范:https ://www.rfc-editor.org/rfc/rfc7208#page-46

有几个可用的开源实现,但大多数都没有定义良好的词法分析器/解析器:

  1. https://github.com/apache/james-jspf
  2. https://github.com/sdgathman/pyspf
  3. https://github.com/softvu/spf-parse/
  4. https://github.com/Mika56/PHP-SPF-Check/
  5. https://github.com/zaccone/spf
  6. https://github.com/kbrw/mailibex

实际上,[5] 确实有一个词法分析器和一个解析器,但我不确定它们的实现方式是否有助于代码架构和可维护性。

我以前没有处理过这样的任务,并且在理解如何处理它方面存在一些差距,所以我遇到的问题与其说是解析 SPF 记录,不如说是构建一个解析器:

  1. 使用词法分析器/解析器解决问题是一个好问题,还是使用一些带有字符串拆分和正则表达式的自定义解析(如 [2]、[3]、[4])更容易?[1] 通过构建一个大型正则表达式来解决这个问题,其中包含所有机制和修饰符的规则,然后将匹配结果组逐组匹配到原始规则 - 这是一种模块化方法,但实现看起来有点复杂,而且很难理解表达式的一部分实际上是在哪里处理的。
  2. 如果我确实写了一个词法分析器,那么标记是什么?会是代币include还是a代币应该是这样的ID: [a-z]+?应该192.0.2.1是 IP 令牌,如果是,应该何时验证?像or之类的宏%{l1r+}和分隔符怎么样?:=
  3. 解析的结果是什么?似乎最好有一个对象列表,而不是 AST [SpfVersion, AMechanism, IncludeMechanism, RedirectModifer]
  4. 解析器会是什么样子?它应该有这样的规则,一一尝试吗?:
   def matchIp4(): Ip4Mechanism {
     if(matchIp4Token() == null) return null
     if(matchSemicolonToken() == null ) return Ip4Mechanism()
     
     val  ip4 = matchIp4Literal()
     if(ip4 == null) throw InvalidSyntax(...)
     ...
     return Ip4Mechanism(ip4, ...)
   }
  1. 什么时候适合进行验证,例如验证 SPF 宏的语法或 ip6 地址的结构?

很明显,我对如何做到这一点的理解存在巨大差距。阅读《语言实现模式》一书并没有太大帮助——它很容易阅读,但我觉得那里的示例过于简单,无法实际展示如何构建真正的解析器/解释器。我还研究了更高级的资源,例如 Dragon book,但我担心当我完成这本书的学习时,我会失去任何实现这一点的动力。也许有一个很好的动手指导如何做到这一点让我现在就开始,而不需要先阅读一年?

谢谢!

标签: parsinginterpreterlexerspf

解决方案


推荐阅读