compiler und interpreter

Post on 15-Jan-2016

45 Views

Category:

Documents

0 Downloads

Preview:

Click to see full reader

DESCRIPTION

Compiler und Interpreter. Klaus Becker 2010. Compiler und Interpreter. Teil 1. Syntax und Semantik im Überblick. Karol / Myka. Karol. MyKa(rol). Aufgabe. links while nichtVorWand: ziegelHinlegen schritt #while. if nichtVorWand: if nichtVorZiegel: schritt schritt - PowerPoint PPT Presentation

TRANSCRIPT

Compiler und Interpreter

Klaus Becker

2010

2 Compiler und Interpreter

3 Teil 1

Syntax und Semantik im Überblick

4 Karol / Myka

Karol

MyKa(rol)

5 Aufgabe

Versuche anhand weiterer Tests die Regeln der Sprache MyKa herauszufinden:

(a) Wie können Programme der Sprache aufgebaut werden?

linkswhile nichtVorWand: ziegelHinlegen schritt#while

if nichtVorWand: if nichtVorZiegel: schritt schritt schritt schritt else: ziegelHinlegen #ifelse: links#if

markeSetzenschrittwhile nichtAufMarke: while nichtVorWand: schritt #while links#while

6 Aufgabe

Versuche anhand weiterer Tests die Regeln der Sprache MyKa herauszufinden:

(b) Welche Bedeutung haben die Sprachkonstrukte?

linkswhile nichtVorWand: ziegelHinlegen schritt#while

if nichtVorWand: if nichtVorZiegel: schritt schritt schritt schritt else: ziegelHinlegen #ifelse: links#if

markeSetzenschrittwhile nichtAufMarke: while nichtVorWand: schritt #while links#while

7 Exkurs - MyKalinkswhile nichtVorWand: ziegelHinlegen schritt#while

if nichtVorWand: if nichtVorZiegel: schritt schritt schritt schritt else: ziegelHinlegen #ifelse: links#if

markeSetzenschrittwhile nichtAufMarke: while nichtVorWand: schritt #while links#while

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

8 Exkurs - MyKalinkswhile nichtVorWand: ziegelHinlegen schritt#while

if nichtVorWand: if nichtVorZiegel: schritt schritt schritt schritt else: ziegelHinlegen #ifelse: links#if

markeSetzenschrittwhile nichtAufMarke: while nichtVorWand: schritt #while links#while

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?

9 Exkurs - MyKalinkswhile nichtVorWand: ziegelHinlegen schritt#while

if nichtVorWand: if nichtVorZiegel: schritt schritt schritt schritt else: ziegelHinlegen #ifelse: links#if

markeSetzenschrittwhile nichtAufMarke: while nichtVorWand: schritt #while links#while

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.

10 Exkurs - MyKalinkswhile nichtVorWand: ziegelHinlegen schritt#while

if nichtVorWand: if nichtVorZiegel: schritt schritt schritt schritt else: ziegelHinlegen #ifelse: links#if

markeSetzenschrittwhile nichtAufMarke: while nichtVorWand: schritt #while links#while

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.

11 Fachkonzept - Syntax

Die Syntax einer Sprache beschreibt, welche Kombinationen von Zeichen fehlerfreie Programme der Sprache bilden.

myka_syn = {Programm1, Programm2, ...}

Programmx

linkswhile nichtVorWand: ziegelHinlegen schritt#while

if nichtVorWand: if nichtVorZiegel: schritt schritt schritt schritt else: ziegelHinlegen #ifelse: links#if

markeSetzenschrittwhile nichtAufMarke: while nichtVorWand: schritt #while links#while

Eine Präzisierung dieser Menge kann z.B. mit Hilfe einer Grammatik vorgenommen werden.

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 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

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.

linkswhile nichtVorWand: ziegelHinlegen schritt#while

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 Teil 3

Interpreter und Compiler im Überblick

20 Myka

Ausführung von

