Build A Parser By Rust(上)
输入“/”快速插入
🔬
Build A Parser By Rust(上)
1月18日创建
14
42
0
背景
最近在跟着
mbrubeck
大佬写的
Robinson
学习用 Rust 来编写一个简单的浏览器引擎(后续写完我也会出一个文档来介绍下),在其过程中因为需要解析 html、css 等格式文件,所以你需要编写相关的解析器来完成。
而从 0 到 1 的手写解析器是
一件非常枯燥且容易出错的行为
,因为你不仅需要考虑其具体需要解析的协议规则,还需要考虑解析器的错误处理、拓展性、解析性能等,所以在文章中大佬也提到,建议后续可通过目前已有的类似 pest 等解析器三方库来优化。
回想在我日常的开发工作中,遇到需要构造解析器的场景较少,往往是,如果出现对解析某格式或协议的信息,如 Json、Csv 等,为了追求效率,直接使用找针对解析该格式或协议的三方库。但实际上并不是所有协议或格式都有别人写好的解析器,
特别是对于各种网络通信协议等,且写好的解析器也很难针对其定制化
,所以借助这个契机,正好学习
了解下解析器,及构造解析器的相关实践,方便后续有类似场景的使用。
💬
注意:
•
此篇文档不会重点深挖解析器和解析器库的相关原理,更多是对于
「
解析器
入门的
了解及其实践
」
•
此系列文档分为上下两篇,上篇主要讲述解析器的了解和三方库的使用,下篇主要讲述具体的实践
•
此系列文档出现的源码可在
https://github.com/catwithtudou/parser_toy
查看
前置知识
下面会介绍一些关于解析器相关的前置背景知识,帮助了解后面的理解。
Parser
这里提到的解析器(Parser)实际是更广泛的定义,通常是指把
某种格式的信息转换成某种数据结构
的组件。
就好比将某种某种格式的信息进行“解码”,抽象成有组织的数据结构信息,方便对信息的理解和处理加工。
举个🌰:此时有一段算数表达式的文本 "1 + 2",期望通过程序能够计算出结果。
为了让程序能够识别算术表达式,可通过针对算法表达式的解析器,转换成 (left,op,right) 的结构体进行计算。
对于计算机领域来说,
在处理数据的过程中解析器必不可少,能够应用各种数据处理场景中
,比如较为常见的:
•
在底层编译器或解释器中的解析器,其主要作用就是将源码进行词法和语法的分析,提取出抽象语法树 AST
•
对于 Web 应用较多的数据交换格式 Json 的文本,可通过对应的解析器序列化需要的数据结构进行处理加工
•
其他如通过解析器解析网络通信协议、脚本语言、数据库语言等
PEG
在介绍 PEG (解析表达文法)之前,我们这里可通过(假设)更为常见的正则表达式来进行方便理解。
正则表达式和 PEG 联系主要是都可在
处理字符文本时通过特定的语法对字符文本进行匹配和解析
,而不同点在于:
•
【语法方面】前者是使用一种特定语法来描述字符串的模式,通常用于处理简单的字符串匹配和搜索。而后者使用一种
更复杂的语法来描述语言结构
,通常用于处理复杂的语言解析和分析需求。
•
【应用领域】前者主要用于处理简单的文本处理需求,例如查找特定模式的文本或验证输入的格式。而后者主要用于
处理复杂的语言结构
,例如编程语言的语法分析和解释器的构建。
通过
介绍
,相信大家对于 PEG 有了简单的理解
。
而为什么介绍 PEG,其原因就是因为
可通过 PEG 实现的工具(称为 Parser Generator)来实现定制的 Parser。
接下来我们来简单正式介绍下 PEG 即 解析表达文法:
1.
PEG(解析表达文法)简介
解析表达文法
,简称
PEG
(英语:
P
arsing
E
xpression
G
rammar):
•
是一种
分析型
形式文法
。在 04年由 Bryan Ford 推出,与20世纪70年代引入的
自顶向下的语法分析语言
家族相关
•
作为描述语言结构的语法,相较于正则表达式可以处理更复杂的语言结构,因
递归性特点可描述无限嵌套的结构
•
使用一种
简单而灵活的方式来定义语法规则
,该规则可以被用来解析输入字符串并生成语法树
•
易用性、正确性和性能
的优势且提供错误报告、可重用规则模板等功能,因此在解析和分析文本时被广泛使用
2.
PEG 应用简介
PEG 的语法类似于编程语言,使用
操作符
和
规则
来描述语言结构
:
•
操作符包括“|”(或)、“&”(与)、“?”(可选)等,规则则用于描述语言的具体结构
•
例如下面是一个简单的 PEG 规则,它描述了一个整数的语法:
Plain Text
int := [0-9]+