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

Fehlerbehandlung überarbeitet

parent da836c18
No related branches found
No related tags found
Loading
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 Exception("Frühzeitiges Ende einer Zuweisung.")
error_handler.handle_error(current_position, "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 Exception("Frühzeitiges Ende eines LOOPs")
error_handler.handle_error(current_position, "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'''))
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
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment