为什么Parslet(在Ruby中)在解析空字符串文字时会返回一个空数组?

时间:2014-09-08 20:22:33

标签: ruby parsing parslet

我正在玩小册子。这是一个简单的解析器,它向我展示了一些非显而易见的行为。

require 'parslet'

class Parser < Parslet::Parser
  rule(:quote) { str('"') }
  rule(:escape_char) { str('\\') }
  def quoted(term)
    quote >> term >> quote
  end
  rule(:string) {
    quoted( (escape_char >> any | quote.absent? >> any).repeat.as(:string) )
  }
end

显然,它应该解析双重字符串。确实如此。但以下结果对我来说似乎很奇怪。

Parser.new.string.parse '""'

此代码返回{:string=>[]}。为什么empty array而不是empty string?我错过了什么?

我正在使用ruby 2.1.1parslet 1.6.1

1 个答案:

答案 0 :(得分:3)

TL; DR; - 通常,Parslet的as应用于repeat会捕获一系列匹配项;除非在所有匹配都是原始字符串的特殊情况下,在这种情况下它会连接它们并返回结果字符串。

在你的代码中,repeat不知道它会捕获的类型,因为它没有,所以它返回空数组。

在这个例子中......空数组似乎是正确的选择。

require 'parslet'

class Parser < Parslet::Parser
  rule(:quote) { str('"') }
  rule(:escape_char) { str('\\') }
  def quoted(term)
    quote >> term >> quote
  end
  rule(:string) {
    quoted( (escape_char >> any | quote.absent? >> any).as(:char).repeat.as(:string) )
  }
end

puts Parser.new.string.parse('""').inspect # => {:string=>[]}
puts Parser.new.string.parse('"test"').inspect 
    # =>  {:string=>[{:char=>"t"@1}, {:char=>"e"@2}, {:char=>"s"@3}, {:char=>"t"@4}]}

当子节点只是字符串时,Parslet会连接成一个字符串。当集合中没有元素时,它默认为空集合而不是空字符串。

maybe不同。

来自http://kschiess.github.io/parslet/parser.html#重复及其特殊情况

  

这些都映射到Parslet :: Atoms :: Repetition。请注意这一点   扭转到#maybe:

     

str('foo')。maybe.as(:f).parse('')#=&gt; {:F =&GT;零}
  str('foo')。repeat(0,1).as(:f).parse('')#=&gt; {:f =&gt; []}

     

'nil' - #maybe的值是零。这是为了满足直觉   foo.maybe或者给我foo或者什么都没有,不是空数组。   但是按你的方式行事吧!