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('') # => {:f=>nil}
str('foo').repeat(0,1).as(:f). parse('') # => {:f=>[]}
'nil' - #maybe の値は nil です。これは、空の配列ではなく、 foo.maybe が foo を返すか、まったく何も返さないという直感に応えています。しかし、それをあなたの方法で持ってください!