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

Erste Version Interpreter für LOOP Programme

parent f8a51ec4
import lexer
loop_program = '''x1 := 2;
x2 := 3;
x3 := x2 + 0;
LOOP x1 DO
x2 := x3 + 1;
x3 := x2 + 0
END;
x0 := x2 + 0'''
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.")
if not token_queue[position + 1].k == 'EQUALS':
raise SyntaxError(":= in Zuweisung erwartet.")
if identifier_1 in value_list:
value_1 = value_list.get(identifier_1)
else:
value_1 = 0
if token_queue[position + 2].k == 'NUMBER':
value_1 += int(token_queue[position + 2].v)
value_list.update({identifier_1: value_1})
return position+3, value_list
if not token_queue[position + 2].k == 'IDENTIFIER':
raise SyntaxError("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.")
if identifier_2 in value_list:
value_2 = value_list.get(identifier_2)
else:
value_2 = 0
if not token_queue[position + 4].k == 'NUMBER':
raise SyntaxError("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.")
value_list.update({identifier_1: value_1})
return position + 5, value_list
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.')
if not token_queue[position+2].k == 'DO':
raise SyntaxError('DO in LOOP erwartet.')
number_of_loops = int(value_list.get(identifier_token.v))
saved_position = position + 3
forbidden_identifiers.append(identifier_token.v)
for index in range(number_of_loops):
position = saved_position
end_found = False
while(not end_found):
position, value_list = process_program(token_queue, position, value_list, 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.")
return position+1, value_list
def process_program(token_queue, position, value_list, forbidden_identifiers):
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.")
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")
else:
raise SyntaxError("Keine passende Anweisung gefunden")
return current_position, values
def interpret(program):
tokens = lexer.tokenize(program)
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")
else:
current_position = current_position + 1
if "x0" in values:
return values.get("x0")
return 0
print(interpret(loop_program))
import re
class Token:
def __init__(self, key, value):
self.k = key
self.v = value
def tokenize(program):
token_queue = []
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'\s+'), 'WHITESPACE')]
current_position = 0
new_position = 0
while current_position < len(program):
for pattern, value in regex_to_token:
match = pattern.match(program, current_position)
if match:
if not value == 'WHITESPACE':
token_queue.append(Token(value, match.group()))
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))
current_position = new_position
return token_queue
%% Cell type:code id: tags:
``` python
%run Interpreter/lexer.py
```
%% Output
HI
File "<string>", line unknown
SyntaxError: Syntax Error in line: 4
%% Cell type:code id: tags:
``` python
tokenize("LOOP x1 DO P END")
```
%% Output
HI
Traceback (most recent call last):
File "/usr/lib/python3.8/site-packages/IPython/core/interactiveshell.py", line 3418, in run_code
exec(code_obj, self.user_global_ns, self.user_ns)
File "<ipython-input-2-93cfbd622072>", line 1, in <module>
tokenize("LOOP x1 DO P END")
File "/home/christopher/uni/Projektarbeit/prob-teaching-notebooks/info4/kapitel-8/Interpreter/lexer.py", line 43, in tokenize
raise SyntaxError('Syntax Error in line: ' + str(program.count("\n", 0, current_position) + 1))
File "<string>", line unknown
SyntaxError: Syntax Error in line: 1
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