9 Theoretische Informatik und Compilerbau

Größe: px
Ab Seite anzeigen:

Download "9 Theoretische Informatik und Compilerbau"

Transkript

1 9 Theoretische Informatik und Compilerbau Theoretische Informatik und Mathematik schaffen die Basis für viele der technischen Entwicklungen, die wir in diesem Buch besprechen. Die boolesche Algebra (S. 409 ff.) legt die theoretischen Grundlagen für den Bau digitaler Schaltungen, die Theorie formaler Sprachen zeigt auf, wie die Syntax von Programmiersprachen aufgebaut werden sollte, damit Programme einfach und effizient in lauffähige Programme übersetzt werden können, und die Theorie der Berechenbarkeit zeigt genau die Grenzen des Berechenbaren auf. Sie zieht eine klare Linie zwischen dem was man prinzipiell programmieren kann und dem was mit Sicherheit nicht von einem Rechner gelöst werden kann. In diesem Kapitel wollen wir einen kurzen Ausflug in die theoretische Informatik unternehmen. Wir werden sehen, dass diese Theorie nicht trocken ist, sondern unmittelbare praktische Anwendungen hat. Die Automatentheorie zeigt, wie man effizient die Wörter einer Programmiersprache festlegen und erkennen kann, die Theorie der kontextfreien Sprachen zeigt, wie man die Grammatik einer Programmiersprache definieren sollte, und wie man Übersetzer und Compiler dafür bauen kann. Letzterem haben wir ein eigenes Unterkapitel Compilerbau gewidmet. Ein fehlerfreies Programm ist aber noch lange nicht korrekt. Wünschenswert wäre es, wenn man feststellen könnte, ob jede Schleife auch terminiert. Dass diese und ähnliche semantischen Eigenschaften nicht automatisch geprüft werden können, ist eine der Konsequenzen der Berechenbarkeitstheorie. Mit dieser kann man zeigen, dass, wenn man einmal von Geschwindigkeit und Speicherplatz absieht, alle Rechner in ihren mathematischen Fähigkeiten identisch sind und damit das gleiche können bzw. nicht können. Schließlich hilft uns die Komplexitätstheorie, Aussagen über den Aufwand zu machen, den man zur Lösung wichtiger Probleme treiben muss. 9.1 Analyse von Programmtexten Programme sind zuerst einmal Texte, also Folgen von Zeichen aus einem gewissen Alphabet. Die ersten Programmiersprachen erlaubten nur Großbuchstaben, Klammern und Ziffern. In Pascal und C sind auch Kleinbuchstaben und Sonderzeichen, wie _, +, (, ), >, :, möglich und in Java sind sogar Unicode-Zeichen, insbesondere auch ä, ö und ü erlaubt. Die Menge aller Zeichen, die in einem Programm einer gewissen Programmiersprache vorkommen dürfen,

2 668 9 Theoretische Informatik und Compilerbau nennt man ihr Alphabet. Aus diesem Alphabet definiert man zunächst einmal die Wörter, aus denen die Sprache aufgebaut werden soll. Im Falle von Java oder Pascal sind dies u.a. Schlüsselwörter (while, do, for, if, else,...), Sonderzeichen (+, -, *, <=, >=,... ), benutzerdefinierte Bezeichner ( testfunktion, betrag, _anfangswert, x37, r2d2 ) und Konstanten. Unter letzteren unterscheidet man noch Integer-Konstanten ( 42, 386, 2004) von Gleitkommazahlen (3.14, 6.025e23,.5 ). Ein Compiler für eine Programmiersprache muss als erstes prüfen, ob eine vorgelegte Datei ein syntaktisch korrektes Programm enthält. Ihm liegt der Quelltext als String, also als eine Folge von Zeichen vor. Die Analyse des Textes zerfällt in zwei Phasen die lexikalische Analyse und die syntaktische Analyse. Dies entspricht in etwa auch unserem Vorgehen bei der Analyse eines fremdsprachlichen Satzes: In der ersten Phase erkennen wir die Wörter, aus denen der Satz besteht vielleicht schlagen wir sie in einem Lexikon nach und in der zweiten Phase untersuchen wir, ob die Wörter zu einem grammatikalisch korrekten Satz zusammengefügt sind Lexikalische Analyse Die erste Phase eines Compilers nennt man lexikalische Analyse. Dabei wird der vorgebliche Programmtext in Wörter zerlegt. Alle Trennzeichen (Leerzeichen, Tab, newline) und alle Kommentare werden entfernt. Aus einem einfachen PASCAL-Programm, wie PROGRAM ggt; BEGIN x := 54; y := 30; WHILE not x = y DO IF x > y THEN x := x-y ELSE y:= y-x; writeln( Das Ergebnis ist:,x) END. wird dabei eine Folge von Token. Dieses englische Wort kann man mit Gutschein übersetzen. Für jede ganze Zahl erhält man z.b. ein Token num, für jeden Bezeichner ein Token id, für jeden String ein Token str. Gleichartige Token stehen für gleichartige Wörter. Andere Token, die in dem Beispielprogramm vorkommen, sind eq (=), gt (>), minus (-), assignop( := ), klauf ( ( ), klzu( ) ), komma (, ), semi (;), punkt (.). Jedes Schlüsselwort bildet ein Token für sich. Nach dieser Zerlegung ist aus dem Programm eine Folge von Token geworden. Damit ist die erste Phase, die lexikalische Analyse, abgeschlossen. Im Beispiel hätten wir: program id semi begin id assignop num semi id assignop num semi while not id eq id do if id gt id then id assignop id minus id else id assignop id minus id semi id klauf str komma id klzu end punkt

3 9.1 Analyse von Programmtexten 669 Aus dem Input erzeugte Token begin id := num ; while id <= num do Jetziger Zustand: q B E G I N x : = 0 ; w h i l e x < = 4 2 d o x : = x + 2 E N D bereits gelesener Input Abb. 9.1: Endlicher Automat als Scanner Diese erste Phase ist nicht schwer, aber auch nicht trivial. Es muss u.a. entschieden werden, ob BeGin das gleiche ist, wie BEGIN, ob beginnen ein id ist, oder das Schlüsselwort begin gefolgt von dem Bezeichner nen. Schließlich muss erkannt werden, ob 00.23e- 001,.523e, 314.e-2 das Token num repräsentieren, oder nicht. Programme für die lexikalische Analyse heißen Scanner. Heutzutage kann man solche Scanner aus einer Beschreibung der Token durch sogenannte reguläre Ausdrücke automatisch erzeugen. Der bekannteste frei erhältlicher Scannergenerator heißt flex. Die lexikalische Analyse ist das Thema des ersten Unterkapitels Syntaxanalyse Wir nehmen an, dass unser Programm die lexikalische Analyse gut überstanden hat. Dann folgt als nächstes die sogenannte Syntaxanalyse. Hier wird geprüft, ob die gefundenen Wörter in der vorliegenden Reihenfolge ein grammatikalisch korrektes Programm bilden. Ausdrücke wie Wörter, Sprache, Grammatik, etc. erinnern nicht zufällig an natürliche Sprachen. Auch eine Analyse eines fremdsprachigen Satzes erfordert zunächst seine Zerlegung in Wörter und deren Klassifikation. Dabei könnte man vielleicht Token wie verb, nomen, artikel, adjektiv, komma, punkt benutzen. Aus einem Satz wie beispielsweise Die lila Kuh legt ein Schokoladenei. hätte die lexikalische Analyse die Tokenfolge artikel adjektiv nomen verb artikel nomen punkt abgeliefert. In der syntaktischen Analyse muss jetzt anhand der Regeln der Sprache überprüft werden, ob diese Folge von Token zulässig ist. Hier würde man Bildungsregeln der deutschen Sprache heranziehen, wie (stark vereinfacht):

4 670 9 Theoretische Informatik und Compilerbau Satz Subjekt Prädikat Objekt :: Subjekt Prädikat Objekt :: artikel nomen artikel adjektiv nomen :: verb hilfsverb :: artikel nomen Ganz analog sehen die Bildungsregeln einer Programmiersprache aus. Im Beispiel von Pascal hat man u.a.: Programm Kopf Anweisungsteil Anweisungen :: Kopf Deklarationen AnweisungsTeil punkt :: program id semi :: begin Anweisungen end :: Anweisung Anweisungen Anweisung In der Syntaxanalyse überprüft man, ob eine Folge von Token diesen Regeln entsprechen. Diesen Überprüfungsprozess nennt man auch Parsen (engl.: to parse = zerlegen). Wie man Regeln für eine Programmiersprache sinnvollerweise festlegt, und wie man einen Parser dafür schreiben und sogar automatisch erzeugen kann, davon handelt der zweite Teil dieses Kapitels. 9.2 Reguläre Sprachen Zuerst erkennen wir eine Gemeinsamkeit von lexikalischer und syntaktischer Analyse. Erstere betrachtet Wörter als Folge von Zeichen und fragt, ob ein Wort zu einer Klasse von Wörtern (num, float, id) gehört, letztere betrachtet Wörter als Folge von Token und fragt ebenfalls, ob das zusammengesetzte Wort zur Klasse der nach gewissen Regeln korrekt aufgebauten Programme gehört. Abstrakt definieren wir einfach: Definition (Alphabet): Ein Alphabet ist eine endliche Menge von Zeichen. Alphabete bezeichnet man gern mit großen griechischen Buchstaben wie Σ oder Γ und Zeichen mit a,b,c, etc. Aus den Zeichen eines Alphabets können wir Wörter bilden, daher folgt sogleich die nächste Definition: Definition (Wort): Ein Wort über einem Alphabet Σ ist eine endliche Folge von Zeichen aus Σ. Die Menge aller Wörter über Σ bezeichnet man mit Σ*. Wörter bezeichnen wir meist mit den Buchstaben u, v, w. Eine besondere Rolle spielt das leere Wort, es wird mit ε bezeichnet. Wörter über Σ sind nichts anderes als Strings, deren Zeichen aus Σ stammen. Als Konkatenation bezeichnet man die Zusammenfügung zweier Wörter u und v zu einem neuen Wort, das man als uv bezeichnet. Für jedes Wort u gilt offensichtlich: εu = uε = u. Die Länge eines Wortes w ist die Anzahl der Zeichen, aus denen w besteht. Man schreibt w für die Länge von w. Offensichtlich gilt: ε =0 und uw = u + w. Ein Zeichen kann man auch

