2012-02-25 10 views
5

Pharo/PetitParserにBNF for EPDを実装しようとしています。PetitParserで貪欲さを防ぐ方法は?

digit18 := $1 asParser/$2 asParser/$3 asParser/$4 asParser/$5 asParser/$6 asParser/$7 asParser/$8 asParser. 
piecePromotion := $N asParser/$B asParser/$R asParser/$Q asParser. 
promotion := ($= asParser) , piecePromotion. 
fileLetter := ($a asParser/$b asParser/$c asParser/$d asParser/$e asParser/$f asParser/$g asParser/$h asParser). 
targetSquare := fileLetter , digit18. 
disambiguation := fileLetter/digit18. 
pieceCode := ($N asParser/$B asParser/$R asParser/$Q asParser/$K asParser) optional. 
castles := $O asParser, $- asParser, $O asParser, (($- asParser, $O asParser) optional) . 
sanMove := (pieceCode, disambiguation optional, targetSquare, promotion optional, ($+ asParser/$# asParser) optional) "/ castles". "commented out because I'd be getting another error with this enabled" 

私は、試してみて、解析し、次のように:

element := PPUnresolvedParser new. 

element def: (sanMove). 
mse := element end. 
mse parse: 'Re4'. 

しかし、私はこのエラーを取得する:私は、入力としてRee4をしようとした場合

$h expected at 2 // btw these indexes seem to start at 0 

それは#($R $e #($e $4) nil nil)として成功裏に解析します。これにより、曖昧さ回避のオプションフラグが正しく機能していないと考えられ、 "e"を解析することなく解析するかどうかは、disambiguationとしても、パーザは試してみません。しかし、PetitParserがなぜあきらめるのか分からないので、義務的な文を解釈することはできません。targetSquare

答えて

4

Parsing Expression Grammars(PetitParserが使用しているパーサー技術の種類)は貪欲です。これは、何かがうまく消費されるとすぐに後戻りすることはないということです。あなたのケースでは、ルール "曖昧さ回避"がうまく消費されます。したがって、パーザは後でパーサーがスタックしても、それをスキップしません。

BNFとPEG文法は同じように見えますが、それらは非常に異なるセマンティクスを持っています。そのため、BNF文法ルールをルールごとにPetitParserに変換することはできません。あなたは注意深く選択肢を並べ替える必要があります(PEGの問題を注文する)。あなたの特定の例では、あなたがsanMoveに変更することができます:そのルールで

sanMove := pieceCode, ((targetSquare, promotion optional, ($+ asParser/$# asParser) optional)/(disambiguation optional, targetSquare, promotion optional, ($+ asParser/$# asParser) optional)). 

あなたのテストの両方が解析:

sanMove end parse: 'Ree4'. 
sanMove end parse: 'Re4'. 
関連する問題