您将如何解析Markdown?[关闭]


126

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

您可以在此处找到语法。

下载后的源代码是用Perl编写的,我无意承担任何责任。它充满了正则表达式,并且依靠MD5散列来转义某些字符。这有点不对劲!

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

如果您对Markdown的实际解析没有任何意义要说,请花点时间。(这听起来可能很刺耳,但是,是的,我正在寻找见识,而不是解决方案,即第三方库)。

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

  • 如果您考虑Markdown,那么它基本上是基于段落的概念。
  • 因此,一种合理的方法可能是将输入分成多个段落。
  • 有许多段,例如标题,文本,列表,块引用和代码。
  • 因此,面临的挑战是确定这些段落及其出现的背景。

一旦找到值得分享的解决方案,我将为您提供解决方案。


2
@cletus正在编写markdown解析器,请参阅cforcoding.com/search/label/markdown
Alex Angas 2010年

我最终做了同样的事情。但是,我并不是试图将markdown解析为正式语法,因为显然不是。我以递归方式应用了不同的正则表达式。并经过数次。效果很好。
约翰·莱德格伦

@JohnLeidegren,是否有其他好奇的用户(例如我自己)看到您尝试解析降价的机会?
jmlopez

@jmlopez对不起,我再也无法访问该源了,如果您需要Markdown解析器,可以使用NuGet包。不过,这个想法很简单,只需在传递过程中应用一系列正则表达式,首先将段落中的输入进行分区,然后尝试确定段落的类型,依此类推。最后,在段落本身中解析链接和字符样式。
John Leidegren

2
您应该查看Parsedown。它将文本分成几行。然后研究这些线如何开始并相互关联。
Emanuil Rusev 2013年

Answers:


69

我所知道的唯一使用实际解析器的markdown实现是Jon MacFarleanepeg-markdown它的解析器基于名为peg解析表达式语法解析器生成器。


编辑:毛里西奥·费尔南德斯(Mauricio Fernandez)最近发布了他的简单标记Markdown解析器,他将其编写为OcsiBlog Weblog引擎的一部分。因为解析器被写入OCaml中,这是非常简单和较短(268 SLOC为解析器,43 SLOC为HTML发射极),但超炫快速(20%的速度比折扣(写在手工优化C)和sixhundred倍的速度比BlueClothRuby)),尽管它尚未针对性能进行优化。因为它仅供Mauricio自己内部使用,以供他的博客使用,所以与Markdown官方规范存在一些差异,但是Mauricio已创建了一个分支,用于还原大部分更改


1
有趣。也许我会尝试将其转换为f#项目
ShuggyCoUk,2010年

@Benjol同样的古老故事:没有时间:/
ShuggyCoUk 2010年

1
Terrence Parr(ANTLR的合著者)为ANTLR 4撰写了一篇文章:github.com/parrt/mini-markdown
Chris S

17

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

也许您感兴趣的事情...


1
现在已正式弃用
Fabich

7

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

基本上,在读取输入文件时,我会构建一个类似于微型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.
    

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

我确定有很多小细节需要处理,而且我很确定Regexes在此过程中会变得很方便。
毕竟,它们是要处理文本的。


3

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

阅读现有的解析器代码当然很出色,既可以查看似乎是复杂性的主要来源,又可以使用任何特殊的巧妙技巧。MD5校验和的使用似乎有点不可思议,但是我还没有研究足够的代码来理解为什么这样做。例程中的注释称为_EscapeSpecialChars()状态:

我们将用相应的MD5校验和值替换每个此类字符;这可能是过大的杀伤力,但是它应该防止我们偶然与逃生值相撞。

用完整的MD5替换单个字符确实很奢侈,但也许确实有道理。

当然,考虑为Flex之类的工具摆脱正则表达式沼泽而创建一个“ true”语法是明智的。


MD5仍然困扰着我,而且过多的字符串操作必须比您可以编写的任何实际的像样的解析器都要慢。
约翰·莱德格伦

2
Flex实际上只是解析器的一半。将输入标记化后,您需要确定标记的含义。这就是解析器生成器的作用。有很多。(“解析器组合器”,“递归下降”和“ LALR(1)”是Google的关键词。)
jrockway,2009年

1
@jrockway:当然是这样,我想我耸了耸肩,想着“但是,如果他读过Flex,他会自动找到Bison的”。:) 谢谢。
放松



1

如果您使用的编程语言具有三个以上的其他用户,则应该能够找到一个库来为您解析。快速的Googleing显示了CL,Haskell,Python,JavaScript,Ruby等库。您极不可能需要重新发明这个轮子。

如果您真的必须从头开始编写它,我建议编写一个适当的解析器。使用此技术,您将不必逃脱带有MD5哈希的事物。(我同意,如果必须执行此类操作,那么该是重新考虑设计的时候了。)


我为挑战而战。我看了看图书馆,但它们简直糟透了。丑陋而愚蠢。我正在考虑用F#编写解析器,因为我需要一个F#项目,但最终我可能会用C#完成它。
约翰·莱德格伦

希望F#拥有像Parsec这样的库;如果是这样,这将是一个有趣的项目;)
jrockway

0

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

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

正则表达式可在perl中使用,因为perl和regex是最好的朋友。


1
正则表达式和perl是最好的朋友,因为有人这么说。这个事实没有比它的历史血统更真实的事实了,那就是它的用法。我没有用过像perl这样的东西。
约翰·莱德格伦

7
然后,不要使用它。此外,要学习讽刺意味。
garrow

0

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

那里有很多开源Wiki,您可以检查解析器的代码。多数使用REGEX

看看Screwturn Wiki,它有一个有趣的多通道格式化程序管道,一种非常好的技术-请参阅/core/Formatter.cs和/core/FormatterPipeline.cs

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


0

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

但它保留了MD5部分。

我无法直接帮助您进行解析的编码,但是也许此链接可以以某种方式帮助您。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.