2

パースレットで遊んでいます。これは自明ではない動作を示す単純なパーサーです。

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.1していますparslet 1.6.1

4

1 に答える 1

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('') # => {:f=>nil}
str('foo').repeat(0,1).as(:f). parse('') # => {:f=>[]}

'nil' - #maybe の値は nil です。これは、空の配列ではなく、 foo.maybe が foo を返すか、まったく何も返さないという直感に応えています。しかし、それをあなたの方法で持ってください!

于 2014-09-09T00:23:52.820 に答える