pegjs是peg文法的一种实现,peg文法是一种解析表达式文法,其具体的解析公式和常用的正则表达式很像,需要注意的是peg不允许解析存在二义性。
pegjs官网 https://pegjs.org/
在正则匹配不能实现或困难时可以选择pegjs来处理解析,如sql语句的解析,在构造dsl时编写自定义规则也非常方便。
1.这里以一段java代码的解析为例,准备一段需要解析的java代码
class Test {
@tag(1)
@label("名字")
String name;
@tag(2)
@label("性别 0-男 1-女")
Int sex;
}
2.定义根节点,包含了类型、版本和代码块数组,使用*号表示多个
CodeBlock = blocks:IdlBlock* {
return {
type: 'javaSchema',
version: '1.0.0',
blocks
}
}
3.使用_表示空白符,匹配class关键字,使用Identifier这条规则匹配类名并赋值给className后返回,
_ '{' children:Children* '}'
解析空白符后两个花括号中间的子节点
IdlBlock =
_ 'class'
_ className:Identifier
_ '{' children:Children* '}'
_ {
return {
className,
children
}
}
_ "whitespace" = [ \t\r\n]*
Identifier = $([a-zA-Z_])+
4.在子节点中解析变量
Children =
_ variable:Variable';'
_ {
return {
variable
}
}
5.定义变量解析规则
Variable =
_ tag:Tag?
_ label:Label?
_ type:DataType?
_ name:Identifier?
_ {
return {
tag,
label,
type,
name
}
}
6.解析@tag(1)
并返回其中的参数
Tag = '@tag('tagColumn:TagColumn')' {
return tagColumn
}
TagColumn = $([0-9])*
7.解析@label("名字")
并返回参数中的描述信息
Label = '@label("'labelColumn:LabelColumn'")' {
return labelColumn
}
LabelColumn = $([^\r\n\t\"\)])*
8.解析变量的类型,这里仅定义了代码块中用到的两种类型,也可以扩展更多类型
DataType = 'String' / 'Int'
CodeBlock = blocks:IdlBlock* {
return {
type: 'javaSchema',
version: '1.0.0',
blocks
}
}
IdlBlock =
_ 'class'
_ className:Identifier
_ '{' children:Children* '}'
_ {
return {
className,
children
}
}
_ "whitespace" = [ \t\r\n]*
Identifier = $([a-zA-Z_])+
Children =
_ variable:Variable';'
_ {
return {
variable
}
}
Variable =
_ tag:Tag?
_ label:Label?
_ type:DataType?
_ name:Identifier?
_ {
return {
tag,
label,
type,
name
}
}
Tag = '@tag('tagColumn:TagColumn')' {
return tagColumn
}
TagColumn = $([0-9])*
Label = '@label("'labelColumn:LabelColumn'")' {
return labelColumn
}
LabelColumn = $([^\r\n\t\"\)])*
DataType = 'String' / 'Int'
{
"type": "javaSchema",
"version": "1.0.0",
"blocks": [
{
"className": "Test",
"children": [
{
"variable": {
"tag": "1",
"label": "名字",
"type": "String",
"name": "name"
}
},
{
"variable": {
"tag": "2",
"label": "性别 0-男 1-女",
"type": "Int",
"name": "sex"
}
}
]
}
]
}
上面的规则可以直接在pegjs官网的网页版中验证,pegjs也提供了npm包,pegjs的js api比较简单可以参考pegjs官方文档