Skip to content
Snippets Groups Projects
Commit be48016d authored by Chris's avatar Chris
Browse files

LOOP-Interpreter zu Klasse gemacht

parent d5d1fc95
No related branches found
No related tags found
1 merge request!1Master
import lexer
import sys
import operator
import re
regex_to_token = [(re.compile(r'\d+'), 'NUMBER'),
(re.compile(r'x\d+'), 'IDENTIFIER'),
(re.compile(r'\+'), 'PLUS'),
(re.compile(r'-'), 'MINUS'),
(re.compile(r':=|≔'), 'EQUALS'),
(re.compile(r'LOOP'), 'LOOP'),
(re.compile(r'DO'), 'DO'),
(re.compile(r'END'), 'END'),
(re.compile(r';'), 'SEMICOLON'),
(re.compile(r'BREAK'), 'BREAK'),
(re.compile(r'\n', re.MULTILINE), 'LINEBREAK'),
(re.compile(r'\s+'), 'WHITESPACE'),
(re.compile(r'[^\n]*'), 'UNKNOWN')]
global error_handler, lex, values
class ErrorHandler:
def __init__(self, program):
sys.tracebacklimit = 0
self.program = program
self.line_number = 0
def handle_error(self, message):
msg = ["Fehler in Zeile " + str(self.line_number + 1),
self.program.split("\n")[self.line_number],
message]
raise SyntaxError("\n".join(msg)) from None
def increase_line(self):
self.line_number += 1
def handle_break(self):
print("BREAK in Zeile " + str(self.line_number))
print("Aktueller Zustand:")
for k, v in values.items():
print("Variable " + k + ": " + str(v))
user_input = input("Drücke ENTER zum Fotfahren oder schreibe EXIT zum Beenden:")
if user_input.lower() == 'exit':
raise KeyboardInterrupt
def process_assignment(forbidden_identifiers, identifier_token_1):
global values
identifier_1 = identifier_token_1.v
if identifier_1 in forbidden_identifiers:
error_handler.handle_error("Identifier " + identifier_1 +
" ist bereits in Loop vorhanden und darf nicht verwendet werden.")
if not next_nonempty_token("Zuweisung", ":=").k == 'EQUALS':
error_handler.handle_error(":= in Zuweisung erwartet.")
identifier_token_2 = next_nonempty_token("Zuweisung", "IDENTIFIER (x0, x1, ...) oder NUMBER")
if identifier_token_2.k == 'NUMBER':
value_1 = int(identifier_token_2.v)
values.update({identifier_token_1.v: value_1})
return next_token()
if not identifier_token_2.k == 'IDENTIFIER':
error_handler.handle_error("IDENTIFIER in Zuweisung erwartet.")
identifier_2 = identifier_token_2.v
if identifier_2 in forbidden_identifiers:
error_handler.handle_error("Identifier " + identifier_2 +
" ist bereits in Loop vorhanden und darf nicht verwendet werden.")
if identifier_2 in values:
value_2 = values.get(identifier_2)
else:
value_2 = 0
operator_token = next_nonempty_token("Zuweisung", "+ oder -")
op = None
if operator_token.k == 'PLUS':
op = operator.__add__
elif operator_token.k == 'MINUS':
op = operator.__sub__
else:
error_handler.handle_error("+ oder - in Zuweisung erwartet.")
number_token = next_nonempty_token("Zuweisung", "NUMBER")
if not number_token.k == 'NUMBER':
error_handler.handle_error("NUMBER in Zuweisung erwartet.")
value_1 = max(0, op(value_2, int(number_token.v)))
values.update({identifier_1: value_1})
return next_token()
def verify_assignment(forbidden_identifiers, identifier_token_1):
identifier_1 = identifier_token_1.v
if identifier_1 in forbidden_identifiers:
error_handler.handle_error("Identifier " + identifier_1 +
" ist bereits in Loop vorhanden und darf nicht verwendet werden.")
if not next_nonempty_token("Zuweisung", ":=").k == 'EQUALS':
error_handler.handle_error(":= in Zuweisung erwartet.")
identifier_token_2 = next_nonempty_token("Zuweisung", "IDENTIFIER (x0, x1, ...) oder NUMBER")
if identifier_token_2.k == 'NUMBER':
return next_token()
if not identifier_token_2.k == 'IDENTIFIER':
error_handler.handle_error("IDENTIFIER in Zuweisung erwartet.")
identifier_2 = identifier_token_2.v
if identifier_2 in forbidden_identifiers:
error_handler.handle_error("Identifier " + identifier_2 +
" ist bereits in Loop vorhanden und darf nicht verwendet werden.")
if next_nonempty_token("Zuweisung", "+ oder -").k not in ['PLUS', 'MINUS']:
error_handler.handle_error("+ oder - in Zuweisung erwartet.")
if not next_nonempty_token("Zuweisung", "NUMBER").k == 'NUMBER':
error_handler.handle_error("NUMBER in Zuweisung erwartet.")
return next_token()
def process_loop(forbidden_identifiers, loop_token):
global values
identifier_token = next_nonempty_token('LOOP', 'IDENTIFIER (x0, x1, ...)')
if not identifier_token.k == 'IDENTIFIER':
error_handler.handle_error('IDENTIFIER in LOOP erwartet.')
if identifier_token.v in forbidden_identifiers:
error_handler.handle_error('Identifier ' + identifier_token.v +
' ist bereits in Loop vorhanden und darf nicht verwendet werden.')
if not next_nonempty_token("LOOP", "DO").k == 'DO':
error_handler.handle_error('DO in LOOP erwartet.')
if identifier_token.v in values:
number_of_loops = int(values.get(identifier_token.v))
else:
number_of_loops = 0
saved_position = lex.current_position
saved_line = error_handler.line_number
forbidden_identifiers.append(identifier_token.v)
if number_of_loops == 0:
end_found = False
while not end_found:
token = verify_program(forbidden_identifiers, next_token())
if token is None or token.k not in ['SEMICOLON', 'END']:
error_handler.handle_error("SEMICOLON oder END in LOOP erwartet.")
elif token.k == 'SEMICOLON':
continue
elif token.k == 'END':
end_found = True
for index in range(number_of_loops):
lex.current_position = saved_position
error_handler.line_number = saved_line
end_found = False
while not end_found:
token = process_program(forbidden_identifiers, next_token())
if token is None or token.k not in ['SEMICOLON', 'END']:
error_handler.handle_error("SEMICOLON oder END in LOOP erwartet.")
elif token.k == 'SEMICOLON':
continue
elif token.k == 'END':
end_found = True
forbidden_identifiers.remove(identifier_token.v)
return next_token()
def verify_loop(forbidden_identifiers, loop_token):
identifier_token = next_nonempty_token("LOOP", "IDENTIFIER")
if not identifier_token.k == 'IDENTIFIER':
error_handler.handle_error('IDENTIFIER in LOOP erwartet.')
if identifier_token.v in forbidden_identifiers:
error_handler.handle_error("Identifier " + identifier_token.v +
" ist bereits in Loop vorhanden und darf nicht verwendet werden.")
if not next_nonempty_token("LOOP", "DO").k == 'DO':
error_handler.handle_error('DO in LOOP erwartet.')
forbidden_identifiers.append(identifier_token.v)
end_found = False
while not end_found:
token = verify_program(forbidden_identifiers, next_token())
if token is None or token.k not in ['SEMICOLON', 'END']:
error_handler.handle_error("SEMICOLON oder END in LOOP erwartet.")
elif token.k == 'SEMICOLON':
continue
elif token.k == 'END':
end_found = True
forbidden_identifiers.remove(identifier_token.v)
return next_token()
def process_program(forbidden_identifiers, current_token):
if current_token is None or current_token.k not in ['IDENTIFIER', 'LOOP']:
error_handler.handle_error("Keine passende Anweisung gefunden\n" +
"Erwartet: IDENTIFIER (x0, x1, ...) oder LOOP")
elif current_token.k == 'IDENTIFIER':
current_token = process_assignment(forbidden_identifiers, current_token)
elif current_token.k == 'LOOP':
current_token = process_loop(forbidden_identifiers, current_token)
return current_token
def verify_program(forbidden_identifiers, current_token):
if current_token is None or current_token.k not in ['IDENTIFIER', 'LOOP']:
error_handler.handle_error("Keine passende Anweisung gefunden\n" +
"Erwartet: IDENTIFIER (x0, x1, ...) oder LOOP")
elif current_token.k == 'IDENTIFIER':
current_token = verify_assignment(forbidden_identifiers, current_token)
elif current_token.k == 'LOOP':
current_token = verify_loop(forbidden_identifiers, current_token)
return current_token
def next_token():
new_token = lex.next()
if new_token is None:
return None
elif new_token.k == 'BREAK':
error_handler.handle_break()
return next_token()
elif new_token.k == 'LINEBREAK':
error_handler.increase_line()
return next_token()
elif new_token.k == 'WHITESPACE':
return next_token()
else:
return new_token
def next_nonempty_token(current_function, expected_token):
token = next_token()
if token is None:
error_handler.handle_error("Frühzeitiges Ende von " + current_function + "\n" + "Erwartet: " + expected_token)
return token
def interpret(program):
try:
global error_handler, lex, values
lex = lexer.Lexer(regex_to_token, program)
error_handler = ErrorHandler(program)
values = {}
forbidden_identifiers = []
current_token = next_token()
while current_token is not None:
current_token = process_program(forbidden_identifiers, current_token)
if current_token is not None:
if not current_token.k == 'SEMICOLON':
error_handler.handle_error("Semicolon erwartet")
current_token = next_token()
if current_token is None:
error_handler.handle_error("Semikolons werden nur zur Trennung und nicht zum " +
"Abschluss von Programmen verwendet")
if "x0" in values:
return values.get("x0")
return 0
except KeyboardInterrupt:
return -1
import lexer
import sys
import operator
import re
class ErrorHandler:
def __init__(self, program, interpreter):
sys.tracebacklimit = 0
self.program = program
self.line_number = 0
self.interpreter = interpreter
def handle_error(self, message):
msg = ["Fehler in Zeile " + str(self.line_number + 1),
self.program.split("\n")[self.line_number],
message]
raise SyntaxError("\n".join(msg)) from None
def increase_line(self):
self.line_number += 1
def handle_break(self):
print("BREAK in Zeile " + str(self.line_number))
print("Aktueller Zustand:")
for k, v in self.interpreter.values.items():
print("Variable " + k + ": " + str(v))
user_input = input("Drücke ENTER zum Fotfahren oder schreibe EXIT zum Beenden:")
if user_input.lower() == 'exit':
raise KeyboardInterrupt
class LOOPInterpreter:
def __init__(self):
self.regex_to_token = [(re.compile(r'\d+'), 'NUMBER'),
(re.compile(r'x\d+'), 'IDENTIFIER'),
(re.compile(r'\+'), 'PLUS'),
(re.compile(r'-'), 'MINUS'),
(re.compile(r':=|≔'), 'EQUALS'),
(re.compile(r'LOOP'), 'LOOP'),
(re.compile(r'DO'), 'DO'),
(re.compile(r'END'), 'END'),
(re.compile(r';'), 'SEMICOLON'),
(re.compile(r'BREAK'), 'BREAK'),
(re.compile(r'\n', re.MULTILINE), 'LINEBREAK'),
(re.compile(r'\s+'), 'WHITESPACE'),
(re.compile(r'[^\n]*'), 'UNKNOWN')]
self.values = {}
self.lex = None
self.error_handler = None
def process_assignment(self, forbidden_identifiers, identifier_token_1):
identifier_1 = identifier_token_1.v
if identifier_1 in forbidden_identifiers:
self.error_handler.handle_error("Identifier " + identifier_1 +
" ist bereits in Loop vorhanden und darf nicht verwendet werden.")
if not self.next_nonempty_token("Zuweisung", ":=").k == 'EQUALS':
self.error_handler.handle_error(":= in Zuweisung erwartet.")
identifier_token_2 = self.next_nonempty_token("Zuweisung", "IDENTIFIER (x0, x1, ...) oder NUMBER")
if identifier_token_2.k == 'NUMBER':
value_1 = int(identifier_token_2.v)
self.values.update({identifier_token_1.v: value_1})
return self.next_token()
if not identifier_token_2.k == 'IDENTIFIER':
self.error_handler.handle_error("IDENTIFIER in Zuweisung erwartet.")
identifier_2 = identifier_token_2.v
if identifier_2 in forbidden_identifiers:
self.error_handler.handle_error("Identifier " + identifier_2 +
" ist bereits in Loop vorhanden und darf nicht verwendet werden.")
if identifier_2 in self.values:
value_2 = self.values.get(identifier_2)
else:
value_2 = 0
operator_token = self.next_nonempty_token("Zuweisung", "+ oder -")
op = None
if operator_token.k == 'PLUS':
op = operator.__add__
elif operator_token.k == 'MINUS':
op = operator.__sub__
else:
self.error_handler.handle_error("+ oder - in Zuweisung erwartet.")
number_token = self.next_nonempty_token("Zuweisung", "NUMBER")
if not number_token.k == 'NUMBER':
self.error_handler.handle_error("NUMBER in Zuweisung erwartet.")
value_1 = max(0, op(value_2, int(number_token.v)))
self.values.update({identifier_1: value_1})
return self.next_token()
def verify_assignment(self, forbidden_identifiers, identifier_token_1):
identifier_1 = identifier_token_1.v
if identifier_1 in forbidden_identifiers:
self.error_handler.handle_error("Identifier " + identifier_1 +
" ist bereits in Loop vorhanden und darf nicht verwendet werden.")
if not self.next_nonempty_token("Zuweisung", ":=").k == 'EQUALS':
self.error_handler.handle_error(":= in Zuweisung erwartet.")
identifier_token_2 = self.next_nonempty_token("Zuweisung", "IDENTIFIER (x0, x1, ...) oder NUMBER")
if identifier_token_2.k == 'NUMBER':
return self.next_token()
if not identifier_token_2.k == 'IDENTIFIER':
self.error_handler.handle_error("IDENTIFIER in Zuweisung erwartet.")
identifier_2 = identifier_token_2.v
if identifier_2 in forbidden_identifiers:
self.error_handler.handle_error("Identifier " + identifier_2 +
" ist bereits in Loop vorhanden und darf nicht verwendet werden.")
if self.next_nonempty_token("Zuweisung", "+ oder -").k not in ['PLUS', 'MINUS']:
self.error_handler.handle_error("+ oder - in Zuweisung erwartet.")
if not self.next_nonempty_token("Zuweisung", "NUMBER").k == 'NUMBER':
self.error_handler.handle_error("NUMBER in Zuweisung erwartet.")
return self.next_token()
def process_loop(self, forbidden_identifiers, loop_token):
identifier_token = self.next_nonempty_token('LOOP', 'IDENTIFIER (x0, x1, ...)')
if not identifier_token.k == 'IDENTIFIER':
self.error_handler.handle_error('IDENTIFIER in LOOP erwartet.')
if identifier_token.v in forbidden_identifiers:
self.error_handler.handle_error('Identifier ' + identifier_token.v +
' ist bereits in Loop vorhanden und darf nicht verwendet werden.')
if not self.next_nonempty_token("LOOP", "DO").k == 'DO':
self.error_handler.handle_error('DO in LOOP erwartet.')
if identifier_token.v in self.values:
number_of_loops = int(self.values.get(identifier_token.v))
else:
number_of_loops = 0
saved_position = self.lex.current_position
saved_line = self.error_handler.line_number
forbidden_identifiers.append(identifier_token.v)
if number_of_loops == 0:
end_found = False
while not end_found:
token = self.verify_program(forbidden_identifiers, self.next_token())
if token is None or token.k not in ['SEMICOLON', 'END']:
self.error_handler.handle_error("SEMICOLON oder END in LOOP erwartet.")
elif token.k == 'SEMICOLON':
continue
elif token.k == 'END':
end_found = True
for index in range(number_of_loops):
self.lex.current_position = saved_position
self.error_handler.line_number = saved_line
end_found = False
while not end_found:
token = self.process_program(forbidden_identifiers, self.next_token())
if token is None or token.k not in ['SEMICOLON', 'END']:
self.error_handler.handle_error("SEMICOLON oder END in LOOP erwartet.")
elif token.k == 'SEMICOLON':
continue
elif token.k == 'END':
end_found = True
forbidden_identifiers.remove(identifier_token.v)
return self.next_token()
def verify_loop(self, forbidden_identifiers, loop_token):
identifier_token = self.next_nonempty_token("LOOP", "IDENTIFIER")
if not identifier_token.k == 'IDENTIFIER':
self.error_handler.handle_error('IDENTIFIER in LOOP erwartet.')
if identifier_token.v in forbidden_identifiers:
self.error_handler.handle_error("Identifier " + identifier_token.v +
" ist bereits in Loop vorhanden und darf nicht verwendet werden.")
if not self.next_nonempty_token("LOOP", "DO").k == 'DO':
self.error_handler.handle_error('DO in LOOP erwartet.')
forbidden_identifiers.append(identifier_token.v)
end_found = False
while not end_found:
token = self.verify_program(forbidden_identifiers, self.next_token())
if token is None or token.k not in ['SEMICOLON', 'END']:
self.error_handler.handle_error("SEMICOLON oder END in LOOP erwartet.")
elif token.k == 'SEMICOLON':
continue
elif token.k == 'END':
end_found = True
forbidden_identifiers.remove(identifier_token.v)
return self.next_token()
def process_program(self, forbidden_identifiers, current_token):
if current_token is None or current_token.k not in ['IDENTIFIER', 'LOOP']:
self.error_handler.handle_error("Keine passende Anweisung gefunden\n" +
"Erwartet: IDENTIFIER (x0, x1, ...) oder LOOP")
elif current_token.k == 'IDENTIFIER':
current_token = self.process_assignment(forbidden_identifiers, current_token)
elif current_token.k == 'LOOP':
current_token = self.process_loop(forbidden_identifiers, current_token)
return current_token
def verify_program(self, forbidden_identifiers, current_token):
if current_token is None or current_token.k not in ['IDENTIFIER', 'LOOP']:
self.error_handler.handle_error("Keine passende Anweisung gefunden\n" +
"Erwartet: IDENTIFIER (x0, x1, ...) oder LOOP")
elif current_token.k == 'IDENTIFIER':
current_token = self.verify_assignment(forbidden_identifiers, current_token)
elif current_token.k == 'LOOP':
current_token = self.verify_loop(forbidden_identifiers, current_token)
return current_token
def next_token(self):
new_token = self.lex.next()
if new_token is None:
return None
elif new_token.k == 'BREAK':
self.error_handler.handle_break()
return self.next_token()
elif new_token.k == 'LINEBREAK':
self.error_handler.increase_line()
return self.next_token()
elif new_token.k == 'WHITESPACE':
return self.next_token()
else:
return new_token
def next_nonempty_token(self, current_function, expected_token):
token = self.next_token()
if token is None:
self.error_handler.handle_error(
"Frühzeitiges Ende von " + current_function + "\n" + "Erwartet: " + expected_token)
return token
def interpret(self, program):
try:
self.lex = lexer.Lexer(self.regex_to_token, program)
self.error_handler = ErrorHandler(program, self)
self.values = {}
forbidden_identifiers = []
current_token = self.next_token()
while current_token is not None:
current_token = self.process_program(forbidden_identifiers, current_token)
if current_token is not None:
if not current_token.k == 'SEMICOLON':
self.error_handler.handle_error("Semicolon erwartet")
current_token = self.next_token()
if current_token is None:
self.error_handler.handle_error("Semikolons werden nur zur Trennung und nicht zum " +
"Abschluss von Programmen verwendet")
if "x0" in self.values:
return self.values.get("x0")
return 0
except KeyboardInterrupt:
return -1
def interpret(program):
interpreter = LOOPInterpreter()
return interpreter.interpret(program)
from loop_interpreter import interpret from loopinterpreter import interpret
import unittest import unittest
from unittest import mock from unittest import mock
def input_exit(prompt): def input_exit(prompt):
return "EXIT" return "EXIT"
def input_continue(prompt): def input_continue(prompt):
return "" return ""
def init_without_tokens(self, regex_to_token, program): def init_without_tokens(self, regex_to_token, program):
self.regex_to_token = {} self.regex_to_token = {}
self.program = program self.program = program
self.current_position = 0 self.current_position = 0
class InterpreterTest(unittest.TestCase):
class LOOPInterpreterTest(unittest.TestCase):
def test_assignment_default_zero(self): def test_assignment_default_zero(self):
self.assertEqual(interpret('x0:=x0 + 0'), 0) self.assertEqual(interpret('x0:=x0 + 0'), 0)
self.assertEqual(interpret('x0:=x1 + 0'), 0) self.assertEqual(interpret('x0:=x1 + 0'), 0)
...@@ -219,12 +223,12 @@ class InterpreterTest(unittest.TestCase): ...@@ -219,12 +223,12 @@ class InterpreterTest(unittest.TestCase):
x0:=x2+2'''), 5) x0:=x2+2'''), 5)
self.assertEqual(interpret('x1:=x1-2;\n x0:=x1+2'), 2) self.assertEqual(interpret('x1:=x1-2;\n x0:=x1+2'), 2)
@mock.patch('interpreter.input', side_effect=input_exit) @mock.patch('loopinterpreter.input', side_effect=input_exit)
def test_break_exit(self, input): def test_break_exit(self, input):
self.assertEqual(interpret('x1:=2; BREAK x0:=2'), -1) self.assertEqual(interpret('x1:=2; BREAK x0:=2'), -1)
self.assertEqual(interpret('LOOP x1 DO BREAK x2:= 2 END'), -1) self.assertEqual(interpret('LOOP x1 DO BREAK x2:= 2 END'), -1)
@mock.patch('interpreter.input', side_effect=input_continue) @mock.patch('loopinterpreter.input', side_effect=input_continue)
def test_break_continue(self, input): def test_break_continue(self, input):
self.assertEqual(interpret('x1:=2; LOOP x1 DO x0:=x0+2 BREAK END'), 4) self.assertEqual(interpret('x1:=2; LOOP x1 DO x0:=x0+2 BREAK END'), 4)
......
%% Cell type:markdown id: tags: %% Cell type:markdown id: tags:
# LOOP-Programme # LOOP-Programme
Im Folgenden werden wir Konzepte von prozeduralen Programmiersprachen kennenlernen. Als erste einfache Programmiersprache betrachten wir LOOP. Im Folgenden werden wir Konzepte von prozeduralen Programmiersprachen kennenlernen. Als erste einfache Programmiersprache betrachten wir LOOP.
Die Syntax solcher Programme ist definiert durch: Die Syntax solcher Programme ist definiert durch:
* $x_i := c$, $x_i := x_j + c$ und $x_i := x_j - c$ mit $i,j,c \in \mathbb{N}$ sind LOOP-Programme * $x_i := c$, $x_i := x_j + c$ und $x_i := x_j - c$ mit $i,j,c \in \mathbb{N}$ sind LOOP-Programme
* Falls $P_1$ und $P_2$ LOOP-Programme sind ist $P_1; P_2$ ein LOOP-Programm * Falls $P_1$ und $P_2$ LOOP-Programme sind ist $P_1; P_2$ ein LOOP-Programm
* Falls $P$ ein LOOP-Programm ist und $x_i$ nicht in $P$ vorkommt, so ist auch $LOOP\ x_i\ DO\ P\ END$ ein LOOP-Programm. * Falls $P$ ein LOOP-Programm ist und $x_i$ nicht in $P$ vorkommt, so ist auch $LOOP\ x_i\ DO\ P\ END$ ein LOOP-Programm.
%% Cell type:markdown id: tags: %% Cell type:markdown id: tags:
Die Semantik von LOOP-Programmen lässt sich wie folgt verstehen: Die Semantik von LOOP-Programmen lässt sich wie folgt verstehen:
* Wenn eine k-stellige Funktion $f(n_1,n_2,...,n_k)$ berechnet wird sind die Startwerte $n_1,...,n_k\in\mathbb{N}$ in den Variablen $x_1,...,x_k$. * Wenn eine k-stellige Funktion $f(n_1,n_2,...,n_k)$ berechnet wird sind die Startwerte $n_1,...,n_k\in\mathbb{N}$ in den Variablen $x_1,...,x_k$.
* Die restlichen Variablen starten mit dem Wert 0. * Die restlichen Variablen starten mit dem Wert 0.
* Zuweisungen $x_i := c$, $x_i := x_j + c$ werden wie üblich interpretiert. Bei $x_i := x_j - c$ wird $x_i$ auf 0 gesetzt, falls $c\geq x_j$ ist. * Zuweisungen $x_i := c$, $x_i := x_j + c$ werden wie üblich interpretiert. Bei $x_i := x_j - c$ wird $x_i$ auf 0 gesetzt, falls $c\geq x_j$ ist.
* Bei $P_1; P_2$ wird erst $P_1$ und dann $P_2$ ausgeführt. * Bei $P_1; P_2$ wird erst $P_1$ und dann $P_2$ ausgeführt.
* Das Programm $P$ in $LOOP\ x_i\ DO\ P\ END$ wird so oft ausgeführt, wie der Wert von $x_i$ zu Beginn des LOOPs ist. * Das Programm $P$ in $LOOP\ x_i\ DO\ P\ END$ wird so oft ausgeführt, wie der Wert von $x_i$ zu Beginn des LOOPs ist.
* Das Programm stoppt mit dem Wert $f(n_1,n_2,...,n_k)$ in der Variablen $x_0$. * Das Programm stoppt mit dem Wert $f(n_1,n_2,...,n_k)$ in der Variablen $x_0$.
%% Cell type:markdown id: tags: %% Cell type:markdown id: tags:
Eine Funktion heißt LOOP-berechenbar, falls es ein LOOP-Programm gibt, das mit $n_1,...,n_k$ in den Variablen $x_1,...,x_k$ gestartet wird und mit $f(n_1,n_2,...,n_k)$ in der Variablen $x_0$ endet. Eine Funktion heißt LOOP-berechenbar, falls es ein LOOP-Programm gibt, das mit $n_1,...,n_k$ in den Variablen $x_1,...,x_k$ gestartet wird und mit $f(n_1,n_2,...,n_k)$ in der Variablen $x_0$ endet.
Ein Beispiel dafür ist die Addition $f(n_1, n_2) = n_1 + n_2$: Ein Beispiel dafür ist die Addition $f(n_1, n_2) = n_1 + n_2$:
%% Cell type:code id: tags: %% Cell type:code id: tags:
``` python ``` python
%run Interpreter/interpreter.py %run Interpreter/loop_interpreter.py
``` ```
%% Cell type:code id: tags: %% Cell type:code id: tags:
``` python ``` python
interpret(''' interpret('''
x1:=3; x1:=3;
x2:=6; x2:=6;
LOOP x1 DO LOOP x1 DO
x0≔ x0 + 1 x2≔ x2 + 1
END''') END;
x0≔ x2 + 0''')
``` ```
%% Output %% Output
9 9
%% Cell type:markdown id: tags: %% Cell type:markdown id: tags:
Für die Visualisierung und das Verständnis haben wir die Syntax um das Keyword BREAK ereitert. Für die Visualisierung und das Verständnis haben wir die Syntax um das Keyword BREAK ereitert.
Wenn dieses erreicht wird, wird der Zustand ausgegeben und man wird gefragt, ob fortgefahren oder abgebrochen werden soll. Wenn dieses erreicht wird, wird der Zustand ausgegeben und man wird gefragt, ob fortgefahren oder abgebrochen werden soll.
Dabei werden Variablen, denen noch kein Wert zugewiesen wurde ignoriert. Dabei werden Variablen, denen noch kein Wert zugewiesen wurde ignoriert.
Im folgenden Fall wird $x_0$ nicht verändet, da $x_2$ nie zugewiesen wurde und die Schleife somit nicht ausgeführt wird. Im folgenden Fall wird $x_0$ nicht verändet, da $x_2$ nie zugewiesen wurde und die Schleife somit nicht ausgeführt wird.
%% Cell type:code id: tags: %% Cell type:code id: tags:
``` python ``` python
interpret(''' interpret('''
x1:=5; x1:=5;
x0:=2; x0:=2;
LOOP x2 DO LOOP x2 DO
x0:=1 x0:=1
BREAK BREAK
END END
''') ''')
``` ```
%% Output %% Output
BREAK in Zeile 5 BREAK in Zeile 5
Aktueller Zustand: Aktueller Zustand:
Variable x1: 5 Variable x1: 5
Variable x0: 2 Variable x0: 2
Drücke ENTER zum Fotfahren oder schreibe EXIT zum Beenden:1 Drücke ENTER zum Fotfahren oder schreibe EXIT zum Beenden:
2 2
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment