Wenn Sie den Grammatik-Debugger verwenden, können Sie genau sehen, wie die Engine die Zeichenfolge analysiert. Fehler sind normal und werden erwartet. Wird beispielsweise als Übereinstimmung a+b*
mit der Zeichenfolge betrachtet aab
. Sie sollten zwei Übereinstimmungen für 'a' erhalten, gefolgt von einem Fehler (weil dies b
nicht der Fall ist a
), aber dann wird es erneut versucht b
und erfolgreich abgeglichen.
Dies ist möglicherweise leichter zu erkennen, wenn Sie einen Wechsel mit ||
(der die Reihenfolge erzwingt) durchführen. Wenn Sie haben
token TOP { I have a <fruit> }
token fruit { apple || orange || kiwi }
und wenn Sie den Satz "Ich habe eine Kiwi" analysieren, sehen Sie, dass er zuerst mit "Ich habe eine" übereinstimmt, gefolgt von zwei Fehlern mit "Apfel" und "Orange" und schließlich mit "Kiwi".
Schauen wir uns nun Ihren Fall an:
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
Der Fehler hier ist normal: Irgendwann werden uns die <score>
Token ausgehen, sodass ein Fehler unvermeidlich ist. In diesem Fall kann die Grammatik-Engine zu dem wechseln, was nach dem <score>+
in Ihrer Grammatik steht. Da es nichts gibt, führt dieser Fehler tatsächlich zu einer Übereinstimmung der gesamten Zeichenfolge (da TOP
Übereinstimmungen mit impliziten Zeichenfolgen vorliegen /^…$/
).
Sie können Ihre Grammatik auch mit einer Regel umschreiben, die <.ws> * automatisch einfügt (es sei denn, es ist wichtig, dass es sich nur um ein einzelnes Leerzeichen handelt):
grammar test {
rule TOP { <score>+ }
token score {
[
| <uc>
| <lc>
]+
}
token uc { <[A..G]> }
token lc { <[a..g]> }
}
Außerdem, IME, möchten Sie möglicherweise auch ein Prototoken für das uc / lc hinzufügen, da bei Ihnen [ <foo> | <bar> ]
immer eines davon undefiniert ist, was die Verarbeitung in einer Aktionsklasse etwas ärgerlich machen kann. Du könntest es versuchen:
grammar test {
rule TOP { <score> + }
token score { <letter> + }
proto token letter { * }
token letter:uc { <[A..G]> }
token letter:lc { <[a..g]> }
}
$<letter>
wird immer so definiert.