Skip to content
GitLab
Explore
Sign in
Primary navigation
Search or go to…
Project
P
prob-teaching-notebooks
Manage
Activity
Members
Labels
Plan
Issues
Issue boards
Milestones
Iterations
Wiki
Requirements
Code
Merge requests
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Snippets
Locked files
Build
Pipelines
Jobs
Pipeline schedules
Test cases
Artifacts
Deploy
Releases
Package registry
Container registry
Model registry
Operate
Environments
Terraform modules
Monitor
Incidents
Analyze
Value stream analytics
Contributor analytics
CI/CD analytics
Repository analytics
Code review analytics
Issue analytics
Insights
Model experiments
Help
Help
Support
GitLab documentation
Compare GitLab plans
Community forum
Contribute to GitLab
Provide feedback
Keyboard shortcuts
?
Snippets
Groups
Projects
Show more breadcrumbs
general
stups
prob-teaching-notebooks
Commits
f17c278f
Commit
f17c278f
authored
4 years ago
by
Chris
Browse files
Options
Downloads
Patches
Plain Diff
Interpreter für GOTO-Programme
parent
b469f216
No related branches found
No related tags found
1 merge request
!1
Master
Changes
1
Show whitespace changes
Inline
Side-by-side
Showing
1 changed file
info4/kapitel-8/Interpreter/gotointerpreter.py
+281
-0
281 additions, 0 deletions
info4/kapitel-8/Interpreter/gotointerpreter.py
with
281 additions
and
0 deletions
info4/kapitel-8/Interpreter/gotointerpreter.py
0 → 100644
+
281
−
0
View file @
f17c278f
import
lexer
from
loopinterpreter
import
ErrorHandler
from
whileinterpreter
import
Timeout
import
re
import
operator
class
GOTOInterpreter
:
def
__init__
(
self
,
timeout
=
60
):
self
.
values
=
{}
self
.
lex
=
None
self
.
error_handler
=
None
self
.
regex_to_token
=
[(
re
.
compile
(
r
'
\d+
'
),
'
NUMBER
'
),
(
re
.
compile
(
r
'
x\d+
'
),
'
IDENTIFIER
'
),
(
re
.
compile
(
r
'
M\d+
'
),
'
MARKER
'
),
(
re
.
compile
(
r
'
\+
'
),
'
PLUS
'
),
(
re
.
compile
(
r
'
-
'
),
'
MINUS
'
),
(
re
.
compile
(
r
'
:=|≔
'
),
'
ALLOCATION
'
),
(
re
.
compile
(
r
'
=
'
),
'
EQUALS
'
),
(
re
.
compile
(
r
'
/=|≠|!=
'
),
'
NOTEQUALS
'
),
(
re
.
compile
(
r
'
IF
'
),
'
IF
'
),
(
re
.
compile
(
r
'
THEN
'
),
'
THEN
'
),
(
re
.
compile
(
r
'
GOTO
'
),
'
GOTO
'
),
(
re
.
compile
(
r
'
HALT
'
),
'
HALT
'
),
(
re
.
compile
(
r
'
;
'
),
'
SEMICOLON
'
),
(
re
.
compile
(
r
'
:
'
),
'
COLON
'
),
(
re
.
compile
(
r
'
BREAK
'
),
'
BREAK
'
),
(
re
.
compile
(
r
'
\s+
'
,
re
.
MULTILINE
),
'
WHITESPACE
'
),
(
re
.
compile
(
r
'
[^\n]*
'
),
'
UNKNOWN
'
)]
self
.
marker_to_position
=
{}
self
.
marker_to_line
=
{}
self
.
timeout
=
timeout
self
.
halted
=
False
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
==
'
WHITESPACE
'
:
if
new_token
.
v
.
count
(
'
\n
'
)
>
0
:
self
.
error_handler
.
increase_line
(
new_token
.
v
.
count
(
'
\n
'
))
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
process_assignment
(
self
,
identifier_token_1
):
identifier_1
=
identifier_token_1
.
v
if
not
self
.
next_nonempty_token
(
'
Zuweisung
'
,
'
:=
'
).
k
==
'
ALLOCATION
'
:
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
})
if
not
self
.
next_nonempty_token
(
"
Zuweisung
"
,
"
SEMICOLON
"
).
k
==
'
SEMICOLON
'
:
self
.
error_handler
.
handle_error
(
"
SEMICOLON zum Abschluss einer Zuweisung erwartet.
"
)
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
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
})
if
not
self
.
next_nonempty_token
(
"
Zuweisung
"
,
"
SEMICOLON
"
).
k
==
'
SEMICOLON
'
:
self
.
error_handler
.
handle_error
(
"
SEMICOLON zum Abschluss einer Zuweisung erwartet.
"
)
return
self
.
next_token
()
def
verify_assignment
(
self
,
identifier_token_1
):
if
not
self
.
next_nonempty_token
(
"
Zuweisung
"
,
"
:=
"
).
k
==
'
ALLOCATION
'
:
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
'
:
if
not
self
.
next_nonempty_token
(
"
Zuweisung
"
,
"
SEMICOLON
"
).
k
==
'
SEMICOLON
'
:
self
.
error_handler
.
handle_error
(
"
SEMICOLON zum Abschluss einer Zuweisung erwartet.
"
)
return
self
.
next_token
()
if
not
identifier_token_2
.
k
==
'
IDENTIFIER
'
:
self
.
error_handler
.
handle_error
(
"
IDENTIFIER in Zuweisung erwartet.
"
)
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.
"
)
if
not
self
.
next_nonempty_token
(
"
Zuweisung
"
,
"
SEMICOLON
"
).
k
==
'
SEMICOLON
'
:
self
.
error_handler
.
handle_error
(
"
SEMICOLON zum Abschluss einer Zuweisung erwartet.
"
)
return
self
.
next_token
()
def
process_goto
(
self
,
goto_token
):
marker_token
=
self
.
next_nonempty_token
(
'
GOTO
'
,
'
MARKER (M1, M2, ...)
'
)
if
not
marker_token
.
k
==
'
MARKER
'
:
self
.
error_handler
.
handle_error
(
'
MARKER (M1, M2, ...) in GOTO erwartet.
'
)
if
not
self
.
next_nonempty_token
(
'
GOTO
'
,
'
SEMICOLON
'
).
k
==
'
SEMICOLON
'
:
self
.
error_handler
.
handle_error
(
'
SEMICOLON zum Abschluss eines GOTO erwartet
'
)
marker_number
=
int
(
marker_token
.
v
[
1
:])
current_token
=
self
.
next_token
()
while
current_token
is
not
None
and
max
(
self
.
marker_to_position
.
keys
())
<
int
(
marker_number
):
current_token
=
self
.
verify_line
(
current_token
)
if
marker_number
not
in
self
.
marker_to_position
.
keys
():
self
.
error_handler
.
handle_error
(
'
GOTO zu nicht vorhandener Markierung
'
)
self
.
lex
.
current_position
=
self
.
marker_to_position
.
get
(
marker_number
)
self
.
error_handler
.
line_number
=
self
.
marker_to_line
.
get
(
marker_number
)
return
self
.
next_token
()
def
verify_goto
(
self
,
goto_token
):
marker_token
=
self
.
next_nonempty_token
(
'
GOTO
'
,
'
MARKER (M1, M2, ...)
'
)
if
not
marker_token
.
k
==
'
MARKER
'
:
self
.
error_handler
.
handle_error
(
'
MARKER (M1, M2, ...) in GOTO erwartet.
'
)
if
not
self
.
next_nonempty_token
(
'
GOTO
'
,
'
SEMICOLON
'
).
k
==
'
SEMICOLON
'
:
self
.
error_handler
.
handle_error
(
'
SEMICOLON zum Abschluss eines GOTO erwartet
'
)
marker_number
=
int
(
marker_token
.
v
[
1
:])
saved_position
=
self
.
lex
.
current_position
saved_line
=
self
.
error_handler
.
line_number
current_token
=
self
.
next_token
()
while
current_token
is
not
None
and
max
(
self
.
marker_to_position
.
keys
())
<
int
(
marker_number
):
current_token
=
self
.
verify_line
(
current_token
)
if
marker_number
not
in
self
.
marker_to_position
.
keys
():
self
.
error_handler
.
handle_error
(
'
GOTO zu nicht vorhandener Markierung
'
)
self
.
lex
.
current_position
=
saved_position
self
.
error_handler
.
line_number
=
saved_line
return
self
.
next_token
()
def
process_if
(
self
,
if_token
):
identifier_token
=
self
.
next_nonempty_token
(
'
IF
'
,
'
IDENTIFIER
'
)
if
not
identifier_token
.
k
==
'
IDENTIFIER
'
:
self
.
error_handler
.
handle_error
(
'
IDENTIFIER in IF erwartet
'
)
if
not
self
.
next_nonempty_token
(
'
IF
'
,
'
=
'
).
k
==
'
EQUALS
'
:
self
.
error_handler
.
handle_error
(
'
= in IF erwartet
'
)
number_token
=
self
.
next_nonempty_token
(
'
IF
'
,
'
NUMBER
'
)
if
not
number_token
.
k
==
'
NUMBER
'
:
self
.
error_handler
.
handle_error
(
'
NUMBER in IF erwartet
'
)
if
not
self
.
next_nonempty_token
(
'
IF
'
,
'
THEN
'
).
k
==
'
THEN
'
:
self
.
error_handler
.
handle_error
(
'
THEN in IF erwartet
'
)
current_token
=
self
.
next_nonempty_token
(
'
IF
'
,
'
GOTO
'
)
if
not
current_token
.
k
==
'
GOTO
'
:
self
.
error_handler
.
handle_error
(
'
GOTO in IF erwartet
'
)
if
identifier_token
.
v
in
self
.
values
.
keys
():
identifier_value
=
self
.
values
.
get
(
identifier_token
.
v
)
else
:
identifier_value
=
0
if
identifier_value
==
int
(
number_token
.
v
):
return
self
.
process_goto
(
current_token
)
else
:
return
self
.
verify_goto
(
current_token
)
def
verify_if
(
self
,
if_token
):
if
not
self
.
next_nonempty_token
(
'
IF
'
,
'
IDENTIFIER
'
).
k
==
'
IDENTIFIER
'
:
self
.
error_handler
.
handle_error
(
'
IDENTIFIER in IF erwartet
'
)
if
not
self
.
next_nonempty_token
(
'
IF
'
,
'
=
'
).
k
==
'
EQUALS
'
:
self
.
error_handler
.
handle_error
(
'
= in IF erwartet
'
)
if
not
self
.
next_nonempty_token
(
'
IF
'
,
'
NUMBER
'
).
k
==
'
NUMBER
'
:
self
.
error_handler
.
handle_error
(
'
NUMBER in IF erwartet
'
)
if
not
self
.
next_nonempty_token
(
'
IF
'
,
'
THEN
'
).
k
==
'
THEN
'
:
self
.
error_handler
.
handle_error
(
'
THEN in IF erwartet
'
)
current_token
=
self
.
next_nonempty_token
(
'
IF
'
,
'
GOTO
'
)
if
not
current_token
.
k
==
'
GOTO
'
:
self
.
error_handler
.
handle_error
(
'
GOTO in IF erwartet
'
)
return
self
.
verify_goto
(
current_token
)
def
process_halt
(
self
,
halt_token
):
if
not
self
.
next_nonempty_token
(
'
HALT
'
,
'
SEMICOLON
'
).
k
==
'
SEMICOLON
'
:
self
.
error_handler
.
handle_error
(
'
SEMICOLON zum Abschluss eines HALT erwartet
'
)
self
.
halted
=
True
current_token
=
self
.
next_token
()
while
current_token
is
not
None
:
current_token
=
self
.
verify_line
(
current_token
)
return
current_token
def
verify_halt
(
self
,
halt_token
):
if
not
self
.
next_nonempty_token
(
'
HALT
'
,
'
SEMICOLON
'
).
k
==
'
SEMICOLON
'
:
self
.
error_handler
.
handle_error
(
'
SEMICOLON zum Abschluss eines HALT erwartet
'
)
return
self
.
next_token
()
def
next_marker_number
(
self
):
if
self
.
marker_to_position
.
keys
():
return
max
(
self
.
marker_to_position
.
keys
())
+
1
else
:
return
1
def
process_line
(
self
,
current_token
):
if
current_token
is
None
or
not
current_token
.
k
==
'
MARKER
'
:
self
.
error_handler
.
handle_error
(
'
Keine passende Anweisung gefunden
\n
'
+
'
Erwartet: MARKER (M1, M2, ...)
'
)
marker_number
=
int
(
current_token
.
v
[
1
:])
if
not
(
marker_number
==
self
.
next_marker_number
()
or
(
marker_number
in
self
.
marker_to_position
.
keys
()
and
current_token
.
p
==
self
.
marker_to_position
.
get
(
marker_number
))):
self
.
error_handler
.
handle_error
(
'
Die Nummern der Anweisungen starten bei 1 und steigen fortlaufend.
'
)
self
.
marker_to_position
.
update
({
marker_number
:
current_token
.
p
})
self
.
marker_to_line
.
update
({
marker_number
:
self
.
error_handler
.
line_number
})
colon_token
=
self
.
next_nonempty_token
(
'
LINE
'
,
'
COLON
'
)
if
not
colon_token
.
k
==
'
COLON
'
:
self
.
error_handler
.
handle_error
(
'
DOPPELPUNKT nach MARKER (M1, M2, ...) erwartet.
'
)
current_token
=
self
.
next_nonempty_token
(
'
LINE
'
,
'
IDENTIFIER (x0, x1, ...), IF, GOTO oder HALT
'
)
if
current_token
.
k
not
in
[
'
IDENTIFIER
'
,
'
IF
'
,
'
GOTO
'
,
'
HALT
'
]:
self
.
error_handler
.
handle_error
(
'
Keine passende Anweisung gefunden
\n
'
+
'
Erwartet: IDENTIFIER (x0, x1, ...), IF, GOTO oder HALT
'
)
elif
current_token
.
k
==
'
IDENTIFIER
'
:
current_token
=
self
.
process_assignment
(
current_token
)
elif
current_token
.
k
==
'
GOTO
'
:
current_token
=
self
.
process_goto
(
current_token
)
elif
current_token
.
k
==
'
IF
'
:
current_token
=
self
.
process_if
(
current_token
)
elif
current_token
.
k
==
'
HALT
'
:
current_token
=
self
.
process_halt
(
current_token
)
return
current_token
def
verify_line
(
self
,
current_token
):
if
current_token
is
None
or
not
current_token
.
k
==
'
MARKER
'
:
self
.
error_handler
.
handle_error
(
'
Keine passende Anweisung gefunden
\n
'
+
'
Erwartet: MARKER (M1, M2, ...)
'
)
marker_number
=
int
(
current_token
.
v
[
1
:])
if
not
(
marker_number
==
self
.
next_marker_number
()
or
(
marker_number
in
self
.
marker_to_position
.
keys
()
and
current_token
.
p
==
self
.
marker_to_position
.
get
(
marker_number
))):
self
.
error_handler
.
handle_error
(
'
Die Nummern der Anweisungen starten bei 1 und steigen fortlaufend.
'
)
self
.
marker_to_position
.
update
({
marker_number
:
current_token
.
p
})
self
.
marker_to_line
.
update
({
marker_number
:
self
.
error_handler
.
line_number
})
if
not
self
.
next_nonempty_token
(
'
LINE
'
,
'
COLON
'
).
k
==
'
COLON
'
:
self
.
error_handler
.
handle_error
(
'
DOPPELPUNKT nach MARKER (M1, M2, ...) erwartet.
'
)
current_token
=
self
.
next_nonempty_token
(
'
LINE
'
,
'
IDENTIFIER (x0, x1, ...), IF, GOTO oder HALT
'
)
if
current_token
.
k
not
in
[
'
IDENTIFIER
'
,
'
IF
'
,
'
GOTO
'
,
'
HALT
'
]:
self
.
error_handler
.
handle_error
(
'
Keine passende Anweisung gefunden
\n
'
+
'
Erwartet: IDENTIFIER (x0, x1, ...), IF, GOTO oder HALT
'
)
elif
current_token
.
k
==
'
IDENTIFIER
'
:
current_token
=
self
.
verify_assignment
(
current_token
)
elif
current_token
.
k
==
'
GOTO
'
:
current_token
=
self
.
verify_goto
(
current_token
)
elif
current_token
.
k
==
'
IF
'
:
current_token
=
self
.
verify_if
(
current_token
)
elif
current_token
.
k
==
'
HALT
'
:
current_token
=
self
.
verify_halt
(
current_token
)
return
current_token
def
interpret
(
self
,
program
):
try
:
with
Timeout
(
self
.
timeout
):
self
.
halted
=
False
self
.
lex
=
lexer
.
Lexer
(
self
.
regex_to_token
,
program
)
self
.
error_handler
=
ErrorHandler
(
program
,
self
)
self
.
values
=
{}
current_token
=
self
.
next_token
()
while
current_token
is
not
None
:
current_token
=
self
.
process_line
(
current_token
)
if
not
self
.
halted
:
self
.
error_handler
.
handle_error
(
'
Ende des Programms ohne HALT erreicht.
'
)
if
'
x0
'
in
self
.
values
:
return
self
.
values
.
get
(
'
x0
'
)
return
0
except
KeyboardInterrupt
:
return
-
1
def
interpret
(
program
,
timeout
=
60
):
interpreter
=
GOTOInterpreter
(
timeout
)
return
interpreter
.
interpret
(
program
)
This diff is collapsed.
Click to expand it.
Preview
0%
Loading
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Save comment
Cancel
Please
register
or
sign in
to comment