5 9.2 Reguläre Sprachen 671 als Wort der Länge 1 auffassen. Daher benutzen wir die Notation aw auch für das Wort, das aus w entsteht, wenn man das Zeichen a davorsetzt, analog versteht man wa. Beispiele: Sei Σ die Menge aller Ziffern, und Γ die Menge aller Großbuchstaben, dann sind 42, 2004, 0, ε Elemente von Σ* und ε, C, ML, LISP sind Elemente von Γ*. Weiter sind R2D2, MX5 und X86 Elemente von ( Σ Γ)*, nicht aber von Σ* Γ*. Definition (Sprache): Eine Sprache über dem Alphabet Σ ist eine Menge von Wörtern über Σ. Eine Sprache über Σ ist also einfach eine beliebige Teilmenge von Σ*. Insbesondere ist auch die leere Menge { } eine Sprache, ebenso wie Σ*. Für Sprachen benutzt man gerne den Buchstaben L, weil dieser an das englische Wort language erinnert. Die folgenden Beispiele sind relevant und motivierend für die Entwicklung der Theorie: Beispiel 1: Die Sprache der Pascal-Bezeichner. Als Alphabet hat man die Ziffern, die Buchstaben (ohne Umlaute) und den Unterstrich, also Σ ={_, 0,..., 9, a,..., z, A,..., Z}. Die Sprache aller gültigen Pascalbezeichner ist L = { au u Σ*, a { 0,, 9} }, also alle nichtleeren Wörter, die nicht mit einer Ziffer beginnen. Beispiel 2: Die Sprache aller dezimalen Konstanten in Assembler. Dezimale Konstanten sind alle Wörter, die optional mit einem Vorzeichen beginnen, gefolgt von einer Folge von Ziffern. Sie dürfen nicht mit 0 beginnen außer wenn keine weitere Ziffer folgt. (In Assembler wird 012 als Hex-Zahl interpretiert.) Als Alphabet wählen wir Γ = Digit Sign mit Digit = { 0, 1,, 9} und Sign = {, + }. Wir definieren zuerst eine Hilfssprache L nat = { au a Digit { 0}, u Digit* } { 0} und dann schließlich L DAss = L nat { au a Sign, u L nat }. Mit einem kleinen Trick hätten wir die Definition kompakter gestalten können: Mit Hilfe des leeren Wortes definieren wir uns eine Sprache OptSign = { +,, ε}. Dann haben wir L DAss = { uv u OptSign, v L nat }. Offensichtlich lässt die bisher verfügbare mathematische Notation noch Wünsche offen. Um z.b. die Sprache aller float-zahlen auf die obige Weise in Java auszudrücken, müsste man sich schon anstrengen. Wir erinnern, dass u.a. die folgenden Zahlen gültige float sind: -3.14, 2.7f, 2.7,.3, 1e-9F, aber auch 00.5E000F Reguläre Ausdrücke Um komplizierte Sprachen aus einfacheren aufbauen zu können, definieren wir uns die Operationen, mit denen wir aus gegebenen Sprachen neue konstruieren können: Seien L und M Sprachen über dem gemeinsamen Alphabet Σ. Wir definieren L M = { uv u L, v M}, das Produkt von L und M, L 0 = { ε}, L n + 1 = L L n,die Potenzen von L, L* = { L n n Nat }, der Kleene-Stern von L.

6 672 9 Theoretische Informatik und Compilerbau Zusammen mit den bekannten mengentheoretischen Operationen und können wir daraus weitere nützliche Operatoren gewinnen: L + = L ( L* ), mehrmals L, L? = L { ε}, optional L. Mit den gerade eingeführten Operationszeichen bauen wir uns zunächst eine Notation, in der wir die betrachteten Sprachen gut beschreiben können. Definition (regulärer Ausdruck): Sei Σ ein Alphabet. und ε sind reguläre Ausdrücke. a ist ein regulärer Ausdruck für jedes a Σ. Sind e und f reguläre Ausdrücke, dann auch e + f, e f und e*. Zur eindeutigen Darstellung erlauben wir Klammern ( und ). Zur Klammernersparung vereinbaren wir, dass * starker bindet als, und dieses stärker als +. Jeder reguläre Ausdruck soll eine Sprache beschreiben. Mit L(e) bezeichnen wir die Sprache, die durch den regulären Ausdruck e beschrieben wird. Die Definition folgt dem induktiven Aufbau der regulären Ausdrücke: L( ) = { } und L( ε) = { ε}. L( a) = { a} für jedes a Σ. L( e + f) L( e f) = = L( e) L( f), L( e) L( f) und L( e* ) = L( e)*. Man beachte den feinen Unterschied zwischen der leeren Sprache { } und der Sprache, die nur das leere Wort enthält, { ε}. Mit regulären Ausdrücken könnten wir jetzt die vorhin diskutierten Sprachen beschreiben. Beispielsweise gilt L nat = ( ) ( )* + 0. Die eingeführte Notation ist noch nicht kompakt genug, daher definieren wir einige Abkürzungen: e? := e+ ε drückt aus, dass e optional ist e + := e e* mehrmals e, mindestens einmal. Teilmengen des Alphabets dürfen wir auch aufzählen, z.b. [ä,ü,ö] statt (ä+ü+ö). Meist sind die Zeichen des Alphabets geordnet. Für diesen Fall definieren wir die Abkürzung [a c] für { x Σ ( a x c) }. Das Konkatenationszeichen lässt man oft weg. So wird aus den vorigen Beispielen: nat := [1 9][0 9]* + 0 DAss := [+, - ]? nat letter := [a z]+[a Z], digit := [0-9], PascalBezeichner := ( _ + letter)( _ + letter+digit)*

7 9.2 Reguläre Sprachen 673 Die so eingeführte reguläre Sprache wird in vielen Unix-Tools (sed, grep, awk) und in vielen Sprachen (Perl, Tcl/Tk) praktisch eingesetzt, vgl. auch Abschnitt auf S Viele Editoren erlauben Textsuche nach beliebigen Zeichenketten mit Hilfe eines regulären Ausdrucks. Reguläre Ausdrücke werden praktisch immer verwendet, um den lexikalischen Anteil von Programmiersprachen festzulegen. So auch in dem Werkzeug lex (bzw. flex), mit dessen Hilfe automatisch ein C-Programm generiert wird, das die lexikalische Analyse für eine selbstdefinierte Programmiersprache übernimmt und somit die erste Stufe eines Compilers bildet. Die folgenden Zeilen zeigen zwei Einträge aus einer flex-datei. Es werden Bezeichner und Dateinamen definiert. Der Schrägstrich / hat für flex eine Spezialbedeutung. Durch das vorangestellte Escape-Zeichen \ wird diese aber aufgehoben. [_a-za-z][a-za-z0-9]* [a-za-z0-9\/.-]+ return BEZEICHNER; return FILENAME; Im folgenden Paragraphen wollen wir uns der Frage widmen, wie Werkzeuge wie lex funktionieren können. Konkret: Wie kann man ein Programm erstellen, das zu einem beliebigen regulären Ausdruck e und einem beliebigen Text s erkennt, ob s L( e) ist, oder das alle Textstellen findet, die auf den regulären Ausdruck passen Automaten und ihre Sprachen Ein Automat ist ein sehr einfaches Modell einer zustandsorientierten Maschine. Wir stellen uns einen Kasten vor, der eine Eingabe erhält und daraufhin seinen internen Zustand ändert. Damit das ganze einen Nutzeffekt hat, soll der Automat auch eine Ausgabe haben, für unsere Zwecke wird es aber ausreichen, wenn wir uns auf zwei mögliche Ausgaben beschränken ja oder nein, true oder false, Licht an oder Licht aus. Als Eingabe des Automaten A verwenden wir ein Alphabet Σ. Wir gehen davon aus, dass der Automat eine Menge Q von möglichen Zuständen einnehmen kann. Mit einer Reset-Taste können wir ihn in einem wohldefinierten Ausgangszustand starten. Danach geben wir Zeichen aus Σ ein. Jedes eingegebene Zeichen kann den Automaten in einen neuen Zustand versetzen. Ist q der gegenwärtige Zustand und geben wir ein Zeichen a ein, so sei δ( q, a) der neue Zustand. Einen Zustand, der die Ausgabe true erzeugt, nennen wir einen finalen oder akzeptierenden Zustand. Die formale Definition ist: Definition (Automat) Σ sei ein endliches Alphabet. Ein Σ -Automat besteht aus einer Menge Q von Zuständen und einer Übergangsfunktion δ: Q Σ Q. Ein spezieller Zustand q 0 Q dient als Anfangszustand und F Q sei eine Menge von finalen oder akzeptierenden Zuständen. Beispiel: Eine Funk-Digitaluhr habe nur zwei Knöpfe: mode, lap. Wir können diese als Alphabet Σ = { mode, lap} auffassen. Die internen Zustände seien Uhr, Timer, Pause und die Zustandsübergänge etwa δ( Uhr, mode) = Pause, δ( Pause, mode) = Uhr δ( Pause, lap) = Timer und δ( Timer, lap) = Pause, δ( Uhr, lap) = Uhr, etc. Uhr sei der Anfangszustand. Die finalen Zustände eines Joggers seien: {Timer, Pause}.