MyKaList-Programmen

Übersetzen von

MyKaList-Programmen

21 Aufgabe

Ausführung von

MyKaList-Programmen

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.

22 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 - MyKaGotolinkswhile nichtVorWand: ziegelHinlegen schritt#while

linkslabel .L0if nichtVorWand: goto .L1else: goto .L2label .L1ziegelHinlegenschrittgoto .L0label .L2

[(None, ['links'])('.L0', ['noop'])(None, ['if', ['nichtVorWand'], ['goto', '.L1'], ['goto', '.L2']])('.L1', ['noop'])(None, ['ziegelHinlegen'])(None, ['schritt'])(None, ['goto', '.L0'])('.L2', ['noop'])]

MyKa-Programm

MyKaGoto-Programm

strukturiertes MyKaGoto-Programm

benutzt Kontrollstruktur

en

benutzt Sprungbefehle

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.

linkswhile 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 Teil 4

Entwicklung eines Compilers - MyWhile

28 Station - MyWhile

x = 24y = 15d = x - ywhile d != 0: if d > 0: x = x - y else: y = y - x #if d = x - y#while

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.

29 Station - MyWhileelem. 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"

Bedingung

x == 0

zahl != 0

x2 > 0

y < 0

Struktur

"Variable" == 0

"Variable" != 0

"Variable" > 0

"Variable" < 0

x = 24y = 15d = x - ywhile d != 0: if d > 0: x = x - y else: y = y - x #if d = x - y#while

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 - MyWhilex = 24y = 15d = x - ywhile d != 0: if d > 0: x = x - y else: y = y - x #if d = x - y#while

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.

31 Aufgabe

x=24 y=15 d=x-ywhile d != 0 : if d > 0 :x = x - yelse: y=y-x#ifd=x-y#while

Ist das folgende Programm ein syntaktisch korrektes MyWhile-Programm?

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 = 24y = 15d = x - ywhile d != 0: if d > 0: x = x - y else: y = y - x #if d = x - y#while

(VAR,'x')(ZUW,'=')(ZAHL,'24')(VAR,'y')(ZUW,'=')(ZAHL,'15')(VAR,'d')(ZUW,'=')(VAR,'x')(MINUS,'-')(VAR,'y')(WHILE,'while')(VAR,'d')(UG,'!=')(NULL,'0')(DP,':')...

Scanner

Quelltext

Tokenfolge / Fehlermeldung

34 Station - Scanner# Beschreibung der Tokent_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')(ZUW,'=')(ZAHL,'15')(VAR,'d')(ZUW,'=')(VAR,'x')(MINUS,'-')(VAR,'y')(WHILE,'while')(VAR,'d')(UG,'!=')(NULL,'0')(DP,':')(IF,'if')...

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. 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 Tokent_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')(ZUW,'=')(ZAHL,'15')(VAR,'d')(ZUW,'=')(VAR,'x')(MINUS,'-')(VAR,'y')(WHILE,'while')(VAR,'d')(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 Station - Scanner# reservierte Wörterreserved = { 'if' : 'IF', 'else' : 'ELSE', 'while' : 'WHILE', 'pass': 'PASS'}

# Namen der Tokentokens = ['VAR', 'ZAHL', 'NULL', 'ZUW', 'PLUS', 'MINUS', 'GL', 'UG', 'GR', 'KL', 'DP', 'ENDWH', 'ENDIF']tokens = tokens + list(reserved.values())

# Beschreibung der Tokendef t_VAR(t): r'[a-z][a-z0-9]*' t.type = reserved.get(t.value, 'VAR') # Überprüfung auf reservierte Wörter return tt_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 - Scannerimport ply.lex as lexfrom syntaxWhile import *# Testprogrammprogramm = '''x = 24y = 15d = x - ywhile d != 0: if d > 0: x = x - y else: y = y - x #if d = x - y#while'''

# Erzeugung des Scannersscanner = lex.lex(debug=0)

