5

複数行のパースレットを一致させる方法を探しています。コードは次のようになります。

rule(:line) { (match('$').absent? >> any).repeat >> match('$') }
rule(:lines) { line.repeat }

ただし、文字列の末尾に一致するように無限に繰り返されるlinesため、常に無限ループになります。match('$')

空にすることができる複数の行を一致させることは可能ですか?

irb(main)> lines.parse($stdin.read)
This
is

a
multiline

string^D

正常に一致するはずです。何か不足していますか?私も試し(match('$').absent? >> any.maybe).repeat(1) >> match('$')ましたが、それは空の行と一致しません。

よろしく、
ダニエル。

4

2 に答える 2

3

マッチングには2つの関連する問題があると思います:

  • 疑似文字の一致で$は、実際の文字は消費されません。何らかの方法で改行を消費する必要があります。

  • Parslet はなんらかの方法で入力を変更し、予期し$ない場所で一致を作成します。私が使用できる最良の結果は$、個々のキャラクターに一致することでした.

\n行末文字として使用する方がはるかに安全です。私は次のように動作しました(私はParsletの初心者なので、もっと明確にできればお詫びします):

require 'parslet'

class Lines < Parslet::Parser
    rule(:text) { match("[^\n]") }
    rule(:line) { ( text.repeat(0) >> match("\n") ) | text.repeat(1) }
    rule(:lines) { line.as(:line).repeat }
    root :lines
end

s = "This
is

a
multiline
string"

p Lines.new.parse( s )

行のルールは複雑です。これは、空の行と\n.

構文を使用する必要はありません。単純に入力全体を消費するのではなく、ルールが各行に個別に一致する.as(:line)ことを明確に示すために追加しただけです。:line

于 2013-07-18T20:19:43.777 に答える