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
8c83627c
Commit
8c83627c
authored
4 years ago
by
Chris
Browse files
Options
Downloads
Patches
Plain Diff
Fehlerbehandlung überarbeitet
parent
da836c18
No related branches found
No related tags found
Loading
Changes
2
Show whitespace changes
Inline
Side-by-side
Showing
2 changed files
info4/kapitel-8/Interpreter/interpreter.py
+108
-82
108 additions, 82 deletions
info4/kapitel-8/Interpreter/interpreter.py
info4/kapitel-8/Interpreter/lexer.py
+6
-1
6 additions, 1 deletion
info4/kapitel-8/Interpreter/lexer.py
with
114 additions
and
83 deletions
info4/kapitel-8/Interpreter/interpreter.py
+
108
−
82
View file @
8c83627c
import
lexer
import
sys
class
ErrorHandler
:
def
__init__
(
self
,
program
,
tokens
):
sys
.
tracebacklimit
=
0
self
.
program
=
program
position_to_line
=
{}
position
=
0
line
=
0
for
token
in
tokens
:
if
token
.
k
==
'
LINEBREAK
'
:
line
+=
1
else
:
position_to_line
[
position
]
=
line
position
=
position
+
1
self
.
position_to_line
=
position_to_line
def
handle_error
(
self
,
position
,
message
):
line_number
=
self
.
position_to_line
[
position
]
msg
=
[
"
Fehler in Zeile
"
+
str
(
line_number
+
1
),
self
.
program
.
split
(
"
\n
"
)[
line_number
],
message
]
raise
SyntaxError
(
"
\n
"
.
join
(
msg
))
from
None
loop_program
=
'''
x1 := 2;
x2 := 3;
x3 := x2 + 0;
LOOP x1 DO
x2 := x3 + 1;
x3 := x2 + 0
END;
x0 := x2 + 0
'''
global
error_handler
def
process_assignment
(
token_queue
,
position
,
value_list
,
forbidden_identifiers
):
identifier_1
=
token_queue
[
position
].
v
if
identifier_1
in
forbidden_identifiers
:
raise
Exception
(
"
Identifier
"
+
identifier_1
+
"
ist bereits in Loop vorhanden und darf nicht verwendet werden.
"
)
error_handler
.
handle_error
(
position
,
"
Identifier
"
+
identifier_1
+
"
ist bereits in Loop vorhanden und darf nicht verwendet werden.
"
)
if
not
token_queue
[
position
+
1
].
k
==
'
EQUALS
'
:
raise
SyntaxError
(
"
:= in Zuweisung erwartet.
"
)
error_handler
.
handle_error
(
position
+
1
,
"
:= in Zuweisung erwartet.
"
)
if
identifier_1
in
value_list
:
value_1
=
value_list
.
get
(
identifier_1
)
...
...
@@ -28,11 +45,12 @@ def process_assignment(token_queue, position, value_list, forbidden_identifiers)
return
position
+
3
,
value_list
if
not
token_queue
[
position
+
2
].
k
==
'
IDENTIFIER
'
:
raise
SyntaxError
(
"
IDENTIFIER in Zuweisung erwartet.
"
)
error_handler
.
handle_error
(
position
+
2
,
"
IDENTIFIER in Zuweisung erwartet.
"
)
identifier_2
=
token_queue
[
position
+
2
].
v
if
identifier_2
in
forbidden_identifiers
:
raise
Exception
(
"
Identifier
"
+
identifier_2
+
"
ist bereits in Loop vorhanden und darf nicht verwendet werden.
"
)
error_handler
.
handle_error
(
position
+
2
,
"
Identifier
"
+
identifier_2
+
"
ist bereits in Loop vorhanden und darf nicht verwendet werden.
"
)
if
identifier_2
in
value_list
:
value_2
=
value_list
.
get
(
identifier_2
)
...
...
@@ -40,13 +58,13 @@ def process_assignment(token_queue, position, value_list, forbidden_identifiers)
value_2
=
0
if
not
token_queue
[
position
+
4
].
k
==
'
NUMBER
'
:
raise
SyntaxError
(
"
NUMBER in Zuweisung erwartet.
"
)
error_handler
.
handle_error
(
position
+
4
,
"
NUMBER in Zuweisung erwartet.
"
)
if
token_queue
[
position
+
3
].
k
==
'
PLUS
'
:
value_1
=
value_2
+
int
(
token_queue
[
position
+
4
].
v
)
elif
token_queue
[
position
+
3
].
k
==
'
MINUS
'
:
value_1
=
max
(
0
,
value_2
+
token_queue
[
position
+
4
].
v
)
else
:
raise
SyntaxError
(
"
PLUS oder MINUS in Zuweisung erwartet.
"
)
error_handler
.
handle_error
(
position
+
3
,
"
PLUS oder MINUS in Zuweisung erwartet.
"
)
value_list
.
update
({
identifier_1
:
value_1
})
return
position
+
5
,
value_list
...
...
@@ -54,81 +72,41 @@ def process_assignment(token_queue, position, value_list, forbidden_identifiers)
def
verify_assignment
(
token_queue
,
position
,
forbidden_identifiers
):
identifier_1
=
token_queue
[
position
].
v
if
identifier_1
in
forbidden_identifiers
:
raise
Exception
(
"
Identifier
"
+
identifier_1
+
"
ist bereits in Loop vorhanden und darf nicht verwendet werden.
"
)
error_handler
.
handle_error
(
position
,
"
Identifier
"
+
identifier_1
+
"
ist bereits in Loop vorhanden und darf nicht verwendet werden.
"
)
if
not
token_queue
[
position
+
1
].
k
==
'
EQUALS
'
:
raise
SyntaxError
(
"
:= in Zuweisung erwartet.
"
)
error_handler
.
handle_error
(
position
+
1
,
"
:= in Zuweisung erwartet.
"
)
if
token_queue
[
position
+
2
].
k
==
'
NUMBER
'
:
return
position
+
3
if
not
token_queue
[
position
+
2
].
k
==
'
IDENTIFIER
'
:
raise
SyntaxError
(
"
IDENTIFIER in Zuweisung erwartet.
"
)
error_handler
.
handle_error
(
position
+
2
,
"
IDENTIFIER in Zuweisung erwartet.
"
)
identifier_2
=
token_queue
[
position
+
2
].
v
if
identifier_2
in
forbidden_identifiers
:
raise
Exception
(
"
Identifier
"
+
identifier_2
+
"
ist bereits in Loop vorhanden und darf nicht verwendet werden.
"
)
error_handler
.
handle_error
(
position
+
2
,
"
Identifier
"
+
identifier_2
+
"
ist bereits in Loop vorhanden und darf nicht verwendet werden.
"
)
if
not
token_queue
[
position
+
4
].
k
==
'
NUMBER
'
:
raise
SyntaxError
(
"
NUMBER in Zuweisung erwartet.
"
)
error_handler
.
handle_error
(
position
+
4
,
"
NUMBER in Zuweisung erwartet.
"
)
if
not
token_queue
[
position
+
3
].
k
in
[
'
PLUS
'
,
'
MINUS
'
]:
raise
SyntaxError
(
"
PLUS oder MINUS in Zuweisung erwartet.
"
)
error_handler
.
handle_error
(
position
+
3
,
"
PLUS oder MINUS in Zuweisung erwartet.
"
)
return
position
+
5
def
verify_loop
(
token_queue
,
position
,
forbidden_identifiers
):
identifier_token
=
token_queue
[
position
+
1
]
if
not
identifier_token
.
k
==
'
IDENTIFIER
'
:
raise
SyntaxError
(
'
IDENTIFIER in LOOP erwartet.
'
)
if
identifier_token
.
v
in
forbidden_identifiers
:
raise
SyntaxError
(
"
Identifier
"
+
identifier_token
.
v
+
"
ist bereits in Loop vorhanden und darf nicht verwendet werden.
"
)
if
not
token_queue
[
position
+
2
].
k
==
'
DO
'
:
raise
SyntaxError
(
'
DO in LOOP erwartet.
'
)
forbidden_identifiers
.
append
(
identifier_token
.
v
)
end_found
=
False
while
not
end_found
:
position
=
verify_program
(
token_queue
,
position
,
forbidden_identifiers
)
if
token_queue
[
position
].
k
==
'
SEMICOLON
'
:
position
=
position
+
1
continue
elif
token_queue
[
position
].
k
==
'
END
'
:
end_found
=
True
else
:
raise
SyntaxError
(
"
SEMICOLON oder END erwartet.
"
)
forbidden_identifiers
.
remove
(
identifier_token
.
v
)
return
position
+
1
def
verify_program
(
token_queue
,
position
,
forbidden_identifiers
):
current_key
=
token_queue
[
position
].
k
if
current_key
==
'
IDENTIFIER
'
:
try
:
current_position
=
verify_assignment
(
token_queue
,
position
,
forbidden_identifiers
)
except
IndexError
:
raise
Exception
(
"
Frühzeitiges Ende einer Zuweisung.
"
)
elif
current_key
==
'
LOOP
'
:
try
:
current_position
=
verify_loop
(
token_queue
,
position
,
forbidden_identifiers
)
except
IndexError
:
raise
Exception
(
"
Frühzeitiges Ende eines LOOPs
"
)
else
:
raise
SyntaxError
(
"
Keine passende Anweisung gefunden
"
)
return
current_position
def
process_loop
(
token_queue
,
position
,
value_list
,
forbidden_identifiers
):
identifier_token
=
token_queue
[
position
+
1
]
if
not
identifier_token
.
k
==
'
IDENTIFIER
'
:
raise
SyntaxError
(
'
IDENTIFIER in LOOP erwartet.
'
)
error_handler
.
handle_error
(
position
+
1
,
'
IDENTIFIER in LOOP erwartet.
'
)
if
identifier_token
.
v
in
forbidden_identifiers
:
raise
SyntaxError
(
"
Identifier
"
+
identifier_token
.
v
+
"
ist bereits in Loop vorhanden und darf nicht verwendet werden.
"
)
error_handler
.
handle_error
(
position
+
1
,
"
Identifier
"
+
identifier_token
.
v
+
"
ist bereits in Loop vorhanden und darf nicht verwendet werden.
"
)
if
not
token_queue
[
position
+
2
].
k
==
'
DO
'
:
raise
SyntaxError
(
'
DO in LOOP erwartet.
'
)
error_handler
.
handle_error
(
position
+
2
,
'
DO in LOOP erwartet.
'
)
if
identifier_token
.
v
in
value_list
:
number_of_loops
=
int
(
value_list
.
get
(
identifier_token
.
v
))
...
...
@@ -137,7 +115,6 @@ def process_loop(token_queue, position, value_list, forbidden_identifiers):
saved_position
=
position
+
3
forbidden_identifiers
.
append
(
identifier_token
.
v
)
# TODO increment position without changing values when number of loops = 0
if
number_of_loops
==
0
:
end_found
=
False
position
=
saved_position
...
...
@@ -149,7 +126,7 @@ def process_loop(token_queue, position, value_list, forbidden_identifiers):
elif
token_queue
[
position
].
k
==
'
END
'
:
end_found
=
True
else
:
raise
SyntaxError
(
"
SEMICOLON oder END erwartet.
"
)
error_handler
.
handle_error
(
position
,
"
SEMICOLON oder END erwartet.
"
)
for
index
in
range
(
number_of_loops
):
position
=
saved_position
...
...
@@ -162,45 +139,94 @@ def process_loop(token_queue, position, value_list, forbidden_identifiers):
elif
token_queue
[
position
].
k
==
'
END
'
:
end_found
=
True
else
:
raise
SyntaxError
(
"
SEMICOLON oder END erwartet.
"
)
error_handler
.
handle_error
(
position
,
"
SEMICOLON oder END erwartet.
"
)
forbidden_identifiers
.
remove
(
identifier_token
.
v
)
return
position
+
1
,
value_list
def
verify_loop
(
token_queue
,
position
,
forbidden_identifiers
):
identifier_token
=
token_queue
[
position
+
1
]
if
not
identifier_token
.
k
==
'
IDENTIFIER
'
:
error_handler
.
handle_error
(
position
+
1
,
'
IDENTIFIER in LOOP erwartet.
'
)
if
identifier_token
.
v
in
forbidden_identifiers
:
error_handler
.
handle_error
(
position
+
1
,
"
Identifier
"
+
identifier_token
.
v
+
"
ist bereits in Loop vorhanden und darf nicht verwendet werden.
"
)
if
not
token_queue
[
position
+
2
].
k
==
'
DO
'
:
error_handler
.
handle_error
(
position
+
2
,
'
DO in LOOP erwartet.
'
)
forbidden_identifiers
.
append
(
identifier_token
.
v
)
end_found
=
False
while
not
end_found
:
position
=
verify_program
(
token_queue
,
position
,
forbidden_identifiers
)
if
token_queue
[
position
].
k
==
'
SEMICOLON
'
:
position
=
position
+
1
continue
elif
token_queue
[
position
].
k
==
'
END
'
:
end_found
=
True
else
:
error_handler
(
position
,
"
SEMICOLON oder END in LOOP erwartet.
"
)
forbidden_identifiers
.
remove
(
identifier_token
.
v
)
return
position
+
1
def
process_program
(
token_queue
,
position
,
value_list
,
forbidden_identifiers
):
current_position
=
position
values
=
value_list
current_key
=
token_queue
[
position
].
k
if
current_key
==
'
IDENTIFIER
'
:
try
:
current_position
,
values
=
process_assignment
(
token_queue
,
position
,
value_list
,
forbidden_identifiers
)
except
IndexError
:
raise
Excep
tion
(
"
Frühzeitiges Ende einer Zuweisung.
"
)
error_handler
.
handle_error
(
current_posi
tion
,
"
Frühzeitiges Ende einer Zuweisung.
"
)
elif
current_key
==
'
LOOP
'
:
try
:
current_position
,
values
=
process_loop
(
token_queue
,
position
,
value_list
,
forbidden_identifiers
)
except
IndexError
:
raise
Excep
tion
(
"
Frühzeitiges Ende eines LOOPs
"
)
error_handler
.
handle_error
(
current_posi
tion
,
"
Frühzeitiges Ende eines LOOPs
"
)
else
:
raise
SyntaxError
(
"
Keine passende Anweisung gefunden
"
)
error_handler
.
handle_error
(
current_position
,
"
Keine passende Anweisung gefunden
"
)
return
current_position
,
values
def
verify_program
(
token_queue
,
position
,
forbidden_identifiers
):
current_key
=
token_queue
[
position
].
k
current_position
=
position
if
current_key
==
'
IDENTIFIER
'
:
try
:
current_position
=
verify_assignment
(
token_queue
,
position
,
forbidden_identifiers
)
except
IndexError
:
error_handler
.
handle_error
(
current_position
,
"
Frühzeitiges Ende einer Zuweisung.
"
)
elif
current_key
==
'
LOOP
'
:
try
:
current_position
=
verify_loop
(
token_queue
,
position
,
forbidden_identifiers
)
except
IndexError
:
error_handler
.
handle_error
(
current_position
,
"
Frühzeitiges Ende eines LOOPs
"
)
else
:
error_handler
.
handle_error
(
current_position
,
"
Keine passende Anweisung gefunden
"
)
return
current_position
def
interpret
(
program
):
tokens
=
lexer
.
tokenize
(
program
)
global
error_handler
error_handler
=
ErrorHandler
(
program
,
tokens
)
tokens
=
[
token
for
token
in
tokens
if
not
token
.
k
==
'
LINEBREAK
'
]
current_position
=
0
values
=
{}
forbidden_identifiers
=
[]
while
current_position
<
len
(
tokens
):
current_position
,
values
=
process_program
(
tokens
,
current_position
,
values
,
forbidden_identifiers
)
if
current_position
<
len
(
tokens
)
and
not
tokens
[
current_position
].
k
==
'
SEMICOLON
'
:
raise
SyntaxError
(
"
Semicolon erwartet
"
)
error_handler
.
handle_error
(
current_position
,
"
Semicolon erwartet
"
)
else
:
if
current_position
==
len
(
tokens
)
-
1
:
error_handler
.
handle_error
(
current_position
,
"
Semikolons werden nur zur Trennung und nicht zum
"
+
"
Abschluss von Programmen verwendet
"
)
current_position
=
current_position
+
1
if
"
x0
"
in
values
:
return
values
.
get
(
"
x0
"
)
return
0
print
(
interpret
(
loop_program
))
print
(
interpret
(
'''
x1:= 2;
LOOP x1 DO x2 := 2 END; x0 := x2 + 1
'''
))
This diff is collapsed.
Click to expand it.
info4/kapitel-8/Interpreter/lexer.py
+
6
−
1
View file @
8c83627c
import
re
class
Token
:
def
__init__
(
self
,
key
,
value
):
self
.
k
=
key
...
...
@@ -17,6 +18,7 @@ def tokenize(program):
(
re
.
compile
(
r
'
DO
'
),
'
DO
'
),
(
re
.
compile
(
r
'
END
'
),
'
END
'
),
(
re
.
compile
(
r
'
;
'
),
'
SEMICOLON
'
),
(
re
.
compile
(
r
'
\n
'
,
re
.
MULTILINE
),
'
LINEBREAK
'
),
(
re
.
compile
(
r
'
\s+
'
),
'
WHITESPACE
'
)]
current_position
=
0
new_position
=
0
...
...
@@ -29,6 +31,9 @@ def tokenize(program):
new_position
=
match
.
span
()[
1
]
break
if
current_position
==
new_position
:
raise
SyntaxError
(
'
Syntax Error in line:
'
+
str
(
program
.
count
(
"
\n
"
,
0
,
current_position
)
+
1
))
msg
=
[
'
Fehler in Zeile :
'
+
str
(
program
.
count
(
"
\n
"
,
0
,
current_position
)
+
1
),
'
Erwartet: xi, :=, NUMBER, LOOP, DO, END, ;
'
,
'
Bekommen :
'
+
re
.
compile
(
r
'
[^\n]*
'
).
match
(
program
,
current_position
).
group
()]
raise
SyntaxError
(
"
\n
"
.
join
(
msg
))
current_position
=
new_position
return
token_queue
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