parsing - 如何编写 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
有几个可用的开源实现,但大多数都没有定义良好的词法分析器/解析器:
- https://github.com/apache/james-jspf
- https://github.com/sdgathman/pyspf
- https://github.com/softvu/spf-parse/
- https://github.com/Mika56/PHP-SPF-Check/
- https://github.com/zaccone/spf
- https://github.com/kbrw/mailibex
实际上,[5] 确实有一个词法分析器和一个解析器,但我不确定它们的实现方式是否有助于代码架构和可维护性。
我以前没有处理过这样的任务,并且在理解如何处理它方面存在一些差距,所以我遇到的问题与其说是解析 SPF 记录,不如说是构建一个解析器:
- 使用词法分析器/解析器解决问题是一个好问题,还是使用一些带有字符串拆分和正则表达式的自定义解析(如 [2]、[3]、[4])更容易?[1] 通过构建一个大型正则表达式来解决这个问题,其中包含所有机制和修饰符的规则,然后将匹配结果组逐组匹配到原始规则 - 这是一种模块化方法,但实现看起来有点复杂,而且很难理解表达式的一部分实际上是在哪里处理的。
- 如果我确实写了一个词法分析器,那么标记是什么?会是代币
include
还是a
代币应该是这样的ID: [a-z]+
?应该192.0.2.1
是 IP 令牌,如果是,应该何时验证?像or之类的宏%{l1r+}
和分隔符怎么样?:
=
- 解析的结果是什么?似乎最好有一个对象列表,而不是 AST
[SpfVersion, AMechanism, IncludeMechanism, RedirectModifer]
。 - 解析器会是什么样子?它应该有这样的规则,一一尝试吗?:
def matchIp4(): Ip4Mechanism {
if(matchIp4Token() == null) return null
if(matchSemicolonToken() == null ) return Ip4Mechanism()
val ip4 = matchIp4Literal()
if(ip4 == null) throw InvalidSyntax(...)
...
return Ip4Mechanism(ip4, ...)
}
- 什么时候适合进行验证,例如验证 SPF 宏的语法或 ip6 地址的结构?
很明显,我对如何做到这一点的理解存在巨大差距。阅读《语言实现模式》一书并没有太大帮助——它很容易阅读,但我觉得那里的示例过于简单,无法实际展示如何构建真正的解析器/解释器。我还研究了更高级的资源,例如 Dragon book,但我担心当我完成这本书的学习时,我会失去任何实现这一点的动力。也许有一个很好的动手指导如何做到这一点让我现在就开始,而不需要先阅读一年?
谢谢!
解决方案
推荐阅读
- node.js - 节点 events.js:292 throw er; // 未处理的“错误”事件
- c# - C# 加载图像导致内存不足异常(我使用的是 .tif 或 .tiff)
- javascript - 如何将 div 链接到 JavaScript 生成的 HTML 中的一个容器?
- php - 从php中的多维数组中提取数据
- apache-kafka - 为什么卡夫卡仍然收到“过期”的消息?
- r - 合并两个长度不等的数据帧并用 NA 填充缺失值
- delphi - 如何使用 TNetHTTPClient 或 TNetHTTPRequest 从 URL 获取图片并将其放在 TImage 中?
- google-apps-script - 谷歌应用脚本在谷歌幻灯片中创建链接
- react-native - 反应原生视图镜头表面 gl-react-native
- kerberos - 来自 TGS-REP 的 KDC 验证