Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- # LEXER
- NUMBER = 'NUMBER'
- ADD = 'ADD'
- SUB = 'SUB'
- MUL = 'MUL'
- DIV = 'DIV'
- LPAR = '('
- RPAR = ')'
- EOF = 'EOF'
- class Token(object):
- def __init__(self, type, val):
- self.type = type
- self.val = val
- def __str__(self):
- return 'Token({type}, {val})'.format(
- type=self.type,
- val=repr(self.val)
- )
- def __repr__(self):
- return self.__str__()
- class Lexer(object):
- def __init__(self, txt):
- self.txt = txt
- self.pos = 0
- self.char_crnt = self.txt[self.pos]
- def movePointer(self):
- self.pos += 1
- if self.pos > len(self.txt) - 1:
- self.char_crnt = None
- else:
- self.char_crnt = self.txt[self.pos]
- def skipSpace(self):
- while self.char_crnt is not None and self.char_crnt.isspace():
- self.movePointer()
- def getMultiNum(self):
- result = ''
- while self.char_crnt is not None and self.char_crnt.isdigit():
- result += self.char_crnt
- self.movePointer()
- return int(result)
- def nextToken(self):
- while self.char_crnt is not None:
- if self.char_crnt.isspace():
- self.skipSpace()
- continue
- if self.char_crnt.isdigit():
- return Token(NUMBER, self.getMultiNum())
- if self.char_crnt == '+':
- self.movePointer()
- return Token(ADD, '+')
- if self.char_crnt == '-':
- self.movePointer()
- return Token(SUB, '-')
- if self.char_crnt == '*':
- self.movePointer()
- return Token(MUL, '*')
- if self.char_crnt == '/':
- self.movePointer()
- return Token(DIV, '/')
- if self.char_crnt == '(':
- self.movePointer()
- return Token(LPAR, '(')
- if self.char_crnt == ')':
- self.movePointer()
- return Token(RPAR, ')')
- self.showError()
- return Token(EOF, None)
- def showError(self):
- raise Exception('Character not valid.')
- # PARSER
- class AbsSynTree(object):
- pass
- class BinaryOperator(AbsSynTree):
- def __init__(self, left, op, right):
- self.left = left
- self.token = self.op = op
- self.right = right
- class UnaryOperator(AbsSynTree):
- def __init__(self, op, expr):
- self.token = self.op = op
- self.expr = expr
- class Num(AbsSynTree):
- def __init__(self, token):
- self.token = token
- self.val = token.val
- class Parser(object):
- def __init__(self, lexer):
- self.lexer = lexer
- self.crntToken = self.lexer.nextToken()
- def eat(self, token_type):
- if self.crntToken.type == token_type:
- self.crntToken = self.lexer.nextToken()
- else:
- self.showError()
- def factor(self):
- token = self.crntToken
- if token.type == ADD:
- self.eat(ADD)
- node = UnaryOperator(token, self.factor())
- return node
- elif token.type == SUB:
- self.eat(SUB)
- node = UnaryOperator(token, self.factor())
- return node
- elif token.type == NUMBER:
- self.eat(NUMBER)
- return Num(token)
- elif token.type == LPAR:
- self.eat(LPAR)
- node = self.expr()
- self.eat(RPAR)
- return node
- def term(self):
- node = self.factor()
- while self.crntToken.type in (MUL, DIV):
- token = self.crntToken
- if token.type == MUL:
- self.eat(MUL)
- elif token.type == DIV:
- self.eat(DIV)
- node = BinaryOperator(left=node, op=token, right=self.factor())
- return node
- def expr(self):
- node = self.term()
- while self.crntToken.type in (ADD, SUB):
- token = self.crntToken
- if token.type == ADD:
- self.eat(ADD)
- elif token.type == SUB:
- self.eat(SUB)
- node = BinaryOperator(left=node, op=token, right=self.term())
- return node
- def parse(self):
- node = self.expr()
- if self.crntToken.type != EOF:
- self.showError()
- return node
- def showError(self):
- raise Exception('Syntax is not valid.')
- # INTERPRETER
- class NodeChecker(object):
- def visit(self, node):
- mthd_name = 'visit_' + type(node).__name__
- visitor = getattr(self, mthd_name, self.visit_Generic)
- return visitor(node)
- def visit_Generic(self, node):
- raise Exception('visit_{} method not found.'.format(type(node).__name__))
- class Interpreter(NodeChecker):
- def __init__(self, parser):
- self.parser = parser
- def visit_BinaryOperator(self, node):
- if node.op.type == ADD:
- return self.visit(node.left) + self.visit(node.right)
- elif node.op.type == SUB:
- return self.visit(node.left) - self.visit(node.right)
- elif node.op.type == MUL:
- return self.visit(node.left) * self.visit(node.right)
- elif node.op.type == DIV:
- return self.visit(node.left) / self.visit(node.right)
- def visit_UnryOprtr(self, node):
- op = node.op.type
- if op == ADD:
- return +self.visit(node.expr)
- elif op == SUB:
- return -self.visit(node.expr)
- def visit_Num(self, node):
- return node.val
- def interpret(self):
- tree = self.parser.parse()
- if tree is None:
- return ''
- return self.visit(tree)
- def main():
- print('Welcome to Basic Arithmetic Expression (BAE) Interpreter.')
- while True:
- try:
- try:
- txt = input('>> ')
- except NameError:
- txt = input('>> ')
- except EOFError:
- break
- if not txt:
- continue
- lexer = Lexer(txt)
- parser = Parser(lexer)
- interpreter = Interpreter(parser)
- result = interpreter.interpret()
- print(result)
- if __name__ == '__main__':
- main()
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement