我与
PEG for Python style indentation基本相同的问题,但是我想要对
this answer有更多的方向.
答案成功地生成一系列字符串,每行的输入行之间有“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 {}}})
解决方法
分析器:
// 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中的位置.