====== Allgemein ======
* Parsing-Library
* für einfachere Parses benutzbar
===== Vorteile =====
* komplett in Python geschrieben
* sehr klein
* "schnell" zu verstehen
===== Nachteile =====
* Bei Fehlermeldungen ist per Default nicht ersichtlich welcher Subparser eigentlich fehlgeschlagen
* kein Syntax-Completion in der IDE, da die eigentlichen Objekte über Methoden-Aufrufe erzeugt werden und nicht direkt instanziert
* Kein einfacher Weg Zeichen aus Primitives auszuschließen -> man kann also nicht einfach sagen: Alle Zeichen, außer ":"
====== Arbeitsweise ======
* Ein Parser-Objekt definiert einen Ausdruck/Element des zu parsenden Strings
* prüft ob der Ausdruck auf den zu parsenden Teil zutrifft
* ist das der Fall wird geguckt ob es ein Nachfolgeobjekt gefunden wird (diese können über verschiedene Methoden definiert werden) und wenn ein solches existiert dieses aufgerufen
* dieses wiederum geht den gleichen Vorgang durch -> dadurch entsteht eine Kette
* validiert das Nachfolgeobjekt auf False (oder eines seiner Nachfolger) und es gibt keine Alternative (OR) wird eine Exception ParseError geraised
* ist kein Nachfolgeobjekt vorhanden oder alle sind ohne Exception durchgelaufen wird das Ergebnis zurückgegeben
====== Seltsamheiten ======
* um einen möglichst guten Workflow (hinteinanderaufrufen von Methoden und Objekten) zu ermöglichen geben die meisten Aufrufe von Methoden des Parser-Objektes eine Kopie des gleichen Objektes zurück
from parsy import regex
a = regex(r"\d{1,4}").descr("Year").map(int)
\\
In obigem Beispiel wird die Funktion regex aufgerufen, die einen Parser für einen regulären Ausdruck zurückgibt. \\
Anschließend wird die "descr"-Methode des Parser-Objektes aufgerufen und eine Beschreibung gesetzt -> was geht da die Funktion ja ein Parser-Objekt zurückgegeben hat und sich der Aufruf auf die Rückgabe der Funktion bezieht. \\
Danach wird "map" des Parser-Objektes aufgerufen - das das geht würde man normalerweise nicht erwarten. Das geht weil descr ein neues Parser-Objekt zurückgegeben hat und man auf die Methode "map" eben jenes zugreift. \\
a wird dann ein Parser zugewiesen der eine Beschreibung (gesetzt über .descr) und eine Typumwandlung (gesetzt über map) beinhaltet.
====== Parser ======
* Parser können die Repräsentation eines Elements sein (einem Abschnitt des zur parsenden Zeichenkette) oder eine Kombination aus Parsern
* ein Parser kann auf ein oder mehrere Parser verweisen die weitere Teile des Strings prüfen sollen
* das Verweisen kann auf verschiedene Art und Weise passieren -> durch einen Methoden-Aufruf oder durch Operatoren (die technisch im Hintergrund auch nur Methodenaufrufe sind)
===== Parser erzeugen =====
* sie werden durch aufrufen einer Factory-Funktion erstellt die den gewünschten Typ erstellt
from parsy import regex
a = regex(r"\d{1,4}")
\\
In obigem Beispiel erstellt die Funktion regex einen Parser der auf einen regulären Ausdruck prüft.
Einige mögliche Funktionen die Parser erstellen können:
^Funktion ^Beschreibung ^
|regex|Es wird ein regulärer Ausdruck ausgewertet|
|string|Es wird ein String gegen zu prüfenden Wert geprüft|
|char_from|Zeichenkette|Prüfe auf ein Zeichen aus einer Liste von Zeichen (repräsentiert durch eine Zeichenkette). \\ Entspricht das aktuelle Zeichen einem der Zeichen in der angegeben Kette dann ist der Parser erfolgreich|
|string_from|Tuple von Zeichenketten|Prüft ob irgend eine der angegebenen Zeichenketten auf die zu prüfende Zeichenkette zutrifft. \\ Wenn eine passt ist der Parser erfolgreich|
Es gibt auch vorgefertigte Parser-Objekte. Diese können
^Parser ^Beschreibung ^
|regex|Es wird ein regulärer Ausdruck ausgewertet|
|string|Es wird ein String gegen zu prüfenden Wert geprüft|
|char_from|Zeichenkette|Prüfe auf ein Zeichen aus einer Liste von Zeichen (repräsentiert durch eine Zeichenkette). \\ Entspricht das aktuelle Zeichen einem der Zeichen in der angegeben Kette dann ist der Parser erfolgreich|
|string_from|Tuple von Zeichenketten|Prüft ob irgend eine der angegebenen Zeichenketten auf die zu prüfende Zeichenkette zutrifft. \\ Wenn eine passt ist der Parser erfolgreich|
===== Parser kombinieren =====
===== Methoden des Parser-Objektes =====
* die meisten Methoden erzeugen ein neues Parser-Objekt und geben dieses zurück, dadurch können mehrere Methoden hintereinander duch "." getrennt aufgerufen werden -> jeder neue Methodenaufruf bezieht sich ja dann auf den Rückgabewert der vorhergehenden Methode -> was ja ein Parser-Objekt war
^Methode ^Parameter ^Beschreibung
|parse|Zeichenfolge|Parst die übergebene Zeichenfolge. Die Regel in Parser oder einer der Parser die der Parser aufruft müssen zusammen die gesamte übergebene Zeichenkette abdecken. Wird sie nicht abgedeckt wird ein ParseError geworfen|
|parse_partial|Zeichenfolge|Parst eine Zeichenfolge
|descr||Fügt eine Beschreibung hinzu für was der Parser steht (also für welche Zeichenfolge). \\ Diese Information wird bei einer Exception ausgegeben statt der Zeichenkette die nicht gefunden wurde. \\ \\ Die Beschreibung kann auch beim Erzeugen des Parsers als zweiter Parameter angeben werden|
|map|Typ|Wandle das Ergebnis des Parsers in den gewünschten Typ um|
====== Hilfsfunktionen ======