2014-12-01 72 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]*