Add swap and pop operations and simplify code

This commit is contained in:
Pavle Portic 2019-04-26 15:07:28 +02:00
parent d7fe9c4ee5
commit a2d9109ae8
Signed by: TheEdgeOfRage
GPG Key ID: 6758ACE46AA2A849
4 changed files with 45 additions and 44 deletions

View File

@ -20,3 +20,6 @@ HEX = 'HEX'
DEC = 'DEC'
BIN = 'BIN'
SWAP = 'SWAP'
POP = 'POP'

View File

@ -10,9 +10,14 @@ from constants import (
NUMBER, EOF,
PLUS, MINUS, MUL, DIV, POW, SQRT,
HEX, DEC, BIN,
SWAP, POP,
)
class InterpreterError(Exception):
pass
class Interpreter:
def __init__(self):
self.stack = []
@ -23,39 +28,20 @@ class Interpreter:
self.lexer = lexer
self.current_token = self.lexer.get_next_token()
def eat(self, type):
if self.current_token.type == type:
self.current_token = self.lexer.get_next_token()
else:
raise Exception('Wrong token eaten')
def get_from_stack(self, pop=True):
if pop:
value = self.stack.pop()
else:
value = self.stack[-1]
if type(value) is str:
return self.ariables[value]
return value
def evaluate_binary_operator(self, token):
if len(self.stack) < 2:
raise Exception('Needs at least 2 values on the stack')
raise InterpreterError('Needs at least 2 values on the stack')
right = self.get_from_stack()
left = self.get_from_stack()
right = self.stack.pop()
left = self.stack.pop()
self.stack.append(token.value(left, right))
self.eat(token.type)
def evaluate_unary_operator(self, token):
if len(self.stack) < 1:
raise Exception('Needs at least 1 value on the stack')
raise InterpreterError('Needs at least 1 value on the stack')
value = self.get_from_stack()
value = self.stack.pop()
self.stack.append(token.value(value))
self.eat(token.type)
def set_mode(self, token):
self.mode = token.type
@ -63,21 +49,27 @@ class Interpreter:
def parse(self, lexer):
self.init_lexer(lexer)
token = self.current_token
while token.type is not EOF:
if token.type in (PLUS, MINUS, MUL, DIV, POW):
self.evaluate_binary_operator(token)
elif token.type in (SQRT):
self.evaluate_unary_operator(token)
elif token.type == NUMBER:
self.stack.append(token.value)
self.eat(NUMBER)
elif token.type in (HEX, DEC, BIN):
self.set_mode(token)
self.eat(token.type)
while self.current_token.type is not EOF:
if self.current_token.type == NUMBER:
self.stack.append(self.current_token.value)
elif self.current_token.type in (PLUS, MINUS, MUL, DIV, POW):
self.evaluate_binary_operator(self.current_token)
elif self.current_token.type in (SQRT):
self.evaluate_unary_operator(self.current_token)
elif self.current_token.type == SWAP:
a = self.stack.pop()
b = self.stack.pop()
self.stack.append(a)
self.stack.append(b)
elif self.current_token.type == POP:
self.stack.pop()
elif self.current_token.type in (HEX, DEC, BIN):
self.set_mode(self.current_token)
else:
raise InterpreterError('Unexpected token')
token = self.current_token
self.current_token = self.lexer.get_next_token()
return self.stack

View File

@ -14,6 +14,7 @@ from constants import (
NUMBER, EOF,
PLUS, MINUS, MUL, DIV, POW, SQRT,
HEX, DEC, BIN,
SWAP, POP,
)
@ -84,14 +85,19 @@ class Lexer():
text += self.current_char
self.advance()
if text.lower() == HEX.lower():
check = text.lower()
if check.lower() == HEX.lower():
return Token(HEX, hex)
elif text.lower() == DEC.lower():
elif check.lower() == DEC.lower():
return Token(DEC, float)
elif text.lower() == BIN.lower():
elif check.lower() == BIN.lower():
return Token(BIN, bin)
elif text.lower() == SQRT.lower():
elif check.lower() == SQRT.lower():
return Token(SQRT, math.sqrt)
elif check.lower() == SWAP.lower():
return Token(SWAP, text)
elif check.lower() == POP.lower():
return Token(POP, text)
else:
self.error(text)

View File

@ -7,7 +7,7 @@
# Distributed under terms of the BSD-3-Clause license.
from lexer import Lexer
from interpreter import Interpreter
from interpreter import Interpreter, InterpreterError
from constants import DEC
@ -37,8 +37,8 @@ def main():
lexer = Lexer(text)
try:
stack = interpreter.parse(lexer)
except Exception as exception:
print(exception)
except InterpreterError as err:
print(err)
print_stack(interpreter, stack)