# lexikalische Analyse mit Erzeugung der Tokenscanner.input(programm)token = []tok = scanner.token()while tok: token = token + [tok] tok = scanner.token()

# Ausgabefor 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; }; d = x - y;};

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

ok

Tokenfolge

Struktur / Fehlermeldung

(VAR,'x')(ZUW,'=')(ZAHL,'24')(VAR,'y')(ZUW,'=')(ZAHL,'15')(VAR,'d')(ZUW,'=')(VAR,'x')(MINUS,'-')(VAR,'y')(WHILE,'while')(VAR,'d')(UG,'!=')(NULL,'0')(DP,':')...

41 Station - Parser / Syntaxanalyse

x = 24y = 15d = x - ywhile d != 0: if d > 0: x = x - y else: y = y - x #if d = x - y#while

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.

VAR ZUW ZAHLVAR ZUW ZAHLVAR ZUW VAR MINUS VARWHILE VAR UG NULL DP IF VAR GR NULL DP VAR ZUW VAR MINUS VAR ELSE DP VAR ZUW VAR MINUS VAR ENDIF VAR ZUW VAR MINUS VARENDWH

# Produktionen

anweisungsfolge -> anweisung anweisungsfolgeanweisungsfolge -> anweisunganweisung -> zuweisunganweisung -> PASSanweisung -> WHILE bedingung DP anweisungsfolge ENDWHanweisung -> IF bedingung DP anweisungsfolge ELSE DP anweisungsfolge ENDIFzuweisung -> VAR ZUW termterm -> VAR op zahlterm -> VAR op VARterm -> zahlterm -> VARzahl -> NULLzahl -> ZAHLop -> PLUSop -> MINUSbedingung -> VAR rel NULLrel -> GLrel -> UGrel -> GRrel -> KL

Grammatik von MyWhile

42 Aufgabe

x = 4while x > 0: x = x - 1#while

Aufgabe:

Zeige, dass man mit den Produktionen der Grammatik eine Ableitung der Tokenfolge zum Demo-Programm erzeugen kann.

VAR ZUW ZAHLWHILE VAR GR NULL DP VAR ZUW VAR MINUS ZAHLENDWH

# Produktionen

anweisungsfolge -> anweisung anweisungsfolgeanweisungsfolge -> anweisunganweisung -> zuweisunganweisung -> PASSanweisung -> WHILE bedingung DP anweisungsfolge ENDWHanweisung -> IF bedingung DP anweisungsfolge ELSE DP anweisungsfolge ENDIFzuweisung -> VAR ZUW termterm -> VAR op zahlterm -> VAR op VARterm -> zahlterm -> VARzahl -> NULLzahl -> ZAHLop -> PLUSop -> MINUSbedingung -> VAR rel NULLrel -> GLrel -> UGrel -> GRrel -> KL

Grammatik von MyWhile

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

YACC-Implementierung

anweisungsfolge -> anweisung anweisungsfolgeanweisungsfolge -> anweisunganweisung -> zuweisunganweisung -> PASSanweisung -> WHILE bedingung DP anweisungsfolge ENDWHanweisung -> IF bedingung DP anweisungsfolge ELSE DP anweisungsfolge ENDIFzuweisung -> VAR ZUW termterm -> VAR op ZAHLterm -> VAR op VARterm -> zahl...

44 Station - Parser / Syntaxanalyseimport ply.lex as leximport ply.yacc as yaccfrom syntaxWhile import *

# Testprogrammprogramm = '''x = 24y = 15d = x - ywhile d != 0: if d > 0: x = x - y else: y = y - x #if d = x - y#while'''

# Erzeugung des Scannersscanner = lex.lex(debug=0)# Erzeugung des Parsersparser = yacc.yacc(debug=False)

# syntaktische Analyse parser.parse(programm, debug=0)

# Ausgabeprint("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; }; d = x - y;};

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')]] ] ]]

Tokenfolge

