Tre*_*xon 9 javascript syntax parsing peg
我有与Python样式缩进的PEG基本相同的问题,但我想对这个答案有更多的指导.
答案成功生成了一个字符串数组,每行输入行之间有'INDENT'和'DEDENT'.看起来他几乎用PEG.js来标记,但是没有真正的解析.
那么我怎样才能扩展他的例子来做一些实际的解析呢?
作为一个例子,我该如何改变这个语法:
start = obj
obj = id:id children:(indent obj* outdent)?
{
if (children) {
let o = {}; o[id] = children[1];
return o;
} else {
return id;
}
}
id = [a-z]
indent = '{'
outdent = '}'
Run Code Online (Sandbox Code Playgroud)
使用缩进而不是大括号来描述块,仍然得到相同的输出?
(使用http://pegjs.majda.cz/online来测试语法具有以下输入:a{bcd{zyx{}}}
)
Jak*_*han 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(); }
Run Code Online (Sandbox Code Playgroud)
输入:
a
b
c
d
z
y
x
Run Code Online (Sandbox Code Playgroud)
输出:
{
"a": [
"b",
"c",
{
"d": [
"z",
"y",
"x"
]
}
]
}
Run Code Online (Sandbox Code Playgroud)
它无法解析空对象(最后一个x
),但它应该很容易解决.这里的伎俩是SAMEDENT
规则,当缩进级别没有改变时它会成功.INDENT
并DEDENT
更改当前缩进级别而不更改文本中的位置pos = offset
.
这是一个在Peggy.js在线 Playground中运行的工作示例。Peggy.js 是 PEG.js 的一个分支,正在积极开发中。David Maida 终止了 PEG.js。
\n该示例显示了如何解析INDENT
、SAMEDENT
和DEDENT
规则,以及如何使用解析位置。检查控制台日志。
它使用这些语法,其他解析器生成器可能不知道这些语法:
\n(文件顶部)
\n{{...}}
(全局初始值设定项) \xe2\x80\x93...
在解析器生成上运行。{...}
(每个解析初始值设定项) \xe2\x80\x93...
在解析器实例化上运行。(文件内)
\nX {...}
(action) \xe2\x80\x93成功...
时执行X
。初始化器中的变量可用。如果...
返回某些内容,它将替换X
返回的内容。$X
\xe2\x80\x93 返回用 解析的原始文本X
,而不是 X 的结果。... @X ...
(pluck 运算符) \xe2\x80\x93 将 的结果替换... X ...
为 的结果X
。X &{...}
(谓词)\xe2\x80\x93“并且...
X 必须为真才能成功”。X = &(...)
\xe2\x80\x93 如果...
成功则X
成功。...
不消耗任何输入。请参阅文档以获取更多信息。
\n{{\n console.clear()\n console.log(\'Parser generated\')\n}}\n\n{\n let indentstack = []\n let indent = \'\'\n function found (what) {\n let loc = location()\n console.log(`[${loc.start.line}:${loc.start.column} - ${loc.end.line}:${loc.end.column}] found ${what}`)\n }\n console.log(\'Parser instantiated\')\n}\n\nDOCUMENT = NEWLINES? @THINGS NEWLINES? _\n\nTHINGS = ( SAMEDENT @( OBJECT / LINE ) )*\n\nOBJECT = key:KEY childs:(BLOCK / INLINE) {\n found(`object "${key}"`)\n let o = {}\n o[key] = childs\n return o\n}\n\nKEY = @$( [^ \\t\\r\\n:]+ ) _ \':\' _\n\nBLOCK = NEWLINES INDENT @THINGS DEDENT\n\nINLINE = line:LINE { return [line] }\n\nLINE = text:$( (!EOL .)+ ) NEWLINES? {\n found(`line "${text}"`)\n return text\n}\n\nINDENT = &(\n spaces:$( [ \\t]+ ) &{\n return spaces.length > indent.length\n } {\n indentstack.push(indent)\n indent = spaces\n }\n) {\n found(\'indent\')\n}\n\nSAMEDENT = spaces:$( [ \\t]* ) &{\n return spaces === indent\n} {\n found(\'samedent\')\n}\n\n/* Because of this rule, results cache must be disabled */\nDEDENT = &{\n indent = indentstack.pop()\n return true\n} {\n found(\'dedent\')\n}\n\n_ = [ \\t]*\nEOL = \'\\r\\n\' / \'\\n\' / \'\\r\'\nNEWLINES = (_ EOL)+\n\n/* Test with this input\n\nH:\n a\n b\n c\n G:\n d\n e\n f\n\n*/\n
Run Code Online (Sandbox Code Playgroud)\n这是 @Jakub Kulhan\xc2\xb4s 语法的修复,适用于 PEG.js v 0.10.0。最后一行需要更改为,= &{ indent = indentStack.pop(); return true;}
因为 PEG.js 现在不再允许{...}
语法中的独立操作 ( )。该行现在是一个谓词 ( &{...}
),它总是成功 ( return true;
)。
我还删除了pos = offset;
因为它给出了错误offset is not defined
。Jakub 可能指的是旧版本 PEG.js 中可用的某些全局变量。PEG.js 现在提供了location()
返回包含偏移量和其他信息的对象的函数。
// do not use result cache, nor line and column tracking\n\n{ var indentStack = [], indent = ""; }\n\nstart\n = INDENT? l:line\n { return l; }\n\nline\n = SAMEDENT line:(!EOL c:. { return c; })+ EOL?\n children:( INDENT c:line* DEDENT { return c; })?\n { var o = {}; o[line] = children; return children ? o : line.join(""); }\n\nEOL\n = "\\r\\n" / "\\n" / "\\r"\n\nSAMEDENT\n = i:[ \\t]* &{ return i.join("") === indent; }\n\nINDENT\n = &(i:[ \\t]+ &{ return i.length > indent.length; }\n { indentStack.push(indent); indent = i.join(""); })\n\nDEDENT\n = &{ indent = indentStack.pop(); return true;}\n
Run Code Online (Sandbox Code Playgroud)\n从 v 0.11.0 开始,PEG.js 还支持Value Plucking 运算符,@
这将使编写此语法变得更加简单,但由于它当前不在在线解析器中,我将避免将其添加到此示例中。
归档时间: |
|
查看次数: |
2421 次 |
最近记录: |