Created
May 24, 2019 12:40
-
-
Save bigshans/086a704fa5a2dc51a7a474658eb0df3e to your computer and use it in GitHub Desktop.
A simple lisp adder interpreter.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/python3 | |
class Tokenize: | |
def __init__(self, context): | |
self.context = context.replace('(', ' ( ').replace(')', ' ) ').split() | |
self.top = -1 | |
def getNextToken(self): | |
self.top += 1 | |
if self.top < len(self.context): | |
return self.context[self.top] | |
return None | |
def getType(self): | |
if self.top >= len(self.context): | |
return None | |
token = self.context[self.top] | |
if token.isdigit(): | |
return 'Integer' | |
elif token == '+': | |
return 'Plus' | |
elif token == '-': | |
return 'Cut' | |
elif token == '*': | |
return 'Mul' | |
elif token == '/': | |
return 'Div' | |
elif token == '(': | |
return '(' | |
elif token == ')': | |
return ')' | |
else: | |
raise Exception('Unknow token ' + token) | |
class Interpreter: | |
def __init__(self, tokens): | |
self.tokens = tokens | |
def error(self): | |
raise Exception('Invalid syntax') | |
def eat(self): | |
self.tokens.getNextToken() | |
def factor(self): | |
current_token = self.tokens.getNextToken() | |
current_type = self.tokens.getType() | |
result = 'Error' | |
# print(current_token) | |
# print(current_type) | |
if current_type == '(': | |
return self.term() | |
elif current_type == ')': | |
return None, current_type | |
elif current_type == 'Integer': | |
result = int(current_token) | |
elif current_type == 'Plus' or \ | |
current_type == 'Cut' or \ | |
current_type == 'Mul' or current_type == 'Div': | |
result = current_type | |
return result, current_type | |
def term(self): | |
result_set = [] | |
result_type = [] | |
while True: | |
result, current_type = self.factor() | |
# print(result, current_type) | |
# print(result is None) | |
if result is not None and result != 'Error': | |
result_set.append(result) | |
result_type.append(current_type) | |
continue | |
if result == 'Error': | |
raise Exception('Less right bracket') | |
break | |
# print(result_set) | |
# print(result_type) | |
opt_args = len(result_set[1:]) | |
if result_type[0] == 'Plus' and opt_args == 2: | |
return result_set[1] + result_set[2], 'Integer' | |
elif result_type[0] == 'Cut' and opt_args == 2: | |
return result_set[1] - result_set[2], 'Integer' | |
elif result_type[0] == 'Mul' and opt_args == 2: | |
return result_set[1] * result_set[2], 'Integer' | |
elif result_type[0] == 'Div' and opt_args == 2: | |
if result_set[2] == 0: | |
raise Exception("Can't divide by zero") | |
else: | |
return result_set[1] // result_set[2], 'Integer' | |
elif result_type[0] == 'Integer': | |
return result_set[0], result_type[0] | |
else: | |
raise Exception('Wrong argument number') | |
def expr(self): | |
result = self.factor() | |
# print(result) | |
if self.tokens.getNextToken() is not None: | |
raise Exception('Too many right bracket') | |
print(result[0]) | |
if __name__ == '__main__': | |
print('Please input your lisp statement!') | |
while True: | |
st = input('>> ') | |
st = st.strip() | |
if st == '': | |
continue | |
else: | |
Interpreter(Tokenize(st)).expr() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment