Beim Schreiben eines Übersetzers einer Musiksprache in eine andere (ABC an Alda) als Ausrede für das Erlernen der Raku-DSL-Fähigkeit fiel mir auf, dass es anscheinend keine Möglichkeit gibt, a zu beenden .parse
! Hier ist mein verkürzter Demo-Code:
#!/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;
Und es ist der letzte Teil des Grammer :: Tracer-Displays, der mein Problem demonstriert.
| 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
」
In der vorletzten Zeile sagt mir das Wort FAIL, dass der .parse-Lauf nicht beendet werden kann. Ich frage mich, ob das richtig ist? Das .say zeigt alles so an, wie es sein sollte, also bin ich mir nicht sicher, wie real der FAIL ist? Die Frage bleibt: "Wie schreibe ich eine Grammatik, die mehrere Zeilen fehlerfrei analysiert, richtig?"
Antworten:
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 betrachtetaab
. Sie sollten zwei Übereinstimmungen für 'a' erhalten, gefolgt von einem Fehler (weil diesb
nicht der Fall ista
), aber dann wird es erneut versuchtb
und erfolgreich abgeglichen.Dies ist möglicherweise leichter zu erkennen, wenn Sie einen Wechsel mit
||
(der die Reihenfolge erzwingt) durchführen. Wenn Sie habenund 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:
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 (daTOP
Ü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):
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:$<letter>
wird immer so definiert.quelle
<.ws>*
automatische Einfügen nicht zu mögen ". Überlegen Sie , wie Sie in einer Raku-Grammatik am besten mit Leerzeichen umgehen können. und Wie passe ich ein Hex-Array in der Perl6-Grammatik an und wann ist Leerraum in Raku-Grammatiken wirklich wichtig? .proto
nicht allzu schwer, und wenn Sie erst einmal den Dreh raus haben, wird Ihr Leben so viel einfacher.