1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74
|
#!/usr/bin/env python3
# -*- coding: UTF-8 -*-
"""
Simple four operations calculator.
"""
import operator
from ptk.lexer import ReLexer, token
from ptk.parser import LRParser, leftAssoc, production, ParseError
@leftAssoc('+', '-')
@leftAssoc('*', '/')
class SimpleCalc(LRParser, ReLexer):
def newSentence(self, result):
print('== Result:', result)
# Lexer
def ignore(self, char):
return char in [' ', '\t']
@token(r'[1-9][0-9]*')
def number(self, tok):
tok.value = int(tok.value)
# Parser
@production('E -> "-" E<value>', priority='*')
def minus(self, value):
print('== Neg: - %d' % value)
return -value
@production('E -> "(" E<value> ")"')
def paren(self, value):
return value
@production('E -> number<number>')
def litteral(self, number):
return number
@production('E -> E<left> "+"<op> E<right>')
@production('E -> E<left> "-"<op> E<right>')
@production('E -> E<left> "*"<op> E<right>')
@production('E -> E<left> "/"<op> E<right>')
def binaryop(self, left, op, right):
print('Binary operation: %s %s %s' % (left, op, right))
return {
'+': operator.add,
'-': operator.sub,
'*': operator.mul,
'/': operator.floordiv
}[op](left, right)
if __name__ == '__main__':
import logging
logging.basicConfig(level=logging.WARNING, format='%(asctime)-15s %(levelname)-8s %(name)-15s %(message)s')
print('Enter an arithmetic expression.')
parser = SimpleCalc()
while True:
try:
line = input('> ')
except (KeyboardInterrupt, EOFError):
print()
break
try:
parser.parse(line)
except ParseError as exc:
print('Parse error: %s' % exc)
print('Expected %s' % exc.expecting())
|