PEGJS:如何将 NOT (!) 逻辑运算符添加到解析 AND (
•浏览 1
PEGJS: How to add NOT (!) logical operator to grammar that parses AND (&&) OR (||) logic statements
我对编写语法非常陌生(确切地说是第一次),我想创建一个可以为基本逻辑语句返回 AST 的语法。到目前为止,我有一个可以处理 AND、OR 逻辑的语法(我只是修改了官方 pegjs 网站上的基本计算器示例)。以下是语法当前的作用:
声明
item1 && item2
{
"type":"AND",
"left":"item1",
"right":"item2"
}
(item1 || item2) && item3
{
"type":"AND",
"left": {
"type":"OR",
"left":"item1",
"right":"item2"
},
"right":"item3"
}
start
= logical_or
logical_or
= left:logical_and ws+"||" ws+ right:logical_or { return {type:"OR", left:left, right:right} }
/ logical_and
logical_and
= left:primary ws+"&&" ws+ right:logical_and { return {type:"AND", left:left, right:right} }
/ primary
primary
= token
/"(" logical_or:logical_or")" { return logical_or; }
token
= token:[a-zA-Z0-9_]+ { return token.join(""); }
ws
= [ \\t]
item1 && !item2
!(item1 && item2 && item3)
logical_and
= left:factor ws+"&&" ws+ right:logical_and { return {type:"AND", left:left, right:right} }
/ factor
factor
="!" ws* operand:factor { return {type:"NOT", operand: operand } }
/ primary
返回 AST
item1 && item2
{
"type":"AND",
"left":"item1",
"right":"item2"
}
(item1 || item2) && item3
{
"type":"AND",
"left": {
"type":"OR",
"left":"item1",
"right":"item2"
},
"right":"item3"
}
start
= logical_or
logical_or
= left:logical_and ws+"||" ws+ right:logical_or { return {type:"OR", left:left, right:right} }
/ logical_and
logical_and
= left:primary ws+"&&" ws+ right:logical_and { return {type:"AND", left:left, right:right} }
/ primary
primary
= token
/"(" logical_or:logical_or")" { return logical_or; }
token
= token:[a-zA-Z0-9_]+ { return token.join(""); }
ws
= [ \\t]
item1 && !item2
!(item1 && item2 && item3)
logical_and
= left:factor ws+"&&" ws+ right:logical_and { return {type:"AND", left:left, right:right} }
/ factor
factor
="!" ws* operand:factor { return {type:"NOT", operand: operand } }
/ primary
声明:
item1 && item2
{
"type":"AND",
"left":"item1",
"right":"item2"
}
(item1 || item2) && item3
{
"type":"AND",
"left": {
"type":"OR",
"left":"item1",
"right":"item2"
},
"right":"item3"
}
start
= logical_or
logical_or
= left:logical_and ws+"||" ws+ right:logical_or { return {type:"OR", left:left, right:right} }
/ logical_and
logical_and
= left:primary ws+"&&" ws+ right:logical_and { return {type:"AND", left:left, right:right} }
/ primary
primary
= token
/"(" logical_or:logical_or")" { return logical_or; }
token
= token:[a-zA-Z0-9_]+ { return token.join(""); }
ws
= [ \\t]
item1 && !item2
!(item1 && item2 && item3)
logical_and
= left:factor ws+"&&" ws+ right:logical_and { return {type:"AND", left:left, right:right} }
/ factor
factor
="!" ws* operand:factor { return {type:"NOT", operand: operand } }
/ primary
返回 AST
item1 && item2
{
"type":"AND",
"left":"item1",
"right":"item2"
}
(item1 || item2) && item3
{
"type":"AND",
"left": {
"type":"OR",
"left":"item1",
"right":"item2"
},
"right":"item3"
}
start
= logical_or
logical_or
= left:logical_and ws+"||" ws+ right:logical_or { return {type:"OR", left:left, right:right} }
/ logical_and
logical_and
= left:primary ws+"&&" ws+ right:logical_and { return {type:"AND", left:left, right:right} }
/ primary
primary
= token
/"(" logical_or:logical_or")" { return logical_or; }
token
= token:[a-zA-Z0-9_]+ { return token.join(""); }
ws
= [ \\t]
item1 && !item2
!(item1 && item2 && item3)
logical_and
= left:factor ws+"&&" ws+ right:logical_and { return {type:"AND", left:left, right:right} }
/ factor
factor
="!" ws* operand:factor { return {type:"NOT", operand: operand } }
/ primary
这是我目前掌握的语法。可以直接粘贴到在线pegjs解析器(http://pegjs.majda.cz/online)。
item1 && item2
{
"type":"AND",
"left":"item1",
"right":"item2"
}
(item1 || item2) && item3
{
"type":"AND",
"left": {
"type":"OR",
"left":"item1",
"right":"item2"
},
"right":"item3"
}
start
= logical_or
logical_or
= left:logical_and ws+"||" ws+ right:logical_or { return {type:"OR", left:left, right:right} }
/ logical_and
logical_and
= left:primary ws+"&&" ws+ right:logical_and { return {type:"AND", left:left, right:right} }
/ primary
primary
= token
/"(" logical_or:logical_or")" { return logical_or; }
token
= token:[a-zA-Z0-9_]+ { return token.join(""); }
ws
= [ \\t]
item1 && !item2
!(item1 && item2 && item3)
logical_and
= left:factor ws+"&&" ws+ right:logical_and { return {type:"AND", left:left, right:right} }
/ factor
factor
="!" ws* operand:factor { return {type:"NOT", operand: operand } }
/ primary
我想做的是添加对 NOT 运算符 (!) 的支持。因此,例如,我希望能够解析以下语句:
item1 && item2
{
"type":"AND",
"left":"item1",
"right":"item2"
}
(item1 || item2) && item3
{
"type":"AND",
"left": {
"type":"OR",
"left":"item1",
"right":"item2"
},
"right":"item3"
}
start
= logical_or
logical_or
= left:logical_and ws+"||" ws+ right:logical_or { return {type:"OR", left:left, right:right} }
/ logical_and
logical_and
= left:primary ws+"&&" ws+ right:logical_and { return {type:"AND", left:left, right:right} }
/ primary
primary
= token
/"(" logical_or:logical_or")" { return logical_or; }
token
= token:[a-zA-Z0-9_]+ { return token.join(""); }
ws
= [ \\t]
item1 && !item2
!(item1 && item2 && item3)
logical_and
= left:factor ws+"&&" ws+ right:logical_and { return {type:"AND", left:left, right:right} }
/ factor
factor
="!" ws* operand:factor { return {type:"NOT", operand: operand } }
/ primary
我的第一个问题是您通常如何在 AST 中表示 NOT 运算符?似乎 not 运算符可以应用于 AST 的整个左分支或右分支,但与 OR 和 AND 不同,它不会同时具有左分支和右分支。
第二个问题是如何在 PEGJS 语法中支持 NOT 运算符?
非常感谢您的宝贵时间!
编辑:修复了 AST 表示
你只需要在 "AND" 和 "primary" 之间引入一个层:
item1 && item2
{
"type":"AND",
"left":"item1",
"right":"item2"
}
(item1 || item2) && item3
{
"type":"AND",
"left": {
"type":"OR",
"left":"item1",
"right":"item2"
},
"right":"item3"
}
start
= logical_or
logical_or
= left:logical_and ws+"||" ws+ right:logical_or { return {type:"OR", left:left, right:right} }
/ logical_and
logical_and
= left:primary ws+"&&" ws+ right:logical_and { return {type:"AND", left:left, right:right} }
/ primary
primary
= token
/"(" logical_or:logical_or")" { return logical_or; }
token
= token:[a-zA-Z0-9_]+ { return token.join(""); }
ws
= [ \\t]
item1 && !item2
!(item1 && item2 && item3)
logical_and
= left:factor ws+"&&" ws+ right:logical_and { return {type:"AND", left:left, right:right} }
/ factor
factor
="!" ws* operand:factor { return {type:"NOT", operand: operand } }
/ primary
由于 ! 是一元运算符,"left" 和 "right" 没有真正意义;我使用了"操作数"。