Ich habe eine Liste, die ich parsen muss, wo das alles bis auf das letzte Element von einem Parser analysiert werden muss, und das letzte Element muss von einem anderen Parser analysiert werden.
%Vor%Ursprünglich habe ich es versucht
%Vor%Das Problem ist, dass parse1 eine parse2-Eingabe verwenden kann. Daher verwendet parse1 immer die gesamte Liste und lässt parse2 mit nichts zurück.
Gibt es eine Möglichkeit zu sagen, dass parse1 auf alles außer dem letzten Element in einer Zeichenfolge angewendet werden soll, und dann parse2 anwenden?
Wie wäre es mit:
%Vor%Die eof stört mich, da das macht diesen Parser nicht kompositorisch. I.e. Du kannst nicht sagen:
%Vor%Dies ist für einen Parser sehr schwierig. Wie soll es wissen, dass es sich lohnt, weiterzumachen, ohne jede Gelegenheit zu nutzen und zu sehen, ob es scheitert? Dies könnte exponentielle Zeit.
Wenn Sie es brauchen, um kompositorisch zu sein, hat Ihr Problem eine zusätzliche Struktur, die Sie ausnutzen können? Können Sie beispielsweise eine Liste aller Elemente analysieren und dann die letzte nach der Tat verarbeiten?
Wenn Sie parser1
so faktorisieren können, dass dies so definiert ist:
Dann wird das Problem zu einer Liste von parser1extra
oder parser2
, die später enden müssen. Sie können das wie folgt programmieren:
Sie können die try
-Aufrufe benötigen oder nicht, je nachdem, ob diese Parser Präfix-Überlappungen haben.
Wenn Sie nicht möchten, dass der Rückgabewert eine Liste ist, sondern Ihr AParse-Datum, dann könnten Sie es wie folgt neu schreiben:
%Vor%Oder ein vollständiges Beispiel:
%Vor% Tatsächlich sind die Aufrufe zum Ausprobieren in diesem Fall nicht erforderlich, da parseNum
und parseWord
keinem gemeinsamen Präfix entsprechen. Beachten Sie, dass parsePartListEndingInWord
nicht wirklich auf parsePart
verweist, sondern stattdessen auf die beiden Optionen, die die Definition von parsePart
(Ursprüngliche Antwort, eine etwas andere Situation lösend:)
Wie wäre es mit etwas wie:
%Vor% Wenn Sie die Interpunktion aus Ihren Parsern herausnehmen und nach parseTest wechseln, können Sie die Kombinatoren between
und endBy
verwenden, um die Arbeit für Sie zu erledigen. Schließlich ist try
vorhanden, so dass parser1
, wenn parser2
und endBy
einem gemeinsamen Präfix entsprechen, die korrekte vollständige Sicherung bis zum Anfang des gemeinsamen Präfixes durchführt.
Abhängig von Ihren Parsern ist es möglich, dass Sie das Interpunktionszeichen in Ihren Unterparsern belassen, und alles, was Sie brauchen, ist a try
around parser1
: