3

peg.js ast文法规则理解

 2 years ago
source link: https://www.zoucz.com/blog/2020/07/28/23f78990-d0b3-11ea-90b5-eb40e9720ed0/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

官方文档 我要说话

先写一点学习文档之后的简单理解吧,后续补上实践过程中的采坑经历。 我要说话

规则基本组成

peg文法基本的组成结构是 我要说话

规则名 "规则别名"
    = 解析表达式

在第一个规则前可以定义一个初始化器,语法为花括号包一段js代码
初始化器会在规则被执行之前运行,其中定义的变量和函数可以在解析表达式中访问 我要说话

{
  function makeInteger(o) {
    return parseInt(o.join(""), 10);
  }
}

解析表达式

一个描述2*(3+4)的文法示例 我要说话

{
  function makeInteger(o) {
    return parseInt(o.join(""), 10);
  }
}

start
  = additive

additive
  = left:multiplicative "+" right:additive { return left + right; }
  / multiplicative

multiplicative
  = left:primary "*" right:multiplicative { return left * right; }
  / primary

primary
  = integer
  / "(" additive:additive ")" { return additive; }

integer "integer"
  = digits:[0-9]+ { return makeInteger(digits); }

一个解析表达式可能由下面这些部分组成我要说话

1.严格字面量

直接匹配一段字符文本,例如上面的 "+"
可以在后面加i表示忽略大小写,例如 "abC"i 我要说话

2.单个字符匹配

就是一个点号 . ,匹配一个任意字符并返回,注意和"."区分开,后者严格匹配一个点号字符我要说话

3.[characters] 类似正则的可选单字符匹配

如:
[abc]+
[abc]*
[^abc]*
[^abc]*i我要说话

4. 其它解析表达式

并不是上面的 left:multiplicativeleft:multiplicative是用一种带label的子解析表达式来解释的 我要说话

这里应该是指直接引用解析表达式,而不给label,例如直接写multiplicative我要说话

5. 子解析表达式

子表达式咋理解呢? 我理解为,一系列匹配规则作为一个整体来解析,这个整体叫一个子表达式我要说话

( expression ) 匹配一个子表达式
expression * 匹配0次或多次的子表达式
expression + 一次或多次
expression ? 0次或1次
& expression 类似于peek,看看能否匹配成功,但是不消耗字符串
! expression 与上面的相反,看看是否匹配不成功
$ expression 尝试匹配该表达式. 如果匹配成功, 不会返回匹配结果, 而是返回匹配成功的字符串.
TODO: 这个咋理解?
label : expression 匹配一个表达式,将匹配结果放到一个label里边,这个大量用到,一般和parse action 或者 predicate 配合使用,其label值可以传递给js代码块使用
expression1 expression2 ... expressionn 匹配一堆表达式,将结果放到数组中返回
expression { action } 如果匹配成功,则运行action
expression1 / expression2 / ... / expressionn 依次匹配,返回第一个匹配上的结果。 我要说话

additive
  = left:multiplicative "+" right:additive { return left + right; }
  / multiplicative

最后一行的斜杠就这么理解我要说话

6. parse action

花括号里边包一段js就是parse action,其作用是把其它rule的结果计算后作为当前rule的结果。如上面的 { return left + right; } 我要说话

action是一段JavaScript代码, 可以把它当做一个方法来运行. labeled表达式的匹配结果会被当做action的参数, 传递给action. action应该通过return返回一个JavaScript结果, 该结果会被当做前面表达式的匹配结果.我要说话

在action代码块中, 遇到非预期情况, 想要中断parse可以调用 expected方法, 该方法会抛出一个异常. expected方法接受俩个参数, 第一个参数是description, 表明当前位置期望输入以及可选的location信息(默认值是what location would return). description会被当做exception中的message的一部分.我要说话

在action代码中也可以调用 error方法, 该方法也会抛出一个异常. error方法接受俩个参数, 第一个参数是error message, 第二个参数是可选的location信息(默认值是 what location would return). message会在抛出异常中使用. action中的代码块可以访问初始器中定义的方法和变量. action代码块的左右大括号必须都在. action 代码块中可以通过text方法访问匹配成功的字符. action代码块中还可以通过访问location方法得到location信息, 该方法会返回下面这种对象. 我要说话

{
  start: { offset: 23, line: 5, column: 6 },
  end:   { offset: 25, line: 5, column: 8 }
}

start属性指向了表达式开始位置, end属性指向表达式的结束位置. offset是一个基于0 的offset索引位置, line和 column 属性是基于1的索引位置. 我要说话

action 代码块中可以通过options变量访问传递给parser的options.我要说话

& { predicate } 判断true,不是true则报错
! { predicate } 判断false,不是false则报错
这里没看到过实例,看起来是和parse action一样使用的,只是前面加了判断我要说话

本文链接:https://www.zoucz.com/blog/2020/07/28/23f78990-d0b3-11ea-90b5-eb40e9720ed0/我要说话

☞ 参与评论我要说话


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK