2012-07-25 65 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

相关问题