Commit e7588d06 authored by Christopher Happe's avatar Christopher Happe
Browse files

Feature: Hilfemeldung für interpret funktionen. closes #1.

parent 334130be
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# GOTO-Programme\n",
"\n",
"Die letzte Programmiersprache, die wir betrachten ist GOTO.\n",
"Die Syntax eines GOTO-Programms ist wie folgt definiert:\n",
"* Ein GOTO-Programm besteht aus Markierten Anweisungen $M_1: A_1; M_2: A_2; ... M_m: A_m;$\n",
"* Die Markierungen beginnen bei 1 und steigen immer um 1 an.\n",
"* Jede Anweisung wird durch 1 Semicolon abgeschlossen (ein GOTO-Programm endet immer mit einem Semicolon)\n",
"* Anweisungen $A_i$ dürfen dabei sein:\n",
" * Zuweisung $x_i:=x_j+c$, $x_i:=x_j-c$ und $x_i:=c$ für $c\\in\\mathbb{N}$\n",
" * Unbedingter Sprung $GOTO\\ M_i$\n",
" * Bedingter Sprung $IF\\ x_i=c\\ THEN\\ GOTO\\ M_j$\n",
" * Abbruchanweisung $HALT$"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Die Semantik eines GOTO-Programms lässt sich wie folgt verstehen:\n",
"Das Programm startet an der mit $M_1$ markierten Anweisung und führt diese aus.\n",
"Ist diese eine Zuweisung oder ein bedingter Sprung, dessen Bedingung nicht erfüllt ist, so wird mit der nächsten Anweisung weiter gemacht.\n",
"Wenn ein unbedingter Sprung oder ein bedingter Sprung miterfüllter Bedingung ausgeführt wird, wird an der entsprechenden Markierung fortgefahren.\n",
"Bei einer Abbruchanweisung hält das Programm sofort an und der Wert von $x_0$ wird zurück gegeben.\n",
"\n",
"Da ein GOTO-Programm stets von einem $HALT$ beendet wird, ist die letze Anweisung in einem GOTO-Programm immer $HALT$ oder $GOTO$."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Eine Funktion heißt GOTO-berechenbar, falls es ein GOTO-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, falls $f(n_1,n_2,...,n_k)$ definiert ist. Andernfalls stoppt das GOTO-Programm nicht.\n",
"Ein Beispiel dafür ist die 2er-Potenz $f(n) = n^2$:"
]
},
{
"cell_type": "code",
"execution_count": 1,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Help on function interpret in module __main__:\n",
"\n",
"interpret(program, timeout=60)\n",
" Funktion zum Ausführen eines GOTO-Programms.\n",
" :param program: GOTO-Programm als String 'M1: A1; M2: A2; ... Mn: An;'\n",
" :param timeout: Zeit nach der die Ausführung eines Programms pausiert wird.\n",
" Gibt eine Möglichkeit zum Abbrechen bei einer Endlosschleife.\n",
" Ein Wert von 0 deaktiviert den Timeout.\n",
" :returns integer: Gibt bei Abbruch -1 und sonst den Wert von x0 nach dem GOTO-Programm zurück.\n",
" :usage interpret('M1: x0 := x0 + 1; M2: IF x0 = 10 THEN GOTO M4; M3: GOTO M1; M4: HALT;')\n",
"\n"
]
}
],
"source": [
"%run ./Interpreter/gotointerpreter.py"
]
},
{
"cell_type": "code",
"execution_count": 2,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"14"
]
},
"execution_count": 2,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"interpret('''\n",
"M1:x1:=6;\n",
"M2:x2:=8;\n",
"M3:x0:=x1+0;\n",
"M4:IF x2=0 THEN GOTO M8;\n",
"M5:x0:=x0 + 1;\n",
"M6:x2:=x2 − 1;\n",
"M7:GOTO M4;\n",
"M8:HALT;''')"
]
},
{
"cell_type": "code",
"execution_count": 3,
"metadata": {
"scrolled": true
},
"outputs": [
{
"data": {
"text/plain": [
"10"
]
},
"execution_count": 3,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"interpret('M1: x0 := x0 + 1; M2: IF x0 = 10 THEN GOTO M4; M3: GOTO M1; M4: HALT;')"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.8.6"
}
},
"nbformat": 4,
"nbformat_minor": 4
}
%% Cell type:markdown id: tags:
# GOTO-Programme
Die letzte Programmiersprache, die wir betrachten ist GOTO.
Die Syntax eines GOTO-Programms ist wie folgt definiert:
* Ein GOTO-Programm besteht aus Markierten Anweisungen $M_1: A_1; M_2: A_2; ... M_m: A_m;$
* Die Markierungen beginnen bei 1 und steigen immer um 1 an.
* Jede Anweisung wird durch 1 Semicolon abgeschlossen (ein GOTO-Programm endet immer mit einem Semicolon)
* Anweisungen $A_i$ dürfen dabei sein:
* Zuweisung $x_i:=x_j+c$, $x_i:=x_j-c$ und $x_i:=c$ für $c\in\mathbb{N}$
* Unbedingter Sprung $GOTO\ M_i$
* Bedingter Sprung $IF\ x_i=c\ THEN\ GOTO\ M_j$
* Abbruchanweisung $HALT$
%% Cell type:markdown id: tags:
Die Semantik eines GOTO-Programms lässt sich wie folgt verstehen:
Das Programm startet an der mit $M_1$ markierten Anweisung und führt diese aus.
Ist diese eine Zuweisung oder ein bedingter Sprung, dessen Bedingung nicht erfüllt ist, so wird mit der nächsten Anweisung weiter gemacht.
Wenn ein unbedingter Sprung oder ein bedingter Sprung miterfüllter Bedingung ausgeführt wird, wird an der entsprechenden Markierung fortgefahren.
Bei einer Abbruchanweisung hält das Programm sofort an und der Wert von $x_0$ wird zurück gegeben.
Da ein GOTO-Programm stets von einem $HALT$ beendet wird, ist die letze Anweisung in einem GOTO-Programm immer $HALT$ oder $GOTO$.
%% Cell type:markdown id: tags:
Eine Funktion heißt GOTO-berechenbar, falls es ein GOTO-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, falls $f(n_1,n_2,...,n_k)$ definiert ist. Andernfalls stoppt das GOTO-Programm nicht.
Ein Beispiel dafür ist die 2er-Potenz $f(n) = n^2$:
%% Cell type:code id: tags:
``` python
%run ./Interpreter/gotointerpreter.py
```
%%%% Output: stream
Help on function interpret in module __main__:
interpret(program, timeout=60)
Funktion zum Ausführen eines GOTO-Programms.
:param program: GOTO-Programm als String 'M1: A1; M2: A2; ... Mn: An;'
:param timeout: Zeit nach der die Ausführung eines Programms pausiert wird.
Gibt eine Möglichkeit zum Abbrechen bei einer Endlosschleife.
Ein Wert von 0 deaktiviert den Timeout.
:returns integer: Gibt bei Abbruch -1 und sonst den Wert von x0 nach dem GOTO-Programm zurück.
:usage interpret('M1: x0 := x0 + 1; M2: IF x0 = 10 THEN GOTO M4; M3: GOTO M1; M4: HALT;')
%% Cell type:code id: tags:
``` python
interpret('''
M1:x1:=6;
M2:x2:=8;
M3:x0:=x1+0;
M4:IF x2=0 THEN GOTO M8;
M5:x0:=x0 + 1;
M6:x2:=x2 − 1;
M7:GOTO M4;
M8:HALT;''')
```
%%%% Output: execute_result
14
%% Cell type:code id: tags:
``` python
interpret('M1: x0 := x0 + 1; M2: IF x0 = 10 THEN GOTO M4; M3: GOTO M1; M4: HALT;')
```
%%%% Output: execute_result
10
......@@ -283,5 +283,16 @@ class GOTOInterpreter:
def interpret(program, timeout=60):
"""Funktion zum Ausführen eines GOTO-Programms.
:param program: GOTO-Programm als String 'M1: A1; M2: A2; ... Mn: An;'
:param timeout: Zeit nach der die Ausführung eines Programms pausiert wird.
Gibt eine Möglichkeit zum Abbrechen bei einer Endlosschleife.
Ein Wert von 0 deaktiviert den Timeout.
:returns integer: Gibt bei Abbruch -1 und sonst den Wert von x0 nach dem GOTO-Programm zurück.
:usage interpret('M1: x0 := x0 + 1; M2: IF x0 = 10 THEN GOTO M4; M3: GOTO M1; M4: HALT;')"""
interpreter = GOTOInterpreter(timeout)
return interpreter.interpret(program)
if __name__ == '__main__':
help(interpret)
......@@ -2,6 +2,7 @@ import lexer
import sys
import operator
import re
from IPython.display import clear_output
class ErrorHandler:
......@@ -21,6 +22,7 @@ class ErrorHandler:
self.line_number += value
def handle_break(self):
clear_output(wait=True)
print('BREAK in Zeile ' + str(self.line_number))
print('Aktueller Zustand:')
for k, v in self.interpreter.values.items():
......@@ -249,5 +251,13 @@ class LOOPInterpreter:
def interpret(program):
"""Funktion zum Ausführen eines LOOP-Programms.
:param program: LOOP-Programm als String 'x1 := 4; LOOP x1 DO x0:=x0+1 END'
:returns integer: Gibt bei Abbruch -1 und sonst den Wert von x0 nach dem LOOP-Programm zurück.
:usage interpret('x1:=10; x2:=8; x0:=x2+0; LOOP x1 DO x0:=x0+1 END')"""
interpreter = LOOPInterpreter()
return interpreter.interpret(program)
if __name__ == '__main__':
help(interpret)
......@@ -2,6 +2,7 @@ import lexer
from loopinterpreter import LOOPInterpreter, ErrorHandler
import re
import signal
from IPython.display import clear_output
class Timeout:
......@@ -18,6 +19,7 @@ class Timeout:
def interrupt(self, sig_num, stack_frame):
try:
clear_output(wait=True)
abort = input('''Die Funktion rechnet relativ lange.
Vielleicht liegt eine Endlosschleife vor.
Möchten sie abbrechen? [J,n]:''')
......@@ -184,5 +186,16 @@ class WHILEInterpreter(LOOPInterpreter):
def interpret(program, timeout=60):
"""Funktion zum Ausführen eines WHILE-Programms.
:param program: WHILE-Programm als String 'x1:=10; x2:=8; x0:=x2+0; WHILE x1 /=0 DO x0:=x0+1; x1:=x1-1 END'
:param timeout: Zeit nach der die Ausführung eines Programms pausiert wird.
Gibt eine Möglichkeit zum Abbrechen bei einer Endlosschleife.
Ein Wert von 0 deaktiviert den Timeout.
:returns integer: Gibt bei Abbruch -1 und sonst den Wert von x0 nach dem WHILE-Programm zurück.
:usage interpret('x1:=10; x2:=8; x0:=x2+0; WHILE x1 /=0 DO x0:=x0+1; x1:=x1-1 END')"""
interpreter = WHILEInterpreter(timeout)
return interpreter.interpret(program)
if __name__ == '__main__':
help(interpret)
......@@ -40,7 +40,22 @@
"metadata": {
"scrolled": false
},
"outputs": [],
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Help on function interpret in module __main__:\n",
"\n",
"interpret(program)\n",
" Funktion zum Ausführen eines LOOP-Programms.\n",
" :param program: LOOP-Programm als String 'x1 := 4; LOOP x1 DO x0:=x0+1 END'\n",
" :returns integer: Gibt bei Abbruch -1 und sonst den Wert von x0 nach dem LOOP-Programm zurück.\n",
" :usage interpret('x1:=10; x2:=8; x0:=x2+0; LOOP x1 DO x0:=x0+1 END')\n",
"\n"
]
}
],
"source": [
"%run Interpreter/loopinterpreter.py"
]
......
%% Cell type:markdown id: tags:
# LOOP-Programme
Im Folgenden werden wir Konzepte von prozeduralen Programmiersprachen kennenlernen. Als erste einfache Programmiersprache betrachten wir LOOP.
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
* 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.
%% Cell type:markdown id: tags:
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$.
* 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.
* 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 stoppt mit dem Wert $f(n_1,n_2,...,n_k)$ in der Variablen $x_0$.
%% 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.
Ein Beispiel dafür ist die Addition $f(n_1, n_2) = n_1 + n_2$:
%% Cell type:code id: tags:
``` python
%run Interpreter/loopinterpreter.py
```
%%%% Output: stream
Help on function interpret in module __main__:
interpret(program)
Funktion zum Ausführen eines LOOP-Programms.
:param program: LOOP-Programm als String 'x1 := 4; LOOP x1 DO x0:=x0+1 END'
:returns integer: Gibt bei Abbruch -1 und sonst den Wert von x0 nach dem LOOP-Programm zurück.
:usage interpret('x1:=10; x2:=8; x0:=x2+0; LOOP x1 DO x0:=x0+1 END')
%% Cell type:code id: tags:
``` python
interpret('''
x1:=3;
x2:=6;
LOOP x1 DO
x2≔ x2 + 1
END;
x0≔ x2 + 0''')
```
%%%% Output: execute_result
9
%% Cell type:markdown id: tags:
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.
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.
%% Cell type:code id: tags:
``` python
interpret('''
x1:=5;
x0:=2;
LOOP x2 DO
x0:=1
BREAK
END
''')
```
%%%% Output: stream
BREAK in Zeile 5
Aktueller Zustand:
Variable x1: 5
Variable x0: 2
Drücke ENTER zum Fotfahren oder schreibe EXIT zum Beenden:
%%%% Output: execute_result
2
......
......@@ -36,7 +36,25 @@
"cell_type": "code",
"execution_count": 1,
"metadata": {},
"outputs": [],
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Help on function interpret in module __main__:\n",
"\n",
"interpret(program, timeout=60)\n",
" Funktion zum Ausführen eines WHILE-Programms.\n",
" :param program: WHILE-Programm als String 'x1:=10; x2:=8; x0:=x2+0; WHILE x1 /=0 DO x0:=x0+1; x1:=x1-1 END'\n",
" :param timeout: Zeit nach der die Ausführung eines Programms pausiert wird.\n",
" Gibt eine Möglichkeit zum Abbrechen bei einer Endlosschleife.\n",
" Ein Wert von 0 deaktiviert den Timeout.\n",
" :returns integer: Gibt bei Abbruch -1 und sonst den Wert von x0 nach dem WHILE-Programm zurück.\n",
" :usage interpret('x1:=10; x2:=8; x0:=x2+0; WHILE x1 /=0 DO x0:=x0+1; x1:=x1-1 END')\n",
"\n"
]
}
],
"source": [
"%run Interpreter/whileinterpreter.py"
]
......
%% Cell type:markdown id: tags:
# WHILE-Programme
Um LOOP-Programme zu erweitern führen wir eine WHILE-Schleife ein und erhalten damit die WHILE-Programme.
Die Syntax solcher WHILE-Programme ist definiert durch:
* Jedes LOOP-Programm ist ein WHILE-Programm
* Falls $P_1$ und $P_2$ WHILE-Programme sind ist $P_1; P_2$ ein WHILE-Programm
* Falls $P$ ein WHILE-Programm ist, so ist auch $WHILE\ x_i\neq 0\ DO\ P\ END$ ein WHILE-Programm.
%% Cell type:markdown id: tags:
Die Semantik von WHILE-Programmen ist analog zu der von LOOP-Programmen zu verstehen.
Der einzige Unterschied sind die WHILE-Schleifen.
Das Programm P in einer WHILE-Schleife wird solange wiederholt, wie $x_i \neq 0$ ist.
Dabei ist zu beachten, dass $x_i$ in P vorkommen sollte, da es sonst nicht verändert wird.
Dies ist ein Unterschied zu LOOP-Programmen, da $x_i$ in dem entsprechenden LOOP nicht verwendet werden darf.
%% Cell type:markdown id: tags:
Eine Funktion heißt WHILE-berechenbar, falls es ein WHILE-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, falls $f(n_1,n_2,...,n_k)$ definiert ist. Andernfalls stoppt das WHILE-Programm nicht.
Ein Beispiel dafür ist die 2er-Potenz $f(n) = n^2$:
%% Cell type:code id: tags:
``` python
%run Interpreter/whileinterpreter.py
```
%%%% Output: stream
Help on function interpret in module __main__:
interpret(program, timeout=60)
Funktion zum Ausführen eines WHILE-Programms.
:param program: WHILE-Programm als String 'x1:=10; x2:=8; x0:=x2+0; WHILE x1 /=0 DO x0:=x0+1; x1:=x1-1 END'
:param timeout: Zeit nach der die Ausführung eines Programms pausiert wird.
Gibt eine Möglichkeit zum Abbrechen bei einer Endlosschleife.
Ein Wert von 0 deaktiviert den Timeout.
:returns integer: Gibt bei Abbruch -1 und sonst den Wert von x0 nach dem WHILE-Programm zurück.
:usage interpret('x1:=10; x2:=8; x0:=x2+0; WHILE x1 /=0 DO x0:=x0+1; x1:=x1-1 END')
%% Cell type:code id: tags:
``` python
interpret('''
x1:=10;
x0:=1;
WHILE x1 /= 0 DO
x2:=x0+0;
LOOP x2 DO
x0:=x0+1
END;
x1:=x1-1
END''')
```
%%%% Output: execute_result
1024
%% Cell type:markdown id: tags:
Ein weiteres Beispiel ist die Funktion f(n) = n mod 2
%% Cell type:code id: tags:
``` python
interpret('''
x1:=16;
x2:=x1-1;
WHILE x2!=0 DO
x1:=x1-2;
x2:=x2-2
END;
x0:=x1+0
''')
```
%%%% Output: execute_result
0
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment