Javascript JS解析逻辑变量名称、操作数和值
经过几个小时的努力,我头痛得厉害。 我使用PEG.js解析将输入查询解析为数组。 现在我正在尽我最大的努力写这本语法书。操作数和连接器是静态的,由应用程序生成Javascript JS解析逻辑变量名称、操作数和值,javascript,boolean-logic,peg,Javascript,Boolean Logic,Peg,经过几个小时的努力,我头痛得厉害。 我使用PEG.js解析将输入查询解析为数组。 现在我正在尽我最大的努力写这本语法书。操作数和连接器是静态的,由应用程序生成 start = start:(statement) statement = statement:block_statement* { return statement; } block_statement = OPENPAREN block:block+ CLOSEPAREN connector:CONNECTOR block2:(b
start = start:(statement)
statement = statement:block_statement* { return statement; }
block_statement = OPENPAREN block:block+ CLOSEPAREN connector:CONNECTOR block2:(block_statement+ / block+) { return [block, block2]; }
/ OPENPAREN block:block+ CLOSEPAREN connector:CONNECTOR* !(block_statement / block) { return block; }
/ block:block
block = control:atom operand:OPERAND atom:atom connector:CONNECTOR* { return { control: control, operand: operand, value: atom, connector: connector[0] || false }; }
atom = _ QUOTE "#"*atom:(word)* QUOTE _ { return atom.toString(); }
OPERAND = _ operand:("=" / "in") _ { return operand.toString(); }
CONNECTOR = _ connector:("or" / "and") _ { return connector.toString(); }
word = w:char+ { return w.join(""); }
char = c:[^\r\n\t\"]
OPENPAREN = _ '(' _
CLOSEPAREN = _ ')' _
QUOTE = _ quote:("\"" / """ / "\xA0") _
_ = [ \r\n\t]*
假设我有以下输入:
"#CTL 1" = "VAL 1" or "#CTL 2" = "VAL 2"
这被解析为-check/works
[
{
"control": "CTL 1",
"operand": "=",
"value": "VAL 1",
"connector": "or"
},
{
"control": "CTL 2",
"operand": "=",
"value": "VAL 2",
"connector": false
}
("#CTL 1" = "VAL 1" or "#CTL 2" = "VAL 2")
]
这一个应该产生相同的输出数组-check/works
[
{
"control": "CTL 1",
"operand": "=",
"value": "VAL 1",
"connector": "or"
},
{
"control": "CTL 2",
"operand": "=",
"value": "VAL 2",
"connector": false
}
("#CTL 1" = "VAL 1" or "#CTL 2" = "VAL 2")
这一个做了一半:
("#CTL 1" = "VAL 1" or "#CTL 2" = "VAL 2") and "#CTL 3" = "VAL 3"
输出如下所示:
[
[
[
{
"control": "CTL 1",
"operand": "=",
"value": "VAL 1",
"connector": "or"
},
{
"control": "CTL 2",
"operand": "=",
"value": "VAL 2",
"connector": false
}
],
[
{
"control": "CTL 3",
"operand": "=",
"value": "VAL 3",
"connector": false
}
]
]
]
CTL 2上的接头应为“和”。因此,我想,需要有某种前瞻性。
与此相同:
("#CTL 1" = "VAL 1" or "#CTL 2" = "VAL 2") and ("#CTL 3" = "VAL 3" or "#CTL 4" = "VAL 4")
真正复杂的事情开始了,wenn将不同的层次混合在一起:
("#CTL 1" = "VAL 1" or ("#CTL 2" = "VAL 2" and "#CTL 3" = "VAL 3")) or ("#CTL 4" = "VAL 4" or "#CTL 5" = "VAL 5")
这根本不起作用。
我能找到的所有例子要么是左联想,要么是右联想。
我认为两者都不是完全必要的
你知道如何解决这个问题吗?我刚想出来。希望它能帮助某人:
{
function findFirstLeftStatement(arr) {
if ( Array.isArray(arr) ) {
return findFirstLeftStatement(arr[0]["left"]);
} else if ( typeof arr === "object" ) {
return arr;
}
}
function inject(arr, connector) {
findFirstLeftStatement(arr)["connector"] = connector;
return arr;
}
}
Start
= Statement*
Statement
= left:Block connector:Connector right:Statement
{ return { left: left, right: inject(right, connector) }; }
/ left: Block
{ return left; }
Block
= pOpen block:Statement* pClose
{ return block; }
/ block:Assignment
{ return block; }
Assignment
= control:ControlAtom operand:Operand value:ValueAtom
{ return { control: control, operand: operand, value: value }; }
ControlAtom
= _ Quote "#"atom:(Word)* Quote _
{ return atom.toString(); }
ValueAtom
= _ Quote atom:(Word)* Quote _
{ return atom.toString(); }
Operand
= _ operand:("=" / "in") _
{ return operand.toString(); }
Connector
= _ connector:("or" / "and") _
{ return connector.toString(); }
Word
= w:Character+ { return w.join(""); }
Character
= c:[^\r\n\t\"]
pOpen
= _ '(' _
pClose
= _ ')' _
Quote
= _ quote:("\"" / """ / "\xA0") _
_
= [ \r\n\t]*