使用简单的基于正则表达式的降价解析器的缺点是什么?

Rya*_*hel 4 javascript regex markdown javascript-marked

我的应用程序需要一个相对简单的降价解析器。只是简单的东西,比如粗体、斜体等。我四处寻找图书馆,许多似乎都很大。例如,marked非常受欢迎,有 20,000 颗星。它接近 2,000 行代码。我什至不确定这个有多大,但它看起来很复杂。

一般来说,我尽量让事情保持简单,并尽可能限制我的依赖。我不确定所有这些行在做什么?我很高兴很快就找到了这个库,它甚至不到 100 行,它只是使用一个简单的正则表达式将文本转换为相应的 Markdown。

我的问题是,基本上,其他图书馆在做什么?通过选择使用更简单的、以正则表达式为中心的方法,我是否遗漏了什么?后一个库在某种程度上不安全吗?我应该考虑其他一些我不知道的因素吗?

显然,我遗漏了一些重要的东西,因为前一个库似乎很受欢迎,而后一个库甚至没有一颗星。我只是不确定那是什么。我希望情况是后者适用于简单情况,如果您需要,前者更“完整”,但我不想跳到那个结论。

Way*_*lan 5

有许多因素会导致 Markdown 解析器的复杂性。也就是说,您可以使用“简单的基于正则表达式”的方法来构建 Markdown 解析器。事实上,这正是参考实现所使用的(在 Perl 中)。它运行一系列正则表达式,用现有文档上的 HTML 语法替换 Markdown 语法。即便如此,源代码也由 1451 行代码组成,包括注释、许可等。当然,它包括对原始语法规则中描述的整个功能列表的支持。这些功能包括支持嵌套、转义等,这使正则表达式的使用变得非常复杂。

有些人发现这样的实现有局限性。这完全取决于您想要从 Markdown 解析器中获得什么。

例如,使用参考实现扩展语法几乎是不可能的。例如,Python-Markdown(我是其开发人员)采用了参考实现,给每个正则表达式一个名称,并为第三方扩展提供了一种方法来替换或插入新的正则表达式到组合中。样板代码只是为了允许这增加了相当多的代码行。顺便说一句,Markdown 已经过时了,而且 Python-Markdown 等库这些年来已经发生了变化和增长。第一个版本非常接近参考实现,但今天你很难看到它们之间的任何相似之处。

其他人对扩展语法并不感兴趣,而是提供一种控制输出的方法。例如,标记的JS 库输出抽象语法树 (AST),然后可以将其传递给渲染器。渲染器接受 AST(基本上是一个令牌列表)并输出一些其他格式。其他格式可以是 HTML,也可以是其他格式。Pandoc利用这一点在许多文档格式之间进行转换。当然,这会增加额外的代码行。

另一个因素,无论是否实现,很多人会争辩说,如果一个实现不支持规则中的所有功能,那么它就不是 Markdown。事实上,多年来,许多实现都添加了非标准功能(以 GitHub Flavored Markdown 为例)。人们开始依赖这些非标准特性,并且会提交错误报告,抱怨实现不支持它们。作为 Python-Markdown 的开发者,当 lib 确实提供支持时,我经常看到这样的报告。它只是默认不启用。当向他们指出这一点时,他们的反应往往不那么理解。因此,如果没有对所有标准功能的支持,那么针对一般消费的实现将不会持续很长时间。

增加额外的复杂性是关于标准特性的实现之间没有完美的一致性。有关详细信息,请参阅Babelmark 2 常见问题解答。在该常见问题解答中,您会发现许多记录在案的差异,这些差异相当细微。人们真的发现这些细微的差异很重要。为此,一群人创建了Commonmark, Markdown 的严格规范。但是,由于 Commonmark 从未得到过 Markdown 创造者的祝福,所以有人质疑它是否可以算是 Markdown。此外,在某些地方,规范本身也承认直接违反了原始规则。无论如何,要使实现成为 Commonmark 实现,必须提供具有规范中所有记录功能的完整解决方案。的参考实现(在JS和C)都是相当大的。事实上,我怀疑您是否可以使用像这样使用简单的基于 rexed 的替换的实现来实现 Commonmark markdown.pl

关键是,除了最简单的实现之外,您获得的不仅仅是一组正则表达式替换。确切的功能因实现而异,需要仔细阅读每个实现的文档。无论如何,即使是“简单”的正则表达式替换集合,实现 Markdown 的所有记录功能也相当复杂和冗长。任何更少的东西都不会被视为降价。

另一个考虑因素是性能。虽然基于正则表达式的解析器对于大多数一般用途“足够好”(从命令行运行,作为参考实现的设计目的),但性能更高的实现(例如标记或 Commonmark 参考实现)会生成 AST 并使用渲染器. 基于正则表达式的实现永远不会在性能上接近匹配,如果您的 Web 服务器在每个请求上将 Markdown 转换为 HTML,这一点很重要。