解析markdown_将markdown编译为html

本文介绍了如何将Markdown转换为HTML的过程,遵循编译原理的步骤,包括提出语法、词法解析、语法解析和代码生成。文章通过一个简化版的Markdown编译器示例,展示了如何处理标题和正文,以及词法状态机和LL(1)文法的应用。
摘要由CSDN通过智能技术生成

缘起

IT人写技术文档,例如我自己写博客,用的最多的就是 markdown.  但是在浏览器中看到的这些博客都是以 html 的格式展示在人们的面前的. 所以一个自然的问题就是markdown怎么变成html的?

分析

背景

众所周知,markdown和html都是全球通用的标记语言,那么从一种语言要转换为另一种语言不就是编译吗? 这学期刚好学了编译原理. 正好用上.

ps:这里墙裂向大家安利一下 coding 迪士尼陈屹老师的免费课程《自己动手用java写编译器》,一节课讲原理,一节课写代码,知行合一,落到实处.

这里并不想一次性写一个非常完善的markdown转html的语法解析器. 只是想将仅仅包含标题和正文的markdown文档严格遵从编译原理的流程步骤转换为html.

也就是我们写这个编译器的步骤如下

  1. 提出语法
  2. 修改语法使之满足 LL(1) 文法. 因为本文打算写一个 自顶向下语法解析器哈~
  3. 完成词法解析
  4. 完成语法解析
  5. 代码生成, 也就是生成 html

为什么要严格遵从上述编译原理的框架? 因为只有这样,这个编译器的扩展性才更好,才能为后续写更复杂的markdown语法转html编译器打下基础框架.  而不是靠灵光一闪的技巧性处理, 那种是很难维护和扩展的.

什么叫做仅仅包含标题和正文? 举个例子,咱们想要处理的markdown文档长下面的样子

### 人类補完计划 Nerv 绝密 \n
不能逃避、不能逃避、不能逃避,知道何谓痛苦的人比较能温柔待人。这和软弱是不同的。 \n
##这是最优先事项 \n
结果人类的敌人还是敌人, 并非使徒. \n
#### 人类终将補完 \n
肉体归于LCL之海,  灵魂回到莉莉丝之卵, 和亚当握手吧!\n
审判日到来之时, 人类还是使徒? 贤者必将做出抉择!
# 死海古卷的仪式被碇源堂改了! SEELE 对 Nerv 绝不会善罢甘休

编译后的html文档如下


人类補完计划 Nerv 绝密 



不能逃避、不能逃避、不能逃避,知道何谓痛苦的人比较能温柔待人。这和软弱是不同的。 



这是最优先事项 



结果人类的敌人还是敌人, 并非使徒. 



人类终将補完


肉体归于LCL之海,  灵魂回到莉莉丝之卵, 和亚当握手吧!



审判日到来之时, 人类还是使徒? 贤者必将做出抉择!



死海古卷的仪式被碇源堂改了! SEELE 对 Nerv 绝不会善罢甘休


语法

首先,我们要制定语法. 我们不难 YY 出如下巴克斯范式

article  ->   title article | line article | ε
title    ->   POUND line
line     ->   TEXT LF

其中遵从国际惯例, 小写英文单词表示非终结符, 大写英文单词表示终结符.  关于语法中的token和symbol的说明如下

  • article 是文档, 它是语法的全局非终结符
  • title 表示文档的标题,
  • line 表示一行文本.
  • POUND是  若干# 字符.
  • TEXT 是遇到换行符之前的文本.
  • LF(line feed) 是换行符, 也就是markdown文档中的 '\n'
  • ε 表示空,因为我们的编译器允许空的markdown文档.

显然,上述语法其实还可以再用一下边角替换再精简一些,变成标准的 LL(1) 语法

article   ->   title_or_line article | ε
title_or_line   ->   title | line
title     ->   POUND line
line      ->   TEXT LF

但是注意上述巴克斯范式的第二条,其实是不利于我们写 LL(1) 的,而只利于写递归下降. 所以要进行单子替换,于是得到我们最终的语法推导规则

article   ->   title_or_line article | ε
title_or_line   ->   POUND line | line
line      ->   TEXT LF
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值