130

编辑:我最近了解了一个名为 CommonMark 的项目,它可以正确识别和处理原始 Markdown 规范中的歧义。http://commonmark.org/它有很好的 C# 库支持。

您可以在此处找到语法。

下载后的源代码是用Perl编写的,我无意兑现。它充斥着正则表达式,它依赖MD5散列来转义某些字符。这有点不对劲!

我即将为Markdown硬编码一个解析器。这有什么经验?

如果你对 Markdown 的实际解析没有任何意义,请抽空。(这听起来可能很苛刻,但是是的,我正在寻找洞察力,而不是解决方案,即第三方库)。

为了对答案有所帮助,正则表达式旨在识别模式!不要解析整个语法。人们认为这样做是 foobar。

  • 如果您考虑 Markdown,它基本上是基于段落的概念。
  • 因此,一种合理的方法可能是将输入分成几段。
  • 段落有很多种,例如标题、文本、列表、块引用和代码。
  • 因此,挑战在于识别这些段落以及它们出现在什么上下文中。

一旦我发现它值得分享,我会回来提供解决方案。

4

10 回答 10

72

我所知道的唯一使用实际解析器的降价实现是Jon MacFarleanepeg-markdown它的解析器基于名为peg的Parsing Expression Grammar解析器生成器。


编辑:Mauricio Fernandez最近发布了他的Simple Markup Markdown parser,这是他作为OcsiBlog Weblog Engine 的一部分编写的。因为解析器是用OCaml编写的,所以它非常简单和简短(解析器为 268 SLOC, HTML 发射器为 43 SLOC ,但速度非常快(比折扣(用手工优化的 C 编写)快 20%,快百倍比BlueCloth (红宝石)),尽管它甚至还没有针对性能进行优化。因为它仅供 Mauricio 自己的博客内部使用,与官方 Markdown 规范有一些偏差,但 Mauricio 创建了一个分支来恢复大部分更改

于 2009-03-03T10:35:56.473 回答
17

上周我发布了一个新的基于解析器的 Markdown Java 实现,称为pegdown。pegdown 使用 PEG 解析器首先构建抽象语法树,然后将其写入 HTML。因此,它比基于正则表达式的方法非常干净,更容易阅读、维护和扩展。PEG 语法基于 John MacFarlanes C 实现“peg-markdown”。

也许你感兴趣的东西...

于 2010-05-03T08:16:07.537 回答
7

如果我要尝试解析 markdown (及其扩展Markdown extra),我想我会尝试使用状态机并一次解析一个字符,然后将一些表示文本位的内部结构链接在一起,一次all 被解析,从所有串在一起的对象中生成输出。

基本上,当我读取输入文件时,我会构建一个类似迷你 DOM 的树。
要生成输出,我只需遍历树并输出 HTML 或其他任何内容(PS、LaTex、RTF、...)

可能增加复杂性的事情:

  • 您可以混合使用 HTML 和 markdown,尽管该规则很容易实现:只需忽略两个平衡标签之间的任何内容并逐字输出。

  • URL 和注释可以在文本底部有参考。使用超链接的数据结构可以简单地记录如下内容:

    [my text to a link][linkkey]
    results in a structure like: 
        URLStructure: 
        |  InnerText : "my text to a link"
        |  Key       : "linkkey"
        |  URL       : <null>
    
  • 标题可以用下划线定义,这可能会迫使我们对通用段落使用简单的数据结构,并在阅读文件时修改其属性:

    ParagraphStructure:
    |  InnerText    : the current paragraph text 
    |                 (beginning of line until end of line).
    |  HeadingLevel : <null> or 1-4 when we can assess 
    |                 that paragraph heading level, if any.
    

无论如何,只是一些想法。

我确信有许多小细节需要处理,并且我很确定正则表达式在此过程中会变得很方便。
毕竟,它们是用来处理文本的。

于 2009-03-03T09:20:06.483 回答
3

我可能已经阅读了足够多的语法规范来了解它,并了解如何解析它。

阅读现有的解析器代码当然很棒,既可以了解复杂性的主要来源,也可以了解是否使用了任何特殊的聪明技巧。使用 MD5 校验和似乎有点奇怪,但我对代码的研究还不够深入,无法理解为什么要这样做。一个名为_EscapeSpecialChars()states 的例程中的注释:

我们将每个这样的字符替换为其对应的 MD5 校验和值;这可能是矫枉过正,但它应该可以防止我们意外地与转义值发生冲突。

用完整的 MD5 替换单个字符确实看起来很奢侈,但也许真的很有意义。

当然,考虑创建一个“真正的”语法是很聪明的,这样像Flex这样的工具才能摆脱正则表达式的困境。

于 2009-03-03T07:45:17.727 回答
2

如果 Perl 不是你的菜,那么至少有 10 种其他语言的 Markdown 实现。它们可能并非都具有 100% 的兼容性,但往往非常接近。

于 2009-03-03T07:44:40.970 回答
2

MarkdownPapers是另一种 Java 实现,其解析器以JavaCC语法定义。

于 2011-04-29T06:11:22.183 回答
1

如果您使用的编程语言有超过三个其他用户,您应该能够找到一个库来为您解析它。快速搜索一下 CL、Haskell、Python、JavaScript、Ruby 等库。您极不可能需要重新发明这个轮子。

如果您真的必须从头开始编写它,我建议您编写一个适当的解析器。使用这种技术,您不必使用 MD5 散列来转义。(我同意如果你必须做这样的事情,是时候重新考虑你的设计了。)

于 2009-03-03T07:54:35.627 回答
0

在这里你可以找到 Markdown 的 JavaScript 实现。它还严重依赖正则表达式,因为这只是解析文本的最快和最简单的方法。

但它保留了 MD5 部分。

我无法直接帮助解析的编码,但也许这个链接可以帮助你。

于 2009-03-03T07:46:16.333 回答
0

有多种语言可用的库,包括 php、ruby、java、c#、javascript。我建议查看其中的一些想法。

这取决于您希望使用哪种语言,为了实现它的最佳方式,将有惯用和非惯用方式来实现它。

正则表达式在 perl 中工作,因为 perl 和正则表达式是最好的朋友。

于 2009-03-03T07:47:22.510 回答
0

Markdown 是一种 JAWL(只是另一种 wiki 语言)

那里有很多开源 wiki,您可以检查解析器的代码。大多数使用正则表达式

查看螺丝转维基,它有一个有趣的多通道格式化程序管道,一个非常好的技术 - 参见 /core/Formatter.cs 和 /core/FormatterPipeline.cs

最好是使用/加入现有项目,这类事情总是比看起来要困难得多

于 2009-03-03T08:20:28.687 回答