2012-07-25 14 views
9

私は本質的にPEG for Python style indentationと同じ質問をしていますが、私はもう少し方向性を考えています。this answerPEG.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ルールで、インデントレベルが変更されていない場合は成功します。 INDENTおよびDEDENTは、テキストの位置を変更せずに現在のインデントレベルを変更しますpos = offset

+0

私は本当にこのanwserに感謝します。あなたはどうやってこの方法を考え出すのですか? – jiyinyiyong

+0

これをhttp://pegjs.majda.cz/onlineに直接コピー/ペーストするとコンパイルされません。いくつかの微調整の後で、それを "修正"する方法が明確ではない。 – Clearly

+0

ちょうどこれをテストした場合、スニペットはコンパイルし、期待される出力をうまく生成します。どのようなエラーが発生したのかはわかりません。 – chakrit

関連する問題