2012-02-25 7 views
5

Estoy tratando de implementar el BNF for EPD en Pharo/PetitParser.¿Cómo prevenir la avaricia con 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" 

I a continuación a tratar de analizar este aspecto:

element := PPUnresolvedParser new. 

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

Pero me sale este error:

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

Si intento Ree4 como entrada se analiza con éxito como #($R $e #($e $4) nil nil). Esto me hace pensar que el indicador opcional de desambiguación no funciona correctamente y que el analizador no intenta ver si analiza sin analizar la "e" como disambiguation, aunque puede serlo. Sin embargo, lleva a no poder analizar obligatoriamente targetSquare, por lo que no entiendo por qué PetitParser se da por vencido.

Respuesta

4

Parsing Expression Grammars (el tipo de tecnología de analizador que utiliza PetitParser) son codiciosos. Esto significa que nunca retroceden tan pronto como algo se haya consumido con éxito. En su caso, la regla "desambiguación" se consume con éxito, por lo que el analizador nunca reintenta omitirla, incluso si el analizador se queda atascado posteriormente.

Las gramáticas BNF y PEG tienen un aspecto similar, pero tienen una semántica muy diferente. Por lo tanto, no se puede simplemente traducir una regla de gramática BNF por regla a PetitParser. Tienes que organizar cuidadosamente las opciones (el orden importa en PEG). En el ejemplo particular que podría cambiar a sanMove:

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

Con esa regla ambos de sus pruebas de análisis:

sanMove end parse: 'Ree4'. 
sanMove end parse: 'Re4'. 
Cuestiones relacionadas