Witam, niedawno zacząłem się uczyć pythona ( znam już C++ ). po raz pierwszy zabrałem się na jakiś prosty projekt w tym języku, jest nim Parser arytmetyczny, oto kod jaki napisałem:
drzewo wyrażeń ( działa ok ):
import Parser.exceptions as err
class Expression:
def eval(self, memory):
raise NotImplementedError
class Constant(Expression):
def __init__(self, value):
self.value = value
def eval(self, memory):
return self.value
class Variable(Expression):
def __init__(self, name):
self.name = name
def eval(self, memory):
if self.name in memory:
return memory[self.name]
else:
raise err.BadASTVariableReferError(self.name)
class BinaryOperator(Expression):
def __init__(self, operator, left_exp, right_exp):
self.operator = operator
self.left_exp = left_exp
self.right_exp = right_exp
def eval(self, memory):
if self.operator == '+':
return self.left_exp.eval(memory) + self.right_exp.eval(memory)
elif self.operator == '-':
return self.left_exp.eval(memory) - self.right_exp.eval(memory)
elif self.operator == '*':
return self.left_exp.eval(memory) * self.right_exp.eval(memory)
elif self.operator == '/':
return self.left_exp.eval(memory) / self.right_exp.eval(memory)
elif self.operator == '%':
return self.left_exp.eval(memory) % self.right_exp.eval(memory)
elif self.operator == '^':
return self.left_exp.eval(memory) ** self.right_exp.eval(memory)
else:
raise err.BadASTOperatorError(self.operator)
parser budujący drzewo wyrażeń ( mnóstwo problemów ):
import Parser.exceptions as err
import Parser.AST as stree
class Parser:
def __init__(self, input_data):
self.input_data = input_data
self.input_data += '$'
self.position = 0
def skip_whitespace(self):
while self.input_data[self.position].isspace():
self.position += 1
def look_ahead(self):
self.skip_whitespace()
return self.input_data[self.position]
def parse_expression(self):
e = self.parse_sum()
if self.look_ahead() == '$':
return e
else:
raise err.NotParsed()
def parse_sum(self):
e = self.parse_mult()
c = self.look_ahead()
while c == '+' or c == '-':
self.position += 1
e = stree.BinaryOperator(c, e, self.parse_mult())
return e
def parse_mult(self):
e = self.parse_term()
c = self.look_ahead()
while c == '*' or c == '/' or c == '%' or c == '^':
self.position += 1
e = stree.BinaryOperator(c, e, self.parse_term())
c = self.look_ahead()
return e
def parse_term(self):
c = self.look_ahead()
if c.isdigit():
return self.parse_constant()
elif c.isalpha():
return self.parse_variable()
elif c == '(':
return self.parse_paren()
else:
raise err.NotParsed()
def parse_constant(self):
s = str()
while self.input_data[self.position].isdigit() or self.input_data[self.position] == '.':
s += self.input_data[self.position]
self.position += 1
try:
v = float(s)
return stree.Constant(v)
except ValueError:
raise err.NotParsed()
def parse_variable(self):
s = str()
while self.input_data[self.position].isalpha():
s += self.input_data[self.position]
self.position += 1
return stree.Variable(s)
def parse_paren(self):
self.position += 1
e = self.parse_sum()
if self.look_ahead() == ')':
self.position += 1
return e
else:
raise err.NotParsed()
oraz plik main.py:
import Parser.parser as prs
var = {
'PI': 3.14
}
# input_data = str(input("Your expression: "))
parser = prs.Parser('10+10')
expression = parser.parse_expression()
# print(expression.eval(var))
Nie dałem tu wszystkich plików ( brakuje pliku z klasami wyjątków ) bo nie wiem czy jest sens dawać dały kod. Jeśli ktoś jednak chce uruchomić ten program to mogę zrobić repozytorium i dać linka...
oto lista błędów:
Traceback (most recent call last):
File "C:/Users/komputer/first/main.py", line 10, in <module>
expression = parser.parse_expression()
File "C:\Users\komputer\first\Parser\parser.py", line 20, in parse_expression
e = self.parse_sum()
File "C:\Users\komputer\first\Parser\parser.py", line 31, in parse_sum
e = stree.BinaryOperator(c, e, self.parse_mult())
File "C:\Users\komputer\first\Parser\parser.py", line 35, in parse_mult
e = self.parse_term()
File "C:\Users\komputer\first\Parser\parser.py", line 44, in parse_term
c = self.look_ahead()
File "C:\Users\komputer\first\Parser\parser.py", line 16, in look_ahead
self.skip_whitespace()
File "C:\Users\komputer\first\Parser\parser.py", line 12, in skip_whitespace
while self.input_data[self.position].isspace():
IndexError: string index out of range
mówiąc szczerze to nie wiem zupełnie o co w tych błędach chodzi poza ostatnim. Starałem się szukać informacji ale dalej nie wiem co zrobiłem źle...
bardzo dziękuje za pomoc i pozdrawiam :)