AbacusNG/abacus_core.py

182 lines
5.8 KiB
Python

class AbacusCore:
def __init__(self):
self._input_string = input
self._vars = dict()
self._funcs = dict()
self._vars['result'] = 0
self._vars['alphabet'] = 28
self._vars['alpha'] = 1
self._vars['beta'] = 2
self._operators = ['+', '-', '/', '*']
self._delimiters = ['(', ')', '[', ']', ';', ' ']
def get_vars(self):
return self._vars
def get_funcs(self):
return self._funcs
def add_var(self, name, value):
self._vars[name] = value
def _calculate(self, input_str):
print('input:', input_str)
try:
return eval(input_str)
except ZeroDivisionError:
res = 'Division by Zero'
except NameError as e:
res = 'Variable '+ e.name + ' not exists'
except SyntaxError as e:
res = 'Syntax Error'
return res
def parse_input(self, input_str):
'''
versuche input_str zu parsen in comment vars und andere teile
:param input_str:
:return:
'''
input_str = input_str.strip()
comment = None
orig_input_str = input_str
if len(input_str) < 1: # leere eingabe wird nicht akzeptiert
return
if input_str[0] == '#': # ganze eingabe ist ein kommentar
comment = input_str
return None, None, None, comment
chunks = input_str.split('#')
if len(chunks) > 1:
input_str = chunks[0]
comment = ' '.join(chunks[1:])
chunks = input_str.split('=') # gibt es variablenzuweisung?
if len(chunks) > 2:
raise ValueError('Mehrfachzuweisung wird nicht unterstützt')
elif len(chunks) > 1:
expression = self._with_variable_another_way(chunks[1])
chunks[0] = '_'.join(chunks[0].strip().split(' '))
self._vars[chunks[0]] = expression
return
chunks = input_str.split(':') # gibt es funktionsdefinition?
if len(chunks) > 1:
self._funcs[chunks[0]] = chunks[1]
return
res = self._with_variable_another_way(input_str)
self._vars['result'] = res
return orig_input_str, None, res, comment
def _with_variable_another_way(self, input_str):
input_str, comment = self._get_input_wo_commentar(input_str)
input_str = ''.join(input_str.split()) # entferne alle leerzeichen
input_str = input_str.replace(',', '.')
opdel = self._operators + self._delimiters
chunks = list()
last_index = 0
for i, v in enumerate(input_str):
if v in opdel:
chunk = input_str[last_index:i]
chunk = self._is_a_variable_or_func(chunk)
chunks.append(chunk)
chunks.append(input_str[i])
last_index = i+1
elif i == len(input_str)-1:
chunk = input_str[last_index:i+1]
chunk = self._is_a_variable_or_func(chunk)
chunks.append(chunk)
return eval(''.join(chunks))
def _is_a_variable_or_func(self, chunk):
var = self._vars.get(chunk)
if not var:
var = self._funcs.get(chunk)
if var:
var = self._with_variable_another_way(var)
if var:
return str(var)
else:
return chunk
def _replace_vars(self, input_str):
'''
try to find vars and replace them
:param input_str:
:return:
'''
first_position = None
new_input_str = ''
op_del = self._operators + self._delimiters
if input_str[0] in self._operators:
input_str = 'result' + input_str
input_str_len = len(input_str)
for i, c in enumerate(input_str):
if c in op_del or i == input_str_len-1: # and first_position is not None:
if first_position is not None:
last_position = i
if i == input_str_len-1:
last_position += 1
temp_var = input_str[first_position:last_position]
print('var', temp_var)
var = self._vars.get(temp_var)
if var is not None:
new_input_str += str(var)
else:
func = self._funcs.get(temp_var)
if func:
new_input_str += str(func)
else:
raise NotImplemented()
first_position = None
if i == input_str_len - 1:
continue
new_input_str += input_str[i]
elif c.isalpha() or c=='_':
if first_position is None:
first_position = i
else:
new_input_str += input_str[i]
return new_input_str
def _get_input_wo_commentar(self, input_str):
'''
Zerlege input in input und kommentar
:param input_str:
:return:
'''
input_str = input_str.strip()
comment_index = input_str.find('#')
if comment_index == 0: # die ganze zeile ist ein kommentar
return None, input_str
elif comment_index == -1:
return input_str, None
else:
comment = input_str[comment_index + 1:]
input_str = input_str[:comment_index]
return input_str, comment
def _is_new_variable(self, input_str):
'''
'''
chunks = input_str.split('=')
chunks_len = len(chunks)
if chunks_len > 2:
raise ValueError()
# chunks.reverse()
elif chunks_len == 2:
return chunks[1], chunks[0]
else:
return chunks[0], None