使用 PEG 解析 JavaScript 的表达式
Parse expression with JavaScript using PEG
我已经编写了解析以下表达式的代码
!=10 AND <=99
到
{
operator: 'AND',
values: [
{
op: '!=',
value: '10',
},
{
op: '<=',
value: '99',
},
],
}
使用 PEG.js。请检查代码沙箱。
但是当我解析以下表达式时,我没有得到预期的输出。
=10 AND <=99 OR =1000
我想要以下输出
{
operator: 'or',
values: [
{
operator: 'and',
values: [
{
op: '=',
value: '10',
},
{
op: '<=',
value: '99',
},
],
},
{
op: '=',
value: '1000',
},
],
}
代码沙箱:https://codesandbox.io/s/javascript-testing-sandbox-forked-h5xh5?file=/src/index.js
不要使用字符串函数来解析比较运算符,让它们成为你语法的一部分。对于像 'AND' 这样的链式操作,使用这样的规则:
operation = head:argument tail:(ws AND ws argument)*
并在代码块中相应地处理 head
和 tail
。
完整示例:
expression = and
and = head:or tail:(ws "OR" ws or)* {
return tail.length ? {op: 'or', values: [head].concat(tail.map(r => r.pop()))} : head
}
or = head:not tail:(ws "AND" ws not)* {
return tail.length ? {op: 'and', values: [head].concat(tail.map(r => r.pop()))} : head
}
not
= "NOT" ws right:not { return {op: 'not', right} }
/ factor
factor
= op:operator value:primary { return {op, value} }
/ value:primary { return {value} }
operator = '!=' / '<=' / '>=' / '<' / '>' / '='
primary = name / number / '(' expression ')'
name = a:[A-Za-z_] b:[0-9a-zA-Z_]* { return a + b.join("") }
number = a:[0-9]+ { return a.join("") }
ws = [ \t]+
我已经编写了解析以下表达式的代码
!=10 AND <=99
到
{
operator: 'AND',
values: [
{
op: '!=',
value: '10',
},
{
op: '<=',
value: '99',
},
],
}
使用 PEG.js。请检查代码沙箱。
但是当我解析以下表达式时,我没有得到预期的输出。
=10 AND <=99 OR =1000
我想要以下输出
{
operator: 'or',
values: [
{
operator: 'and',
values: [
{
op: '=',
value: '10',
},
{
op: '<=',
value: '99',
},
],
},
{
op: '=',
value: '1000',
},
],
}
代码沙箱:https://codesandbox.io/s/javascript-testing-sandbox-forked-h5xh5?file=/src/index.js
不要使用字符串函数来解析比较运算符,让它们成为你语法的一部分。对于像 'AND' 这样的链式操作,使用这样的规则:
operation = head:argument tail:(ws AND ws argument)*
并在代码块中相应地处理 head
和 tail
。
完整示例:
expression = and
and = head:or tail:(ws "OR" ws or)* {
return tail.length ? {op: 'or', values: [head].concat(tail.map(r => r.pop()))} : head
}
or = head:not tail:(ws "AND" ws not)* {
return tail.length ? {op: 'and', values: [head].concat(tail.map(r => r.pop()))} : head
}
not
= "NOT" ws right:not { return {op: 'not', right} }
/ factor
factor
= op:operator value:primary { return {op, value} }
/ value:primary { return {value} }
operator = '!=' / '<=' / '>=' / '<' / '>' / '='
primary = name / number / '(' expression ')'
name = a:[A-Za-z_] b:[0-9a-zA-Z_]* { return a + b.join("") }
number = a:[0-9]+ { return a.join("") }
ws = [ \t]+