1

项目简介: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++全部 - 课程


xiaoxiaozi
736 声望236 粉丝

Learn by doing @ shiyanlou.com