предисловие
В этой статье мы кратко попрактикуемся в лексическом анализе компилятора.Учитывая сложность реализации лексического анализа, здесь мы выбрали текстовый язык уценки в качестве объекта для краткого введения.
текст
1. Что такое уценка?
определение:
Markdown — это легкий язык разметки, основанный Джоном Грубером. Это позволяет людям писать документы в формате простого текста, который легко читать и писать, а затем преобразовывать их в действительные документы XHTML (или HTML).
Благодаря легким, удобным для чтения и написания функциям Markdown, а также поддержке изображений, диаграмм, математических выражений и блоков кода многие веб-сайты в настоящее время широко используют Markdown для написания справочных документов или публикации сообщений на форумах. .
стандартизация:
Со временем Markdown стал неофициальной спецификацией и эталонной реализацией, обычно конвертируемой в HTML, и появилось множество реализаций Markdown. Люди разработали их в основном из-за необходимости в дополнительных функциях поверх основного синтаксиса, таких как таблицы, сноски, списки определений (технически списки описаний HTML) и Markdown в блоках HTML. В то же время обращают на себя внимание некоторые неясности в неформальных нормах. Эти проблемы побудили некоторых разработчиков парсеров Markdown работать над стандартизацией.
RFC 7763 и RFC 7764 были опубликованы в марте 2016 года. RFC 7763 представил текст/уценку типа MIME из исходного варианта. RFC 7764 обсуждает и регистрирует варианты MultiMarkdown, GitHub Flavored Markdown (GFM), Pandoc, CommonMark и Markdown.
2. Связь между markdowm и html
Ниже перечислены соответствия между некоторым синтаксисом уценки и синтаксисом html.
синтаксис уценки | HTML-синтаксис |
---|---|
# Название 1 | <h1>标题</h1> |
## Название 2 | <h2> 标题2 </h2> |
Пустые разделители строк обозначают абзацы | <p></p> |
Два пробела в конце строки обозначают новую строку | <p> <br /> </p> |
_курсив_ | <em>斜体</em> |
жирный | <strong>粗体</strong> |
`код` | <code>代码<code> |
--- | <hr /> |
* 1 | <ul> <li> 1 </li> </ul> |
Из-за ограниченного места здесь перечислено так много грамматик.Чтобы узнать о других грамматиках, пожалуйста, обратитесь к книге "The Great Markdown".
Теперь, когда известно грамматическое соответствие между разметкой и html, как реализовать компилятор (парсер) для распознавания и преобразования грамматики?
3. лексический анализ уценки
С грамматическим стандартом уценки вы можете анализировать грамматику, то есть лексический анализ здесь, Возьмем заголовок в качестве примера.
Во-первых, лексический синтаксический анализатор необходим для создания соответствующей последовательности токенов в соответствии с грамматическими правилами заголовка.
// 词法解析器
Class Lexer {
constructor(options) {
this.tokens = [];
this.tokens.links = Object.create(null);
this.options = options || {};
this.rules = {
// heading 匹配规则
heading: /^ {0,3}(#{1,6}) +([^\n]*?)(?: +#+)? *(?:\n+|$)/
// ...
};
}
// 生成 token 序列
token(src) {
while (src) {
// heading
if (cap = this.rules.heading.exec(src)) {
src = src.substring(cap[0].length);
this.tokens.push({
type: 'heading',
depth: cap[1].length,
text: cap[2]
});
continue;
}
// other
// ...
}
return this.tokens;
}
}
4. Компилировать (парсить) уценку в html
Последовательность маркеров уценки была получена выше, и ее необходимо разобрать на соответствующие теги в соответствии с грамматикой html следующим образом.
// 解析器 - Parsing & Compiling
class Parser {
constructor(options) {
this.tokens = [];
this.token = null;
this.options = options || {};
this.renderer = new Renderer();
}
parse(src) {
this.tokens = src.reverse(); // 先进先出
var out = '';
while (this.next()) {
out += this.tok();
}
return out;
}
next() {
this.token = this.tokens.pop();
return this.token;
}
tok() {
switch (this.token.type) {
// ...
case 'heading': {
return this.renderer.heading(
this.token.text,
this.token.depth
)
}
// ...
}
}
}
// 渲染器(代码生产器)
class Renderer {
constructor(options) {
this.options = options || {};
}
heading(text, level, raw) {
if (this.options.headerIds) {
return '<h'
+ level
+ ' id="'
+ this.options.headerPrefix
+ '">'
+ text
+ '</h'
+ level
+ '>\n';
}
return '<h' + level + '>' + text + '</h' + level + '>\n';
};
}
постскриптум
Поскольку markdown является языком разметки текста, нет необходимости анализировать абстрактное синтаксическое дерево (часть генерации/анализа AST) при разборе и преобразовании кода, что эквивалентно только процессу лексического анализа и генерации кода. Процесс его компиляции и разбора относительно прост по сравнению с полными по Тьюрингу языками.
Вопросы для размышления:
Можно ли построить простой синтаксический анализатор грамматики в соответствии с приоритетом сложения, вычитания, умножения и деления грамматики javascript?
Например:var a = 1 + 3 * 2;
- Статьи по Теме