2014-12-01 77 views
1

经过数小时试图使其工作后,发现了令人头疼的头痛。 我正在使用PEG.js解析来获取解析到数组中的输入查询。 现在即时通过这个语法来尽我所能。操作数和连接器是静态的,并由应用程序生成。PEG.JS解析逻辑变量名称,其操作数和值

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") 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

我只是想通了。希望它可以帮助别人:

{ 
    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]*