Syntaxanalyse. Parsergeneratoren. Kurzform für: Was ist das? GOLD Parser. Beispiele. G.O.L.D. Grammatiken. Funktionsweise



Ähnliche Dokumente
Compilerbau für die Common Language Run-Time

30. Parser-Generatoren

Definition von LR(k)-Grammatiken

yacc - eine Einführung

Software Entwicklung 1. Fallstudie: Arithmetische Ausdrücke. Rekursive Klassen. Überblick. Annette Bieniusa / Arnd Poetzsch-Heffter

Lex und Yacc Lt. Worf, scannen Sie das Schiff! 300dpi, Sir?

Lexikalische Programmanalyse der Scanner

Software Entwicklung 1

Angewandte Mathematik und Programmierung

Implementierung eines LR-Parser-Generators mit syntaktischen Prädikaten

Einführung Compilergenerierung Bewertung Referenzen. SableCC. Benjamin Daeumlich

Zuerst wird die Bedingung ausgewertet. Ist sie erfüllt, wird der Rumpf des while-statements ausgeführt. Nach Ausführung des Rumpfs wird das gesamte

Praktikum Softwareanalyse und -transformation

Ein kleiner Blick auf die generische Programmierung

Compilerbau. Einführung in Bison

Struktur des MicroJava-Compilers

Wiederholung, Abbruch von Schleifen, switch-anweisung Datentypen, char, formatierte Ausgabe

Wintersemester Maschinenbau und Kunststofftechnik. Informatik. Tobias Wolf Seite 1 von 29

Das Programm aufg11_0.cpp realisiert einen Tischrechner, der von DOS aus u.a. folgende Eingaben akzeptiert und Berechnungen durchführt:

Programmierkurs Java

Übung zu Grundlagen des Übersetzerbaus

Inhalt Kapitel 11: Formale Syntax und Semantik

Klausur: Grundlagen der Informatik I, am 06. Februar 2009 Gruppe: A Dirk Seeber, h_da, Fb Informatik. Nachname: Vorname: Matr.-Nr.

7. Syntax: Grammatiken, EBNF

Konstruktor/Destruktor

Deterministische PDAs

Compilerbau (1 KU) SS 2011

Einführung Sprachfeatures Hinweise, Tipps und Styleguide Informationen. Einführung in C. Patrick Schulz

Einleitung Entwicklung in C Hello-World! Konstrukte in C Zusammenfassung Literatur. Grundlagen von C. Jonas Gresens

Programmierung 2. Übersetzer: Das Frontend. Sebastian Hack. Klaas Boesche. Sommersemester

Stratego/XT und ASF+SDF Meta-Environment. Paul Weder Seminar Transformationen Datum:

Praxisorientierte Einführung in C++ (Variadische Funktionen)

Übersetzerbau Cluj-Napoca, Rumänien 2007

Programmiertechnik. Teil 4. C++ Funktionen: Prototypen Overloading Parameter. C++ Funktionen: Eigenschaften

Programmieren in C. Eine Einführung in die Programmiersprache C. Prof. Dr. Nikolaus Wulff

Die Syntax von Java. Ursprünge. Konsequenzen. Das Wichtigste in Kürze. Weiteres Vorgehen. Rund um Java. Sun Microsystems. Borland Software Corp

Einführung in die STL

Grundlagen. Felix Döring, Felix Wittwer 24. April Python-Kurs

Der Grid-Occam-Compiler. Syntaxanalyse

Einfache Liste: Ein Stapel (Stack) Ansatz. Schaubild. Vorlesung 1. Handout S. 2. Die einfachste Form einer Liste ist ein Stapel (stack).

Einführung in die Programmierung I. 2.0 Einfache Java Programme. Thomas R. Gross. Department Informatik ETH Zürich

Inhalte der Vorlesung. 4. Der Scanner-Generator lex. 4. Der Scanner-Generator lex. 4.1 lex: Grundlagen

Aufgabe 1.1. Wählen Sie jene Variablendeklarationen mit Initialisierungen aus, die in Java hinsichtlich der Typen korrekt sind:

Ergänzungen zur Theoretischen Informatik. Compilerbau mit ANTLR. Literatur Das Standardwerk zum Compilerbau ist [1].

So schreiben Sie ein Parser-Programm

Konzepte der Programmiersprachen

Java für Anfänger Teil 2: Java-Syntax. Programmierkurs Manfred Jackel

Pascal Schärli

Grammatiken und ANTLR

Struktur des MicroJava-Compilers

3.1 Reservierte Wörter

Die Klasse MiniJava ist in der Datei MiniJava.java definiert:

Klausur: Grundlagen der Informatik I, am 27. März 2009 Gruppe: F Dirk Seeber, h_da, Fb Informatik. Nachname: Vorname: Matr.-Nr.

Java für Anfänger Teil 2: Java-Syntax. Programmierkurs Manfred Jackel

Spezifikation lexikalischer Einheiten (Token) als reguläre Ausdrücke in einer Lexer-Spezifikationsdatei (z.b. tiger.lex) Übersetzen nach lex.yy.

Einführung in C. Alexander Batoulis. 5. Mai Fakutltät IV Technische Universität Berlin

Algorithmen zur Datenanalyse in C++

2 Programmieren in Java I noch ohne Nachbearbeitung

Definition Compiler. Bekannte Compiler

Programmieren in C++ Templates

17. Rekursion 2. Bau eines Taschenrechners, Ströme, Formale Grammatiken, Extended Backus Naur Form (EBNF), Parsen von Ausdrücken

C++ Templates. Wozu Templates? Definition von Templates. Gebrauch von Templates. Instanziierung und Organisation

5. Syntaxanalyse und der Parser-Generator yacc. 5.5 Aufsteigende Analyse. Absteigende Analyse versus aufsteigende Analyse. 5.5 Aufsteigende Analyse

Ursprünge. Die Syntax von Java. Das Wichtigste in Kürze. Konsequenzen. Weiteres Vorgehen. Rund um Java

Javakurs für Anfänger

FLEX - Einleitung. Ausführbares Programm lexer. C-Programm lex.yy.c. flex-programm tiger.lex. WS 02/03 Übung Compilerbau Seifert, A.

Struktur des MicroJava-Compilers

Statische und dynamische Analyse der Bedingungsüberdeckung. objektorientierter Java-Programme

9 Compilerbau-Werkzeuge

Introduction to Python. Introduction. First Steps in Python. pseudo random numbers. May 2016

Annehmende Schleife do while

Klausur: Informatik, am 11. Juli 2013 Gruppe: B Dirk Seeber, h_da, Fb Informatik. Nachname: Vorname: Matr.-Nr.: Punkte:

Übungsstunde 11. Einführung in die Programmierung

Nachklausur: Grundlagen der Informatik I, am 02. April 2008 Dirk Seeber, h_da, Fb Informatik. Nachname: Vorname: Matr.-Nr.

Nachklausur: Grundlagen der Informatik I, am 02. April 2008 Dirk Seeber, h_da, Fb Informatik. Nachname: Vorname: Matr.-Nr.

Programmiersprachen Einführung in C

Grundlagen. Die Komponenten eines C Programms. Das erste Programm

ANTLR (ANother Tool for Language Recognation)

lex - Eine Einführung

Einstieg in die Informatik mit Java

15. Rekursion. Rekursive Funktionen, Korrektheit, Terminierung, Aufrufstapel, Bau eines Taschenrechners, BNF, Parsen

Vorlesung Programmieren

Java Scripting. Java Erweiterungen mittels Groovy- oder JavaScript Sprachen. Prof. Dr. Nikolaus Wulff

Praktikum Funktionale Programmierung Teil 1: Lexen und Parsen

Struktur des MicroJava- Compilers

Struktur des MicroJava-Compilers

Wo sind wir? Übersicht lexikale Struktur von Java

Klausur: Informatik, am 11. Juli 2013 Gruppe: A Dirk Seeber, h_da, Fb Informatik. Nachname: Vorname: Matr.-Nr.: Punkte:

C-Kurs 2010 Pointer. 16. September v2.7.3

Fachbericht DPR. Name: René Wagener. Klasse: CI3O1. Fachlehrer: Herr Balog

Einführung in die Programmiertechnik

15. Rekursion 2. Motivation: Taschenrechner. Naiver Versuch (ohne Klammern) Analyse des Problems (15 7 3) = Eingabe * 3 = Ergebnis 15

Institut für Computational Science Prof. Dr. H. Hinterberger. Praxismodul 1. Einführung in die Programmierung Erste Programme

Programmierung mit C Zeiger

Grundlagen der Informatik 2. Typen

: Einführung in die Programmierung Übungsblatt 11

The ACCENT Compiler Compiler. A compiler compiler for the entire class of context-free languages

Transkript:

