2

对于以下 Parslet 解析器

require 'parslet'
require 'parslet/convenience'

class Lines < Parslet::Parser
        rule(:open_tag) {str('[')}
    rule(:close_tag) {str(']')}
    rule(:data) {str('name') | str('name_id') }
    rule(:text) { open_tag >> data >> close_tag }
    root :text
end

begin
    p Lines.new.parse("[name_id]")    <---- It throws error
rescue Parslet::ParseFailed => failure
    Lines.new.parse_with_debug("[name_id]")
end

它给出以下错误

Failed to match sequence (OPEN_TAG NAME CLOSE_TAG) at line 1 char 6.
`- Expected "]", but got "_" at line 1 char 6.

如果我data rule

rule(:data) {str('name') | str('name_id') }

rule(:data) {str('name_id') | str('name') }

然后它按预期工作。

但是,我正在根据用户输入动态生成规则。所以这个解决方案对我不起作用。

提前致谢。

4

2 回答 2

2

:data正在构建规则,然后按照提供项目的顺序进行检查。要强制较长的匹配器出现在较短的匹配器之前,可以简单地对它们进行排序:

data = %w|name name_id|

data = data.sort { |a, b| b <=> a }

rule(:data) { data.map(&method(:str)).reduce(:|) }
于 2017-05-10T12:09:07.560 回答
1

正如 mudasobwa 所说...名称将匹配,因此没有机会尝试 name_id。您要么需要更改顺序以便首先尝试 name_id,要么需要使 name 不匹配。你如何做到这一点取决于你的语法。

require 'parslet'
require 'parslet/convenience'

class Lines < Parslet::Parser
    rule(:open_tag) {str('[')}
    rule(:close_tag) {str(']')}
    rule(:data) { str('name]') | str('name_id]')  } # <-- you can't let a matcher match unless it really is a match, so here it works because name] fails for name_id

    rule(:text) { open_tag >> data  }
    root :text
end

begin
    p Lines.new.parse("[name_id]")   
rescue Parslet::ParseFailed => failure
    Lines.new.parse_with_debug("[name_id]")
end

我想我会改为让解析器为我分解文本,然后检查结构.. 例如

require 'parslet'
require 'parslet/convenience'

class Lines < Parslet::Parser
    rule(:open_tag) {str('[')}
    rule(:close_tag) {str(']')}
    rule(:data) { (close_tag.absnt? >> any).repeat(1).as(:data)  }
    rule(:text) { open_tag >> data >> close_tag }
    root :text
end

begin
    p Lines.new.parse("[name_id]")   # =>  {:data=>"name_id"@1}
rescue Parslet::ParseFailed => failure
    Lines.new.parse_with_debug("[name_id]")
end

Parslet 旨在分两个阶段工作。第一个阶段将您的文档转换为树。第二个将您的树转换为您想要的数据表示。

在这种情况下,第一次解析会提取结构。秒通过可以检查“name_id”是否有效。等等

于 2017-05-11T05:15:25.800 回答