2012-01-31 3 views
3

私はこのようになります(非常に)簡単な言語のパーサ作成しようとしてきた:私は正規表現を使用して、それをばらばらにすることができますScalaのパーサコンビネータ

block{you are a cow too blkA{ but maybe not} and so is he} hear me moo blockZ{moooooo} 

を:

.*?[^ ]*?\\{ 
.*?\\} 

[^ ]*?\\{または\\}と一致するものが見つかるまで本質的に摂食を続けていたブロックの開始または終了。私の質問は、ScalaのParser Combinatorsを使ってそれをやりたいのですが、どうしたらいいですか?私は現在持っている:

def expr: Parser[Any] = (block | text)+ 
    def text = ".+?".r 
    def block = "[^ ]*?\\{".r ~ expr ~ "}" 

が、これは動作しません:

parsed: List(b, l, o, c, k, {, y, o, u, a, r, e, a, c, o, w, t, o, o, b, l, k, A, {, b, u, t, m, a, y, b, e, n, o, t, }, a, n, d, s, o, i, s, h, e, }, h, e, a, r, m, e, m, o, o) 

blockパーサが発射されていない、ので、textパーサが繰り返し発生しているようです。私はtextパーサ取り外すときには:

def expr: Parser[Any] = (block)+ 

を私が取得:

failure: string matching regex `[^ ]*?\{' expected but `y' found 

block{you are a cow too blkA{ but maybe not} and so is he} hear me moo 
    ^

だから、明らかに blockパーサ textパーサが存在していないときを除き、作業を行います。何が起こっていますか?これを行うための「適切な」方法は、基本的な文法のためですか?

EDIT:それは不本意についてはあまりありませんので、ただ問題に

EDITを解決するようもう、タイトルを変更しました:私は今、この持っている:

def expr: Parser[Any] = (block | text)+ 

def text = "[^\\}]".r 

def block = "[^ ]*?\\{".r ~ expr ~ "}" 

をこの背後にあるロジックがあることがそれぞれにありそれがブロックの開始かどうかをテストします。そうでない場合は、次の文字に移動します。これは私に与えます:

parsed: List(((block{~List(y, o, u, a, r, e, a, c, o, w, t, o, o, ((blkA{~List(b, u, t, m, a, y, b, e, n, o, t))~}), a, n, d, s, o, i, s, h, e))~}), h, e, a, r, m, e, m, o, o) 

これは正しいです。非ブロック文字を1つずつ解析していますが、これはおそらくパフォーマンス上の問題です(私は思っていますか?)。一度にすべての非ブロック文字を解析し、それらを1つの大きな文字列に残す方法はありますか?

+0

既存の質問に新しい質問を追加しないでください。改善する、確かに、新しい質問のために新しい質問をする。あなたが非貪欲な星を使ったので、それは1つずつ解析しています。ちょうど非貪欲さを落とす。 –

答えて

2

textがすべての中括弧(})を消費しているという問題があります。それはこのように書き:この時点で

expr -> block -> expr -> text.+ (until all input is consumed) 

、それは、存在して失敗し、最初のexprに戻っtextに落ちない、exprを終了し、}を解析しようとします。

logを使用すると、解析時の状況を確認できます。

+0

これは疑問を招きます。「テキスト」が閉じた '}'を食べるのを止めるにはどうすればいいですか? regex-landのように、 '。+?[^] *?\\ {'と '。+?\\}'とマッチして、次のオープンブロックまたはクローズブロックのシンボルまで、 '。+?'PCライブラリ(私が知る限り)で。同じ効果を達成する他の方法はありますか? –

+0

@LiHaoyiさて、 '.. *?'は '。+? 'と同じですが、代わりに' [^ {}] + 'を使わないのはなぜですか?ネストされた中カッコを持っているならば、 'text'を正規表現ではなく再帰パーザに変換する必要があります。regexは再帰を処理しません。 –