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

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

require 'parslet' class Parser > 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

TL; DR; – 作为一项规则Parslet应用于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#Repetition及其特例

这些都映射到Parslet :: Atoms :: Repetition。 请注意#maybe的这个小转折:

str(’foo’)。maybe.as(:f).parse(”)#=> {:f => nil}
str(’foo’)。repeat(0,1).as(:f).parse(”)#=> {:f => []}

#maybe的’nil’值是零。 这是为了满足foo的直觉。可能要么给我foo,要么根本不给我任何东西,而不是空数组。 但是按你的方式行事吧!