项目简介:Markdown 已经是程序员的标配,其语法简单的特点让我们能够更加专注于内容输出与写作。本次项目我们将针对 Markdown 的一些最常用语法,手动实现一个 Markdown 解析器,作为展示,还将为文档生成目录
本项目由欧龙崎发布在实验楼,完整教程及在线练习地址:C++ 打造 Markdown 解析器
一、概述
效果展示
如图所示:
项目涉及的知识点
词法分析技术
语法树
DFS 深度优先搜索
C++11
使用指针进行字符流处理
Markdown 常用语法
Markdown 的语法非常简单,下面是一些常用的语法:
## 标题
# 一级标题
## 二级标题
### 三级标题
## 强调
- **粗体**
- _斜体_
## 引用
> 引用内容
## 列表
- 列表内容7
- 列表内容8
- 列表内容9
1. 列表内容10
2. 列表内容11
3. 列表内容12
## 代码
代码的插入方式 `printf('\n');`
function method()
{
alert("javascript");
}
## 链接
行内连接 [github](https://github.com/) 的链接
## 图片
![shiyanlou logo](https://static.shiyanlou.com/img/logo_03.png)
可以看到,Markdown 的语法之所以不复杂,是因为它的大部分词法规则都位于行首。这就为我们快速编写一个简单的 Markdown 解析器提供了方便之处。
唯一需要考虑的,就是诸如链接、图片、代码、粗体、斜体等这些特殊的标记。
二、测试驱动
为了更加专注于编写 Markdown 解析器本身,我们先部署好相关测测试文件。
首先你可以输入:
http://labfile.oss.aliyuncs.com/courses/569/test.md
来获取 Markdown 的测试文件。
其次,为了测试 Markdown 的解析结果,我们很自然的想到把解析结果直接转换到 HTML 进行展示,所以,这里已经为你准备好了好看的 CSS 文件,你可以先下载:
wget http://labfile.oss.aliyuncs.com/courses/569/github-markdown.css
为了让我们的代码便于测试,我们先编写好主函数:
//
// main.cpp
// MarkdownParser
//
#include <fostream> // std::ofstream
#include "mdtransform.hpp" // 需要实现的 Markdown 解析类
int main() {
// 装载构造 Markdown 文件
MarkdownTransform transformer("test.md");
// 编写一个 `getTableOfContents()` 方法来获取 Markdown 文件 HTML 格式的目录
std::string table = transformer.getTableOfContents();
// 编写一个 `getContents()` 方法来获取 Markdown 转成 HTML 后的内容
std::string contents = transformer.getContents();
// 准备要写入的 HTML 文件头尾信息
std::string head = "<!DOCTYPE html><html><head>\
<meta charset=\"utf-8\">\
<title>Markdown</title>\
<link rel=\"stylesheet\" href=\"github-markdown.css\">\
</head><body><article class=\"markdown-body\">";
std::string end = "</article></body></html>";
// 将结果写入到文件
std::ofstream out;
out.open("output/index.html");
// 将转换后的内容构造到 HTML 的 <article></article> 标签内部
out << head+table+contents+end;
out.close();
return 0;
}
至此,我们的整个项目目录结构树为:
MarkdownParser
├── main.cpp
├── output
│ └── github-markdown.css
└── test.md
生成这个目录树的工具叫做
tree
, 如果你感兴趣可以使用sudo apt-get install tree
来获取这个命令工具,使用方法如图所示:
三、mdtransform
设计
我们要解析 Markdown 文件,自然就要先在程序中定义好相关的词法信息、语法规则,这样才能后为后续的转换工作提供铺垫。
如果你对编译原理有所了解,就能够立刻明白对 Markdown 的解析,其实就是编译过程中的词法分析和语法分析阶段,而最后的到 HTML 的转换,实际上就是『目标代码的生成』这个阶段。
幸运的是,Markdown 的语法是在是太过于简单,它所支持的这些语法,几乎完全不需要我们对它的语义进行分析,这就省去了语义分析、代码优化等这些阶段。使得整个 Markdown 解析器变得非常的简单。
本项目实现的完整教程和代码详解,可在实验楼中查看并在线完成,立即【开始实验】
更多C++经典项目:C/C++全部 - 课程
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。