i

Station - Ein Code-Interpreter für strukturierte MyGoto-Programme

Aufgabe des Code-Interpreters

Der Code-Erzeuger hat die Aufgabe, strukturierte MyGoto-Programme auszuführen. Wir verdeutlichen die Ausführung an einem entsprechenden MyGoto-Programm.

Bei der Ausführung müssen der aktuelle Variablenzustand und die aktuelle Ausführungsstelle im Programm verwaltet werden. Zur Verwaltung der Ausführungsstelle wird hier ein sog. Programmzähler benutzt. Dieser Programmzähler wird im Folgenden durch das Symbol > gekennzeichnet.

Programm:

>x=24
y=15
d=x-y
label .L3
if d!=0:
    goto .L4
else:
    goto .L5
label .L4
if d>0:
    goto .L0
else:
    goto .L1
label .L0
x=x-y
goto .L2
label .L1
y=y-x
label .L2
d=x-y
goto .L3
label .L5

Variablenzustand:
{}

======================

Programm:

x=24
>y=15
d=x-y
label .L3
if d!=0:
    goto .L4
else:
    goto .L5
label .L4
if d>0:
    goto .L0
else:
    goto .L1
label .L0
x=x-y
goto .L2
label .L1
y=y-x
label .L2
d=x-y
goto .L3
label .L5

Variablenzustand:
{x -> 24}

======================

Programm:

x=24
y=15
>d=x-y
label .L3
if d!=0:
    goto .L4
else:
    goto .L5
label .L4
if d>0:
    goto .L0
else:
    goto .L1
label .L0
x=x-y
goto .L2
label .L1
y=y-x
label .L2
d=x-y
goto .L3
label .L5

Variablenzustand:
{x -> 24, y -> 15}

======================

Programm:

x=24
y=15
d=x-y
>label .L3
if d!=0:
    goto .L4
else:
    goto .L5
label .L4
if d>0:
    goto .L0
else:
    goto .L1
label .L0
x=x-y
goto .L2
label .L1
y=y-x
label .L2
d=x-y
goto .L3
label .L5

Variablenzustand:
{x -> 24, y -> 15, d -> 9}

======================

Programm:

x=24
y=15
d=x-y
label .L3
>if d!=0:
    goto .L4
else:
    goto .L5
label .L4
if d>0:
    goto .L0
else:
    goto .L1
label .L0
x=x-y
goto .L2
label .L1
y=y-x
label .L2
d=x-y
goto .L3
label .L5

Variablenzustand:
{x -> 24, y -> 15, d -> 9}

======================

Programm:

x=24
y=15
d=x-y
label .L3
if d!=0:
    goto .L4
else:
    goto .L5
>label .L4
if d>0:
    goto .L0
else:
    goto .L1
label .L0
x=x-y
goto .L2
label .L1
y=y-x
label .L2
d=x-y
goto .L3
label .L5

Variablenzustand:
{x -> 24, y -> 15, d -> 9}

======================

...

======================

Programm:

x=24
y=15
d=x-y
label .L3
if d!=0:
    goto .L4
else:
    goto .L5
label .L4
if d>0:
    goto .L0
else:
    goto .L1
label .L0
x=x-y
goto .L2
label .L1
y=y-x
label .L2
d=x-y
goto .L3
>label .L5

Variablenzustand:
{x -> 3, y -> 3, d -> 0}

Alles klar?

Implementierung des Code-Interpreters

Zur Verwaltung des Variablenzustans wird ein Objekt der Klasse Variablenzustand benutzt. Dieses Objekt stellt Operationen bereit, mit denen ein Variablenwert ermittelt und auch ein Variablenwert neu gesetzt werden kann.

class Variablenzustand(object):
    def __init__(self):
        self.variablen = {}

    def initVariablen(self):
        self.variablen = {}

    def getVariable(self, bezeichner):
        return self.variablen[bezeichner]

    def setVariable(self, bezeichner, wert):
        self.variablen[bezeichner] = wert

Der Code-Interpreter wird durch ein Objekt der Klasse InterpreterGoto realisiert. Dieses Objekt verfügt insbesondere über eine Methode anweisungAusfuehren, die letztlich für das Auswerten von Anweisungen zuständig ist.

class InterpreterGoto(object):
    def __init__(self, v):
        self.programm = None
        self.pc = 0
        self.variablenzustand = v

    def initProgramm(self, p):
        self.programm = p
        self.pc = 0

    def getProgramm(self):
        return self.programm

    def getPC(self):
        return self.pc

    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

    def verarbeiteZuweisung(self, anweisung):
        variable = anweisung[1][1]
        term = anweisung[2]
        self.variablenzustand.setVariable(variable, self.wertTerm(term))

    def verarbeiteGoto(self, anweisung):
        label = anweisung[1]
        self.pc = 0
        while self.programm[self.pc][0] != label:
            self.pc = self.pc + 1
            
    def wertOperand(self, operand):
        if operand[0] == "ZAHL":
            return int(operand[1])
        elif operand[0] == "VAR":
            return self.variablenzustand.getVariable(operand[1])

    def wertTerm(self, term):
        if len(term) == 1:
            return self.wertOperand(term[0])
        else:
            wertOperand1 = self.wertOperand(term[1])
            wertOperand2 = self.wertOperand(term[2])
            op = term[0]
            if op == "+":
                return wertOperand1 + wertOperand2
            elif op == "-":
                return wertOperand1 - wertOperand2

    def verarbeiteBedingung(self, bedingung):
        wertOperand1 = self.wertOperand(bedingung[1])
        wertOperand2 = self.wertOperand(bedingung[2])
        rel = bedingung[0]
        if rel == "!=":
            return (wertOperand1 != wertOperand2)
        elif rel == ">":
            return (wertOperand1 > wertOperand2)
        elif rel == "<":
            return (wertOperand1 < wertOperand2)
        elif rel == "==":
            return (wertOperand1 == wertOperand2)

Objekte der vorgestellten Klassen können jetzt direkt genutzt werden, um strukturierte Goto-Programme auszuführen.

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

# 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')
print(variablenzustand.variablen)

Aufgabe 1

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

Suche

v
4.3.5.8
dev.inf-schule.de/automaten-sprachen/interpretercompiler/compilerwhile/station_codeinterpreter
dev.inf-schule.de/4.3.5.8
dev.inf-schule.de/@/page/swMUgpAHJZ2wRDKq

Rückmeldung geben