Struktur / Fehlermeldung

(VAR,'x')(ZUW,'=')(ZAHL,'24')(VAR,'y')(ZUW,'=')(ZAHL,'15')(VAR,'d')(ZUW,'=')(VAR,'x')(MINUS,'-')(VAR,'y')(WHILE,'while')(VAR,'d')(UG,'!=')(NULL,'0')(DP,':')...

48 Station - Parser / Strukturgerüst

Idee: Die Grammatikregeln werden um Beschreibungen zur Erzeugung des Strukturgerüsts erweitert.

# Produktionen

anweisungsfolge -> anweisung anweisungsfolgeanweisungsfolge -> anweisunganweisung -> zuweisunganweisung -> PASSanweisung -> WHILE bedingung DP anweisungsfolge ENDWHanweisung -> IF bedingung DP anweisungsfolge ELSE DP anweisungsfolge ENDIFzuweisung -> VAR ZUW termterm -> VAR op zahlterm -> VAR op VARterm -> zahlterm -> VARzahl -> NULLzahl -> ZAHLop -> PLUSop -> MINUSbedingung -> VAR rel NULLrel -> GLrel -> UGrel -> GRrel -> KL

# erweiterte Produktionen...

zahl -> ZAHL | |p[0] p[1]p[0] = p[1]

term -> zahl | |p[0] p[1]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]p[0] = p[1]

49

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 -> zuweisungzuweisung WHILE VAR GR NULL DP VAR ZUW VAR MINUS ZAHL ENDWH -> # zuweisung -> VAR ZUW termVAR ZUW term WHILE VAR GR NULL DP VAR ZUW VAR MINUS ZAHL ENDWH -> # term -> zahlVAR ZUW zahl WHILE VAR GR NULL DP VAR ZUW VAR MINUS ZAHL ENDWH -> # zahl -> ZAHLVAR ZUW ZAHL WHILE VAR GR NULL DP VAR ZUW VAR MINUS ZAHL ENDWH

Station - Parser / Strukturgerüst

x = 4while x > 0: x = x - 1#while

VAR ZUW ZAHLWHILE VAR GR NULL DP VAR ZUW VAR MINUS ZAHLENDWH

Rechtsableitung der Tokenfolge

Quelltext

Tokenfolge

Grammatikregeln

50 Station - Parser / Strukturgerüst

Grammatik von MyWhile

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] p[1]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 = 4while x > 0: x = x - 1#while

VAR ZUW ZAHLWHILE VAR GR NULL DP VAR ZUW VAR MINUS ZAHLENDWH

[ ['=', ('VAR', 'x'), [('ZAHL', '4')]], ['while', ['>', ('VAR', 'x'), ('ZAHL', '0')], [ ['=', ('VAR', 'x'), ['-', ('VAR', 'x'), ('ZAHL', '1')]] ] ]]

erweiterte Grammatikregel

produzierte Struktur

Rechtsableitung der Tokenfolge ( rückwärts

betrachtet) - erweitert um die Erzeugung des Strukturgerüsts

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' p[0] = [p[1]]

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üstimport ply.lex as leximport ply.yacc as yaccfrom syntaxWhile import *

# Testprogrammprogramm = '''x = 4while x > 0: x = x - 1#while'''

# Erzeugung des Scannersscanner = lex.lex(debug=0)# Erzeugung des Parsersparser = yacc.yacc(debug=False)

# syntaktische Analyse mit Erzeugung des Strukturbaumsif len(programm) != 0: strukturbaum = parser.parse(programm, debug=0)else: strukturbaum = []

# Ausgabeprint(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.

Parser

[ ['=', ('VAR', 'x'), [('ZAHL', '4')]], ['while', ['>', ('VAR', 'x'), ('ZAHL', '0')], [ ['=', ('VAR', 'x'), ['-', ('VAR', 'x'), ('ZAHL', '1')]] ] ]]

Tokenfolge

Struktur / Fehlermeldung

(VAR,'x')(ZUW,'=')(ZAHL,'4')(SEM, ';')(WHILE,'while')(KL_AUF, '(')(VAR, 'X')(GR, '>')(NULL, '0')(KL_ZU, ')')(WH_BEGINN, '{')...

x = 4;while (x > 0) { x = x - 1;};

55 Station - Interpreter

[ ['=', ('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

Variablenzustand

Zuweisung ausführen

neues Restprogramm

neuer Variablenzustand

56 Station - Interpreter

[ ['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')]] ] ]]{'x' -> 24, 'y' -> 15, 'd' -> 9}

[ ['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')], [ ['if', ['>', ('VAR', 'd'), ('NAT', '0')], [ ['=', ('VAR', 'x'), ['-', ('VAR', 'x'), ('VAR', 'y')]] ], [ ['=', ('VAR', 'y'), ['-', ('VAR', 'y'), ('VAR', 'x')]] ] ], ['=', ('VAR', 'd'), ['-', ('VAR', 'x'), ('VAR', 'y')]] ] ]]

{'x' -> 24, 'y' -> 15, 'd' -> 9}

Wiederholung ausführen

Bedingung

True

57 Station - Interpreter

[ ['if', ['>', ('VAR', 'd'), ('NAT', '0')], [ ['=', ('VAR', 'x'), ['-', ('VAR', 'x'), ('VAR', 'y')]] ], [ ['=', ('VAR', 'y'), ['-', ('VAR', 'y'), ('VAR', 'x')]] ] ], ['=', ('VAR', 'd'), ['-', ('VAR', 'x'), ('VAR', 'y')]], ...]{'x' -> 24, 'y' -> 15, 'd' -> 9}

[ ['=', ('VAR', 'x'), ['-', ('VAR', 'x'), ('VAR', 'y')]], ['=', ('VAR', 'd'), ['-', ('VAR', 'x'), ('VAR', 'y')]], ...]

{'x' -> 24, 'y' -> 15, 'd' -> 9}

Fallunterscheidung ausführen

Bedingung

True

58 Station - Interpreter

[ ['if', ['>', ('VAR', 'd'), ('NAT', '0')], [ ['=', ('VAR', 'x'), ['-', ('VAR', 'x'), ('VAR', 'y')]] ], [ ['=', ('VAR', 'y'), ['-', ('VAR', 'y'), ('VAR', 'x')]] ] ], ['=', ('VAR', 'd'), ['-', ('VAR', 'x'), ('VAR', 'y')]], ...]{'x' -> 9, 'y' -> 15, 'd' -> -6}

[ ['=', ('VAR', 'y'), ['-', ('VAR', 'y'), ('VAR', 'x')]], ['=', ('VAR', 'd'), ['-', ('VAR', 'x'), ('VAR', 'y')]], ...]

{'x' -> 9, 'y' -> 15, 'd' -> -6}

Fallunterscheidung ausführen

Bedingung

False

59 Station - Interpreter

[ ['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')]] ] ]]{'x' -> 3, 'y' -> 3, 'd' -> 0}

[]

{'x' -> 3, 'y' -> 3, 'd' -> 0}

Wiederholung ausführen

Bedingung

False

60 Station - Interpreterclass 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": self.programm = self.programm[1:] elif bezeichner == "while": bedingung = anweisung[1] if self.verarbeiteBedingung(bedingung): self.programm = anweisung[2] + self.programm else: self.programm = self.programm[1:] elif bezeichner == "if": bedingung = anweisung[1] if self.verarbeiteBedingung(bedingung): self.programm = anweisung[2] + self.programm[1:] else: self.programm = anweisung[3] + self.programm[1:]

...

Implementierung

61 Station - Interpreterfrom variablenzustand import *

# Testprogrammprogramm = [ ['=', ('VAR', 'x'), [('ZAHL', '24')]], ['=', ('VAR', 'y'), [('ZAHL', '15')]], ['=', ('VAR', 'd'), ['-', ('VAR', 'x'), ('VAR', 'y')]], #...]

# Erzeugung des Interpretersvariablenzustand = Variablenzustand()interpreter = InterpreterWhileList(variablenzustand)# Initialisierung des Programmsinterpreter.setProgramm(programm)

# Ausführung des Programms und Ausgabe der Zuständeprint('Programm:')print(interpreter.programm)print('Variablenzustand')print(variablenzustand.variablen)print('---------------------------')while interpreter.getProgramm() != []: interpreter.anweisungAusfuehren() print('Programm:') print(interpreter.programm) print('Variablenzustand') print(variablenzustand.variablen) print('---------------------------')

62 Aufgabe

Aufgabe:

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

63 Station - Code-Erzeuger

[(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, ['=', ('VAR', 'd'), ['-', ('VAR', 'x'), ('VAR', 'y')]]),(None, ['goto', '.L3']),('.L5', ['noop'])]

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

[ ['=', ('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')]] ] ]]

Quellcode Zielcode

64 Station - Code-Erzeuger

[(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, ['=', ('VAR', 'd'), ['-', ('VAR', 'x'), ('VAR', 'y')]]),(None, ['goto', '.L3']),('.L5', ['noop'])]

[ ['=', ('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')]] ] ]]

Quellcode Zielcode

x = 24y = 15d = x - ywhile d != 0: if d > 0: x = x - y else: y = y - x #if d = x - y#while

x=24y=15d=x-ylabel .L3if d!=0: goto .L4else: goto .L5label .L4if d>0: goto .L0else: goto .L1label .L0x=x-ygoto .L2label .L1y=y-xlabel .L2d=x-ygoto .L3label .L5

65 Station - Code-Erzeuger

x = 1if x1 != 0: y = xelse: y = 0#if

x=1if x1!=0: # Auswertung der Bedingung goto .L0 # Sprung zum wahr-Fallelse: goto .L1 # Sprung zum falsch-Falllabel .L0 # wahr-Fally=xgoto .L2 # Sprung zum Ende der Fallunterscheidunglabel .L1 # wahr-Fally=0label .L2 # Ende der Fallunterscheidung

Fallunterscheidung übersetzen

66 Station - Code-Erzeuger

x = 5while x != 0: x = x - 1#while

x=5label .L0 # Beginn der Schleifeif x!=0: # Auswertung der Bedingung goto .L1 # Sprung zum Schleifenkörperelse: goto .L2 # Sprung aus der Schleifelabel .L1 # Beginn des Schleifenkörpersx=x-1goto .L0 # Sprung zum Beginn der schleifelabel .L2 # Ende der Schleife

Wiederholung übersetzen

67 Station - Code-Erzeugerclass 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) else: 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_true = c_anweisungsfolge(p[2]) 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'])] + \ ergebnis_true + \ [(None, ['goto', '.L' + str(self.zaehler+2)])] + \ [('.L' + str(self.zaehler+1), ['noop'])]+ \ ergebnis_false + \ [('.L' + str(self.zaehler+2), ['noop'])] self.zaehler = self.zaehler + 3 return ergebnis_if...

Implementierung

69 Station - Code-Erzeugerfrom uebersetzerWhileList import *

# Testprogrammquellcode = [ ['=', ('VAR', 'x'), [('ZAHL', '24')]], ['=', ('VAR', 'y'), [('ZAHL', '15')]], ['=', ('VAR', 'd'), ['-', ('VAR', 'x'), ('VAR', 'y')]], # ...]codeerzeuger = UebersetzerWhileList()# Erzeugung des Zielcodescodeerzeuger.setQuellcode(quellcode)zielcode = codeerzeuger.uebersetzen()# Ausführung des Programms und Ausgabe der Zuständeprint('Quellcode:')print()for zeile in quellcode: print(zeile)print()print('Zielcode:')print()for zeile in zielcode: print(zeile)

70 Aufgabe

Aufgabe:

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

71 Station - CodeInterpreter

[(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, ['=', ('VAR', 'd'), ['-', ('VAR', 'x'), ('VAR', 'y')]]),(None, ['goto', '.L3']),('.L5', ['noop'])]pc -> 0

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, ['=', ('VAR', 'd'), ['-', ('VAR', 'x'), ('VAR', 'y')]]),(None, ['goto', '.L3']),('.L5', ['noop'])]pc -> 1

{'x' -> 1,}

Programmzähler

Variablenzustand

Programmzähler

Variablenzustand

72 Station - CodeInterpreter

>x=24y=15d=x-ylabel .L3if d!=0: goto .L4else: goto .L5label .L4if d>0: goto .L0else: goto .L1label .L0x=x-ygoto .L2label .L1y=y-xlabel .L2d=x-ygoto .L3label .L5

{}

Zuweisung ausführen

x=24>y=15d=x-ylabel .L3if d!=0: goto .L4else: goto .L5label .L4if d>0: goto .L0else: goto .L1label .L0x=x-ygoto .L2label .L1y=y-xlabel .L2d=x-ygoto .L3label .L5

{'x' -> 24}

73 Station - CodeInterpreter

x=24y=15d=x-ylabel .L3>if d!=0: goto .L4else: goto .L5label .L4if d>0: goto .L0else: goto .L1label .L0x=x-ygoto .L2label .L1y=y-xlabel .L2d=x-ygoto .L3label .L5

{'x' -> 24, 'y' -> 15, 'd' -> 9}

bedingter Sprung ausführen

x=24>y=15d=x-ylabel .L3if d!=0: goto .L4else: goto .L5>label .L4if d>0: goto .L0else: goto .L1label .L0x=x-ygoto .L2label .L1y=y-xlabel .L2d=x-ygoto .L3label .L5

{'x' -> 24, 'y' -> 15, 'd' -> 9}

74 Station - CodeInterpreter

x=24y=15d=x-ylabel .L3if d!=0: goto .L4else: goto .L5label .L4if d>0: goto .L0else: goto .L1label .L0x=x-y>goto .L2label .L1y=y-xlabel .L2d=x-ygoto .L3label .L5

{'x' -> 9, 'y' -> 15, 'd' -> 9}

unbedingter Sprung ausführen

x=24>y=15d=x-ylabel .L3if d!=0: goto .L4else: goto .L5label .L4if d>0: goto .L0else: goto .L1label .L0x=x-ygoto .L2label .L1y=y-x>label .L2d=x-ygoto .L3label .L5

{'x' -> 9, 'y' -> 15, 'd' -> 9}

75 Station - Interpreterclass 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) self.pc = self.pc + 1 elif anweisung[0] == "if": if self.verarbeiteBedingung(anweisung[1]): self.verarbeiteGoto(anweisung[2]) else: self.verarbeiteGoto(anweisung[3]) elif anweisung[0] == "goto": self.verarbeiteGoto(anweisung) elif anweisung[0] == "noop": self.pc = self.pc + 1 elif anweisung[0] == "stop": self.pc = self.pc + 1

...

Implementierung

76 Station - Interpreterfrom interpreterGoto import *from variablenzustand import *

# Testprogrammprogramm = [(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 Interpretersvariablenzustand = Variablenzustand()interpreterGoto = InterpreterGoto(variablenzustand)# Initialisierung des ProgrammsinterpreterGoto.initProgramm(programm)

# Ausführung des Programms und Ausgabe der Zuständeprint('Variablenzustand vorher')print(variablenzustand.variablen)print()while interpreterGoto.getPC() < len(interpreterGoto.getProgramm()): interpreterGoto.anweisungAusfuehren()print('Variablenzustand nachher')print(variablenzustand.variablen)

77 Aufgabe

Aufgabe:

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

78 Station - Simulationsprogramm

top related