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"
这被解析为 - 检查/工作。
[
{
"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上的连接器应为" AND"。所以需要有一些展望(我猜)。 与此相同:
("#CTL 1" = "VAL 1" or "#CTL 2" = "VAL 2") and ("#CTL 3" = "VAL 3" or "#CTL 4" = "VAL 4")
真正复杂的东西开始了,混合不同的水平:
("#CTL 1" = "VAL 1" or ("#CTL 2" = "VAL 2" and "#CTL 3" = "VAL 3")) or ("#CTL 4" = "VAL 4" or "#CTL 5" = "VAL 5")
这根本不起作用。 我能找到的所有例子都是左或右关联的。 我认为两者都没有完全被要求。
您是否知道如何解决此问题?
答案 0 :(得分:0)
我只是想通了。希望它可以帮助某人:
{
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]*