2017-11-05 4 views
3

BibTeXパーサーを書き始めました。私がしたい最初のことは、括弧内の項目を解析することです。ブレースされたアイテムは、著者フィールドまたはタイトルなどです。フィールド内にネストされた中カッコがある可能性があります。次のコードは、は、ネストされた括弧を扱うしません:文法を使って入れ子になっている可能性のある項目を解析する

use v6; 

my $str = q:to/END/; 
    author={Belayneh, M. and Geiger, S. and Matth{\"{a}}i, S.K.}, 
    END 

$str .= chomp; 

grammar ExtractBraced { 
    rule TOP { 
     'author=' <braced-item> .* 
    } 
    rule braced-item  { '{' <-[}]>* '}' } 
} 

ExtractBraced.parse($str).say; 

出力

「author={Belayneh, M. and Geiger, S. and Matth{\"{a}}i, S.K.},」 
braced-item => 「{Belayneh, M. and Geiger, S. and Matth{\"{a}」 

さて、パーサは、ネストされた括弧を受け入れるようにするために、私はのカウンタを維持したいと思います現在解析されている中括弧の数。閉じ中括弧に遭遇したときに、カウンタを減らします。カウンタがゼロになると、完全な項目を解析したものとみなします。

この考え方に従うために、braced-item正規表現を分割して、各文字に文法アクションを実装しようとしました。 (以下braced-item-char正規表現上のアクションメソッドは、ブレースカウンターを処理する必要があります):

grammar ExtractBraced { 
    rule TOP { 
     'author=' <braced-item> .* 
    } 
    rule braced-item  { '{' <braced-item-char>* '}' } 
    rule braced-item-char { <-[}]> } 
} 

しかし、突然、今構文解析が失敗しました。おそらく愚かな間違いですが、今はなぜ失敗するのか分かりません。

+1

1.私の知る限り、ルールは 'ルール'または '正規表現'が必要な場合を除いて常に 'token'を使います。処理を進めるには 'token braced-item-char ...'を使います。 2.私は、 'use Grammar :: Tracer'を追加することで、問題を数秒で分離しました。 [私のSO文法のデバッグについての答え](https://stackoverflow.com/a/19640657/1077672)を読んでいますか? 3.マニュアルカウントを導入するのではなく、正規表現エンジンで再帰レベルを追跡するのはなぜですか? 4. [私のOTTがbibtex質問に答える](https://stackoverflow.com/a/45181464/1077672)を見たことがありますか? – raiph

+0

@raiphありがとう! 'rule'の代わりに' token'を使うことで問題が解決されました。私はどのように私は正規表現のエンジンが再帰を追跡することができた興味がありますか?私は間違いなくあなたの他の記事を見ています! –

+0

P6正規表現は完全に再帰に満足していることに注意してください。たぶん[バランスの取れた括弧の例](https://examples.perl6.org/categories/best-of-rosettacode/balanced-brackets.html)がインスピレーションのために役立つでしょうか? – raiph

答えて

6

あなたは結果のデータは、私がこのような何かを見て、それを変更します見てみたい方法を知らず:

my $str = 「author={Belayneh, M. and Geiger, S. and Matth{\"{a}}i, S.K.},」; 

grammar ExtractBraced { 
    token TOP { 
     'author=' 
     $<author> = <.braced-item> 
     .* 
    } 
    token braced-item { 
     '{' ~ '}' 

      [ 
      || <- [{}] >+ 
      || <.before '{'> <.braced-item> 
      ]* 
    } 
} 

ExtractBraced.parse($str).say; 
「author={Belayneh, M. and Geiger, S. and Matth{\"{a}}i, S.K.},」 
author => 「{Belayneh, M. and Geiger, S. and Matth{\"{a}}i, S.K.}」 

あなたはもう少し構造は、それが少し見えるかもしれませんしたい場合

my $str = 「author={Belayneh, M. and Geiger, S. and Matth{\"{a}}i, S.K.},」; 

grammar ExtractBraced { 
    token TOP { 
     'author=' 
     $<author> = <.braced-item> 
     .* 
    } 
    token braced-part { 
     || <- [{}] >+ 
     || <.before '{'> <braced-item> 
    } 
    token braced-item { 
     '{' ~ '}' 
      <braced-part>* 
    } 
} 

class Print { 
    method TOP ($/){ 
     make $<author>.made 
    } 
    method braced-part ($/){ 
     make $<braced-item>.?made // ~$/ 
    } 
    method braced-item ($/){ 
     make [~] @<braced-part>».made 
    } 
} 


my $r = ExtractBraced.parse($str, :actions(Print)); 
say $r; 
put(); 
say $r.made; 
「author={Belayneh, M. and Geiger, S. and Matth{\"{a}}i, S.K.},」 
author => 「{Belayneh, M. and Geiger, S. and Matth{\"{a}}i, S.K.}」 
    braced-part => 「Belayneh, M. and Geiger, S. and Matth」 
    braced-part => 「{\"{a}}」 
    braced-item => 「{\"{a}}」 
    braced-part => 「\"」 
    braced-part => 「{a}」 
    braced-item => 「{a}」 
     braced-part => 「a」 
    braced-part => 「i, S.K.」 

Belayneh, M. and Geiger, S. and Matth\"ai, S.K. 
:このような、より10

<-[{}]>++が最適化され、<before '{'>となり、両方とも省略でき、それでも機能します。

関連する問題