Logo des digitalen Schulbuchs inf-schule.de. Schriftzug in Zustandsübergangsdiagramm eines endlichen Automaten.

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.

X

Fehler melden

X

Suche