# 实现一个计算器(二)

2017-01-11 19:30:45来源:cnblogs.com作者:backinfile人点击

` 1 patterns = { 2     '+':  r'(/+)'    , 3     '-':  r'(-)'    , 4     '*':  r'(/*)'    , 5     '/':  r'(/)'    , 6     '(':  r'(/()'    , 7     ')':  r'(/))'    , 8     'int':r'((/+|-)?/d+(/./d+)?)' 9 }10 class Parse(object):11     def __init__(self, buf):12         self.buf = buf13         self.value = self.expr2()14     def expr2(self):15         value = self.expr1()16         while 1:17             if self.test('+'):18                 self.match('+')19                 value += self.expr1()20             elif self.test('-'):21                 self.match('-')22                 value -= self.expr1()23             else:24                 break25         return value26     def expr1(self):27         value = self.expr()28         while 1:29             if self.test('*'):30                 self.match('*')31                 value *= self.expr()32             elif self.test('/'):33                 self.match('/')34                 value /= self.expr()35             else:36                 break37         return value38     def expr(self):39         if self.test('int'):40             return self.match('int')41         elif self.test('('):42             self.match('(')43             value = self.expr2()44             self.match(')')45             return value46         else:47             raise Exception("ERROR")48     def test(self, name):49         if re.match(patterns[name], self.buf):50             return 151         else:52             return 053     def match(self, name):54         m = re.match(patterns[name], self.buf)55         if m:56             self.buf = self.buf[len(m.group(0)):]57             if name == 'int':58                 return float(m.group(1))59         Exception('cannot parse "'+name+'" out')`

`  1 import sys  2 import itertools  3 import re  4 from PyQt4 import QtGui,QtCore  5   6 patterns = {  7     '+':  r'(/+)'    ,  8     '-':  r'(-)'    ,  9     '*':  r'(/*)'    , 10     '/':  r'(/)'    , 11     '(':  r'(/()'    , 12     ')':  r'(/))'    , 13     'int':r'((/+|-)?/d+(/./d+)?)' 14 } 15 class Parse(object): 16     def __init__(self, buf): 17         self.buf = buf 18         self.value = self.expr2() 19     def expr2(self): 20         value = self.expr1() 21         while 1: 22             if self.test('+'): 23                 self.match('+') 24                 value += self.expr1() 25             elif self.test('-'): 26                 self.match('-') 27                 value -= self.expr1() 28             else: 29                 break 30         return value 31     def expr1(self): 32         value = self.expr() 33         while 1: 34             if self.test('*'): 35                 self.match('*') 36                 value *= self.expr() 37             elif self.test('/'): 38                 self.match('/') 39                 value /= self.expr() 40             else: 41                 break 42         return value 43     def expr(self): 44         if self.test('int'): 45             return self.match('int') 46         elif self.test('('): 47             self.match('(') 48             value = self.expr2() 49             self.match(')') 50             return value 51         else: 52             raise Exception("ERROR") 53     def test(self, name): 54         if re.match(patterns[name], self.buf): 55             return 1 56         else: 57             return 0 58     def match(self, name): 59         m = re.match(patterns[name], self.buf) 60         if m: 61             self.buf = self.buf[len(m.group(0)):] 62             if name == 'int': 63                 return float(m.group(1)) 64         Exception('cannot parse "'+name+'" out') 65 def calc(buf): 66     try: 67         p = Parse(str(buf)) 68         if p.buf: 69             return "ERROR" 70         return p.value 71     except Exception: 72         return "ERROR" 73 def log(buf): 74     f = open("calc.log","a") 75     f.write(buf+"/n") 76     f.close() 77  78 class Example(QtGui.QWidget): 79     def __init__(self): 80         super(Example, self).__init__() 81         self.initUI() 82         self.initData() 83     def initUI(self): 84         self.setWindowTitle('grid layout') 85         names = ['(', ')', 'back', 'clear', '7', '8', '9', '/', 86                  '4', '5', '6', '*', '1', '2', '3', '-','0', '.', '=', '+'] 87         grid = QtGui.QGridLayout() 88         self.text = QtGui.QLineEdit() 89         self.text.setFocusPolicy(QtCore.Qt.NoFocus) 90         grid.addWidget(self.text,0,0,1,4) 91         pos = list(itertools.product(range(1,6), range(4))) 92         for j,i in enumerate(names): 93             button = QtGui.QPushButton(i) 94             self.connect(button, QtCore.SIGNAL('clicked()'), self.deal) 95             grid.addWidget(button, pos[j][0], pos[j][1]) 96         self.setLayout(grid) 97     def initData(self): 98         self.oldtexts = [] 99     def deal(self):100         curtext = self.text.text()101         text = self.sender().text()102         if text == 'back':103             if self.oldtexts:104                 self.text.setText(self.oldtexts.pop())105         elif text == 'clear':106             self.text.setText("")107             self.oldtexts.append(curtext)108         elif text == '=':109             ans = str(calc(curtext))110             log(curtext+" = "+ans)111             self.text.setText(ans)112             self.oldtexts.append(curtext)113         else:114             self.text.setText(curtext+text)115             self.oldtexts.append(curtext)116 117 app = QtGui.QApplication(sys.argv)118 ex = Example()119 ex.show()120 sys.exit(app.exec_())`

`pyinstaller -F calc.py && dist/calc`