Die Präsentation wird geladen. Bitte warten

Die Präsentation wird geladen. Bitte warten

Compiler und Interpreter

Ähnliche Präsentationen


Präsentation zum Thema: "Compiler und Interpreter"—  Präsentation transkript:

1 Compiler und Interpreter
Klaus Becker 2010

2 Compiler und Interpreter

3 Syntax und Semantik im Überblick
Teil 1 Syntax und Semantik im Überblick

4 Karol / Myka Karol MyKa(rol)

5 Aufgabe links while nichtVorWand: ziegelHinlegen schritt #while if nichtVorWand: if nichtVorZiegel: schritt else: ziegelHinlegen #if links Versuche anhand weiterer Tests die Regeln der Sprache MyKa herauszufinden: (a) Wie können Programme der Sprache aufgebaut werden? markeSetzen schritt while nichtAufMarke: while nichtVorWand: #while links

6 Aufgabe links while nichtVorWand: ziegelHinlegen schritt #while if nichtVorWand: if nichtVorZiegel: schritt else: ziegelHinlegen #if links Versuche anhand weiterer Tests die Regeln der Sprache MyKa herauszufinden: (b) Welche Bedeutung haben die Sprachkonstrukte? markeSetzen schritt while nichtAufMarke: while nichtVorWand: #while links

7 Exkurs - MyKa Anweisung schritt links rechts ziegelHinlehen
ziegelAufheben markeSetzen markeLoeschen pass Bedeutung einen Schritt vorwärts bewegen - sofern möglich um 90° nach links drehen um 90° nach rechts drehen einen Ziegen in das vor dem Roboter liegende Feld hinlegen - sofern möglich einen Ziegen von dem vor dem Roboter liegenden Feld aufheben - sofern möglich eine Marke auf das Feld setzen, auf dem sich der Roboter befindet eine Marke löschen, die sich auf dem Feld des Roboters befindet - sofern möglich mache nichts links while nichtVorWand: ziegelHinlegen schritt #while if nichtVorWand: if nichtVorZiegel: schritt else: ziegelHinlegen #if links markeSetzen schritt while nichtAufMarke: while nichtVorWand: #while links

8 Exkurs - MyKa Bedingung vorWand nichtVorWand vorZiegel nichtVorZiegel
aufMarke nichtAufMarke Bedeutung Befindet sich der Roboter vor einer Wand? Befindet sich der Roboter nicht vor einer Wand? Befindet sich der Roboter vor einem Ziegel? Befindet sich der Roboter nicht vor einem Ziegel? Befindet sich der Roboter auf einer Marke? Befindet sich der Roboter nicht auf einer Marke? links while nichtVorWand: ziegelHinlegen schritt #while if nichtVorWand: if nichtVorZiegel: schritt else: ziegelHinlegen #if links markeSetzen schritt while nichtAufMarke: while nichtVorWand: #while links

9 Exkurs - MyKa Kontrollstruktur Sequenz:
"Anweisung" "Anweisung" "Anweisung" Fallunterscheidung: if "Bedingung": "Anweisungssequenz" else: "Anweisungssequenz" #if Wiederholung: while "Bedingung": "Anweisungssequenz" #while Bedeutung Sequenz: Führe die Anweisungen der Reihe nach aus. Fallunterscheidung: Wenn die Bedingung erfüllt ist, dann führe die erste Anweisungssequenz aus, ansonsten die zweite Anweisungssequenz. Wiederholung: Solange die Bedingung erfüllt ist, führe die Anweisungssequenz aus. links while nichtVorWand: ziegelHinlegen schritt #while if nichtVorWand: if nichtVorZiegel: schritt else: ziegelHinlegen #if links markeSetzen schritt while nichtAufMarke: while nichtVorWand: #while links

10 Exkurs - MyKa Syntax und Semantik - informell oder formal?
Eine informelle Beschreibung von Syntax und Semantik liefert einen ersten Überblick über die Struktur und Bedeutung der Sprachelemente der Programmiersprache. Bei einer informellen Beschreibung bleiben meist aber noch Fragen offen. Im Fall der Programmiersprache MyKa ist beispielsweise noch nicht geklärt, ob es auch leere Anweisungssequenzen geben kann (z.B. in der Anweisung while nichtVorWand: #while). Ungeklärt ist auch noch, wie sich ein mehrfaches Setzen einer Marke auswirkt. Alle diese Fragen werden geklärt, wenn Syntax und Semantik präzise beschrieben werden. Für die Programmiersprache MyKa wird das in den folgenden Abschnitten nachgeholt. links while nichtVorWand: ziegelHinlegen schritt #while if nichtVorWand: if nichtVorZiegel: schritt else: ziegelHinlegen #if links markeSetzen schritt while nichtAufMarke: while nichtVorWand: #while links

11 Fachkonzept - Syntax Die Syntax einer Sprache beschreibt, welche Kombinationen von Zeichen fehlerfreie Programme der Sprache bilden. myka_syn = {Programm1, Programm2, ...} Eine Präzisierung dieser Menge kann z.B. mit Hilfe einer Grammatik vorgenommen werden. links while nichtVorWand: ziegelHinlegen schritt #while if nichtVorWand: if nichtVorZiegel: schritt else: ziegelHinlegen #if links Programmx markeSetzen schritt while nichtAufMarke: while nichtVorWand: #while links

12 Fachkonzept - Semantik
Die Semantik einer Sprache beschreibt, welche Bedeutung den Einheiten der Sprache zugeordnet wird. myka_sem: (programm, zustand_vorher) --> zustand_nachher Eine Präzisierung dieser Zuordnung kann z.B. mit Hilfe eines Interpreters vorgenommen werden.

13 Scanner und Parser im Überblick
Teil 2 Scanner und Parser im Überblick

14 Myka syntaktisch korrektes Programm Programm mit Syntaxfehler
Struktur-darstellung d. Programms

15 Aufgabe Untersuche verschiedene Programme (siehe inf-schule) auf syntaktische Korrektheit. Schaue dir die Quelltexte zunächst genau an und stelle Vermutungen über Syntaxfehler auf. Gib die vorgegebenen MyKa-Programm-Quelltexte in das linke obere Fenster ein. Erzeuge mit der Schaltfläche [scannen / parsen] ein MyKaList-Programm - das ist eine mit Hilfe von Listen erstellte strukturierte Darstellung des MyKa-Programms. In welchen Fällen funktioniert das, in welchen Fällen nicht? Die Programme 3, 4 und 5 sind aus unterschiedlichen Gründen syntaktisch nicht korrekt. Gegen welche Regeln wird hier wohl verstoßen?

16 Aufgabe links while nichtVorWand: ziegelHinlegen schritt #while Versuche anhand weiterer Tests zu erschließen, wie ein syntaktisch korrektes MyKa-Programm mit Hilfe von Listen strukturiert als MyKaList-Programm dargestellt wird. Bei der Erzeugung eines MyKaList-Programms werden zusätzliche Informationen über den Analysevorgang ausgegeben. Diese Informationen im Detail zu verstehen ist schwierig. Vielleicht hast du trotzdem eine Idee, um was es hier geht. Scanner erzeugt: LexToken(ELANW,'links',9,0) LexToken(WH,'while',10,6) LexToken(BED,'nichtVorWand',10,12) LexToken(DP,':',10,24) LexToken(ELANW,'ziegelHinlegen',11,28) LexToken(ELANW,'schritt',12,45) LexToken(WH_ENDE,'#while',13,53) Parser erzeugt: [ ['links'], ['while', ['nichtVorWand'], [['ziegelHinlegen'], ['schritt']]] ]

17 Fachkonzept - Scanner Ein (lexikalischer) Scanner ist eine Programmeinheit, die eine Zeichenfolge nach vorgegebenen Mustern in lexikalische Einheiten zerlegt oder anzeigt, dass eine solche Zerlegung nicht möglich ist.

18 Fachkonzept - Parser Ein Parser ist eine Programmeinheit, die analysiert, ob eine Tokenfolge zu einem Programmquelltext vorgegebene Grammatikregeln befolgt. Ist das nicht der Fall, so wird eine Fehlermeldung erzeugt. Andernfalls wird eine strukturierte Darstellung des Programmquelltextes erzeugt, die die von den Grammatikregeln verlangte syntaktische Struktur widerspiegelt.

19 Interpreter und Compiler im Überblick
Teil 3 Interpreter und Compiler im Überblick

20 Myka Ausführung von MyKaList-Programmen
Übersetzen von MyKaList-Programmen

21 Ausführung von MyKaList-Programmen
Aufgabe Ein MyKaList-Programm kann man mit der Schaltfläche [Anw. ausführen] schrittweise ausführen. Probiere das mit verschiedenen Testprogrammen aus und beobachte die Entwicklung im MyKaList-Fenster. Beachte, dass der MyKaList-Editor nur zum Anzeigen von MyKaList-Programmen dient. Veränderungen an MyKaList-Programmen kann man hier nicht vornehmen. Ausführung von MyKaList-Programmen

22 Übersetzen von MyKaList-Programmen
Aufgabe Mit der Schaltfläche [Code erzeugen] lässt sich ein MyKaList-Programm in ein sog. MyKaGoto-Programm übersetzen. Probiere das mit verschiedenen Testprogrammen aus. Versuche mit Hilfe gezielter Experimente die Syntax und Semantik der Code-Sprache MyKaGoto zu erschließen. Übersetzen von MyKaList-Programmen

23 Fachkonzept - Interpreter
Ein Interpreter für eine Programmiersprache ist ein universelles Programm (Algorithmus), das jedes Programm der zu interpretierenden Programmiersprache schrittweise ausführen kann. MyKaList-Programm

24 Exkurs - MyKaGoto links while nichtVorWand: ziegelHinlegen schritt
MyKa-Programm benutzt Kontrollstrukturen benutzt Sprungbefehle links label .L0 if nichtVorWand: goto .L1 else: goto .L2 label .L1 ziegelHinlegen schritt goto .L0 label .L2 MyKaGoto-Programm [ (None, ['links']) ('.L0', ['noop']) (None, ['if', ['nichtVorWand'], ['goto', '.L1'], ['goto', '.L2']]) ('.L1', ['noop']) (None, ['ziegelHinlegen']) (None, ['schritt']) (None, ['goto', '.L0']) ('.L2', ['noop']) ] strukturiertes MyKaGoto-Programm

25 Fachkonzept - Compiler
Ein Compiler (im engeren Sinn) ist ein universelles Programm (Algorithmus), das jedes Programm einer Quell-Programmiersprache in ein äquivalentes Programm einer Ziel-Programmiersprache übersetzt. MyKaList-Programm MyKaGoToList-Programm

26 Fachkonzept - Compiler
Ein Compiler (im weiteren Sinn) ist ein System, das aus Scanner, Parser, Codererzeuger und Codeoptimierer besteht. links while nichtVorWand: ziegelHinlegen schritt #while LexToken(ELANW,'links',9,0) LexToken(WH,'while',10,6) LexToken(BED,'nichtVorWand',10,12) LexToken(DP,':',10,24) LexToken(ELANW,'ziegelHinlegen',11,28) LexToken(ELANW,'schritt',12,45) LexToken(WH_ENDE,'#while',13,53) [ ['links'], ['while', ['nichtVorWand'], [['ziegelHinlegen'], ['schritt']]] ] [ (None, ['links']), ('.L0', ['noop']), (None, ['if', ['nichtVorWand'], ['goto', '.L1'], ['goto', '.L2']]), ('.L1', ['noop']), (None, ['ziegelHinlegen']), (None, ['schritt']), (None, ['goto', '.L0']), ('.L2', ['noop']) ]

27 Entwicklung eines Compilers - MyWhile
Teil 4 Entwicklung eines Compilers - MyWhile

28 Station - MyWhile Die Sprache While ist eine sehr einfache Programmiersprache, die auf vieles verzichtet und nur ganz wenige Konstrukte zur Verfügung stellt. Diese Sprache wird wegen ihrere Einfachheit oft für theoretische Untersuchungen genutzt. Wir benutzen eine Variante von While, die wir MyWhile nennen. Die Sprache MyWhile ist nicht ganz so restriktiv wie die Sprache While, aber dennoch so einfach, dass Funktionsprinzipien von Interpretern und Compilern in einem überschaubaren Kontext verdeutlicht werden können. x = 24 y = 15 d = x - y while d != 0: if d > 0: x = x - y else: y = y - x #if #while

29 Station - MyWhile elem. Anweisung x = 0 neu = alt x = x + 1 y1 = x0 - 2 z = x + y x = x - y pass Struktur "Variable" = "Zahl" "Variable" = "Variable" "Variable" = "Variable" + "Zahl" "Variable" = "Variable" - "Zahl" "Variable" = "Variable" + "Variable" "Variable" = "Variable" - "Variable" x = 24 y = 15 d = x - y while d != 0: if d > 0: x = x - y else: y = y - x #if #while Bedingung x == 0 zahl != 0 x2 > 0 y < 0 Struktur "Variable" == 0 "Variable" != 0 "Variable" > 0 "Variable" < 0 Als Bezeichner von Variablen sind alle Zeichenketten erlaubt, die aus Kleinbuchstaben und Ziffern bestehen und mit einem Buchstaben beginnen. Als Zahlen dürfen hier nur die ganzen Zahlen benutzt werden.

30 Station - MyWhile Kontrollstruktur Sequenz:
"Anweisung" "Anweisung" "Anweisung" Fallunterscheidung: if "Bedingung": "Anweisungssequenz" else: "Anweisungssequenz" #if Wiederholung: while "Bedingung": "Anweisungssequenz" #while Bedeutung Sequenz: Führe die Anweisungen der Reihe nach aus. Fallunterscheidung: Wenn die Bedingung erfüllt ist, dann führe die erste Anweisungssequenz aus, ansonsten die zweite Anweisungssequenz. Wiederholung: Solange die Bedingung erfüllt ist, führe die Anweisungssequenz aus. x = 24 y = 15 d = x - y while d != 0: if d > 0: x = x - y else: y = y - x #if #while

31 Aufgabe Ist das folgende Programm ein syntaktisch korrektes MyWhile-Programm? x=24 y=15 d=x-y while d != 0 : if d > 0 : x = x - y else: y=y-x#if d=x-y #while Warum ist die Klärung der Frage schwierig?

32 Station - LEX und YACC LEX ist ein Programm, das Scanner automatisiert erzeugen kann. Gibt man LEX eine genaue Beschreibung der Token vor, so erzeugt LEX einen endlichen Automaten, der Token erkennt. YACC (Akronym für yet another compiler compiler) ist ein Programm, das Parser automatisiert erzeugen kann. Gibt man YACC die Grammatik einer (Programmier-) Sprache vor, so erzeugt YACC einen Shift-Reduce-Parser zur Erkennung der Sprache, die durch die Grammatik beschrieben wird. Wir benutzen im Folgenden die Python-Implementierung PLY von LEX und YACC.

33 Station - Scanner Ein (lexikalischer) Scanner ist eine Programmeinheit, die eine Zeichenfolge nach vorgegebenen Mustern in lexikalische Einheiten zerlegt oder anzeigt, dass eine solche Zerlegung nicht möglich ist. x = 24 y = 15 d = x - y while d != 0: if d > 0: x = x - y else: y = y - x #if #while Scanner Quelltext (VAR,'x') (ZUW,'=') (ZAHL,'24') (VAR,'y') (ZAHL,'15') (VAR,'d') (MINUS,'-') (WHILE,'while') (UG,'!=') (NULL,'0') (DP,':') ... Tokenfolge / Fehlermeldung

34 Station - Scanner Der Aufbau lexikalischer Einheiten wird in der Regel mit Hilfe regulärer Ausdrücke beschrieben. Als Beispiel betrachten wir Variablenbezeichner. Variablenbezeichner beginnen mit einem Kleinbuchstaben. Danach können beliebig viele Kleinbuchstaben oder Ziffern folgen. Dieses Muster lässt sich mit dem regulären Ausdruck [a-z][a-z0-9]* beschreiben. # Beschreibung der Token t_VAR = r'[a-z][a-z0-9]*' t_ZAHL = r'[\+|-]?[1-9][0-9]*' t_NULL = r'0' t_WHILE = r'while' t_IF = r'if' t_ELSE = r'else' t_PASS = r'pass' t_ENDWH = r'\#while' t_ENDIF = r'\#if' t_ZUW = r'=' t_PLUS = r'\+' t_MINUS = r'-' t_GL = r'==' t_UG = r'!=' t_GR = r'\>' t_KL = r'\<' t_DP = r':' (VAR,'x') (ZUW,'=') (ZAHL,'24') (VAR,'y') (ZAHL,'15') (VAR,'d') (MINUS,'-') (WHILE,'while') (UG,'!=') (NULL,'0') (DP,':') (IF,'if') ... Das Programm LEX ist in der Lage, ausgehend von einer Tokenbeschreibung in Form regulärer Ausdrücke ein System zur lexikalischen Analyse zu erzeugen. Letztlich generiert LEX aus den regulären Ausdrücken endliche Automaten, die die Analyse von Zeichenketten vornehmen.

35 Aufgabe # Beschreibung der Token t_VAR = r'[a-z][a-z0-9]*' t_ZAHL = r'[\+|-]?[1-9][0-9]*' t_NULL = r'0' t_WHILE = r'while' t_IF = r'if' t_ELSE = r'else' t_PASS = r'pass' t_ENDWH = r'\#while' t_ENDIF = r'\#if' t_ZUW = r'=' t_PLUS = r'\+' t_MINUS = r'-' t_GL = r'==' t_UG = r'!=' t_GR = r'\>' t_KL = r'\<' t_DP = r':' (VAR,'x') (ZUW,'=') (ZAHL,'24') (VAR,'y') (ZAHL,'15') (VAR,'d') (MINUS,'-') (WHILE,'while') (UG,'!=') (NULL,'0') (DP,':') (IF,'if') ... Aufgabe: (a) Welche Zeichenketten passen auf das Token-Muster ZAHL?. Gib Beispiele für solche Zeichenketten an. Beachte die Sonderrolle der Zahl Null, für die ein eigenes Token-Muster vorgesehen ist. (b) Die Festlegung der Token-Muster ist in der vorliegenden Form nicht eindeutig. So passt z.B. die Zeichenkette 'if' auf zwei verschiedene Token-Muster. Welche sind das? Gibt es weitere problematische Zeichenketten?

36 Token-Muster von MyWhile
Station - Scanner # reservierte Wörter reserved = { 'if' : 'IF', 'else' : 'ELSE', 'while' : 'WHILE', 'pass': 'PASS' } # Namen der Token tokens = ['VAR', 'ZAHL', 'NULL', 'ZUW', 'PLUS', 'MINUS', 'GL', 'UG', 'GR', 'KL', 'DP', 'ENDWH', 'ENDIF'] tokens = tokens + list(reserved.values()) # Beschreibung der Token def t_VAR(t): r'[a-z][a-z0-9]*' t.type = reserved.get(t.value, 'VAR') # Überprüfung auf reservierte Wörter return t t_ZAHL = r'[\+|-]?[1-9][0-9]*' t_NULL = r'0' t_ZUW = r'=' t_PLUS = r'\+' t_MINUS = r'-' t_GL = r'==' t_UG = r'!=' t_GR = r'\>' t_KL = r'\<' t_DP = r':' t_ENDWH = r'\#while' t_ENDIF = r'\#if' ... Token-Muster von MyWhile

37 Station - Scanner import ply.lex as lex from syntaxWhile import *
# Testprogramm programm = ''' x = 24 y = 15 d = x - y while d != 0: if d > 0: x = x - y else: y = y - x #if #while ''' # Erzeugung des Scanners scanner = lex.lex(debug=0) # lexikalische Analyse mit Erzeugung der Token scanner.input(programm) token = [] tok = scanner.token() while tok: token = token + [tok] # Ausgabe for tok in token: print(tok) >>> LexToken(VAR,'x',2,1) LexToken(ZUW,'=',2,3) LexToken(ZAHL,'24',2,5) LexToken(VAR,'y',3,8) LexToken(ZUW,'=',3,10) LexToken(ZAHL,'15',3,12) LexToken(VAR,'d',4,15) LexToken(ZUW,'=',4,17) LexToken(VAR,'x',4,19) LexToken(MINUS,'-',4,21) LexToken(VAR,'y',4,23) LexToken(WHILE,'while',5,25) LexToken(VAR,'d',5,31) LexToken(UG,'!=',5,33) LexToken(NULL,'0',5,36) LexToken(DP,':',5,37) LexToken(IF,'if',6,43) LexToken(VAR,'d',6,46) LexToken(GR,'>',6,48) LexToken(NULL,'0',6,50) LexToken(DP,':',6,51) LexToken(VAR,'x',7,61) LexToken(ZUW,'=',7,63) LexToken(VAR,'x',7,65) LexToken(MINUS,'-',7,67) LexToken(VAR,'y',7,69) LexToken(ELSE,'else',8,75) LexToken(DP,':',8,79) LexToken(VAR,'y',9,89) ...

38 Aufgabe Aufgabe: (a) Probiere das selbst einmal aus. Teste auch andere Quelltexte. Teste u.a. den Quelltext: x=24y=15d=x-ywhiled!=0:ifd>0:x=x-yelse:y=y-x#ifd=x-y#while Teste auch solche Quelltexte, die sich nicht in die vorgegebenen Token zerlegen lassen. Wie reagiert der Scanner auf Variablenbezeichner der Gestalt 007? Hast du eine Vermutung? Was macht der Scanner mit einem unsinnigen Quelltext wie z.B. :while 7:? Hast du eine Vermutung? (b) Versuche, durch Tests herauszufinden, welche Bedeutung die zusätzlichen Zahlangaben in den Token haben. (c) Ändere selbst die Beschreibung der Token in sinnvoller Weise ab und teste die neuen Festlegungen.

39 Aufgabe Aufgabe: Das oben gezeigte MyWhile-Programm könnte man auch in einer Java-ähnlichen Schreibweise darstellen. Ändere die Beschreibung der Token so ab, dass sie auf die Java-ähnliche Schweibweise passt. x = 24; y = 15; d = x - y; while (d != 0) { if (d > 0) { x = x - y; } else { y = y - x; };

40 Station - Parser / Syntaxanalyse
Ein Parser ist eine Programmeinheit, die analysiert, ob eine Tokenfolge zu einem Programmquelltext vorgegebene Grammatikregeln befolgt. Ist das nicht der Fall, so wird eine Fehlermeldung erzeugt. Andernfalls wird eine strukturierte Darstellung des Programmquelltextes erzeugt, die die von den Grammatikregeln verlangte syntaktische Struktur widerspiegelt. Parser (VAR,'x') (ZUW,'=') (ZAHL,'24') (VAR,'y') (ZAHL,'15') (VAR,'d') (MINUS,'-') (WHILE,'while') (UG,'!=') (NULL,'0') (DP,':') ... Tokenfolge Struktur / Fehlermeldung ok

41 Station - Parser / Syntaxanalyse
Zunächst muss die Grammatik der Sprache MyWhile festgelegt werden. Die Terminalsymbole der Grammatik sind die Tokennamen. Die Nichtterminalsymbole ergeben sich aus den linken Seiten der folgenden Produktionen. Startsymbol ist das Symbol auf der linken Seite der ersten Produktion. # Produktionen anweisungsfolge -> anweisung anweisungsfolge anweisungsfolge -> anweisung anweisung -> zuweisung anweisung -> PASS anweisung -> WHILE bedingung DP anweisungsfolge ENDWH anweisung -> IF bedingung DP anweisungsfolge ELSE DP anweisungsfolge ENDIF zuweisung -> VAR ZUW term term -> VAR op zahl term -> VAR op VAR term -> zahl term -> VAR zahl -> NULL zahl -> ZAHL op -> PLUS op -> MINUS bedingung -> VAR rel NULL rel -> GL rel -> UG rel -> GR rel -> KL x = 24 y = 15 d = x - y while d != 0: if d > 0: x = x - y else: y = y - x #if #while VAR ZUW ZAHL VAR ZUW VAR MINUS VAR WHILE VAR UG NULL DP IF VAR GR NULL DP ELSE DP ENDIF ENDWH Grammatik von MyWhile

42 Aufgabe Aufgabe: Zeige, dass man mit den Produktionen der Grammatik eine Ableitung der Tokenfolge zum Demo-Programm erzeugen kann. # Produktionen anweisungsfolge -> anweisung anweisungsfolge anweisungsfolge -> anweisung anweisung -> zuweisung anweisung -> PASS anweisung -> WHILE bedingung DP anweisungsfolge ENDWH anweisung -> IF bedingung DP anweisungsfolge ELSE DP anweisungsfolge ENDIF zuweisung -> VAR ZUW term term -> VAR op zahl term -> VAR op VAR term -> zahl term -> VAR zahl -> NULL zahl -> ZAHL op -> PLUS op -> MINUS bedingung -> VAR rel NULL rel -> GL rel -> UG rel -> GR rel -> KL x = 4 while x > 0: x = x - 1 #while VAR ZUW ZAHL WHILE VAR GR NULL DP VAR ZUW VAR MINUS ZAHL ENDWH Grammatik von MyWhile

43 Station - Parser / Syntaxanalyse
def p_anweisungsfolge_anweisung_anweisungsfolge(p): 'anweisungsfolge : anweisung anweisungsfolge' p[0] = None def p_anweisungsfolge_anweisung(p): 'anweisungsfolge : anweisung' def p_anweisung_zuw(p): 'anweisung : zuweisung' def p_anweisung_pass(p): 'anweisung : PASS' def p_anweisung_wh(p): 'anweisung : WHILE bedingung DP anweisungsfolge ENDWH' def p_anweisung_if(p): 'anweisung : IF bedingung DP anweisungsfolge ELSE DP anweisungsfolge ENDIF' def p_zuweisung(p): 'zuweisung : VAR ZUW term' def p_term_var_op_zahl(p): 'term : VAR op zahl' def p_term_var_op_var(p): 'term : VAR op VAR' def p_term_zahl(p): 'term : zahl' ... YACC-Implementierung anweisungsfolge -> anweisung anweisungsfolge anweisungsfolge -> anweisung anweisung -> zuweisung anweisung -> PASS anweisung -> WHILE bedingung DP anweisungsfolge ENDWH anweisung -> IF bedingung DP anweisungsfolge ELSE DP anweisungsfolge ENDIF zuweisung -> VAR ZUW term term -> VAR op ZAHL term -> VAR op VAR term -> zahl ...

44 Station - Parser / Syntaxanalyse
import ply.lex as lex import ply.yacc as yacc from syntaxWhile import * # Testprogramm programm = ''' x = 24 y = 15 d = x - y while d != 0: if d > 0: x = x - y else: y = y - x #if #while ''' # Erzeugung des Scanners scanner = lex.lex(debug=0) # Erzeugung des Parsers parser = yacc.yacc(debug=False) # syntaktische Analyse parser.parse(programm, debug=0) # Ausgabe print("ok!") >>> ok!

45 Aufgabe Aufgabe: (a) Probiere das selbst einmal aus. Teste Quelltexte, die den Syntaxregeln von MyWhile entsprechen und teste auch fehlerhafte Quelltexte. Wie zeigt sich in der vorliegenden Implementierung, ob der Quelltext fehlerfrei ist? (b) Du kannst ja auch einmal versuchen, die Grammatik von MyWhile in sinnvoller Weise zu ergänzen oder abzuändern.

46 Aufgabe Aufgabe: Ändere die Grammatik (und Tokenbeschreibungen) so ab, dass folgendes Programm erkannt wird: x = 24; y = 15; d = x - y; while (d != 0) { if (d > 0) { x = x - y; } else { y = y - x; };

47 Station - Parser / Strukturgerüst
Ein Parser ist eine Programmeinheit, die analysiert, ob eine Tokenfolge zu einem Programmquelltext vorgegebene Grammatikregeln befolgt. Ist das nicht der Fall, so wird eine Fehlermeldung erzeugt. Andernfalls wird eine strukturierte Darstellung des Programmquelltextes erzeugt, die die von den Grammatikregeln verlangte syntaktische Struktur widerspiegelt. Parser [ ['=', ('VAR', 'x'), [('ZAHL', '24')]], ['=', ('VAR', 'y'), [('ZAHL', '15')]], ['=', ('VAR', 'd'), ['-', ('VAR', 'x'), ('VAR', 'y')]], ['while', ['!=', ('VAR', 'd'), ('ZAHL', '0')], ['if', ['>', ('VAR', 'd'), ('ZAHL', '0')], ['=', ('VAR', 'x'), ['-', ('VAR', 'x'), ('VAR', 'y')]] ], ['=', ('VAR', 'y'), ['-', ('VAR', 'y'), ('VAR', 'x')]] ] ['=', ('VAR', 'd'), ['-', ('VAR', 'x'), ('VAR', 'y')]] (VAR,'x') (ZUW,'=') (ZAHL,'24') (VAR,'y') (ZAHL,'15') (VAR,'d') (MINUS,'-') (WHILE,'while') (UG,'!=') (NULL,'0') (DP,':') ... Tokenfolge Struktur / Fehlermeldung

48 Station - Parser / Strukturgerüst
Idee: Die Grammatikregeln werden um Beschreibungen zur Erzeugung des Strukturgerüsts erweitert. # Produktionen anweisungsfolge -> anweisung anweisungsfolge anweisungsfolge -> anweisung anweisung -> zuweisung anweisung -> PASS anweisung -> WHILE bedingung DP anweisungsfolge ENDWH anweisung -> IF bedingung DP anweisungsfolge ELSE DP anweisungsfolge ENDIF zuweisung -> VAR ZUW term term -> VAR op zahl term -> VAR op VAR term -> zahl term -> VAR zahl -> NULL zahl -> ZAHL op -> PLUS op -> MINUS bedingung -> VAR rel NULL rel -> GL rel -> UG rel -> GR rel -> KL # erweiterte Produktionen ... zahl -> ZAHL | | p[0] p[1] p[0] = p[1] term -> zahl p[0] = [('ZAHL', p[1])] zuweisung -> VAR ZUW term | | | | p[0] p[1]p[2]p[3] p[0] = [p[2], ('VAR', p[1]), p[3]] anweisung -> zuweisung | | p[0] p[1]

49 Station - Parser / Strukturgerüst
x = 4 while x > 0: x = x - 1 #while Quelltext VAR ZUW ZAHL WHILE VAR GR NULL DP VAR ZUW VAR MINUS ZAHL ENDWH Tokenfolge anweisungsfolge -> anweisung anweisungsfolge -> anweisung anweisung -> anweisung WHILE bedingung DP anweisungsfolge ENDWH -> anweisung WHILE bedingung DP anweisung ENDWH -> anweisung WHILE bedingung DP zuweisung ENDWH -> anweisung WHILE bedingung DP VAR ZUW term ENDWH -> anweisung WHILE bedingung DP VAR ZUW VAR op ZAHL ENDWH -> anweisung WHILE bedingung DP VAR ZUW VAR MINUS ZAHL ENDWH -> anweisung WHILE VAR rel NULL DP VAR ZUW VAR MINUS ZAHL ENDWH -> anweisung WHILE VAR GR NULL DP VAR ZUW VAR MINUS ZAHL ENDWH -> # anweisung -> zuweisung zuweisung WHILE VAR GR NULL DP VAR ZUW VAR MINUS ZAHL ENDWH -> # zuweisung -> VAR ZUW term VAR ZUW term WHILE VAR GR NULL DP VAR ZUW VAR MINUS ZAHL ENDWH -> # term -> zahl VAR ZUW zahl WHILE VAR GR NULL DP VAR ZUW VAR MINUS ZAHL ENDWH -> # zahl -> ZAHL VAR ZUW ZAHL WHILE VAR GR NULL DP VAR ZUW VAR MINUS ZAHL ENDWH Rechtsableitung der Tokenfolge Grammatikregeln

50 Station - Parser / Strukturgerüst
VAR ZUW ZAHL WHILE VAR GR NULL DP VAR ZUW VAR MINUS VAR ENDWH zahl -> ZAHL | | p[0] p[1] p[0] = p[1] zahl: '4' VAR ZUW zahl WHILE VAR GR NULL DP VAR ZUW VAR MINUS VAR ENDWH term -> zahl p[0] = [('ZAHL', p[1])] term: [('ZAHL', '4')] VAR ZUW term WHILE VAR GR NULL DP VAR ZUW VAR MINUS ZAHL ENDWH zuweisung -> VAR ZUW term | | | | p[0] p[1]p[2]p[3] p[0] = [p[2], ('VAR', p[1]), p[3]] zuweisung: ['=', ('VAR', 'x'), [('ZAHL', '4')]] zuweisung WHILE VAR GR NULL DP VAR ZUW VAR MINUS ZAHL ENDWH anweisung -> zuweisung | | p[0] p[1] p[0] = p[1] anweisung: ['=', ('VAR', 'x'), [('ZAHL', '4')]] x = 4 while x > 0: x = x - 1 #while erweiterte Grammatikregel produzierte Struktur VAR ZUW ZAHL WHILE VAR GR NULL DP VAR ZUW VAR MINUS ZAHL ENDWH Rechtsableitung der Tokenfolge ( rückwärts betrachtet) - erweitert um die Erzeugung des Strukturgerüsts Grammatik von MyWhile [ ['=', ('VAR', 'x'), [('ZAHL', '4')]], ['while', ['>', ('VAR', 'x'), ('ZAHL', '0')], ['=', ('VAR', 'x'), ['-', ('VAR', 'x'), ('ZAHL', '1')]] ]

51 Station - Parser / Strukturgerüst
# erweiterte Produktionen def p_anweisungsfolge_anweisung_anweisungsfolge(p): 'anweisungsfolge : anweisung anweisungsfolge' p[0] = [p[1]] + p[2] def p_anweisungsfolge_anweisung(p): 'anweisungsfolge : anweisung' p[0] = [p[1]] def p_anweisung_zuw(p): 'anweisung : zuweisung' p[0] = p[1] def p_anweisung_pass(p): 'anweisung : PASS' def p_anweisung_wh(p): 'anweisung : WHILE bedingung DP anweisungsfolge ENDWH' p[0] = [p[1]] + [p[2]] + [p[4]] def p_anweisung_if(p): 'anweisung : IF bedingung DP anweisungsfolge ELSE DP anweisungsfolge ENDIF' p[0] = [p[1]] + [p[2]] + [p[4]] + [p[7]] def p_zuweisung(p): 'zuweisung : VAR ZUW term' p[0] = [p[2], ('VAR', p[1]), p[3]] ... YACC-Implementierung

52 Station - Parser / Strukturgerüst
import ply.lex as lex import ply.yacc as yacc from syntaxWhile import * # Testprogramm programm = ''' x = 4 while x > 0: x = x - 1 #while ''' # Erzeugung des Scanners scanner = lex.lex(debug=0) # Erzeugung des Parsers parser = yacc.yacc(debug=False) # syntaktische Analyse mit Erzeugung des Strukturbaums if len(programm) != 0: strukturbaum = parser.parse(programm, debug=0) else: strukturbaum = [] # Ausgabe print(strukturbaum) >>> [['=', ('VAR', 'x'), [('ZAHL', '4')]], ['while', ['>', ('VAR', 'x'), ('ZAHL', '0')], [['=', ('VAR', 'x'), ['-', ('VAR', 'x'), ('ZAHL', '1')]]]]]

53 Aufgabe Aufgabe (a) Probiere das selbst einmal aus. Teste verschiedene Quelltexte, die syntaktisch korrekt sind. (b) Was liefert der Parser, wenn ein syntaktischer Fehler vorliegt? (c) Versuche auch einmal, die Strukturelemente anders zu gestalten.

54 Aufgabe Aufgabe: Erweitere die Grammatik zur Java-ähnlichen Syntax um Erzeugungsregeln für ein Strukturgerüst. Konzipiere die Erzeugungsregeln so, dass das gleiche Strukturgerüst wie bei der Python-ähnlichen Syntax entsteht. x = 4; while (x > 0) { x = x - 1; }; Parser (VAR,'x') (ZUW,'=') (ZAHL,'4') (SEM, ';') (WHILE,'while') (KL_AUF, '(') (VAR, 'X') (GR, '>') (NULL, '0') (KL_ZU, ')') (WH_BEGINN, '{') ... Tokenfolge [ ['=', ('VAR', 'x'), [('ZAHL', '4')]], ['while', ['>', ('VAR', 'x'), ('ZAHL', '0')], ['=', ('VAR', 'x'), ['-', ('VAR', 'x'), ('ZAHL', '1')]] ] Struktur / Fehlermeldung

55 neuer Variablenzustand
Station - Interpreter Zuweisung ausführen [ ['=', ('VAR', 'x'), [('NAT', '24')]], ['=', ('VAR', 'y'), [('NAT', '15')]], ['=', ('VAR', 'd'), ['-', ('VAR', 'x'), ('VAR', 'y')]], ['while', ['!=', ('VAR', 'd'), ('NAT', '0')], ... ] [ ['=', ('VAR', 'y'), [('NAT', '15')]], ['=', ('VAR', 'd'), ['-', ('VAR', 'x'), ('VAR', 'y')]], ['while', ['!=', ('VAR', 'd'), ('NAT', '0')], ... ] {'x' -> 24} {} Restprogramm neues Restprogramm Variablenzustand neuer Variablenzustand

56 Wiederholung ausführen
Station - Interpreter Wiederholung ausführen [ ['while', ['!=', ('VAR', 'd'), ('ZAHL', '0')], ['if', ['>', ('VAR', 'd'), ('ZAHL', '0')], ['=', ('VAR', 'x'), ['-', ('VAR', 'x'), ('VAR', 'y')]] ], ['=', ('VAR', 'y'), ['-', ('VAR', 'y'), ('VAR', 'x')]] ] ['=', ('VAR', 'd'), ['-', ('VAR', 'x'), ('VAR', 'y')]] Bedingung True [ ['if', ['>', ('VAR', 'd'), ('NAT', '0')], ['=', ('VAR', 'x'), ['-', ('VAR', 'x'), ('VAR', 'y')]] ], ['=', ('VAR', 'y'), ['-', ('VAR', 'y'), ('VAR', 'x')]] ] ['=', ('VAR', 'd'), ['-', ('VAR', 'x'), ('VAR', 'y')]], ['while', ['!=', ('VAR', 'd'), ('NAT', '0')], ['=', ('VAR', 'd'), ['-', ('VAR', 'x'), ('VAR', 'y')]] {'x' -> 24, 'y' -> 15, 'd' -> 9} {'x' -> 24, 'y' -> 15, 'd' -> 9}

57 Fallunterscheidung ausführen
Station - Interpreter Fallunterscheidung ausführen [ ['if', ['>', ('VAR', 'd'), ('NAT', '0')], ['=', ('VAR', 'x'), ['-', ('VAR', 'x'), ('VAR', 'y')]] ], ['=', ('VAR', 'y'), ['-', ('VAR', 'y'), ('VAR', 'x')]] ] ['=', ('VAR', 'd'), ['-', ('VAR', 'x'), ('VAR', 'y')]], ... Bedingung True [ ['=', ('VAR', 'x'), ['-', ('VAR', 'x'), ('VAR', 'y')]], ['=', ('VAR', 'd'), ['-', ('VAR', 'x'), ('VAR', 'y')]], ... ] {'x' -> 24, 'y' -> 15, 'd' -> 9} {'x' -> 24, 'y' -> 15, 'd' -> 9}

58 Fallunterscheidung ausführen
Station - Interpreter Fallunterscheidung ausführen [ ['if', ['>', ('VAR', 'd'), ('NAT', '0')], ['=', ('VAR', 'x'), ['-', ('VAR', 'x'), ('VAR', 'y')]] ], ['=', ('VAR', 'y'), ['-', ('VAR', 'y'), ('VAR', 'x')]] ] ['=', ('VAR', 'd'), ['-', ('VAR', 'x'), ('VAR', 'y')]], ... Bedingung False [ ['=', ('VAR', 'y'), ['-', ('VAR', 'y'), ('VAR', 'x')]], ['=', ('VAR', 'd'), ['-', ('VAR', 'x'), ('VAR', 'y')]], ... ] {'x' -> 9, 'y' -> 15, 'd' -> -6} {'x' -> 9, 'y' -> 15, 'd' -> -6}

59 Wiederholung ausführen
Station - Interpreter Wiederholung ausführen [ ['while', ['!=', ('VAR', 'd'), ('ZAHL', '0')], ['if', ['>', ('VAR', 'd'), ('ZAHL', '0')], ['=', ('VAR', 'x'), ['-', ('VAR', 'x'), ('VAR', 'y')]] ], ['=', ('VAR', 'y'), ['-', ('VAR', 'y'), ('VAR', 'x')]] ] ['=', ('VAR', 'd'), ['-', ('VAR', 'x'), ('VAR', 'y')]] Bedingung False [ ] {'x' -> 3, 'y' -> 3, 'd' -> 0} {'x' -> 3, 'y' -> 3, 'd' -> 0}

60 Station - Interpreter class InterpreterWhileList(object):
def __init__(self, v): self.programm = None self.variablenzustand = v ... def anweisungAusfuehren(self): if self.programm != []: anweisung = self.programm[0] bezeichner = anweisung[0] if bezeichner == "=": self.verarbeiteZuweisung(anweisung) self.programm = self.programm[1:] if bezeichner == "pass": elif bezeichner == "while": bedingung = anweisung[1] if self.verarbeiteBedingung(bedingung): self.programm = anweisung[2] + self.programm else: elif bezeichner == "if": self.programm = anweisung[2] + self.programm[1:] self.programm = anweisung[3] + self.programm[1:] Implementierung

61 Station - Interpreter from variablenzustand import * # Testprogramm
['=', ('VAR', 'x'), [('ZAHL', '24')]], ['=', ('VAR', 'y'), [('ZAHL', '15')]], ['=', ('VAR', 'd'), ['-', ('VAR', 'x'), ('VAR', 'y')]], #... ] # Erzeugung des Interpreters variablenzustand = Variablenzustand() interpreter = InterpreterWhileList(variablenzustand) # Initialisierung des Programms interpreter.setProgramm(programm) # Ausführung des Programms und Ausgabe der Zustände print('Programm:') print(interpreter.programm) print('Variablenzustand') print(variablenzustand.variablen) print(' ') while interpreter.getProgramm() != []: interpreter.anweisungAusfuehren()

62 Aufgabe Aufgabe: Probiere das selbst einmal aus. Teste verschiedene strukturierte MyWhile-Programme.

63 Station - Code-Erzeuger
Ein Compiler (im engeren Sinn) ist ein universelles Programm (Algorithmus), das jedes Programm einer Quell-Programmiersprache in ein äquivalentes Programm einer Ziel-Programmiersprache übersetzt. Quellcode Zielcode [ ['=', ('VAR', 'x'), [('ZAHL', '24')]], ['=', ('VAR', 'y'), [('ZAHL', '15')]], ['=', ('VAR', 'd'), ['-', ('VAR', 'x'), ('VAR', 'y')]], ['while', ['!=', ('VAR', 'd'), ('ZAHL', '0')], ['if', ['>', ('VAR', 'd'), ('ZAHL', '0')], ['=', ('VAR', 'x'), ['-', ('VAR', 'x'), ('VAR', 'y')]] ], ['=', ('VAR', 'y'), ['-', ('VAR', 'y'), ('VAR', 'x')]] ] ['=', ('VAR', 'd'), ['-', ('VAR', 'x'), ('VAR', 'y')]] [ (None, ['=', ('VAR', 'x'), [('NAT', '24')]]), (None, ['=', ('VAR', 'y'), [('NAT', '15')]]), (None, ['=', ('VAR', 'd'), ['-', ('VAR', 'x'), ('VAR', 'y')]]), ('.L3', ['noop']), (None, ['if', ['!=', ('VAR', 'd'), ('NAT', '0')], ['goto', '.L4'], ['goto', '.L5']]), ('.L4', ['noop']), (None, ['if', ['>', ('VAR', 'd'), ('NAT', '0')], ['goto', '.L0'], ['goto', '.L1']]), ('.L0', ['noop']), (None, ['=', ('VAR', 'x'), ['-', ('VAR', 'x'), ('VAR', 'y')]]), (None, ['goto', '.L2']), ('.L1', ['noop']), (None, ['=', ('VAR', 'y'), ['-', ('VAR', 'y'), ('VAR', 'x')]]), ('.L2', ['noop']), (None, ['goto', '.L3']), ('.L5', ['noop']) ]

64 Station - Code-Erzeuger
Quellcode Zielcode [ ['=', ('VAR', 'x'), [('ZAHL', '24')]], ['=', ('VAR', 'y'), [('ZAHL', '15')]], ['=', ('VAR', 'd'), ['-', ('VAR', 'x'), ('VAR', 'y')]], ['while', ['!=', ('VAR', 'd'), ('ZAHL', '0')], ['if', ['>', ('VAR', 'd'), ('ZAHL', '0')], ['=', ('VAR', 'x'), ['-', ('VAR', 'x'), ('VAR', 'y')]] ], ['=', ('VAR', 'y'), ['-', ('VAR', 'y'), ('VAR', 'x')]] ] ['=', ('VAR', 'd'), ['-', ('VAR', 'x'), ('VAR', 'y')]] [ (None, ['=', ('VAR', 'x'), [('NAT', '24')]]), (None, ['=', ('VAR', 'y'), [('NAT', '15')]]), (None, ['=', ('VAR', 'd'), ['-', ('VAR', 'x'), ('VAR', 'y')]]), ('.L3', ['noop']), (None, ['if', ['!=', ('VAR', 'd'), ('NAT', '0')], ['goto', '.L4'], ['goto', '.L5']]), ('.L4', ['noop']), (None, ['if', ['>', ('VAR', 'd'), ('NAT', '0')], ['goto', '.L0'], ['goto', '.L1']]), ('.L0', ['noop']), (None, ['=', ('VAR', 'x'), ['-', ('VAR', 'x'), ('VAR', 'y')]]), (None, ['goto', '.L2']), ('.L1', ['noop']), (None, ['=', ('VAR', 'y'), ['-', ('VAR', 'y'), ('VAR', 'x')]]), ('.L2', ['noop']), (None, ['goto', '.L3']), ('.L5', ['noop']) ] x=24 y=15 d=x-y label .L3 if d!=0: goto .L4 else: goto .L5 label .L4 if d>0: goto .L0 goto .L1 label .L0 x=x-y goto .L2 label .L1 y=y-x label .L2 goto .L3 label .L5 x = 24 y = 15 d = x - y while d != 0: if d > 0: x = x - y else: y = y - x #if #while

65 Station - Code-Erzeuger
Fallunterscheidung übersetzen x = 1 if x1 != 0: y = x else: y = 0 #if x=1 if x1!=0: # Auswertung der Bedingung goto .L0 # Sprung zum wahr-Fall else: goto .L1 # Sprung zum falsch-Fall label .L # wahr-Fall y=x goto .L # Sprung zum Ende der Fallunterscheidung label .L # wahr-Fall y=0 label .L # Ende der Fallunterscheidung

66 Station - Code-Erzeuger
Wiederholung übersetzen x = 5 while x != 0: x = x - 1 #while x=5 label .L # Beginn der Schleife if x!=0: # Auswertung der Bedingung goto .L1 # Sprung zum Schleifenkörper else: goto .L2 # Sprung aus der Schleife label .L # Beginn des Schleifenkörpers x=x-1 goto .L # Sprung zum Beginn der schleife label .L # Ende der Schleife

67 Station - Code-Erzeuger
class UebersetzerWhileList(object): def __init__(self): self.quellcode = None def setQuellcode(self, q): self.quellcode = q def uebersetzen(self): def c_programm(p): 'programm : anweisungsfolge' return c_anweisungsfolge(p) def c_anweisungsfolge(p): '''anweisungsfolge : anweisung anweisungsfolge | anweisung''' if len(p) > 1: return c_anweisung(p[0]) + c_anweisungsfolge(p[1:]) else: return c_anweisung(p[0]) def c_anweisung(p): '''anweisung : VAR ZUW term | PASS | WHILE bedingung DP anweisungsfolge ENDWH | IF bedingung DP anweisungsfolge ELSE DP anweisungsfolge ENDIF''' ... self.zaehler = 0 if self.quellcode != None: return c_programm(self.quellcode) return [] Implementierung

68 Station - Code-Erzeuger
... def c_anweisung(p): if p[0] == "=": return [(None, p)] elif p[0] == "pass": return [(None, ['noop'])] elif p[0] == 'while': ergebnis_true = c_anweisungsfolge(p[2]) ergebnis_wh = [('.L' + str(self.zaehler), ['noop']), \ (None, ['if', p[1], ['goto', '.L' + str(self.zaehler+1)], \ ['goto', '.L' + str(self.zaehler+2)]]), \ ('.L' + str(self.zaehler+1), ['noop'])] + \ ergebnis_true + \ [(None, ['goto', '.L' + str(self.zaehler)]), \ ('.L' + str(self.zaehler+2), ['noop'])] self.zaehler = self.zaehler + 3 return ergebnis_wh elif p[0] == 'if': ergebnis_false = c_anweisungsfolge(p[3]) ergebnis_if = [(None, ['if', p[1], ['goto', '.L' + str(self.zaehler)], \ ['goto', '.L' + str(self.zaehler+1)]]), \ ('.L' + str(self.zaehler), ['noop'])] + \ [(None, ['goto', '.L' + str(self.zaehler+2)])] + \ [('.L' + str(self.zaehler+1), ['noop'])]+ \ ergebnis_false + \ [('.L' + str(self.zaehler+2), ['noop'])] return ergebnis_if Implementierung

69 Station - Code-Erzeuger
from uebersetzerWhileList import * # Testprogramm quellcode = [ ['=', ('VAR', 'x'), [('ZAHL', '24')]], ['=', ('VAR', 'y'), [('ZAHL', '15')]], ['=', ('VAR', 'd'), ['-', ('VAR', 'x'), ('VAR', 'y')]], # ... ] codeerzeuger = UebersetzerWhileList() # Erzeugung des Zielcodes codeerzeuger.setQuellcode(quellcode) zielcode = codeerzeuger.uebersetzen() # Ausführung des Programms und Ausgabe der Zustände print('Quellcode:') print() for zeile in quellcode: print(zeile) print('Zielcode:') for zeile in zielcode:

70 Aufgabe Aufgabe: Probiere das selbst einmal aus. Übersetze verschiedene strukturierte MyWhile-Programme.

71 Station - CodeInterpreter
Zuweisung ausführen [ (None, ['=', ('VAR', 'x'), [('NAT', '24')]]), (None, ['=', ('VAR', 'y'), [('NAT', '15')]]), (None, ['=', ('VAR', 'd'), ['-', ('VAR', 'x'), ('VAR', 'y')]]), ('.L3', ['noop']), (None, ['if', ['!=', ('VAR', 'd'), ('NAT', '0')], ['goto', '.L4'], ['goto', '.L5']]), ('.L4', ['noop']), (None, ['if', ['>', ('VAR', 'd'), ('NAT', '0')], ['goto', '.L0'], ['goto', '.L1']]), ('.L0', ['noop']), (None, ['=', ('VAR', 'x'), ['-', ('VAR', 'x'), ('VAR', 'y')]]), (None, ['goto', '.L2']), ('.L1', ['noop']), (None, ['=', ('VAR', 'y'), ['-', ('VAR', 'y'), ('VAR', 'x')]]), ('.L2', ['noop']), (None, ['goto', '.L3']), ('.L5', ['noop']) ] [ (None, ['=', ('VAR', 'x'), [('NAT', '24')]]), (None, ['=', ('VAR', 'y'), [('NAT', '15')]]), (None, ['=', ('VAR', 'd'), ['-', ('VAR', 'x'), ('VAR', 'y')]]), ('.L3', ['noop']), (None, ['if', ['!=', ('VAR', 'd'), ('NAT', '0')], ['goto', '.L4'], ['goto', '.L5']]), ('.L4', ['noop']), (None, ['if', ['>', ('VAR', 'd'), ('NAT', '0')], ['goto', '.L0'], ['goto', '.L1']]), ('.L0', ['noop']), (None, ['=', ('VAR', 'x'), ['-', ('VAR', 'x'), ('VAR', 'y')]]), (None, ['goto', '.L2']), ('.L1', ['noop']), (None, ['=', ('VAR', 'y'), ['-', ('VAR', 'y'), ('VAR', 'x')]]), ('.L2', ['noop']), (None, ['goto', '.L3']), ('.L5', ['noop']) ] pc -> 0 pc -> 1 Programmzähler Programmzähler { } { 'x' -> 1, } Variablenzustand Variablenzustand

72 Station - CodeInterpreter
Zuweisung ausführen >x=24 y=15 d=x-y label .L3 if d!=0: goto .L4 else: goto .L5 label .L4 if d>0: goto .L0 goto .L1 label .L0 x=x-y goto .L2 label .L1 y=y-x label .L2 goto .L3 label .L5 { } x=24 >y=15 d=x-y label .L3 if d!=0: goto .L4 else: goto .L5 label .L4 if d>0: goto .L0 goto .L1 label .L0 x=x-y goto .L2 label .L1 y=y-x label .L2 goto .L3 label .L5 { 'x' -> 24 }

73 Station - CodeInterpreter
bedingter Sprung ausführen x=24 y=15 d=x-y label .L3 >if d!=0: goto .L4 else: goto .L5 label .L4 if d>0: goto .L0 goto .L1 label .L0 x=x-y goto .L2 label .L1 y=y-x label .L2 goto .L3 label .L5 { 'x' -> 24, 'y' -> 15, 'd' -> 9 } x=24 >y=15 d=x-y label .L3 if d!=0: goto .L4 else: goto .L5 >label .L4 if d>0: goto .L0 goto .L1 label .L0 x=x-y goto .L2 label .L1 y=y-x label .L2 goto .L3 label .L5 { 'x' -> 24, 'y' -> 15, 'd' -> 9 }

74 Station - CodeInterpreter
unbedingter Sprung ausführen x=24 y=15 d=x-y label .L3 if d!=0: goto .L4 else: goto .L5 label .L4 if d>0: goto .L0 goto .L1 label .L0 x=x-y >goto .L2 label .L1 y=y-x label .L2 goto .L3 label .L5 { 'x' -> 9, 'y' -> 15, 'd' -> 9 } x=24 >y=15 d=x-y label .L3 if d!=0: goto .L4 else: goto .L5 label .L4 if d>0: goto .L0 goto .L1 label .L0 x=x-y goto .L2 label .L1 y=y-x >label .L2 goto .L3 label .L5 { 'x' -> 9, 'y' -> 15, 'd' -> 9 }

75 Station - Interpreter class InterpreterGoto(object): ...
def anweisungAusfuehren(self): if self.pc < len(self.programm): zeile = self.programm[self.pc] label = zeile[0] if label != None: self.pc = self.pc + 1 else: anweisung = zeile[1] if anweisung[0] == "=": self.verarbeiteZuweisung(anweisung) elif anweisung[0] == "if": if self.verarbeiteBedingung(anweisung[1]): self.verarbeiteGoto(anweisung[2]) self.verarbeiteGoto(anweisung[3]) elif anweisung[0] == "goto": self.verarbeiteGoto(anweisung) elif anweisung[0] == "noop": elif anweisung[0] == "stop": Implementierung

76 Station - Interpreter from interpreterGoto import *
from variablenzustand import * # Testprogramm programm = [ (None, ['=', ('VAR', 'x'), [('ZAHL', '24')]]), (None, ['=', ('VAR', 'y'), [('ZAHL', '15')]]), (None, ['=', ('VAR', 'd'), ['-', ('VAR', 'x'), ('VAR', 'y')]]), ('.L3', ['noop']), (None, ['if', ['!=', ('VAR', 'd'), ('ZAHL', '0')], ['goto', '.L4'], ['goto', '.L5']]), ('.L4', ['noop']), (None, ['if', ['>', ('VAR', 'd'), ('ZAHL', '0')], ['goto', '.L0'], ['goto', '.L1']]), ('.L0', ['noop']), ... ] # Erzeugung des Interpreters variablenzustand = Variablenzustand() interpreterGoto = InterpreterGoto(variablenzustand) # Initialisierung des Programms interpreterGoto.initProgramm(programm) # Ausführung des Programms und Ausgabe der Zustände print('Variablenzustand vorher') print(variablenzustand.variablen) print() while interpreterGoto.getPC() < len(interpreterGoto.getProgramm()): interpreterGoto.anweisungAusfuehren() print('Variablenzustand nachher')

77 Aufgabe Aufgabe: Probiere das selbst einmal aus. Teste verschiedene strukturierte MyGoto-Programme.

78 Station - Simulationsprogramm


Herunterladen ppt "Compiler und Interpreter"

Ähnliche Präsentationen


Google-Anzeigen