我与
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中的位置.