Quando si utilizza il debugger grammaticale, consente di vedere esattamente come il motore sta analizzando la stringa: i guasti sono normali e previsti. Considerato, ad esempio, l'abbinamento a+b*
con la stringa aab
. Dovresti ottenere due corrispondenze per "a", seguite da un errore (perché b
non lo è a
) ma poi riproverà b
e corrisponderà correttamente.
Questo potrebbe essere visto più facilmente se si fa un'alternanza ||
(che rafforza l'ordine). Se hai
token TOP { I have a <fruit> }
token fruit { apple || orange || kiwi }
e tu analizzi la frase "I have a kiwi", la vedrai prima abbinare "I have a", seguita da due errori con "apple" e "orange", e infine una corrispondenza con "kiwi".
Ora diamo un'occhiata al tuo 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
Il fallimento qui è normale: a un certo punto finiremo i <score>
token, quindi un fallimento è inevitabile. Quando ciò accade, il motore grammaticale può passare a qualsiasi cosa venga dopo la <score>+
tua grammatica. Dal momento che non c'è nulla, quel fallimento in realtà si traduce in una corrispondenza dell'intera stringa (perché TOP
corrisponde a implicita /^…$/
).
Inoltre, potresti considerare di riscrivere la tua grammatica con una regola che inserisce automaticamente <.ws> * (a meno che non sia importante che sia un solo spazio):
grammar test {
rule TOP { <score>+ }
token score {
[
| <uc>
| <lc>
]+
}
token uc { <[A..G]> }
token lc { <[a..g]> }
}
Inoltre, IME, potresti voler aggiungere anche un proto token per uc / lc, perché quando lo avrai [ <foo> | <bar> ]
ne avrai sempre uno indefinito che può rendere un po 'fastidioso elaborarli in una classe di azioni. Puoi provare:
grammar test {
rule TOP { <score> + }
token score { <letter> + }
proto token letter { * }
token letter:uc { <[A..G]> }
token letter:lc { <[a..g]> }
}
$<letter>
sarà sempre definito in questo modo.