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 cadena aab
. Debería obtener dos coincidencias para 'a', seguido de una falla (porque b
no lo es a
), pero luego volverá a intentarlo b
y coincidirá con éxito.
Esto podría verse más fácilmente si realiza una alternancia con ||
(que impone el orden). Si usted tiene
token TOP { I have a <fruit> }
token fruit { apple || orange || kiwi }
y 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:
TOP # Trying to match top (need >1 match of score)
| score # Trying to match score (need >1 match of lc/uc)
| | lc # Trying to match lc
| | * MATCH "a" # lc had a successful match! ("a")
| * MATCH "a " # and as a result so did score! ("a ")
| score # Trying to match score again (because <score>+)
| | lc # Trying to match lc
| | * MATCH "b" # lc had a successful match! ("b")
| * MATCH "b " # and as a result so did score! ("b ")
…………… # …so forth and so on until…
| score # Trying to match score again (because <score>+)
| | uc # Trying to match uc
| | * MATCH "G" # uc had a successful match! ("G")
| * MATCH "G\n" # and as a result, so did score! ("G\n")
| score # Trying to match *score* again (because <score>+)
| * FAIL # failed to match score, because no lc/uc.
|
| # <-------------- At this point, the question is, did TOP match?
| # Remember, TOP is <score>+, so we match TOP if there
| # was at least one <score> token that matched, there was so...
|
* MATCH "a b c d e f g\nA B C D E F G\n" # this is the TOP match
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 (porque TOP
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):
grammar test {
rule TOP { <score>+ }
token score {
[
| <uc>
| <lc>
]+
}
token uc { <[A..G]> }
token lc { <[a..g]> }
}
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:
grammar test {
rule TOP { <score> + }
token score { <letter> + }
proto token letter { * }
token letter:uc { <[A..G]> }
token letter:lc { <[a..g]> }
}
$<letter>
siempre se definirá de esta manera.