2012-02-25 1 views
5

J'essaie d'implémenter le BNF for EPD dans Pharo/PetitParser.Comment éviter la gourmandise avec 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" 

Je puis essayer de parser comme ceci:

element := PPUnresolvedParser new. 

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

Mais je reçois cette erreur:

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

Si je tente Ree4 en entrée avec succès comme il analyse #($R $e #($e $4) nil nil). Cela me fait penser que le drapeau optionnel sur la désambiguïsation ne fonctionne pas correctement, et que l'analyseur n'essaie pas de voir s'il analyse sans analyser le "e" comme un disambiguation, même si cela peut l'être. Cela conduit à ne pas être capable d'analyser targetSquare cependant, donc je ne comprends pas pourquoi PetitParser abandonne. (Le type de technologie d'analyseur utilisé par PetitParser) est gourmand.

Répondre

4

Parsing Expression Grammars Cela signifie qu'ils ne font jamais marche arrière dès que quelque chose a été consommé avec succès. Dans votre cas, la règle "désambiguïsation" est consommée avec succès, donc l'analyseur ne réessaie jamais de l'ignorer même si l'analyseur est bloqué plus tard.

Les grammaires BNF et PEG se ressemblent, mais elles ont des sémantiques très différentes. Vous ne pouvez donc pas simplement traduire une règle de grammaire BNF par règle à PetitParser. Vous devez organiser soigneusement les choix (l'ordre est important dans les PEG). Dans votre exemple particulier, vous pouvez changer sanMove à:

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

Avec cette règle à la fois de vos tests Parse:

sanMove end parse: 'Ree4'. 
sanMove end parse: 'Re4'. 
Questions connexes