2012-07-25 69 views
9

我的問題與PEG for Python style indentation基本相同,但我想要了解更多有關this answer的方向。使用PEG.js解析縮進級別

答案成功地生成了一行字符串數組,這些字符串行之間的每行輸入爲'INDENT'和'DEDENT'。看起來他非常習慣使用PEG.js進行標記,但沒有真正的解析發生。

那麼如何擴展他的例子來做一些實際的解析?

舉個例子,我怎樣才能改變這種語法:

start = obj 
obj = id:id children:(indent obj* outdent)? 
     { 
      var o = {}; 
      o[id] = children[1]; 
      return (children[1] ? o : id); 
     } 
id = [a-z] 
indent = '{' 
outdent = '}' 

使用縮進而不是括號劃定區塊,並仍然得到同樣的輸出?

(使用http://pegjs.majda.cz/online來測試語法具有以下輸入:a{bcd{zyx{}}}

回答

18

分析器:

// do not use result cache, nor line and column tracking 

{ var indentStack = [], indent = ""; } 

start 
    = INDENT? l:line 
    { return l; } 

line 
    = SAMEDENT line:(!EOL c:. { return c; })+ EOL? 
    children:(INDENT c:line* DEDENT { return c; })? 
    { var o = {}; o[line] = children; return children ? o : line.join(""); } 

EOL 
    = "\r\n"/"\n"/"\r" 

SAMEDENT 
    = i:[ \t]* &{ return i.join("") === indent; } 

INDENT 
    = &(i:[ \t]+ &{ return i.length > indent.length; } 
     { indentStack.push(indent); indent = i.join(""); pos = offset; }) 

DEDENT 
    = { indent = indentStack.pop(); } 

輸入:

a 
    b 
    c 
    d 
    z 
    y 
    x 

輸出:

{ 
    "a": [ 
     "b", 
     "c", 
     { 
     "d": [ 
      "z", 
      "y", 
      "x" 
     ] 
     } 
    ] 
} 

它無法解析空對象(最後的x),但是,它應該很容易解決。這裏的技巧是SAMEDENT規則,它在縮進級別沒有改變時成功。 INDENTDEDENT更改當前縮進級別而不更改文本中的位置pos = offset

+0

我真的很感激這個anwser。你怎麼想出這種方法? – jiyinyiyong 2012-12-07 08:40:59

+0

如果我直接複製/粘貼到http://pegjs.majda.cz/online它不會編譯。經過一些調整,目前還不清楚如何「修復」它。 – Clearly 2013-02-15 22:53:36

+0

剛剛測試過,代碼片段編譯併產生預期的輸出就好了。不知道你在那裏發生了什麼錯誤。 – chakrit 2013-04-13 16:32:02

相關問題