Add swap and pop operations and simplify code
This commit is contained in:
parent
d7fe9c4ee5
commit
a2d9109ae8
|
@ -20,3 +20,6 @@ HEX = 'HEX'
|
|||
DEC = 'DEC'
|
||||
BIN = 'BIN'
|
||||
|
||||
SWAP = 'SWAP'
|
||||
POP = 'POP'
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
14
lexer.py
14
lexer.py
|
@ -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)
|
||||
|
||||
|
|
6
main.py
6
main.py
|
@ -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)
|
||||
|
||||
|
|
Loading…
Reference in New Issue