Parser Combinators in C#

Slides:



Advertisements
Ähnliche Präsentationen
Algorithmentheorie 08 – Dynamische Programmierung (1)
Advertisements

Algorithmentheorie 08 – Dynamische Programmierung (4) Editierdistanz Approximative Zeichenkettensuche Sequence Alignment Prof. Dr. Th. Ottmann WS
XML-Programmierung mit XDuce
Schwierigkeit von Aufgabenstellungen
Sortieren I - Bubblesort -
Rekursionen Erstellt von J. Rudolf im November 2001 /
2. Kapitel: Komplexität und Komplexitätsklassen
Rekursion Was ist Rekursion? Was sind rekursive Methoden?
der Universität Oldenburg
Kapitel 4 Syntaktische Analyse: LR Parsing.
Parser generieren Yet Another Compiler – Compiler YACC.
Sortierverfahren Richard Göbel.
Formale Sprachen – Mächtigkeit von Maschinenmodellen
Dynamische Programmierung (2) Matrixkettenprodukt
1 Vorlesung Informatik 2 Algorithmen und Datenstrukturen (02 – Funktionenklassen) Prof. Dr. Th. Ottmann.
WS Algorithmentheorie 01 – Divide and Conquer (Segmentschnitt) Prof. Dr. Th. Ottmann.
Vorlesung Informatik 2 Algorithmen und Datenstrukturen (02 – Funktionenklassen) Tobias Lauer.
Vorlesung Informatik 2 Algorithmen und Datenstrukturen (02 – Funktionenklassen) Prof. Dr. Th. Ottmann.
WS Algorithmentheorie 08 – Dynamische Programmierung (2) Matrixkettenprodukt Prof. Dr. Th. Ottmann.
Geometrisches Divide and Conquer
Deklaratives Debugging (Seminar Software Engineering) Tim Sender Deklaratives Debugging Seminar Software Engineering.
EINI-I Einführung in die Informatik für Naturwissenschaftler und Ingenieure I Vorlesung 2 SWS WS 99/00 Gisbert Dittrich FBI Unido
Oracle PL/SQL Server Pages (PSP). © Prof. T. Kudraß, HTWK Leipzig Grundidee: PSP – Internet-Seiten mit dynamischer Präsentation von Inhalten durch Einsatz.
Zusammenfassung Vorwoche
Algorithmische Geometrie
Günter Kniesel Advanced Prolog. 2 Bisher: Grundlagen Klauseln –Regeln –Fakten Terme –Die einzige Datenstruktur in Prolog –Listen als Sonderfall mit eigener.
Programmierung 1 - Repetitorium WS 2002/2003 Programmierung 1 - Repetitorium Andreas Augustin und Marc Wagner Homepage:
Programmierung 1 - Repetitorium
DVG Methoden 1 Methoden. 2 int dezi = Integer.parseInt(args[0]); boolean vz = (dezi>=0); dezi = Math.abs(dezi); String Bin = ""; do { } while.
Beispielrelation Buchbestellungen H = Menge der bedeutenden Ziele = {a, d} Schwelle T = 4 Stichprobe S = {a, b, a, a, a, a} mit s = |S| = 6 N = Anzahl.
JavaScript - Einführung
Datenstrukturen, Algorithmen und Programmierung 2 (DAP2)
Rekursion Richard Göbel.
Programmiersprachen II Integration verschiedener Datenstrukturen
Einführung in die Programmiersprache C 1
Black Box Algorithmen Hartmut Klauck Universität Frankfurt SS
Polynome und schnelle Fourier-Transformation
Einführung in die Programmierung
Einführung in die Informatik für Naturwissenschaftler und Ingenieure
Institut für Wirtschaftsinformatik – Software Engineering, JKU Linz 1 Algorithmen und Datenstrukturen SS 2005 Mag.Th. Hilpold u. Dr. A.Stritzinger Institut.
2.4 Rekursion Klassifikation und Beispiele
Aufgabenstellung Aufgabenstellung: What do the following terms (formulae) express? Which of these terms characterize all sequences of real numbers , x_n.
Unterprogramme in JAVA
Algorithmen und Datenstrukturen Übungsmodul 8
Objectives Verstehen was unterDelegate verstanden wird
BMEVIEEA100 Grundlagen der Programmierung
Programmieren ... in C++ Prof. Dr.-Ing. Franz-Josef Behr, HfT Stuttgart Programmeiren I.
Das Traveling Salesman Problem (TSP)
SFZ FN Sj. 13/14 Python 3 Rekursion Inf K1/2 Sj 13/14
Java Syntaxdiagramme Buchstabe A B Z a z ... Ziffer
Algorithmen und Datenstrukturen 1 SS 2002
Sortiernetzwerke1 Seminar über Algorithmen SS 2005 von Arash Sarkohi und Christian Bunse.
Wann ist eine Funktion (über den natürlichen Zahlen) berechenbar?
Mag. Thomas Hilpold, Universität Linz, Institut für Wirtschaftsinformatik – Software Engineering 1 Algorithmen und Datenstrukturen 1 SS 2002 Mag.Thomas.
Unterprogramme / Methoden
Funktionen. Aufgabe : Eingabe zweier Zahlen ---> Minimum bestimmen Dann nochmals Eingabe zweier Zahlen ---> Minimum bestimmen.
Funktionen, Felder und Parameter- übergabe. Funktionsaufruf mit Feld als Parameter: Parameter = Name des Feldes.
Tutorium Software-Engineering SS14 Florian Manghofer.
Pointer, Arrays und verkettete Listen. Mehrdimensionale Arrays  Pointer auf ein Array von Pointern  int32 **matrix = new int32*[3];  matrix: Zeiger.
Praktische Informatik 1
Informatik II – Übung 4 Gruppe 3
Dynamischer Speicher malloc wird in c++ eher nicht mehr verwendet.
Simple Recurrent Networks
Tabellengesteuerte Verfahren
Nksainf.ch/oinf.
Left Join, Right Join, Outer Join
Rekursionen Erstellt von J. Rudolf im November 2001
Einführung in die Programmierung
1. Die rekursive Datenstruktur Liste 1.5 Das Entwurfsmuster Kompositum
The Programming Language Pascal
 Präsentation transkript:

Parser Combinators in C# Thomas Krause

Gliederung Einführung Was ist ein Parser? Einfache und komplexe Parser Probleme DEMO: Combinator Framework in C# Parser Combinators in C# 27.11.2018

Parser Combinators Parsing-Technik Top-Down-Ansatz Ähnelt rekursivem Abstieg Einfache Parser werden zu immer komplexeren Parsern kombiniert Keine separate Sprache für Syntaxbeschreibung Syntax wird als Serie von Funktionsaufrufen beschrieben Direkt ausführbare Grammatik! Basiert auf Higher Order Functions Parser Combinators in C# 27.11.2018

Was ist ein Parser? Funktion: input => {(result_1, newstate_1), …)} Eingabe Zu parsende Tokens Ausgabe Liste von Tupeln: ((Teil)Ergebnis, Verbleibende Tokens) Parser Combinators in C# 27.11.2018

Beispiele Parser für einzelne Ziffer: Parser für eine Zahl: Mehrdeutige Grammatiken sind möglich: Ausdruck: „1+2*3“ => {(9, „“),(7, „“)} Bei erfolglosem Parsen  leere Menge: Zahl: „abc“ => { } Parser Combinators in C# 27.11.2018

Parser & Combinators Combinator: Funktion die ein oder mehrere Parser zu einem neuen Parser verknüpft Beispiel: Symbol = (Letter | Digit)* Primitive Parser Primitive Combinators Komplexe Parser & Combinators Return Fail Accept Then Or Digit Expression Statement Rep1 … Parser Combinators in C# 27.11.2018

Primitive Parser - Return Return(result) – Fabrik für Return-Parser Konsumiert keine Eingabe Gibt immer einen bestimmten Wert (result) zurück Beispiel: Return(2): „xyz“ => {(2, „xyz“)} Parser Combinators in C# 27.11.2018

Primitive Parser - Fail Fail – Fail-Parser Gibt immer eine leere Menge zurück (Parse-Vorgang fehlgeschlagen) Beispiel: Fail: „xyz“ => { } Parser Combinators in C# 27.11.2018

Primitive Parser: Accept Accept – Accept-Parser Konsumiert einzelnes Zeichen aus der Eingabe und gibt es zurück Beispiel: Accept: „xyz“=> {(„x“, „yz“)} Ist die Eingabe leer (Ende der Eingabe), wird leere Menge zurückgegeben: Accept: „“ => { } Parser Combinators in C# 27.11.2018

Combinator Primitive - Or p1.Or(p2): input => p1(input) ⋃ p2(input) Ergebnismenge ist die Vereinigung der Ergebnismengen der einzelnen Parser Beispiel: Char: “123” => {(“1”, “23”)} Digit: “123” => {(1, “23”)} CharOrDigit = Char.Or(Digit); CharOrDigit: “123” => {{(“1”, “23”), (1, “23”)} Parser Combinators in C# 27.11.2018

Combinator Primitive - Then In Literatur als Bind bekannt Entspricht einer Sequenz in Grammatik Konkatenieren von 2 Parsern p1, p2 Problem: Wie werden die Ergebnisse von p1 und p2 Zusammengeführt? Lösung: p2 wird nicht direkt übergeben, sondern jeweils aus dem Ergebnis von p1 erstellt Parser Combinators in C# 27.11.2018

Beispiel: Then-Combinator Digit2Num: Digit.Then(d => Return(int.Parse(d))) Digit2Num ::= Digit:d { RESULT = int.Parse(d); } Then erstellt hier einen Parser, der: Zunächst eine Ziffer aus dem Eingabestrom liest (Digit) Mithilfe dieser Ziffer einen Return-Parser erstellt, der den Zahlenwert der Ziffer zurückgibt (d => …) Diesen neuen Parser mit der verbleibenden Eingabe aufruft Und das Ergebnis des neuen Parsers zurückgibt Parser Combinators in C# 27.11.2018

Beispiel: Then-Combinator (2) Digit2Num: Digit.Then(d => Return(int.Parse(d))) Digit.Then(ReturnInt) ReturnInt(d) { return Return(int.Parse(d)); } Parsen des Strings „1“ Digit-Parser wird angewendet: „1“ => {(„1“, „“)} (daher: Ergebnis: „1“, Rest-Tokens: „“) Funktion ReturnInt wird mit „1“ als Parameter aufgerufen ReturnInt(„1“) gibt den Parser Return(1) zurück Return(1) wird mit dem Rest der Eingabe aufgerufen („“) Return(1): „“ => {(1, „“)} Also: Digit2Num: „1“ => {(1, „“)} Parser Combinators in C# 27.11.2018

Beispiel: Then-Combinator (3) Combinator-Grammatik „Normale“ Grammatik AddExpression = number.Then(n1 => AddToken.Then(a => number.Then(n2 => Return(n1 + n2)))) AddExpression ::= EX:n1 ADD:a EX:n2 {{ RESULT = n1+n2 }} Parser Combinators in C# 27.11.2018

Zusammengesetze Parser Accept(Token t) – Parser für bestimmtes Token Accept().Then(token => token == t ? Return(token) : Fail() ); Accept(‚a‘): „abc“ => {(„a“, „bc“)} //Return(„a“) Accept(‚b‘): „abc“ => { } //Fail() Parser Combinators in C# 27.11.2018

Zusammengesetze Kombinatoren p.Rep() – Wiederholung p* = p+ | eps p.Rep1().Or(Return({ })) p.Rep1() – Wiederholung (mindestens einmal) p+ = pp* p.Then(first => p.Rep1.Then(remainder => Return({first} ⋃ remainder) Beispiel Letter.Rep1(): „abc“ => {(„a“, „bc“),(„ab“, „c“),(„abc“, „“)} Parser Combinators in C# 27.11.2018

Probleme Laufzeit Linksrekursion Fehlerbehandlung Parser Combinators in C# 27.11.2018

Problem: Laufzeit Es werden immer alle Möglichkeiten durchprobiert Ein Parser parst oft mehrmals gleiche Eingabe Beispiel: Ausdruck = Term + Rest | Term – Rest „5-3“: Doppelter Aufruf des Term-Parsers für „5“ Bei komplexeren Grammatiken sehr ineffizient Exponentielle Laufzeit! Einfache Lösung: Memoization Teilergebnisse der Parser speichern  O(n3) Komplexer: Spezielle Combinators + Grammatiken Lineare Laufzeit, aber dafür Verlust der Flexibilität Parser Combinators in C# 27.11.2018

Problem: Linksrekursion ex = ex.Then(…) „ex“-Parser ruft „ex“-Parser auf, der „ex“-Parser aufruft, … Stack-Overflow Lösungsansatz: Für jeden Parser-Aufruf Rekursionstiefe merken Maximale Rekursionstiefe ist durch die Länge der Eingabe begrenzt Lässt sich mit Memoize Funktion kombinieren Laufzeit inkl. Memoization: O(n4) Korrekte Implementierung nicht trivial! Literatur: Frost, R. and Hafiz, R. (2006-2010) PoC-Implementierung in Haskell Parser Combinators in C# 27.11.2018

Fehlerbehandlung In der vorgestellten Form keine Fehlerbehandlung Parse-Fehler resultieren in leerer Ergebnismenge Lösungsansatz: Parser-Ergebnisse mit Fehlermeldungen anreichern Zusammensetzen der Fehlermeldungen auf höheren Ebenen Beispiel: Letter: „%“ => #Letter expected# Digit: „%“ => #Digit expected# Letter.Or(Digit): „%“ => #Letter or Digit expected# Parser Combinators in C# 27.11.2018

Implementierung Geschrieben in C# Stark vereinfacht dank Lambdas+LINQ in C# 3.0 Unterstützt beliebige Tokens als Eingabe (generisch) Unterstützt Mehrdeutige Grammatiken Unterstützt Linksrekursion! Inklusive Beispiel: Einfacher Parser für mathematische Ausdrücke und Funktionen Parser Combinators in C# 27.11.2018

DEMO Parser Combinator Framework in C#

Fazit Akademisch sehr interessant Aktives Forschungsgebiet „Sehr einfach“ und trotzdem sehr mächtig Nachteile Schlechte Laufzeit Tief verschachtelte Funktionsaufrufe (Stack-Overflow) Oft schwierig zu debuggen Oft schwierig nachzuvollziehen Nicht in jeder Programmiersprache gut umsetzbar Parser Combinators in C# 27.11.2018

Quellen Monadic Parser Combinators using C# 3.0 LukeH's WebLog – http://blogs.msdn.com/lukeh mit LINQ, keine Linksrekursion oder Mehrdeutigkeit Monadic parser combinators (I-VII) Brian McNamara – http://lorgonblog.spaces.live.com/blog/ Sehr Ausführlich, inklusive Fehlerbehandlung Keine Linksrekursion oder Mehrdeutigkeit X-SAIGA Project Hafiz, R. and Frost, R – http://www.cs.uwindsor.ca/~hafiz/xsaiga/pub.html Publikationen zum Thema Linksrekursion und Mehrdeutigkeit Implementierung in Haskell Parser Combinators in C# 27.11.2018

FRAGEN? Vielen Dank für die Aufmerksamkeit!