76 lines
1.9 KiB
Python
76 lines
1.9 KiB
Python
#! /usr/bin/env python
|
|
# -*- coding: utf-8 -*-
|
|
# vim:fenc=utf-8
|
|
#
|
|
# Copyright © 2019 pavle <pavle.portic@tilda.center>
|
|
#
|
|
# Distributed under terms of the BSD-3-Clause license.
|
|
|
|
from constants import (
|
|
NUMBER, EOF,
|
|
PLUS, MINUS, MUL, DIV, IDIV, MOD, POW, SQRT,
|
|
HEX, DEC, BIN,
|
|
SWAP, POP,
|
|
)
|
|
|
|
|
|
class InterpreterError(Exception):
|
|
pass
|
|
|
|
|
|
class Interpreter:
|
|
def __init__(self):
|
|
self.stack = []
|
|
self.mode = DEC
|
|
self.mode_func = float
|
|
|
|
def init_lexer(self, lexer):
|
|
self.lexer = lexer
|
|
self.current_token = self.lexer.get_next_token()
|
|
|
|
def evaluate_binary_operator(self, token):
|
|
if len(self.stack) < 2:
|
|
raise InterpreterError('Needs at least 2 values on the stack')
|
|
|
|
right = self.stack.pop()
|
|
left = self.stack.pop()
|
|
self.stack.append(token.value(left, right))
|
|
|
|
def evaluate_unary_operator(self, token):
|
|
if len(self.stack) < 1:
|
|
raise InterpreterError('Needs at least 1 value on the stack')
|
|
|
|
value = self.stack.pop()
|
|
self.stack.append(token.value(value))
|
|
|
|
def set_mode(self, token):
|
|
self.mode = token.type
|
|
self.mode_func = token.value
|
|
|
|
def parse(self, lexer):
|
|
self.init_lexer(lexer)
|
|
|
|
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, IDIV, MOD, 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')
|
|
|
|
self.current_token = self.lexer.get_next_token()
|
|
|
|
return self.stack
|
|
|