Was ist das? Ein Parsergenerator erzeugt einen Parser zur grammatikalischen Analyse in einer gewünschten Programmiersprache. Übernimmt Vorverarbeitung, besonders bei LL, LR u.ä. Syntaxanalyse Parsergeneratoren Unterschiede: Verfahren Erzeugte Programmiersprache Allgemeiner Aufbau Ingrid Fischer Lehrstuhl für Programmiersysteme Universität Erlangen-Nürnberg 2 Beispiele LEX / YACC GOLD ANTLR Spirit An YACC: Codeinklusion An GOLD: Tabellen An ANTLR: Auswertung An Spirit: Außergewöhnliche Techniken GOLD Parser Kurzform für: Generalized Object-oriented Language Developer http://www.devincook.com/goldparser/ Mehrere Freizeitentwickler Closed Source Kostenlos Verfügt über Benutzeroberfläche Generischer Parser als Windows OCX/ActiveX verfügbar 3 4 Funktionsweise G.O.L.D. Grammatiken Grammatik mittels normalem Editor oder GOLD GUI beschreiben GOLD Parser prüft die Grammatik und bildet LALR(1) Automat und Tabelle Speichert proprietäres Format Parser analysiert mittels.cgt File einen Text Kann z.b. bei jedem Reduce/Shift benutzerdefinierte Aktion ausführen Source Grammar Outline Gold Parser Compiled Grammar Table DFA & LALR Parser Engine Source text Parsed Data 5 6 1

G.O.L.D. Grammatiken G.O.L.D. Grammatiken 7 8 G.O.L.D. Grammatiken G.O.L.D. Grammatiken EBNF orientiert Definition von Terminalzeichen und Grammatikregeln sind in einem zusammen gefasst Häufig benutzte Terminale bereits eingebaut (z.b.: digit oder letter ) 9 10 Ausschnitte aus der Pascal Definition in G.O.L.D. G.O.L.D. Benutzeroberfläche DecLiteral HexLiteral FloatLiteral <constant> = [123456789]{digit}* = '$'{Hex Digit}+ = {Digit}*.{Digit}+ ::= DecLiteral StringLiteral FloatLiteral HexLiteral CharLiteral <ConstantDef> ::= id '=' <constant> '' <VariableDeclarations> ::= VAR <VarDeclList> <VarDeclList> ::= <VariableDec> <VariableDec> <VarDeclList> <VariableDec> ::= <IdList> ':' <TypeSpecifier> '' Symbol Definitionen Konstanten Definitionen Variablen Definition Normaler Arbeitsablauf: 1. Grammatik editieren 2. Grammatik in das G.O.L.D. Format übersetzen 3. Ggf. Blick auf die LALR Zustände und den DFA werfen 4. Testtext parsen 5. Parsebaum betrachten 11 12 2

Integration Generischer Parser wird eingebunden: Visual Basic : ActiveX / OCX Komponente C / C++ / Java : Open Source Klassen Delphi : VCL Komponente dot net : Source Klasse oder Komponente Wertet Quelltext mittels DFA aus und teilt dem Anwender shift und reduce Operationen mit. Demonstration 13 14 G.O.L.D. - Beurteilung Vorteile Grammatiken leicht les- und schreibbar Besitzt Benutzeroberfläche, die Entwickeln und Testen von Grammatiken sehr angenehm macht LALR Parser erlaubt Linksrekursionen In sich abgeschlossen, leicht zu benutzen und zu integrieren Parser Engine für viele Sprachen verfügbar Nachteile Mäßige Fehlerlokalisierung Quellcode nicht verfügbar Unter Umständen langsamer, da ein generischer Parser verwendet wird. Unmöglich Parser zu debuggen Yacc bzw. gliedert sich, wie jeder Parser in 2 Teile. 1. LEX: Fungiert als Abtaster (Scanner) erkennt bedeutungstragende Einheiten (Token), entfernt überflüssige Zeichen wie Kommentare, Einrückungen etc. 2. YACC: Eigentlicher Zerteiler (Parser), setzt auf Ergebnisse von LEX auf. Erkennt Struktur des Programms, da er mittels Grammatik über den Aufbau und Syntax informiert ist. 15 16 Stephen Johnson: Yet Another Compiler Compiler (1979) Entwickelt bei den Bell Labs von AT&T für Unix Eingabe: EBNF Ausgabe: C Parservariante: LALR Fester Bestandteil von Unix Viele Varianten Berkeley Yacc http://dickey.his.com/byacc/byacc.html GNU bison http://www.gnu.org/software/bison/ MKS yacc http://www.mkssoftware.com/docs/wp/wp_lyuse.asp %{ C-Deklarationen %} yacc-deklarationen %% yacc-regeln (Grammatikteil) %% Benutzerdefinierte Routinen (Hilfsfunktionsteil) z.b. main, yyerror, yylex Zitat: A successful tool is one that was used to do something undreamt of by its author. 17 18 3

%{ #include <ctype.h> #include <stdio.h> %} %token NUMBER %% lines : lines expr '\n' { printf("%d \n", $2) } lines '\n' expr : expr '+' term { $$= $1 + $3 } expr '-' term { $$= $1 - $3 } term term : term '*' factor { $$= $1 * $3 } term '/' factor { $$= $1 / $3 } factor factor : '(' expr ')' { $$=$2 } NUMBER 19 20 21 22 23 24 4

Demonstration 25 26 Beispiel Beispiel 27 28 Beispiel Yacc - Beurteilung Vorteile Lange Entwicklungszeit hinter sich Deshalb hoher Grad an Ausgereiftheit Ausführlichst dokumentiert In sich abgeschlossen, leicht zu benutzen und zu integrieren LALR Parser erlaubt Linksrekursionen Nachteile Sehr schlechte Fehlerlokalisierung im zerteilten Text: Syntax error in line XXX Fehler in Grammatiken unverständlich dargestellt. Erzeugt C code Wegen LALR Tabelle ist es sehr schwierig den Parser zu debuggen 29 30 5

ANTLR Kurz für: ANother Tool for Language Recognition hieß vorher: PCCTS (Purdue Compiler Construction Tool Set) wird seit 1989 von Terence Parr entwickelt und gepflegt Parr ist Professor für Informatik an der Universität San Francisco ANTLR Ursprünglich für/in Java entwickelt. Unterstützt auch C++, C#, Python LL(k) Parser. Mächtiges Werkzeug. Fasst Scanner und Parser zusammen. Zitat: "Why program by hand in five days what you can spend five years of your life automating." 31 32 Taschenrechner - Lexer Beispiel Parser class ExprLexer extends Lexer options { k=2 // needed for newline junk charvocabulary='\u0000'..'\u007f' // allow ascii} Optionen Taschenrechner Grammatik - analysierend class ExprParser extends Parser Parserklasse LPAREN: '(' RPAREN: ')' PLUS : '+' MINUS : '-' STAR : '*' INT : ('0'..'9')+ WS : ( ' ' '\r' '\n' '\n' '\t' ) {$settype(token.skip)} Operatoren Zahl Überflüssige Zeichen expr: mexpr ((PLUS MINUS) mexpr)* mexpr : atom (STAR atom)* atom: INT LPAREN expr RPAREN Ausdruck, schachtelbar mit plus und minus Multiplikation Atomarer Ausdruck: Integer oder Klammerausdruck 33 34 Erkennende Testausgabe Taschenrechner - berechnend class ExprParser extends Parser Testausgaben 3+(4*5) $ 3+(4 line 1:6: expecting RPAREN, found 'null' $ 3++ line 1:3: unexpected token: + $ Grammatik Grammatik: expr: mexpr ((PLUS MINUS) mexpr)* mexpr : atom (STAR atom)* atom: INT LPAREN expr RPAREN expr returns [int value=0] {int x} : value=mexpr ( PLUS x=mexpr {value += x} MINUS x=mexpr {value -= x} )* mexpr returns [int value=0] {int x} : value=atom ( STAR x=atom {value *= x} )* atom returns [int value=0] : i:int {value=integer.parseint(i.gettext())} LPAREN value=expr RPAREN Ausgabe Variablen Deklaration 35 36 6

Erzeugter Code Abstract Syntax Trees public int mexpr() { int value=0 int x // local variable def from rule mexpr value = atom() while ( LA(1)==STAR ) { match(star) x = atom() value *= x} return value} public int atom() { int value=0 switch ( LA(1) ) { // switch on lookahead token type case INT : Token i = LT(1) // make label i point to next lookahead token object match(int) value=integer.parseint(i.gettext()) // compute int value of token break case LPAREN : match(lparen) value = expr() // return whatever expr() computes match(rparen) break default : // error} return value} ANTLR kann selbstständig ASTs erzeugen. Dazu wird die Grammatik geringfügig geändert, um ANTLR anzuzeigen, wo die Wurzeln der Unterbäume liegen sollen (Änderungen sind unterstrichen). class ExprParser extends Parser options { buildast=true } expr: mexpr ((PLUS^ MINUS^) mexpr)* mexpr : atom (STAR^ atom)* atom: INT LPAREN! expr RPAREN! class ExprParser extends Parser expr: mexpr ((PLUS MINUS) mexpr)* mexpr : atom (STAR atom)* atom: INT LPAREN expr RPAREN 37 38 Testausgaben 3+4 ( + 3 4 ) + 3+4*5 ( + 3 ( * 4 5 ) ) 3 4 + Übung! (3+4)*5 ( * ( + 3 4 ) 5 ) * 3 * 4 5 + 5 3 4 39 40 ANTLR - Beurteilung Vorteile Großes Paket, unterstützt eine Vielzahl an Funktionen Für mehrere Sprachen verfügbar (Java, C++, C#) Platformunabhängig Mittlerweile große Gemeinschaft (Google liefert ~ 126000 Treffer) Kann direkt mit ASTs umgehen Spirit Teil der BOOST Bibliothek. (www.boost.org) Boost ist eine C/C++ Bibliothek um das Schreiben von platformunabhängigen Code zu vereinfachen. Verschiedene Autoren: Joel de Guzman oder Martin Wille Nachteile Lange Einarbeitungszeit Fehler in der Grammatik kann u.u. schwer zu finden sein, wenn Fehlermeldung in einer entfernteren Produktion angezeigt wird ANTLR ist schwer mit anderen Komponenten zu verknüpfen (z.b. ANTLR-Parser verwenden aber anderen Scanner) Keine Linksrekursion 41 42 7

Spirit Fakten Ausschließlich für C++ entwickelt. basiert auf generischem Programmieren, das heißt "C++ Templates". Lässt mittels Operatorenoverloading Grammatiken direkt in C++ schreiben. Für kleine bis mittlere Parser gedacht. LL(k) Parser. Beispiel EBNF: group ::= '(' expression ')' factor ::= integer group term ::= factor (('*' factor) ('/' factor))* expression ::= term (('+' term) ('-' term))* Spirit: group = '(' >> expression >> ')' factor = integer group term = factor >> *(('*' >> factor) ('/' >> factor)) expression = term >> *(('+' >> term) ('-' >> term)) Die Ähnlichkeit zwischen den beiden Formen ist sehr leicht erkennbar. Grammatiken können also in Spirit leicht gelesen und geschrieben werden. 43 44 Weiter Beispiele Taschenrechner - analysierend real_p >> *(',' >> real_p) Real_p ist ein Parser, der eine reele Zahl parst. Das Komma ist eine Abkürzung für ch_p(','), was wiederum ein Parser für Kommas ist. Das Beispiel liest also eine beliebig lange, durch Komma getrennte Liste an reellen Zahlen ein. real_p[&f] >> *(',' >> real_p[&f]) Dieses Beispiel funktioniert wie obiges allerdings mit dem Zusatz, dass für jede gelesene reelle Zahl, die Funktion f aufgerufen wird. range_p('a','z') range_p überprüft, ob ein Zeichen innerhalb bestimmter Werte ist. In diesem Beispiel zwischen a und z. struct calculator : public grammar<calculator> { template <typename ScannerT> struct definition { definition(calculator const& self) { expression = term >> *( ('+' >> term)[&do_add] ('-' >> term)[&do_subt] ) term = factor >> *( ('*' >> factor)[&do_mult] ('/' >> factor)[&do_div] ) factor = lexeme_d[(+digit_p)[&do_int]] '(' >> expression >> ') ' ('-' >> factor)[&do_neg] ('+' >> factor) } rule<scannert> expression, term, factor rule<scannert> const& start() const { return expression } } } Funktionsaufruf 45 46 Funktionseinsprünge namespace { void do_int(char const* str, char const* end) { string s(str, end) cout << "PUSH(" << s << ')' << endl } void do_add(char const*, char const*) { cout << "ADD\n" } void do_subt(char const*, char const*) { cout << "SUBTRACT\n" } void do_mult(char const*, char const*) { cout << "MULTIPLY\n" } void do_div(char const*, char const*) { cout << "DIVIDE\n" } void do_neg(char const*, char const*) { cout << "NEGATE\n" } } Zusammenfassung Grammatik wird direkt in den Source eingefügt, der dann mittels generischem Programmieren zur Laufzeit Parser ist. Ausführen einer Methode in einem Template startet den Parse Vorgang. Semantische Aktionen führen zu: Eingabe: (-1 + 2) * (3 + -4) Ausgabe: -1 2 ADD 3-4 ADD MULT 47 48 8

Spirit - Beurteilung Vorteile Sehr handlich und kompakt Entwickelt von anerkannten Profis (<> Boost) Professionelle Programmiermethodik Sehr gut brauchbar um kleine Dinge, wie Email-Adressen oder URLs zu parsen Nachteile Nur für C++ verfügbar Fehler in der Grammatik kann u.u. schwer zu finden sein. Beschränkter Funktionsumfang Kompliziert zu lernen Unter Umständen langsam, da intensives OO Programmieren Keine Linksrekursion 49 9