Formale Sprachen und Grammatiken
Ein Taschenrechner nimmt 3+4*(2-1) an und lehnt 3+*4 ab. Es gibt unendlich viele zulässige Terme, und trotzdem entscheidet das Programm in Sekundenbruchteilen, ob eine Eingabe dazugehört.
Wie beschreibt man unendlich viele erlaubte Zeichenketten mit endlich vielen Regeln? Und wie macht ein Programm aus einem Quelltext etwas, das es versteht? Reguläre Ausdrücke und endliche Automaten kennst du. Hier kommen Grammatiken dazu, die mehr können.
Alphabet, Wort, formale Sprache, Syntax und Semantik
Ein Alphabet ist eine endliche, nicht leere Menge von Zeichen. Ein Wort ist eine endliche Folge von Zeichen aus . Das leere Wort hat keine Zeichen. bezeichnet alle Wörter über . Eine formale Sprache ist eine Teilmenge von .
Die Syntax legt fest, welche Wörter zur Sprache gehören, also wie sie aufgebaut sind. Die Semantik legt fest, was sie bedeuten. Natürliche Sprachen sind gewachsen: Sie haben Ausnahmen, Sätze können mehrdeutig sein, und die Bedeutung hängt vom Zusammenhang ab. Formale Sprachen sind genau festgelegt, ihre Wörter haben eine eindeutige Bedeutung, und eine Maschine kann ihre Syntax prüfen.
Grammatik
Eine Grammatik ist ein Tupel :
- N ist die Menge der Nichtterminale: Platzhalter, die noch ersetzt werden.
- T ist die Menge der Terminale: die Zeichen des Alphabets, aus denen die fertigen Wörter bestehen. N und T haben keine gemeinsamen Elemente.
- P ist die Menge der Produktionsregeln : Ersetze durch .
- ist das Startsymbol.
Ein Ableitungsschritt wendet eine Regel auf einen Teil von u an. Die erzeugte Sprache besteht aus allen Wörtern aus Terminalen, die sich in endlich vielen Schritten aus S ableiten lassen. Mehrere Regeln für dasselbe Nichtterminal schreibt man kurz mit einem Strich: . Hier steht links stets ein einzelnes Nichtterminal.
Eine Grammatik für
Eine Grammatik für
Sei mit den Regeln . Leite aabb ab und beschreibe .
S ⇒ aSb ⇒ aaSbb ⇒ aabb. Die erste Regel setzt außen ein a und ein b und lässt innen S stehen. Die Regel beendet die Ableitung. Wendest du die erste Regel n-mal an und dann die zweite, entsteht . Also gilt . Diese Sprache hat in der letzten Lektion kein endlicher Automat erkannt, eine Grammatik erzeugt sie mit zwei Regeln.
Reguläre und kontextfreie Grammatiken
Der Bau der Regeln bestimmt die Art der Grammatik. In einer kontextfreien Grammatik hat jede Regel die Form : links ein einzelnes Nichtterminal, rechts eine beliebige Folge aus Terminalen und Nichtterminalen. „Kontextfrei“ heißt: A wird ersetzt, egal was daneben steht. In einer regulären Grammatik hat jede Regel eine der Formen , oder (a Terminal, A und B Nichtterminale). Jede reguläre Grammatik ist kontextfrei. Die Grammatik ist kontextfrei, aber nicht regulär, denn bei steht ein Terminal hinter dem Nichtterminal.
Reguläre Grammatik und endlicher Automat
Zu jedem DFA gibt es eine reguläre Grammatik für dieselbe Sprache und umgekehrt. Aus dem Automaten wird die Grammatik so gebaut: Jeder Zustand wird ein Nichtterminal, der Startzustand das Startsymbol. Zu jedem Übergang vom Zustand A mit dem Zeichen x nach B gehört die Regel . Für jeden Endzustand A kommt hinzu. Die Ableitung folgt dem Weg des Automaten. Ein Fangzustand braucht keine Regeln: Wo keine Regel passt, entsteht kein Wort.
Vom Automaten zur Grammatik
Vom Automaten zur Grammatik
Der Automat „keine zwei Einsen hintereinander“ hat die Zustände q0 (Start, Endzustand), q1 (Endzustand) und den Fangzustand q_tot. Von q0 führt 0 nach q0 und 1 nach q1, von q1 führt 0 nach q0. Gib die Grammatik an und leite 10101 ab.
Sei A das Nichtterminal für q0 und B das für q1. Die Regeln sind und . Die Übergänge nach q_tot entfallen.
Ableitung: A ⇒ 1B ⇒ 10A ⇒ 101B ⇒ 1010A ⇒ 10101B ⇒ 10101. Das Wort 11 ist nicht ableitbar: Nach A ⇒ 1B gibt es für B keine Regel mit der Ziffer 1.
EBNF, Syntaxdiagramm und Ableitungsbaum
Die EBNF (erweiterte Backus-Naur-Form) schreibt kontextfreie Regeln kompakt. Ein Gleichheitszeichen verbindet Nichtterminal und rechte Seite, ein Punkt beendet die Regel. Ein senkrechter Strich trennt Alternativen, Terminale stehen in Anführungszeichen. Eckige Klammern markieren Optionales (null- oder einmal), geschweifte Klammern eine Wiederholung (null- oder mehrmals), runde Klammern fassen zusammen. Beispiel für einfache Terme:
Ein Syntaxdiagramm zeigt dieselbe Regel grafisch: ein Diagramm je Nichtterminal, ein eckiger Kasten für ein Nichtterminal, ein runder für ein Terminal, eine Verzweigung für den Strich, eine Schleife für die geschweifte Klammer.
Ein Ableitungsbaum zeigt, wie ein Wort entsteht. Die Wurzel ist das Startsymbol, jeder innere Knoten ein Nichtterminal, seine Kinder stehen von links nach rechts auf der rechten Seite der angewendeten Regel. Die Blätter sind Terminale und ergeben von links nach rechts das Wort. Hat ein Wort mehrere Ableitungsbäume, ist die Grammatik mehrdeutig.
Der Ableitungsbaum von 2+3*4
Der Ableitungsbaum von 2+3*4
Zeichne den Baum für 2+3*4 nach der Term-Grammatik. Zur Kürze steht eine Zahl statt der Kette zahl, ziffer.
Als Klammerschreibweise, bei der jede Klammer die Kinder eines Knotens enthält: ausdruck( term( faktor(2) ), +, term( faktor(3), *, faktor(4) ) ).
Die Wurzel ausdruck hat die Kinder term, + und term. Das zweite term hat die Kinder faktor, * und faktor. 3*4 steht also im Baum tiefer und wird zuerst zusammengefasst, danach wird addiert: 2 + 12 = 14. Die Regel „Punkt vor Strich“ steckt in der Schichtung der Grammatik.
Wortproblem
Das Wortproblem fragt: Gehört das Wort w zu ? Bei einer regulären Grammatik liest man w einmal durch den zugehörigen DFA, der Aufwand wächst mit der Länge von w. Bei kontextfreien Grammatiken gibt es Verfahren, die es mit polynomiellem Aufwand lösen: Man versucht, einen Ableitungsbaum für w zu bauen. Ein Programm, das das tut, ist ein Parser.
Compiler, Interpreter, Scanner und Parser
Programmiersprachen sind formale Sprachen. Ein Compiler übersetzt den ganzen Quelltext vor der Ausführung in ein anderes Programm, etwa Maschinen- oder Zwischencode. Ein Interpreter liest den Quelltext und führt ihn Schritt für Schritt aus. Beide verarbeiten den Text in Phasen:
- Der Scanner (lexikalische Analyse) zerlegt die Zeichenfolge in Token: Bezeichner, Zahlen, Operatoren, Schlüsselwörter. Dafür genügen reguläre Ausdrücke.
- Der Parser (syntaktische Analyse) prüft, ob die Folge der Token zur kontextfreien Grammatik der Sprache passt, und baut den Ableitungsbaum.
- Danach folgt die Semantik: Typen prüfen, Code erzeugen oder direkt ausführen.
Aus macht der Scanner die Token (Bezeichner), (Zuweisung), (Zahl), (Operator) und (Zahl). Einen Syntaxfehler meldet der Parser, Fehler der Bedeutung zeigen sich oft erst später.
Nichtterminale im fertigen Wort
Nichtterminale im fertigen Wort
„Mit S → aSb entsteht das Wort aSb. Es gehört zur Sprache.“
Ein Wort der Sprache besteht nur aus Terminalen. Solange ein Nichtterminal wie S dasteht, ist die Ableitung nicht fertig. Erst die Regel beendet sie.
Eine einfache Grammatik beschreibt eine reguläre Sprache
Eine einfache Grammatik beschreibt eine reguläre Sprache
„Die Grammatik hat nur zwei Regeln, also reicht ein endlicher Automat.“
Auf die Form der Regeln kommt es an, nicht auf ihre Zahl. hat nur zwei Regeln, erzeugt aber , und diese Sprache ist nicht regulär.
Zusammenfassung
Eine formale Sprache ist eine Menge von Wörtern über einem Alphabet. Die Syntax regelt den Aufbau, die Semantik die Bedeutung.
Eine Grammatik erzeugt Wörter durch Ableiten aus dem Startsymbol. Fertige Wörter enthalten nur Terminale.
Kontextfreie Regeln haben links ein einzelnes Nichtterminal. Reguläre Regeln haben die Form , oder .
Reguläre Grammatiken und endliche Automaten beschreiben dieselben Sprachen. Jeder Zustand wird zu einem Nichtterminal.
EBNF und Syntaxdiagramme beschreiben kontextfreie Regeln. Ein Ableitungsbaum zeigt den Aufbau eines Wortes und die Rangfolge der Operatoren.
Das Wortproblem fragt, ob ein Wort zur Sprache gehört. Der Parser löst es für kontextfreie Grammatiken.
Der Scanner zerlegt den Quelltext in Token, der Parser baut den Ableitungsbaum. Ein Compiler übersetzt, ein Interpreter führt aus.
Übungen
Welche Regel ist kontextfrei, aber nicht regulär?
Die Grammatik hat die Regeln S → aSb und S → ε. Wie viele Ableitungsschritte braucht man für das Wort aaabbb?
Gehört das Wort aab zur Sprache der Grammatik S → aSb | ε?
Gegeben ist die EBNF: buchstabe = "a" | "b" | "c" . ziffer = "0" | "1" . name = buchstabe { buchstabe | ziffer } . Welches Wort gehört zu name?
Der Quelltext y = 7 * (z + 1) wird verarbeitet. Beschreibe die Aufgabe von Scanner und Parser an diesem Beispiel.