8 674 9 Theoretische Informatik und Compilerbau Beispiel: Ein Erkenner (engl.: scanner) für Pascal-Bezeichner habe als Alphabet das ASCII- Alphabet und als Zustände: {Start, OK, Error} mit δ( Start, b) = OK, für jeden Buchstaben (engl.: letter) b und δ( OK, c) = OK für jeden Buchstaben oder Ziffer (engl.: digit) c. (Wir rechnen einfach _ zu den Buchstaben.) In jedem anderen Fall sei δ( q, a) = Error. Automaten kann man veranschaulichen, indem man jeden Zustand q durch einen Kreis darstellt und jeden Übergang δ( q, a) = q' durch einen Pfeil von q nach q', den man mit a beschriftet. Zwischen zwei Zuständen malt man höchstens einen Pfeil und beschriftet ihn mit allen Zeichen, die diesen Zustandsübergang hervorrufen. Auf den Anfangszustand zeigt ein Pfeil, der aus dem Nichts kommt. Akzeptierende Zustände kennzeichnet man durch eine doppelte Umrandung. Für jedes Zeichen a muss aus jedem Zustand q ein Pfeil ausgehen, der mit a beschriftet ist. Allerdings ist diese Bedingung manchmal lästig. Man kann sie aber immer erfüllen, wenn man einen Errorzustand E hinzunimmt, zu dem alle fehlenden Pfeile gerichtet werden. In der Figur haben wir diese durch gestrichelte Pfeile hervorgehoben. Später werden wir diese weglassen. digit digit S letter letter, digit Ok Err s 0 +, - digit s 1 s 2.. s 5 s 4 digit digit s 3 Abb. 9.2: Automaten für Bezeichner und für Dezimalzahlen Wie das letzte Beispiel andeutet, kann man Automaten dazu benutzen, Wörter zu akzeptieren oder zurückzuweisen. Dazu startet man sie im Anfangszustand q 0 und gibt der Reihe nach die Zeichen c 1, c 2, c 3, eines Wortes w ein. Der Automat geht dabei durch die Zustände q 0, q 1 = δ( q 0, c 1 ), q 2 = δ( q 1, c 2 ), Ist er zum Schluss, wenn das Wort w komplett abgearbeitet ist, in einem akzeptierenden Zustand, so wird das Wort akzeptiert, ansonsten zurückgewiesen. Man kann ein Wort w = c 1 c 2 c 3 c n als eine Art Fahrplan durch den Automaten auffassen. Am Anfangsknoten q 0 ist dem Pfeil zu folgen, der mit c 1 beschriftet ist, im Folgezustand q 1 = δ( q 0, c 1 ) dem Pfeil mit Beschriftung c 2, etc. Die Folge der dabei besuchten Zustände nennt man auch einen Lauf für w.

9 9.2 Reguläre Sprachen 675 c 1 c 2 q 0 q 1 q 2 q n-1 q n c n Abb. 9.3: Lauf für w = c 1 c 2 c 3... c n Somit interessiert uns hauptsächlich, welche Wirkung ein ganzes Wort auf den Automaten hat. Daher erweitern wir die Funktion δ zu einer Funktion δ: Q Σ* Q durch δ* ( q, ε) = q δ* ( q, aw) = δ* ( δ( q, a), w) für jedes Wort w und Zeichen a. Jeder Automat definiert auf diese Weise eine Sprache, nämlich die Menge aller Wörter, die uns vom Anfangszustand in einen Endzustand führen: Definition (Sprache eines Automaten): Sei A ein Σ -Automat mit Anfangszustand q 0, Transitionsfunktion δ und akzeptierenden Zuständen F Q, dann heißt L( A) = { w Σ* δ* ( q 0, w) F} die Sprache des Automaten A. Die Sprache des linken Automaten in Abbildung 9.2 besteht aus allen Wörtern, die mit einem Buchstaben (letter) beginnen, auf den dann beliebig viele Buchstaben oder Ziffern folgen. Die Sprache des rechten Automaten ist die Menge aller Dezimalzahlen Implementierung endlicher Automaten Für alle uns interessierenden Anwendungen werden die Automaten nur endlich viele Zustände haben. Für solche endlichen Automaten kann man die Abbildung δ: Q Σ Q durch eine Q Σ -Tabelle mit Einträgen aus Q implementieren. Für q Q und a Σ findet man δ( q, a) in der q-ten Zeile und der a-ten Spalte. Die Abbildung δ* wird durch eine einfache for-schleife realisiert: Zustand deltastern(zustand z,string wort){ for(int i=0;i<wort.length;i++) z = tabelle[z][wort.charat(i)]; return z; } und die Endzustände durch ihre charakteristische Funktion: boolean isfinal(zustand z){... } Für Sprachen, die durch endliche Automaten beschrieben werden, ist ein Scanner also einfach zu implementieren. Allerdings wird, wie bereits gesagt, der lexikalische Anteil von Programmiersprachen meist durch reguläre Ausdrücke spezifiziert. Wie kann man aber den regulären Ausdruck in einen Automaten umwandeln? Leider geht dies nicht direkt, sondern nur auf dem Umweg über sogenannte nichtdeterministische Automaten.

10 676 9 Theoretische Informatik und Compilerbau ε -Transitionen und nichtdeterministische Automaten ε -Transitionen sind Zustandsübergänge, die ein Automat machen kann, ohne dass ein Eingabezeichen verbraucht wird. Wir erweitern unser Automatenkonzept, indem wir jetzt erlauben, dass Transitionen eingefügt werden, die wir mit ε beschriften. Von einem Zustand q dürfen keine, eine oder mehrere solche ε -Transitionen ausgehen. Ein Lauf für ein Wort w = c 1 c 2 c 3 c n ist jetzt eine Zustandsfolge q 0, q 1, q 2,, q k bei der in jedem Schritt entweder ein Zeichen c i verbraucht wird oder einer ε -Transition gefolgt wird. Wir wollen uns die formale Definition hier sparen und veranschaulichen die Situation graphisch: c 1 ε ε c 2 c n q 0 q 1 q 2 q 3 q 4 q n-1 q n Abb. 9.4: Lauf mit ε-transitionen Ein Wort w = c 1 c 2 c n ist nun kein eindeutiger Fahrplan mehr. Ist man nach i Schritten zum Zustand q i gelangt, dann können wir entweder einem mit c i + 1 beschrifteten Pfeil oder einer ε -Transition folgen, sofern eine solche vorhanden ist. Jetzt sagt man, dass ein Wort akzeptiert wird, wenn es möglich ist, mit diesem Wort in einen akzeptierenden Zustand zu kommen. Für einen Automaten A mit ε -Transitionen definieren wir also die Sprache L(A), die durch den Automaten A erkannt wird als L( A) = { w Σ* Es gibt einen w Lauf zu einem akzeptierenden Zustand. } Meist führt man an dieser Stelle noch sogenannte nichtdeterministische Automaten ein. Sie erlauben, dass für beliebige Zeichen a Σ aus jedem Zustand keiner oder mehrere Pfeile mit Beschriftung a führen können. Für unsere Zwecke benötigen wir diese allgemeinere Automatendefinition aber nicht Automaten für reguläre Sprachen Für jeden regulären Ausdruck e wollen wir jetzt einen Automaten A e mit ε -Transitionen konstruieren, der genau die gleiche Sprache erkennt, also mit L( e) = L( A e ). Wir folgen dem induktiven Aufbau der regulären Ausdrücke. Dabei konstruieren wir in jedem Schritt sogar Automaten mit genau einem akzeptierenden Zustand, der verschieden ist vom Anfangszustand. Für die regulären Ausdrücke, ε und a Σ wählen wir: ε a Abb. 9.5: Automaten für, ε und a.

11 9.2 Reguläre Sprachen 677 Für die regulären Operatoren +, und * gehen wir jeweils davon aus, dass wir für die regulären Ausdrücke e und f schon Automaten A e und A f mit je einem Anfangs- und Endzustand konstruiert haben. Wir fügen ggf. neue Anfangs- und Endzustände und ε -Transitionen hinzu und machen früher akzeptierende Zustände zu nicht akzeptierenden, um die Automaten für e + f, e f und e* zu erhalten. ε ε A ε e A e A f A e ε ε ε ε A f ε ε Abb. 9.6: Automatenkonstruktionen für +, und * Von nichtdeterministischen zu deterministischen Automaten Wir haben gesehen, wie man zu jedem regulären Ausdruck e einen Automaten A finden kann, der die durch e spezifizierte Sprache erkennt. Da der Automat aber ε -Übergänge haben kann, funktioniert unsere vorher gezeigte Implementierung von Automaten durch eine Tabelle nicht mehr unmittelbar. Daher müssen wir zuerst unseren ε -Automaten durch einen gleichwertigen deterministischen Automaten ersetzen. Die Potenzmengenkonstruktion, die wir hier vorstellen, funktioniert für jeden nichtdeterministischen Automaten. Sei also A ε unser Ausgangsautomat mit endlicher Zustandsmenge Q, Anfangszustand q 0 und Finalzuständen F Q. Zu jedem Wort w Σ* sei Q( w) Q die Menge aller Zustände, zu denen es einen w -Pfad von q 0 aus gibt. Wir konstruieren einen deterministischen endlichen Automaten D, der die gleiche Sprache erkennt wie A ε. Wir wählen als Zustandsmenge { Q( w) w Σ* }. D hat also maximal 2 Q viele Zustände. als Anfangszustand Q( ε) und als finale Zustände alle Q( w), mit F Q( w), als Zustandsübergangsfunktion ϑ( Q( w), a) = Q( wa) für a Σ und w Σ*. Da aus Q( w) = Q( w' ) folgt Q( wa) = Q( w'a), ist ϑ wohldefiniert und es gilt: Hilfssatz: Für alle w, v Σ* ist ϑ* ( Q( w), v) = Q( wv). Beweis durch Induktion über den Aufbau der Wörter v Σ* : Ist v = ε, dann gilt nach Def von ϑ* sofort ϑ* ( Q( w), ε) = Q( w) = Q( wε). Ist v = au und sei für alle w Σ* die Behauptung ϑ* ( Q( w), u) = Q( wu) schon gezeigt, insbesondere also auch ϑ* ( Q( wa), u) = Q( wau), dann rechnen wir: ϑ* ( Q( w), au) = ϑ* ( ϑ( Q( w), a), u) = ϑ* ( Q( wa), u) = Q( wau) = Q( wv). Satz: A ε und D erkennen die gleiche Sprache, kurz: L( A ε ) = L( D).

12 678 9 Theoretische Informatik und Compilerbau Beweis: w L( D) δ* ( Q( ε), w) ist final in D Q( w) ist final in D (aufgrund des Hilfssatzes) es gibt einen finalen Zustand q f Q( w) in A ε gibt es einen w-pfad zu einem finalen Zustand q f Q w L( A ε ). Wir haben also einen deterministischen Automaten gefunden, der die gleiche Sprache erkennt wie A ε. Somit halten wir als Hauptergebnis fest: Satz: Zu jedem regulären Ausdruck e gibt es einen deterministischen endlichen Automaten A e, der die durch e spezifizierte Sprache erkennt. Diesen können wir mittels einer Tabelle implementieren. Die Umkehrung, dass es zu jedem endlichen Automaten A auch einen entsprechenden regulären Ausdruck gibt, wollen wir hier nicht beweisen. Für praktische Zwecke ist diese Richtung nicht so interessant Anwendung: flex Das bereits erwähnte Programm flex ist eine freie Variante des UNIX-Programms lex. Es akzeptiert als Eingabe einen oder mehrere reguläre Ausdrücke und erzeugt daraus ein C-Programm, das einen Scanner für die besagten regulären Ausdrücke implementiert. Mittlerweile gibt es auch Varianten von flex für andere Sprachen, u.a. für Pascal, perl, oder Java. flex funktioniert prinzipiell wie oben theoretisch beschrieben, allerdings transformiert es nicht nur einen, sondern gleich mehrere reguläre Ausdrücke in Automaten und dann das ganze in ein tabellengesteuertes Programm. Außerdem werden die gefundenen Automaten noch minimiert, indem äquivalente Zustände identifiziert werden. Zustände q und q' heißen dabei äquivalent, wenn für alle w Σ* gilt: δ* ( q, w) F δ* ( q', w) F. Der von flex generierte Scanner liest einen String von der Eingabe (standard input) und versucht jeweils Anfangsstücke abzutrennen, die zu einem der regulären Ausdrücke gehören. Immer wenn er erfolgreich ist, kann er noch eine gewünschte Aktion ausführen. Die beiden Zeilen einer flex-datei, die auf S. 673 gezeigt sind, geben jeweils ein Token in Form von benutzerdefinierten Konstanten BEZEICHNER, bzw. FILENAME zurück. Für solche Zwecke können im Vorspann einer flex-sprachbeschreibung entsprechende Token definiert werden. Eine flex-datei besteht aus drei Teilen, die durch %% getrennt sind. Im ersten Teil werden Abkürzungen für reguläre Ausdrücke definiert. Im zweiten Teil stehen auf jeder Zeile ein regulärer Ausdruck und die zugehörige Aktion als C-Anweisung. Die von flex erzeugte Scannerfunktion hat den Namen yylex(). Sie hat einen input-stream yyin, auf dem sie die Eingabedatei erwartet. Wenn immer ein Anfangsstück aus der Eingabe erkannt wurde, wird es in der

13 9.3 Kontextfreie Sprachen 679 Variablen yytext zwischengespeichert. Die Aktionen, der jeweils erkannten regulären Ausdrücke können jeweils auf diesen String zurückgreifen. Im folgenden zeigen wir eine komplette flex-datei zeit.lxi. Sie soll alle Zeitangaben in einem Text finden und ausdrucken. Im Vorspann wird zeit als regulärerer Ausdruck mit den Hilfsausdrücken für stunde und minsec definiert Im Hauptteil stehen die regulären Ausdrücke zeit, ein Punkt., und $. Letztere stehen für ein beliebiges Zeichen, bzw. für ein Zeilenende. stunde [01][0-9] 2[0-3] minsec [0-5][0-9] zeit {stunde}:{minsec}(:{min_sec})? %% {zeit} { printf("%s\n",yytext); }. { } $ { zeilenzahl++;} %% main( argc, argv){ int argc; int zeilenzahl=0; char **argv;{ yyin = stdin; yylex(); printf("%d Zeilen gelesen\n",zeilenzahl); } Im dritten Teil kann der Aufruf von yylex() in ein Hauptprogramm main() eingebettet werden. In diesem Falle erzeugt flex aus zeit.lxi einen lauffähigen Scanner. Dieser muss nur noch mit einem C-Compiler übersetzt und mit Funktionen der lex-library ll verlinkt werden: flex zeit.lxi cc -ll > zeit.exe 9.3 Kontextfreie Sprachen Mit regulären Ausdrücken kann man die Wörter, aus denen Programmiersprachen aufgebaut sind, beschreiben. Technisches Ergebnis dieser Beschreibung kann ein Scanner sein, der einen Programmtext in Wörter zerteilt und für jedes gefundene Wort ein entsprechendes Token liefert. In der nächsten Phase muss entschieden werden, ob die entstandene Folge von Token ein korrektes Programm darstellt. Fasst man die Token als neues Alphabet Γ auf, so ist ein Programm ein Wort über diesem Alphabet. Die Menge aller korrekten Programme ist also eine Sprache über Γ. Die Frage liegt nahe, ob man diese Sprache auch durch reguläre Ausdrücke beschreiben kann. Die Antwort ist negativ, was man an dem folgenden Beispiel sieht:

14 680 9 Theoretische Informatik und Compilerbau Beispiel: Sei Σ = { (, ) } das Alphabet, das aus einer öffnenden und schließenden Klammer besteht. Die Sprache KK, der korrekten Klammerausdrücke, bestehe aus allen Wörtern über Σ, die aus einem korrekten arithmetischen Ausdruck entstehen, wenn man alles, bis auf die Klammern, löscht. Beispielsweise gilt ( )((( )( ))( )) KK, dagegen ist z.b. (()))(( ) KK. Angenommen, man könnte KK durch einen regulären Ausdruck beschreiben, dann gäbe es auch einen endlichen deterministischen Automaten, der KK erkennt. Geben wir diesem ein Wort ein, das mit k vielen öffnenden Klammern beginnt, also ((( (, so sei q k der erreichte Zustand. Für k k' muss aber q k q k' gelten, denn aus ersterem Zustand muss man mit k schließenden Klammern in einen akzeptierenden Zustand gelangen, aus dem zweiten darf man dies nicht. Mithin müsste der Automat unendlich viele Zustände haben Kontextfreie Grammatiken Klammerausdrücke kommen in allen Programmiersprachen vor, sei es in arithmetischen Ausdrücken, oder in Form von begin und end, { und }. Eine allgemeinere Notation für die Sprachdefinition bieten sogenannte kontextfreie Grammatiken. Wir zeigen zuerst als Beispiel eine Grammatik für eine einfache Sprache, die wir WHILE nennen wollen: Programm :: begin Anweisungen end Anweisungen :: ε Anweisung Anweisung ; Anweisungen Anweisung :: Zuweisung Schleife Alternative Zuweisung :: id := Expr Schleife :: while Bexpr do Anweisung Alternative :: if Bexpr then Anweisung Expr :: Expr + Expr Expr - Expr Expr * Expr ( Expr ) id num Bexpr :: Expr = Expr Expr < Expr not Bexpr true false Der Lesbarkeit halber verwenden wir hier die Zeichen ;, :=, +, etc. anstatt der Tokennamen semi, assignop, plus, minus, etc. Jede Zeile ist als Definition des Begriffes links von dem zweifachen Doppelpunkt zu verstehen. Auf der rechten Seite trennt der senkrechte Strich Alternativen, er ist als oder zu lesen. ε bezeichnet wie bisher das leere Wort. Beispielsweise besagen die ersten beiden Zeilen: Ein Programm beginnt mit dem Token begin, dann folgen Anweisungen dann das Token end und Anweisungen sind leer oder bestehen aus einer Anweisung oder aus einer Anweisung gefolgt von einem ; und Anweisungen. WHILE ist also eine Sprache über dem Alphabet { begin, end, ;, id, :=, while, do, if, then, +, -, *, (, ), =, <, num, not, true, false }. Man nennt diese Zeichen Terminale oder Token. Als Nonterminale bezeichnet man die in der Grammatik definierten Begriffe wie Programm, Anweisungen, Anweisung, Zuweisung, Expr, Bexpr, etc. Definition: Eine kontextfreie Grammatik besteht aus einer Menge T von Terminalen (oder Token), einer dazu disjunkten Menge NT von Non-Terminalen, einer endlichen Menge von Produktionen P NT ( T NT) * und einem Startsymbol S NT. Eine Produktion ist also ein Paar ( A, α) bestehend aus einem A NT und einem Wort α ( T NT)*, das aus Terminalen und Nonterminalen bestehen kann. Ein solches Wort nennt man auch Satzform. Im Zusammenhang mit Grammatiken verwenden wir vorwiegend

15 9.3 Kontextfreie Sprachen 681 griechische Buchstaben α, β, γ für Satzformen, kursive Großbuchstaben A,B,C oder S für Nonterminale und Kleinbuchstaben a,b,c,t für Terminale. Statt ( A, α) schreibt man auch A α oder A :: α. Außerdem fasst man verschiedene Produktionen mit gleicher linker Seite zu einer sogenannten Regel zusammen, wobei man die rechten Seiten durch trennt. Eine Regel A :: α 1 α 2 α n steht dann für die Menge { A α 1, A α 2,, A α n } von Produktionen. Wenn man eine Grammatik aufschreibt, versteht man das Nonterminal der ersten Produktion als Startsymbol. In unserer WHILE-Sprache ist also Programm das Startsymbol Ableitungen Wir beschäftigen uns als erstes damit, wie man aus einer Grammatik irgendwelche syntaktisch korrekte Programme ableiten kann. Das wird natürlich nicht unser endgültiges Ziel sein, denn später wollen wir herausfinden, wie man zu einem vorliegenden Programm feststellen kann, ob (und wie) es aus einer Grammatik abgeleitet werden kann. Eine Ableitung beginnt mit dem Startsymbol S und ersetzt jeweils ein Nonterminal A durch eine Satzform α, sofern A α eine Produktion ist. Die Ableitung endet, wenn nur noch Terminale vorhanden sind. Im Beispiel unserer WHILE-Grammatik haben wir Programm begin Anweisungen end begin end als kürzestmögliche Ableitung einer terminalen Satzform. Im ersten Schritt wurde die Produktion Programm :: begin Anweisungen end benutzt, im zweiten: Anweisungen :: ε. Eine Ableitung eines anderen Programms ist z.b.: Programm begin Anweisungen end begin Anweisung ; Anweisungen end begin Zuweisung ; Anweisungen end begin id := Expr ; Anweisungen end begin id := num ; Anweisungen end begin id := num ; end Im Allgemeinen leitet man in jedem Schritt aus einer Satzform αaβ mithilfe einer Produktion A γ die Satzform αγβ ab. Man notiert einen solchen Schritt als αaβ αγβ. Verwendete Produktion: Anweisung id := Expr begin Anweisung ; Anweisungen end begin id := Expr ; Anweisungen end Abb. 9.7: Ableitungsschritt

16 682 9 Theoretische Informatik und Compilerbau Hat die ursprüngliche Satzform mehrere Nonterminale, so darf man in jedem Schritt ein beliebiges davon ersetzen welches spielt keine Rolle. In den obigen Beispielen haben wir immer das linkeste Nonterminal ersetzt. Eine solche Ableitung heißt Linksableitung analog gibt es auch den Begriff der Rechtsableitung. Gibt es eine Folge α β γ von Ableitungen, so schreibt man α * γ. Definition: Sei G eine kontextfreie Grammatik mit Startsymbol S. Als Sprache von G bezeichnet man L( G) = { w T* S * w}. L(WHILE) enthält somit u.a. begin end und begin id := num ; end. Die vorher erwähnte Sprache KK der korrekten Klammerausdrücke ist L( G) für folgende Grammatik: A ::= ( A ) A A ε Stackautomaten (Kellerautomaten) Ähnlich wie im Falle der regulären Sprachen wollen wir zu einer beliebigen Grammatik einen Automaten finden, der die zugehörige Sprache erkennt. Allerdings ist dies mit dem Konzept des endlichen Automaten unmöglich, da endliche Automaten nur reguläre Sprachen erkennen können. Speziell für die Sprache der korrekten Klammerausdrücke haben wir gesehen, dass man mit endlich vielen Zuständen nicht auskommen kann. Wir müssen daher einen neuen Automatenbegriff einführen, den sogenannten Stackautomaten, auf Deutsch auch als Kellerautomat bezeichnet. (Im Süddeutschen wird Stack oft mit Keller übersetzt. Vermutlich beruht dies auf der Erkenntnis, dass die zuletzt eingekellerten Kartoffeln zuerst auf den Tisch kommen.) Zusätzlich zu den endlich vielen Zuständen besitzt dieser noch einen unbegrenzten Stack, auf dem er Symbole eines speziellen Alphabets Γ ablegen kann. Offiziell besteht ein Stackautomat also aus einem endlichen Alphabet Σ, dem sog. Eingabealphabet einem endlichen Alphabet Γ, dem sog. Stackalphabet einer nichtdeterministischen Übergangsfunktion δ : Q ( Σ { ε} ) Γ ( Q Γ* ) Die Absicht ist, dass ein Stackautomat ein Wort w Σ* akzeptieren soll, wobei er jeweils das erste Zeichen a des Inputs sieht und folgendermaßen arbeitet: Ist der Automat im Zustand q Q und ist das oberste Stackelement A Γ, so kann er ein beliebiges ( q', α) δ( q, ε, A) wählen und in den neuen Zustand q' wechseln, das oberste Stackelement durch das Wort ersetzen. Ist das Eingabezeichen a, so kann er stattdessen auch ein ( q', α) δ( q, a, A) wählen, das Zeichen a einlesen, in den neuen Zustand q' wechseln, das oberste Stackelement durch das Wort α Γ* α Γ* ersetzen.

17 9.3 Kontextfreie Sprachen 683 Bei der Ersetzung des obersten Stackelementes durch die Satzform α Γ* werden die Zeichen von α in umgekehrter Reihenfolge auf dem Stack abgelegt, so dass also das erste Element von α zuoberst liegt. Für die Erkennung eines Wortes w Γ* startet der Automat mit einem speziellen Startsymbol S Γ auf dem ansonsten leeren Stack und dem Wort w im Input. Es gilt als akzeptiert, wenn es von der Eingabe komplett eingelesen werden kann, so dass anschließend der Stack leer ist. Der Stackautomat arbeitet also nichtdeterministisch, da er bei Eingabesymbol a Σ und mit A Γ zuoberst auf dem Stack ein beliebiges ( q', α) aus δ( q, ε, A) δ( q, a, A) wählen kann. Mit L( A) bezeichnet man die Sprache des Automaten, d.h. die Menge aller Wörter, die der Stackautomat A akzeptieren kann. Man kann zeigen, dass die Zustandskomponente Q überflüssig ist, da man immer mit einem einzigen Zustand auskommen kann. Wenn man will, kann man daher Q weglassen und δ als Funktion δ : ( Σ { ε} ) Γ ( Γ* ) angeben. Beispiel: Wähle Σ = { (, ) } und Γ = { (, ), S}. Setze δ( ε, S) = { ε, ( S), SS} und δ ( (, ( ) = δ ( ), ) ) = { ε}. Ansonsten sei δ( x, Y) =. Offensichtlich kann man diesen Automaten folgendermassen beschreiben: Liegt ein Terminalzeichen, im aktuellen Beispiel kann es sich nur um ( oder ) handeln, auf dem Stack und findet sich das gleiche Zeichen im Input, so wird es eingelesen (akzeptiert). Das oberste Element des Stacks wird dabei durch ε ersetzt, d.h. entfernt. Liegt ein Nonterminalzeichen (im Beispiel S) auf dem Stack, so wird es durch die rechte Seite einer seiner Produktionen gemäß der folgenden Grammatik ersetzt: S :: S S ( S ) ε Die folgende Figur zeigt die Stackmaschine mitten in der Erkennung eines Inputwortes. Da das oberste Element des Stacks ein Token ist und mit dem aktuellen Token im Input übereinstimmt, wird es vom Stack entfernt, denn δ ( ), ) ) = { ε}, und der Input rückt eins weiter. Jetzt liegt das Nonterminal S zuoberst auf dem Stack. Es kann durch eine beliebige rechte Seite einer Regel expandiert werden, wobei kein Input verbraucht wird, dies besagt gerade δ( ε, S) = { ε, ( S), SS}. Wählen wir die zweite Regel, so besteht der Stack anschließend aus ( S ) ), was dem restlichen Input entspricht, wenn wir später S mit der dritten Regel S ε reduzieren. Zu jedem Zeitpunkt gilt, dass die Satzform auf dem Stack gerade dem noch abzuarbeitenden Rest des Inputwortes entspricht. Grammatik S S S ( S ) ε ) S ) Stack S Invariante: Satzform auf Stack * Rest des Inputs ( ( ) ( ) ) Input Abb. 9.8: Stackautomatbeim Parsen eines Klammerausdrucks

18 684 9 Theoretische Informatik und Compilerbau Stackautomaten für beliebige kontextfreie Sprachen Das gerade betrachtete Beispiel verrät schon das Rezept, nach dem zu einer beliebigen kontextfreien Grammatik ein Stackautomat konstruiert werden kann. Sei dazu G eine Grammatik mit Terminalsymbolen T und Nonterminalen NT, dann wählen wir Σ = T und Γ = T NT. Für jedes Terminalsymbol t T setzen wir δ( t, t) = { ε} und für jede Regel A :: α 1 α 2 α n setzen wir δ( ε, A) = { α 1, α 2,, α n }. Startet man den Automaten mit dem Startsymbol S auf dem ansonsten leeren Stack, und Wort w Σ* im Input, so kann er offensichtlich jede Linksableitung von w nachvollziehen. Betrachten wir nämlich eine solche Linksableitung S w 1 A 1 β 1 w 1 w k A k β k w 1 w k α k β k w A i α i wobei jeweils die A i die linkesten Nonterminale sein sollen, dann müssen natürlich w 1, w 1 w 2,, w 1 w k Anfangsstücke von w sein. Sie können daher durch die Transitionen δ( t, t) = { ε} sukzessive entfernt werden, bis wieder ein Nonterminal A i zuoberst auf dem Stack liegt. Ist dann A i α i die für die Linksableitung benutzte Produktion, so ist auch α i δ( ε, A i ), weshalb durch ersetzt werden kann. Wir erhalten also: Satz: Zu jeder kontextfreien Grammatik G gibt es einen nichtdeterministischen Stackautomaten A mit L( A) = L( G). do Anweisung end Stack Zustände vorübergehend außerbetrieb Q lookahead Noch nicht gelesener Input Satzform auf dem Stack entspricht dem noch erwarteten Input <= id while ; num := id begin id do num eof end num + id := Bereits gelesen Abb. 9.9: Stackautomat beim nichtdeterministischen Top-Down Parsen Nichtdeterministische Algorithmen und Backtracking Eine konkrete Implementierung eines nichtdeterministischen Algorithmus wie des obigen Stackautomaten erfordert meist einen Backtracking Algorithmus. Unter Backtracking versteht man die Möglichkeit, eine von mehreren Alternativen spekulativ auszuwählen. Falls die Auswahl sich später als falsch herausstellt, kann zu dem letzten Entscheidungspunkt zurückge-

9 Theoretische Informatik und Compilerbau

9 Theoretische Informatik und Compilerbau 9 Theoretische Informatik und Compilerbau Theoretische Informatik und Mathematik schaffen die Basis für viele der technischen Entwicklungen, die wir in diesem Buch besprechen. Die boolesche Algebra (S.

Mehr

Lexikalische Programmanalyse der Scanner

Lexikalische Programmanalyse der Scanner Der Scanner führt die lexikalische Analyse des Programms durch Er sammelt (scanned) Zeichen für Zeichen und baut logisch zusammengehörige Zeichenketten (Tokens) aus diesen Zeichen Zur formalen Beschreibung

Mehr

9.4 Grundlagen des Compilerbaus

9.4 Grundlagen des Compilerbaus Kap09.fm Seite 717 Dienstag, 7. September 2010 2:06 14 9.4 Grundlagen des Compilerbaus 717 so dass die Benutzung dieser Regeln zum Aufbau eines + -Knotens bzw. eines Negations- Knotens im abstrakten Syntaxbaum

Mehr

Automaten und formale Sprachen Klausurvorbereitung

Automaten und formale Sprachen Klausurvorbereitung Automaten und formale Sprachen Klausurvorbereitung Rami Swailem Mathematik Naturwissenschaften und Informatik FH-Gießen-Friedberg Inhaltsverzeichnis 1 Definitionen 2 2 Altklausur Jäger 2006 8 1 1 Definitionen

Mehr

Theoretische Grundlagen der Informatik

Theoretische Grundlagen der Informatik Theoretische Grundlagen der Informatik Vorlesung am 18. Januar 2018 INSTITUT FÜR THEORETISCHE 0 18.01.2018 Dorothea Wagner - Theoretische Grundlagen der Informatik INSTITUT FÜR THEORETISCHE KIT Die Forschungsuniversität

Mehr

kontextfreie Grammatiken Theoretische Informatik kontextfreie Grammatiken kontextfreie Grammatiken Rainer Schrader 14. Juli 2009 Gliederung

kontextfreie Grammatiken Theoretische Informatik kontextfreie Grammatiken kontextfreie Grammatiken Rainer Schrader 14. Juli 2009 Gliederung Theoretische Informatik Rainer Schrader Zentrum für Angewandte Informatik Köln 14. Juli 2009 1 / 40 2 / 40 Beispiele: Aus den bisher gemachten Überlegungen ergibt sich: aus der Chomsky-Hierarchie bleiben

Mehr

Ein Fragment von Pascal

Ein Fragment von Pascal Ein Fragment von Pascal Wir beschreiben einen (allerdings sehr kleinen) Ausschnitt von Pascal durch eine kontextfreie Grammatik. Wir benutzen das Alphabet Σ = {a,..., z, ;, :=, begin, end, while, do} und

Mehr

Algorithmen mit konstantem Platzbedarf: Die Klasse REG

Algorithmen mit konstantem Platzbedarf: Die Klasse REG Algorithmen mit konstantem Platzbedarf: Die Klasse REG Sommerakademie Rot an der Rot AG 1 Wieviel Platz brauchen Algorithmen wirklich? Daniel Alm Institut für Numerische Simulation Universität Bonn August

Mehr

Kontextfreie Sprachen. Automaten und Formale Sprachen alias Theoretische Informatik. Sommersemester Kontextfreie Sprachen

Kontextfreie Sprachen. Automaten und Formale Sprachen alias Theoretische Informatik. Sommersemester Kontextfreie Sprachen Automaten und Formale Sprachen alias Theoretische Informatik Sommersemester 2012 Dr. Sander Bruggink Übungsleitung: Jan Stückrath Wortproblem: der CYK-Algorithmus Pumping Lemma für kontextfreie Sprachen

Mehr

Formale Sprachen und endliche Automaten

Formale Sprachen und endliche Automaten Formale Sprachen und endliche Automaten Formale Sprachen Definition: 1 (Alphabet) Ein Alphabet Σ ist eine endliche, nichtleere Menge von Zeichen oder Symbolen. Ein Wort über dem Alphabet Σ ist eine endliche

Mehr

Grundlagen der theoretischen Informatik

Grundlagen der theoretischen Informatik Grundlagen der theoretischen Informatik Kurt Sieber Fakultät IV, Department ETI Universität Siegen SS 2013 Vorlesung vom 09.04.2013 Inhalt der Vorlesung Teil I: Automaten und formale Sprachen (Kurt Sieber)

Mehr

Lexikalische Analyse, Tokenizer, Scanner

Lexikalische Analyse, Tokenizer, Scanner Lexikalische Analyse, Tokenizer, Scanner Frühe Phase des Übersetzers Aufgabenteilung: Scanner (lokale) Zeichen (Symbol-)Analyse Parser Syntax-Analyse Aufgabe des Scanners: Erkennung von: Zahlen, Bezeichner,

Mehr

Grammatiken. Eine Grammatik G mit Alphabet Σ besteht aus: Variablen V. Startsymbol S V. Kurzschreibweise G = (V, Σ, P, S)

Grammatiken. Eine Grammatik G mit Alphabet Σ besteht aus: Variablen V. Startsymbol S V. Kurzschreibweise G = (V, Σ, P, S) Grammatiken Eine Grammatik G mit Alphabet Σ besteht aus: Variablen V Startsymbol S V Produktionen P ( (V Σ) \ Σ ) (V Σ) Kurzschreibweise G = (V, Σ, P, S) Schreibweise für Produktion (α, β) P: α β 67 /

Mehr

Definition 78 Ein NPDA = PDA (= Nichtdeterministischer Pushdown-Automat) besteht aus:

Definition 78 Ein NPDA = PDA (= Nichtdeterministischer Pushdown-Automat) besteht aus: 4.7 Kellerautomaten In der Literatur findet man häufig auch die Bezeichnungen Stack-Automat oder Pushdown-Automat. Kellerautomaten sind, wenn nichts anderes gesagt wird, nichtdeterministisch. Definition

Mehr

Inhalt Kapitel 11: Formale Syntax und Semantik

Inhalt Kapitel 11: Formale Syntax und Semantik Inhalt Kapitel 11: Formale Syntax und Semantik 1 Abstrakte und konkrete Syntax 2 Lexikalische Analyse 3 Formale Sprachen, Grammatiken, BNF 4 Syntaxanalyse konkret 266 Abstrakte und konkrete Syntax Abstrakte

Mehr

Kapitel 5: Syntaxdiagramme und Grammatikregeln

Kapitel 5: Syntaxdiagramme und Grammatikregeln 5. Syntaxdiagramme und Grammatikregeln 5-1 Objektorientierte Programmierung (Winter 2010/2011) Kapitel 5: Syntaxdiagramme und Grammatikregeln Syntaxdiagramme Grammatikregeln (kontextfrei) Beispiele: Lexikalische

Mehr

Compilerbau Syntaxanalyse 68. LR(1)-Syntaxanalyse

Compilerbau Syntaxanalyse 68. LR(1)-Syntaxanalyse Compilerbau Syntaxanalyse 68 LR(1)-Syntaxanalyse Bei der LL(1)-Syntaxanalyse wird allein aufgrund des nächsten Tokens die zu verwendende Produktion ermittelt. Bei der LR(1)-Syntaxanalyse braucht diese

Mehr

Turing Maschine. Thorsten Timmer. SS 2005 Proseminar Beschreibungskomplexität bei Prof. D. Wotschke. Turing Maschine SS 2005 p.

Turing Maschine. Thorsten Timmer. SS 2005 Proseminar Beschreibungskomplexität bei Prof. D. Wotschke. Turing Maschine SS 2005 p. Thorsten Timmer SS 2005 Proseminar Beschreibungskomplexität bei Prof. D. Wotschke Turing Maschine SS 2005 p. 1/35 Inhalt Einführung Formale Definition Berechenbare Sprachen und Funktionen Berechnung ganzzahliger

Mehr

5.2 Endliche Automaten

5.2 Endliche Automaten 114 5.2 Endliche Automaten Endliche Automaten sind Turingmaschinen, die nur endlichen Speicher besitzen. Wie wir bereits im Zusammenhang mit Turingmaschinen gesehen haben, kann endlicher Speicher durch

Mehr

DisMod-Repetitorium Tag 4

DisMod-Repetitorium Tag 4 DisMod-Repetitorium Tag 4 Endliche Automaten, Reguläre Sprachen und Kontextfreie Grammatiken 22. März 2018 1 Endliche Automaten Definition DFA Auswertungen Äquivalenzrelationen Verschmelzungsrelation und

Mehr

Alphabet, formale Sprache

Alphabet, formale Sprache n Alphabet Alphabet, formale Sprache l nichtleere endliche Menge von Zeichen ( Buchstaben, Symbole) n Wort über einem Alphabet l endliche Folge von Buchstaben, die auch leer sein kann ( ε leere Wort) l

Mehr

Theoretische Informatik. Reguläre Sprachen und Automaten

Theoretische Informatik. Reguläre Sprachen und Automaten Theoretische Informatik Reguläre Sprachen und Automaten Reguläre Sprachen Reguläre Ausdrücke und Sprachen Gleichungen Syntaxdiagramme Erweiterungen Anwendungen Reguläre Ausdrücke über Σ Syntax: Konstante

Mehr

Reguläre Sprachen und endliche Automaten

Reguläre Sprachen und endliche Automaten Reguläre Sprachen und endliche Automaten 1 Motivation: Syntaxüberprüfung Definition: Fließkommazahlen in Java A floating-point literal has the following parts: a whole-number part, a decimal point (represented

Mehr

Satz (Abschluß unter der Stern-Operation)

Satz (Abschluß unter der Stern-Operation) Satz (Abschluß unter der Stern-Operation) Wenn L eine reguläre Sprache ist, dann ist auch L regulär. Beweis: Es gibt einen NFA M = (Z, Σ, S, δ, S, E) mit L(M) = L. Wir bauen aus diesem NFA nun wie folgt

Mehr

Formalismen für REG. Formale Grundlagen der Informatik 1 Kapitel 7 Kontextfreie Sprachen. Das Pumping Lemma. Abschlusseigenschaften

Formalismen für REG. Formale Grundlagen der Informatik 1 Kapitel 7 Kontextfreie Sprachen. Das Pumping Lemma. Abschlusseigenschaften Formalismen für RE Formale rundlagen der Informatik 1 Kapitel 7 Kontextfreie Sprachen Frank Heitmann [email protected] Satz Zu jeder regulären Sprache L gibt es einen DFA A mit L(A) =

Mehr

Kapitel 2. Methoden zur Beschreibung von Syntax

Kapitel 2. Methoden zur Beschreibung von Syntax 1 Kapitel 2 Methoden zur Beschreibung von Syntax Grammatik, die sogar Könige zu kontrollieren weiß... aus Molière, Les Femmes Savantes (1672), 2. Akt 2 Ziele Zwei Standards zur Definition der Syntax von

Mehr

Grundlagen der Theoretischen Informatik Musterlösungen zu ausgewählten Übungsaufgaben

Grundlagen der Theoretischen Informatik Musterlösungen zu ausgewählten Übungsaufgaben Dieses Dokument soll mehr dazu dienen, Beispiele für die formal korrekt mathematische Bearbeitung von Aufgaben zu liefern, als konkrete Hinweise auf typische Klausuraufgaben zu liefern. Die hier gezeigten

Mehr

Ogden s Lemma: Der Beweis (1/5)

Ogden s Lemma: Der Beweis (1/5) Ogden s Lemma: Der Beweis (1/5) Wir betrachten zuerst die Rahmenbedingungen : Laut dem auf der vorhergehenden Folie zitierten Satz gibt es zur kontextfreien Sprache L eine Grammatik G = (Σ, V, S, P) in

Mehr

4. Die lexikalische Analyse

4. Die lexikalische Analyse zerlegt Folge von Zeichen in Eingabedatei in Folge von Symbolen (Token) Scanner-Sieber-Modul Token: Typ und Inhalt übliche Token-Typen: reservierte Wörter (if, while, for, ) Bezeichner (x, dauer, name,..)

Mehr

Die mathematische Seite

Die mathematische Seite Kellerautomaten In der ersten Vorlesung haben wir den endlichen Automaten kennengelernt. Mit diesem werden wir uns in der zweiten Vorlesung noch etwas eingängiger beschäftigen und bspw. Ansätze zur Konstruktion

Mehr

Syntax von Programmiersprachen

Syntax von Programmiersprachen "Grammatik, die sogar Könige zu kontrollieren weiß... aus Molière, Les Femmes Savantes (1672), 2. Akt Syntax von Programmiersprachen Prof. Dr. Christian Böhm in Zusammenarbeit mit Gefei Zhang WS 07/08

Mehr

Syntax von Programmiersprachen

Syntax von Programmiersprachen "Grammatik, die sogar Könige zu kontrollieren weiß... aus Molière, Les Femmes Savantes (1672), 2. Akt Syntax von Programmiersprachen Prof. Dr. Martin Wirsing in Zusammenarbeit mit Michael Barth, Philipp

Mehr

Vorlesung Automaten und Formale Sprachen Sommersemester Beispielsprachen. Sprachen

Vorlesung Automaten und Formale Sprachen Sommersemester Beispielsprachen. Sprachen Vorlesung Automaten und Formale Sprachen Sommersemester 2018 Prof. Barbara König Übungsleitung: Christina Mika-Michalski Wörter Wort Sei Σ ein Alphabet, d.h., eine endliche Menge von Zeichen. Dann bezeichnet

Mehr

Algorithmen und Datenstrukturen I - Exkurs Formale Sprachen -

Algorithmen und Datenstrukturen I - Exkurs Formale Sprachen - Algorithmen und Datenstrukturen I - Exkurs Formale Sprachen - Thies Pfeiffer Technische Fakultät [email protected] Vorlesung, Universität Bielefeld, Winter 2012/2013 1 / 1 Exkurs: Formale

Mehr

Berechenbarkeitstheorie 1. Vorlesung

Berechenbarkeitstheorie 1. Vorlesung Berechenbarkeitstheorie Dr. Institut für Mathematische Logik und Grundlagenforschung WWU Münster WS 15/16 Alle Folien unter Creative Commons Attribution-NonCommercial 3.0 Unported Lizenz. Zentrale Themen

Mehr

Einführung - Parser. Was ist ein Parser?

Einführung - Parser. Was ist ein Parser? Gliederung 1. Einleitung 1.1 Was ist ein Parser? 1.2 Was ist ein tabellengesteuerter TD-Parser? 1. Tabellengesteuerter TD-Parser 2.1 Funktionsweise 2.2 Darstellung als Pseudocode 2.3 Konstruktion von prädiktiven

Mehr

Definition 4 (Operationen auf Sprachen) Beispiel 5. Seien A, B Σ zwei (formale) Sprachen. Konkatenation: AB = {uv ; u A, v B} A + = n 1 An

Definition 4 (Operationen auf Sprachen) Beispiel 5. Seien A, B Σ zwei (formale) Sprachen. Konkatenation: AB = {uv ; u A, v B} A + = n 1 An Definition 4 (Operationen auf Sprachen) Seien A, B Σ zwei (formale) Sprachen. Konkatenation: AB = {uv ; u A, v B} A 0 = {ɛ}, A n+1 = AA n A = n 0 An A + = n 1 An Beispiel 5 {ab, b}{a, bb} = {aba, abbb,

Mehr

Rekursiv aufzählbare Sprachen

Rekursiv aufzählbare Sprachen Kapitel 4 Rekursiv aufzählbare Sprachen 4.1 Grammatiken und die Chomsky-Hierarchie Durch Zulassung komplexer Ableitungsregeln können mit Grammatiken größere Klassen als die kontextfreien Sprachen beschrieben

Mehr

Pumping-Lemma 2 Pumping-Lemma Sei L eine von einem endlichen Automaten erkannte Sprache. Dann existiert eine natürliche Zahl p N derart, dass jedes Wo

Pumping-Lemma 2 Pumping-Lemma Sei L eine von einem endlichen Automaten erkannte Sprache. Dann existiert eine natürliche Zahl p N derart, dass jedes Wo 1 Endliche Automaten Modellierungskonzept mit vielen brauchbaren Eigenschaften schnelle Spracherkennung graphisch-visuelle Beschreibung automatische Korrektheitsbeweise gute Kompositionalitätseigenschaften

Mehr

1. Der Begriff Informatik 2. Syntax und Semantik von Programmiersprachen - 1 -

1. Der Begriff Informatik 2. Syntax und Semantik von Programmiersprachen - 1 - 1. Der Begriff Informatik 2. Syntax und Semantik von Programmiersprachen I.2. I.2. Grundlagen von von Programmiersprachen. - 1 - 1. Der Begriff Informatik "Informatik" = Kunstwort aus Information und Mathematik

Mehr

1. Der Begriff Informatik 2. Syntax und Semantik von Programmiersprachen - 1 -

1. Der Begriff Informatik 2. Syntax und Semantik von Programmiersprachen - 1 - 1. Der Begriff Informatik 2. Syntax und Semantik von Programmiersprachen I.2. I.2. Grundlagen von von Programmiersprachen. - 1 - 1. Der Begriff Informatik "Informatik" = Kunstwort aus Information und Mathematik

Mehr

3 Syntax von Programmiersprachen

3 Syntax von Programmiersprachen 3 Syntax von Programmiersprachen Syntax ( Lehre vom Satzbau ) formale Beschreibung des Aufbaus der Worte und Sätze, die zu einer Sprache gehören; im Falle einer Programmiersprache Festlegung, wie Programme

Mehr

3.1 Reservierte Wörter

3.1 Reservierte Wörter 3.1 Reservierte Wörter int Bezeichner für Basis-Typen; if, else, while Schlüsselwörter aus Programm-Konstrukten; (,), ",, {,},,,; Sonderzeichen. 62 3.2 Was ist ein erlaubter Name? Schritt 1: Angabe der

Mehr

FORMALE SYSTEME. 3. Vorlesung: Endliche Automaten. TU Dresden, 17. Oktober Markus Krötzsch

FORMALE SYSTEME. 3. Vorlesung: Endliche Automaten. TU Dresden, 17. Oktober Markus Krötzsch FORMALE SYSTEME 3. Vorlesung: Endliche Automaten Markus Krötzsch TU Dresden, 17. Oktober 2016 Rückblick Markus Krötzsch, 17. Oktober 2016 Formale Systeme Folie 2 von 31 Wiederholung Mit Grammatiken können

Mehr

Übungsblatt 6. Vorlesung Theoretische Grundlagen der Informatik im WS 18/19

Übungsblatt 6. Vorlesung Theoretische Grundlagen der Informatik im WS 18/19 Institut für Theoretische Informatik Lehrstuhl Prof. Dr. D. Wagner Übungsblatt 6 Vorlesung Theoretische Grundlagen der Informatik im WS 18/19 Ausgabe 8. Januar 2019 Abgabe 22. Januar 2019, 11:00 Uhr (im

Mehr

Automaten und Formale Sprachen alias Theoretische Informatik. Sommersemester 2011

Automaten und Formale Sprachen alias Theoretische Informatik. Sommersemester 2011 Automaten und Formale Sprachen alias Theoretische Informatik Sommersemester 2011 Dr. Sander Bruggink Übungsleitung: Jan Stückrath Sander Bruggink Automaten und Formale Sprachen 1 Wir beschäftigen uns ab

Mehr

Objektorientierte Programmierung. Kapitel 3: Syntaxdiagramme

Objektorientierte Programmierung. Kapitel 3: Syntaxdiagramme Stefan Brass: OOP (Java), 3. 1/31 Objektorientierte Programmierung Kapitel 3: Stefan Brass Martin-Luther-Universität Halle-Wittenberg Wintersemester 2014/15 http://www.informatik.uni-halle.de/ brass/oop14/

Mehr

Reguläre Ausdrücke. Michael Jäger. 4. April 2017

Reguläre Ausdrücke. Michael Jäger. 4. April 2017 Reguläre Ausdrücke Michael Jäger 4. April 2017 Zeichenketten und Sprachen Ein Alphabet ist eine endliche Menge von Symbolen. Beispiele: 1. Σ 1 = {0, 1} 2. Σ 2 = {a, b, c, d, e, f, g, h, i, j, k, l, m,

Mehr

Informatik III - WS07/08

Informatik III - WS07/08 Informatik III - WS07/08 Kapitel 5 1 Informatik III - WS07/08 Prof. Dr. Dorothea Wagner [email protected] Kapitel 5 : Grammatiken und die Chomsky-Hierarchie Informatik III - WS07/08 Kapitel 5 2 Definition

Mehr

7. Syntax: Grammatiken, EBNF

7. Syntax: Grammatiken, EBNF 7. Syntax: Grammatiken, EBNF Teil 1 Sehr schönes Beispiel für Notwendigkeit der Theoretischen Informatik für Belange der Praktischen Informatik Vertiefung in: Einführung in die Theoretische Informatik

Mehr

Theoretische Informatik I

Theoretische Informatik I Theoretische Informatik I Rückblick Theoretische Informatik I 1. Mathematische Methoden 2. Reguläre Sprachen 3. Kontextfreie Sprachen Themen der Theoretischen Informatik I & II Mathematische Methodik in

Mehr

Sei Σ ein endliches Alphabet. Eine Sprache L Σ ist genau dann regulär, wenn sie von einem regulären Ausdruck beschrieben werden kann.

Sei Σ ein endliches Alphabet. Eine Sprache L Σ ist genau dann regulär, wenn sie von einem regulären Ausdruck beschrieben werden kann. Der Satz von Kleene Wir haben somit Folgendes bewiesen: Der Satz von Kleene Sei Σ ein endliches Alphabet. Eine Sprache L Σ ist genau dann regulär, wenn sie von einem regulären Ausdruck beschrieben werden

Mehr

Automaten und Coinduktion

Automaten und Coinduktion Philipps-Univestität Marburg Fachbereich Mathematik und Informatik Seminar: Konzepte von Programmiersprachen Abgabedatum 02.12.03 Betreuer: Prof. Dr. H. P. Gumm Referentin: Olga Andriyenko Automaten und

Mehr

Kontextfreie Sprachen werden von PDAs akzeptiert

Kontextfreie Sprachen werden von PDAs akzeptiert Kontextfreie Sprachen werden von PDAs akzeptiert Sei G = (Σ, V, S, P) eine kontextfreie Grammatik. Dann gibt es einen PDA A mit L(A) = L(G). Der PDA A arbeitet mit nur einem Zustand q 0, besitzt das Kelleralphabet

Mehr

Kapitel 4: Syntaxdiagramme und Grammatikregeln

Kapitel 4: Syntaxdiagramme und Grammatikregeln 4. Syntaxdiagramme und Grammatikregeln 4-1 Objektorientierte Programmierung (Winter 2006/2007) Kapitel 4: Syntaxdiagramme und Grammatikregeln Syntaxdiagramme Grammatikregeln (kontextfrei) Beispiele: Lexikalische

Mehr

Übungsblatt 6. Vorlesung Theoretische Grundlagen der Informatik im WS 17/18

Übungsblatt 6. Vorlesung Theoretische Grundlagen der Informatik im WS 17/18 Institut für Theoretische Informatik Lehrstuhl Prof. Dr. D. Wagner Übungsblatt 6 Vorlesung Theoretische Grundlagen der Informatik im WS 17/18 Ausgabe 10. Januar 2018 Abgabe 23. Januar 2018, 11:00 Uhr (im

Mehr

Das Halteproblem für Turingmaschinen

Das Halteproblem für Turingmaschinen Das Halteproblem für Turingmaschinen Das Halteproblem für Turingmaschinen ist definiert als die Sprache H := { T w : T ist eine TM, die bei Eingabe w {0, 1} hält }. Behauptung: H {0, 1} ist nicht entscheidbar.

Mehr

Grundlagen der theoretischen Informatik

Grundlagen der theoretischen Informatik Grundlagen der theoretischen Informatik Kurt Sieber Fakultät IV, Department ETI Universität Siegen SS 2013 Vorlesung vom 04.06.2013 An den Transitionen sieht man zunächst, dass nur die folgenden Zustandsübergänge

Mehr

Syntax von Programmiersprachen

Syntax von Programmiersprachen "Grammatik, die sogar Könige zu kontrollieren weiß aus Molière, Les Femmes Savantes (1672), 2. kt Syntax von Programmiersprachen Prof. Dr. Martin Wirsing Ziele Zwei Standards zur Definition der Syntax

Mehr

Reguläre Sprachen. R. Stiebe: Theoretische Informatik für ING-IF und Lehrer,

Reguläre Sprachen. R. Stiebe: Theoretische Informatik für ING-IF und Lehrer, Reguläre Sprachen Reguläre Sprachen (Typ-3-Sprachen) haben große Bedeutung in Textverarbeitung und Programmierung (z.b. lexikalische Analyse) besitzen für viele Entscheidungsprobleme effiziente Algorithmen

Mehr

Nachklausur zur Vorlesung Informatik 3 mit einigen Anmerkungen zu Lösungen

Nachklausur zur Vorlesung Informatik 3 mit einigen Anmerkungen zu Lösungen Nachklausur zur Vorlesung Informatik 3 mit einigen Anmerkungen zu Lösungen Aufgabe 1 2 3 4 5 6 7 max. Punkte 6 6 7 7 8 8 12 err. Punkte Gesamtpunktzahl: Note: 1 Aufgabe 1 (3+1+1+1 = 6 Punkte) Es seien

Mehr

Formale Sprachen und Automaten

Formale Sprachen und Automaten Formale Sprachen und Automaten Kapitel 1: Grundlagen Vorlesung an der DHBW Karlsruhe Thomas Worsch Karlsruher Institut für Technologie, Fakultät für Informatik Wintersemester 2012 Ziel Einführung der wichtigsten

Mehr

Induktive Definition

Induktive Definition Rechenregeln A B = B A A (B C) = (A B) C A (B C) = (A B) C A (B C) = A B A C (B C) A = B A C A {ε} A = A A {ε} = A (A {ε}) = A (A ) = A A A = A + A A = A + A + {ε} = A Beispiel. Real-Zahlen = {0,..., 9}

Mehr

Anwenundg regulärer Sprachen und endlicher Automaten

Anwenundg regulärer Sprachen und endlicher Automaten Proseminar Theoretische Informatik Dozent: Prof. Helmut Alt Anwenundg regulärer Sprachen und endlicher Automaten Madlen Thaleiser 30. Oktober 2012 Reguläre Sprachen Regulärer Ausdruck definiert über einem

Mehr

2. Klausur zur Vorlesung Theoretische Grundlagen der Informatik Wintersemester 2017/2018

2. Klausur zur Vorlesung Theoretische Grundlagen der Informatik Wintersemester 2017/2018 2. Klausur zur Vorlesung Theoretische Grundlagen der Informatik Wintersemester 2017/2018 Hier Aufkleber mit Name und Matrikelnummer anbringen Vorname: Nachname: Matrikelnummer: Beachten Sie: Bringen Sie

Mehr

Kontextfreie Grammatiken. Kontextfreie Grammatiken 1 / 45

Kontextfreie Grammatiken. Kontextfreie Grammatiken 1 / 45 Kontextfreie Grammatiken Kontextfreie Grammatiken 1 / 45 Was kann man mit kontextfreien Grammatiken anfangen? Kontextfreie Grammatiken, kurz: werden zur Modellierung von KFGs beliebig tief geschachtelten

Mehr

Grundlagen der Theoretischen Informatik

Grundlagen der Theoretischen Informatik Grundlagen der Theoretischen Informatik Sommersemester 2015 23.04.2015 Viorica Sofronie-Stokkermans e-mail: [email protected] 1 Bis jetzt 1. Terminologie 2. Endliche Automaten und reguläre Sprachen

Mehr

Übungen zur Vorlesung Modellierung WS 2003/2004 Blatt 11 Musterlösungen

Übungen zur Vorlesung Modellierung WS 2003/2004 Blatt 11 Musterlösungen Dr. Theo Lettmann Paderborn, den 9. Januar 24 Abgabe 9. Januar 24 Übungen zur Vorlesung Modellierung WS 23/24 Blatt Musterlösungen AUFGABE 7 : Es sei der folgende partielle deterministische endliche Automat

Mehr

Beweisidee: 1 Verwende den Keller zur Simulation der Grammatik. Leite ein Wort. 2 Problem: der Keller darf nicht beliebig verwendet werden, man kann

Beweisidee: 1 Verwende den Keller zur Simulation der Grammatik. Leite ein Wort. 2 Problem: der Keller darf nicht beliebig verwendet werden, man kann Automaten und Formale prachen alias Theoretische Informatik ommersemester 2011 Dr. ander Bruggink Übungsleitung: Jan tückrath Wir beschäftigen uns ab jetzt einige Wochen mit kontextfreien prachen: Kontextfreie

Mehr

Theoretische Informatik I

Theoretische Informatik I heoretische Informatik I Einheit 2 Endliche Automaten & Reguläre Sprachen. Deterministische endliche Automaten 2. Nichtdeterministische Automaten 3. Reguläre Ausdrücke 4. Grammatiken 5. Eigenschaften regulärer

Mehr

Hauptklausur zur Vorlesung Theoretische Grundlagen der Informatik Wintersemester 2011/2012

Hauptklausur zur Vorlesung Theoretische Grundlagen der Informatik Wintersemester 2011/2012 Institut für Theoretische Informatik Lehrstuhl Prof. Dr. D. Wagner Hauptklausur zur Vorlesung Theoretische Grundlagen der Informatik Wintersemester 2011/2012 Hier Aufkleber mit Name und Matrikelnr. anbringen

Mehr

10 Kellerautomaten. Kellerautomaten

10 Kellerautomaten. Kellerautomaten 10 Kellerautomaten Bisher hatten wir kontextfreie Sprachen nur mit Hilfe von Grammatiken charakterisiert. Wir haben gesehen, dass endliche Automaten nicht in der Lage sind, alle kontextfreien Sprachen

Mehr

Lösung zur Klausur. Grundlagen der Theoretischen Informatik im WiSe 2003/2004

Lösung zur Klausur. Grundlagen der Theoretischen Informatik im WiSe 2003/2004 Lösung zur Klausur Grundlagen der Theoretischen Informatik im WiSe 2003/2004 1. Geben Sie einen deterministischen endlichen Automaten an, der die Sprache aller Wörter über dem Alphabet {0, 1} akzeptiert,

Mehr

Syntax von Programmiersprachen

Syntax von Programmiersprachen Syntax von Programmiersprachen SEP 209 Programmiersprachen Sprache = Menge von Wörtern, typischerweise unendlich Programmiersprache: Wörter repräsentieren Programme Programm kann auf einem Computer evtl.

Mehr

Konstruieren der SLR Parsing Tabelle

Konstruieren der SLR Parsing Tabelle Konstruieren der SLR Parsing Tabelle Kontextfreie Grammatik (CFG) Notation 1. Diese Symbole sind Terminals: (a) Kleinbuchstaben vom Anfang des Alphabets wie a, b, c. (b) Operator Symbole wie +,, usw. (c)

Mehr

1 Σ endliches Terminalalphabet, 2 V endliche Menge von Variablen (mit V Σ = ), 3 P (V (Σ ΣV )) {(S, ε)} endliche Menge von Regeln,

1 Σ endliches Terminalalphabet, 2 V endliche Menge von Variablen (mit V Σ = ), 3 P (V (Σ ΣV )) {(S, ε)} endliche Menge von Regeln, Theorie der Informatik 9. März 24 7. Reguläre Sprachen I Theorie der Informatik 7. Reguläre Sprachen I Malte Helmert Gabriele Röger Universität Basel 9. März 24 7. Reguläre Grammatiken 7.2 DFAs 7.3 NFAs

Mehr

Übungsaufgaben zu Formalen Sprachen und Automaten

Übungsaufgaben zu Formalen Sprachen und Automaten Universität Freiburg PD Dr. A. Jakoby Sommer 27 Übungen zum Repetitorium Informatik III Übungsaufgaben zu Formalen Sprachen und Automaten. Untersuchen Sie das folgende Spiel: A B x x 2 x 3 C D Eine Murmel

Mehr

Theoretische Informatik I

Theoretische Informatik I Theoretische Informatik I Einheit 2.5 Grammatiken 1. Arbeitsweise 2. Klassifizierung 3. Beziehung zu Automaten Beschreibung des Aufbaus von Sprachen Mathematische Mengennotation Beschreibung durch Eigenschaften

Mehr

Frank Heitmann 2/47. 1 Ein PDA beginnt im Startzustand z 0 und mit im Keller. 2 Ist der Automat

Frank Heitmann 2/47. 1 Ein PDA beginnt im Startzustand z 0 und mit im Keller. 2 Ist der Automat Formale Grundlagen der Informatik 1 Kapitel 5 Über reguläre Sprachen hinaus und (Teil 2) Frank Heitmann [email protected] 21. April 2015 Der Kellerautomat - Formal Definition (Kellerautomat

Mehr

Grundlagen der Theoretischen Informatik

Grundlagen der Theoretischen Informatik Grundlagen der Theoretischen Informatik Sommersemester 2017 20.04.2017 Viorica Sofronie-Stokkermans e-mail: [email protected] 1 Bis jetzt Organisatorisches Literatur Motivation und Inhalt Kurzer

Mehr