Skip to content

Instantly share code, notes, and snippets.

@bigshans
Created May 24, 2019 12:40
Show Gist options
  • Save bigshans/086a704fa5a2dc51a7a474658eb0df3e to your computer and use it in GitHub Desktop.
Save bigshans/086a704fa5a2dc51a7a474658eb0df3e to your computer and use it in GitHub Desktop.
A simple lisp adder interpreter.
#!/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