在Ruby中使用Parslet的压缩敏感解析器?
发布时间:2020-12-16 22:29:33 所属栏目:百科 来源:网络整理
导读:我正在尝试使用 Ruby中的 Parslet库解析一个简单的缩进敏感语法. 以下是我尝试解析的语法示例: level0child0level0child1 level1child0 level1child1 level2child0 level1child2 结果树将如下所示: [ { :identifier = "level0child0",:children = [] },{ :
我正在尝试使用
Ruby中的
Parslet库解析一个简单的缩进敏感语法.
以下是我尝试解析的语法示例: level0child0 level0child1 level1child0 level1child1 level2child0 level1child2 结果树将如下所示: [ { :identifier => "level0child0",:children => [] },{ :identifier => "level0child1",:children => [ { :identifier => "level1child0",:children => [] },{ :identifier => "level1child1",:children => [ { :identifier => "level2child0",:children => [] } ] },{ :identifier => "level1child2",] } ] 我现在可以解析嵌套级别0和1个节点的解析器,但无法解析: require 'parslet' class IndentationSensitiveParser < Parslet::Parser rule(:indent) { str(' ') } rule(:newline) { str("n") } rule(:identifier) { match['A-Za-z0-9'].repeat.as(:identifier) } rule(:node) { identifier >> newline >> (indent >> identifier >> newline.maybe).repeat.as(:children) } rule(:document) { node.repeat } root :document end require 'ap' require 'pp' begin input = DATA.read puts '','----- input ----------------------------------------------------------------------','' ap input tree = IndentationSensitiveParser.new.parse(input) puts '','----- tree -----------------------------------------------------------------------','' ap tree rescue IndentationSensitiveParser::ParseFailed => failure puts '','----- error ----------------------------------------------------------------------','' puts failure.cause.ascii_tree end __END__ user name age recipe name foo bar 很明显,我需要一个动态计数器,期望3个缩进节点匹配嵌套级别3上的标识符. 如何以这种方式实现使用Parslet的压缩敏感语法解析器?可能吗? 解决方法
有几种方法
>通过将每一行识别为缩进和标识符的集合来解析文档,然后根据缩进数重新构建层次结构. 这使您可以根据节点(深度1)定义节点(深度).然而,这种方法的问题是node方法与一个字符串不匹配,它会生成一个解析器.所以递归调用永远不会完成. 这就是动态存在的原因.它返回一个解析器,直到它尝试匹配它为止,让您现在可以递归没有问题. 请参阅以下代码: require 'parslet' class IndentationSensitiveParser < Parslet::Parser def indent(depth) str(' '*depth) end rule(:newline) { str("n") } rule(:identifier) { match['A-Za-z0-9'].repeat(1).as(:identifier) } def node(depth) indent(depth) >> identifier >> newline.maybe >> (dynamic{|s,c| node(depth+1).repeat(0)}).as(:children) end rule(:document) { node(0).repeat } root :document end 这是我最喜欢的解决方案. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |