Station - Ein Code-Erzeuger für strukturierte MyKa-Programme
Aufgabe des Code-Erzeugers
Der Code-Erzeuger hat die Aufgabe, (strukturierte) MyKa-Programme in (strukturierte) MyKaGoto-Programme zu übersetzen. Die Arbeitsweise des Code-Erzeugers soll am folgenden Beispiel-Programm verdeutlicht werden.
Aus einer strukturierten Darstellung des MyKa-Programms
links while nichtVorWand: ziegelHinlegen schritt #while
soll eine strukturierte Darstellung des folgenden MyKaGoto-Programms erzeugt werden:
links label .L0 if nichtVorWand: goto .L1 else: goto .L2 label .L1 ziegelHinlegen schritt goto .L0 label .L2
Der Code-Erzeuger verarbeitet als Quellcode also eine Listen-Darstellung des MyKa-Programms.
[
    ['links'], 
    ['while', 
        ['nichtVorWand'], 
        [
            ['ziegelHinlegen'], 
            ['schritt']
        ]
    ]
]
Diesen Quellcode transformiert der Code-Erzeuger in ein strukturiertes MyKaGoto-Programm.
[
(None, ['links']),
('.L0', ['noop']),
(None, ['if', ['nichtVorWand'], ['goto', '.L1'], ['goto', '.L2']]),
('.L1', ['noop']),
(None, ['ziegelHinlegen']),
(None, ['schritt']),
(None, ['goto', '.L0']),
('.L2', ['noop'])
]
Implementierung des Code-Erzeugers
Der Code-Erzeuger wird durch ein Objekt der Klasse UebersetzerWhileList realisiert.
Dieses Objekt verfügt insbesondere über eine Methode uebersetzen, die 
letztlich für die Erzeugung des Zielcodes zuständig ist.
class UebersetzerMyKaList(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 : ELANW
                         | PASS
                         | WHILE bedingung DP anweisungsfolge ENDWH
                         | IF bedingung DP anweisungsfolge ELSE DP anweisungsfolge ENDIF'''
            if p[0] in ["schritt",
                        "links",
                        "rechts",
                        "ziegelHinlegen",
                        "ziegelAufheben",
                        "markeSetzen",
                        "markeLoeschen",
                        "pass"]:
                return [(None, p)]
            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
        self.zaehler = 0
        if self.quellcode != []:
            return c_programm(self.quellcode)
        else:
            return [(0, "p")]
Ein Objekt der Klasse UebersetzerMyKaList kann also benutzt werden, um strukturierte
While-Programme in strukturierte Goto-Programme zu übersetzen.
from uebersetzerMyKaList import *
# Testprogramm
quellcode = [
    ['links'], 
    ['while', 
        ['nichtVorWand'], 
        [
            ['ziegelHinlegen'], 
            ['schritt']
        ]
    ]
]
codeerzeuger = UebersetzerMyKaList()
# 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()
print('Zielcode:')
print()
for zeile in zielcode:
    print(zeile)
Aufgabe 1
Probiere das selbst einmal aus. Teste verschiedene strukturierte MyKa-Programme.