PEG
PEG(Parsing Expression Garmmer,解析文法表达式)是一种用于定义语法规则的形式化的方法,主要用于解析(Parsing)。它特别适合解析器的实现。
PEG 语法规则
PEG 规则通常由以下几种基本操作组成:
- 序列(Sequence):
A B表示A解析成功后,继续解析B。 - 选择(Ordered Choice):
A / B表示尝试解析A,如果失败,再尝试B。 - 零次或多次(Zero or More):
A*表示匹配A0 次或多次。 - 一次或多次(One or More):
A+表示匹配A1 次或多次。 - 可选(Optional):
A?表示A可以出现 0 或 1 次。 - 前瞻(Lookahead):
- - 正前瞻:`&A` 表示如果 `A` 可以匹配,则继续(但不消费输入)。
- - 负前瞻:`!A` 表示如果 `A` 不能匹配,则继续(不消费输入)。
举个例子
以解析一行最基础的sql为例,来实现一个最简单的解析器, sql如下:
SELECT name, age FROM users;
拆解成不同的组成部分:
SELECT关键字(必须有)。- 列列表:
name, age(可以是多个,用 , 分隔)。 FROM关键字(必须有)。- 表名:
users(单个标识符)。 - 语句以
;结束(可选)。
定义PEG语法
SelectStatement <- "SELECT" _ ColumnList _ "FROM" _ TableName _ ";"
ColumnList <- "*" / Identifier ("," _ Identifier)*
TableName <- Identifier
Identifier <- [a-zA-Z_][a-zA-Z0-9_]*
_ <- [ \t\n\r]*
语法解释
SelectStatement- - 以`SELECT`开头(区分大小写)
- - 解析`ColumnList`(支持*或多个列名)
- - `FROM`关键字
- - `TableName`单个标识符
- - 以`;`结束
ColumnList- - `*`代表所有列
- - 或者是一组`Identifier`(列名),用`,`分隔
TableName- - 解析一个`标识符`,代表表名
Identifier- - 匹配`SQL允许的标识符`(字母,数字,下划线)
_- - 允许空格,换行等,确保解析不会被空格干扰|
解析实例
SELECT name, age FROM users;
解析步骤
SELECT匹配成功。ColumnList解析:- - `name`(标识符)
- - `, age`(标识符)
FROM匹配成功。TableName解析users。;结束,解析成功!
SELECT * FROM employees;
解析步骤
SELECT匹配成功。ColumnList解析*。FROM匹配成功。TableName解析employees。;结束,解析成功!