En el proceso de escribir un traductor de un lenguaje musical a otro (ABC a Alda) como una excusa para aprender la habilidad Raku DSL, ¡me di cuenta de que no parece haber una manera de terminar a .parse
! Aquí está mi código de demostración acortado:
#!/home/hsmyers/rakudo741/bin/perl6
use v6d;
# use Grammar::Debugger;
use Grammar::Tracer;
my $test-n01 = q:to/EOS/;
a b c d e f g
A B C D E F G
EOS
grammar test {
token TOP { <score>+ }
token score {
<.ws>?
[
| <uc>
| <lc>
]+
<.ws>?
}
token uc { <[A..G]> }
token lc { <[a..g]> }
}
test.parse($test-n01).say;
Y es la última parte de la pantalla Grammer :: Tracer la que demuestra mi problema.
| score
| | uc
| | * MATCH "G"
| * MATCH "G\n"
| score
| * FAIL
* MATCH "a b c d e f g\nA B C D E F G\n"
「a b c d e f g
A B C D E F G
」
En la penúltima línea, la palabra FAIL me dice que la ejecución .parse no tiene forma de salir. Me pregunto si esto es correcto? El .say muestra todo como debe ser, así que no tengo claro qué tan real es el FALLO. La pregunta sigue siendo: "¿Cómo escribo correctamente una gramática que analiza múltiples líneas sin error?"
Respuestas:
Cuando utiliza el depurador gramatical, le permite ver exactamente cómo el motor analiza la cadena: los errores son normales y esperados. Considerado, por ejemplo, coincidir
a+b*
con la cadenaaab
. Debería obtener dos coincidencias para 'a', seguido de una falla (porqueb
no lo esa
), pero luego volverá a intentarlob
y coincidirá con éxito.Esto podría verse más fácilmente si realiza una alternancia con
||
(que impone el orden). Si usted tieney analiza la frase "Tengo un kiwi", verá que primero coincide con "Tengo un", seguido de dos fallas con "manzana" y "naranja", y finalmente una coincidencia con "kiwi".
Ahora veamos su caso:
El fallo aquí es normal: en algún momento nos quedaremos sin
<score>
tokens, por lo que un fallo es inevitable. Cuando eso sucede, el motor de gramática puede pasar a lo que viene después de la<score>+
gramática. Como no hay nada, ese fallo en realidad da como resultado una coincidencia de toda la cadena (porqueTOP
coincide con implícito/^…$/
).Además, puede considerar reescribir su gramática con una regla que inserte <.ws> * automáticamente (a menos que sea importante que sea solo un espacio):
Además, IME, es posible que también desee agregar un token de proto para el uc / lc, porque cuando lo tenga
[ <foo> | <bar> ]
, siempre tendrá uno de ellos indefinido, lo que puede hacer que procesarlos en una clase de acciones sea un poco molesto. Tu podrías intentar:$<letter>
siempre se definirá de esta manera.fuente
<.ws>*
automáticamente". Considere revisar ¿Cuál es la mejor manera de ser laxo en los espacios en blanco en una gramática Raku? y ¿Cómo hago coincidir una matriz hexadecimal en gramática perl6 y cuándo es realmente importante el espacio en blanco en las gramáticas Raku? .proto
no es demasiado difícil y una vez que te acostumbras te hace la vida mucho más fácil.