7 from libraries.recipes import algorithms
18 def parse_number(userInput):
20 base = __BASE_MAPPINGS.get(userInput[0:2], 10)
22 userInput = userInput[2:] # Remove prefix
23 value = int(userInput, base)
29 value = float(userInput)
35 value = complex(userInput)
40 raise ValueError('Cannot parse "%s" as a number' % userInput)
43 class AbstractHistory(object):
45 Is it just me or is this class name begging for some jokes?
49 raise NotImplementedError
52 raise NotImplementedError
56 for child in node.get_children():
60 raise NotImplementedError
63 raise NotImplementedError
66 raise NotImplementedError
69 raise NotImplementedError
72 class CalcHistory(AbstractHistory):
75 super(CalcHistory, self).__init__()
79 assert node is not None
80 self.__nodeStack.append(node)
84 popped = self.__nodeStack[-1]
85 del self.__nodeStack[-1]
89 return self.__nodeStack[-1]
95 return len(self.__nodeStack)
98 return self.__nodeStack[::-1]
101 class RpnCalcHistory(object):
103 def __init__(self, history, entry, errorReporting, constants, operations):
104 self.history = history
105 self.__entry = weakref.ref(entry)
107 self.__errorReporter = errorReporting
108 self.__constants = constants
109 self.__operations = operations
111 self.__serialRenderer = operation.render_number()
114 def errorReporter(self):
115 return self.__errorReporter
118 def OPERATIONS(self):
119 return self.__operations
123 return self.__constants
127 self.__entry().clear()
129 def push_entry(self):
131 @todo Add operation duplication. If value is empty, peek at the top
132 item. If it has children, grab the last one, push it and reapply the
133 operation. If there are no children then just duplicate the item
136 value = self.__entry().get_value()
140 valueNode = self._parse_value(value)
141 self.history.push(valueNode)
143 self.__entry().clear()
146 def apply_operation(self, Node):
150 node = self._apply_operation(Node)
152 except StandardError, e:
153 self.errorReporter.push_exception()
156 def serialize_stack(self):
158 stackNode.serialize(self.__serialRenderer)
159 for stackNode in self.history
161 serialized = list(serialized)
165 def deserialize_stack(self, data):
166 for possibleNode in data:
167 for nodeValue in possibleNode:
168 if nodeValue in self.OPERATIONS:
169 Node = self.OPERATIONS[nodeValue]
170 self._apply_operation(Node)
172 node = self._parse_value(nodeValue)
173 self.history.push(node)
175 def _parse_value(self, userInput):
177 value, base = parse_number(userInput)
178 return operation.Value(value, base)
183 return self.CONSTANTS[userInput]
187 return operation.Variable(userInput)
189 def _apply_operation(self, Node):
190 numArgs = Node.argumentCount
192 if len(self.history) < numArgs:
194 "Not enough arguments. The stack has %d but %s needs %d" % (
195 len(self.history), Node.symbol, numArgs
199 args = [arg for arg in algorithms.func_repeat(numArgs, self.history.pop)]
204 except StandardError:
206 self.history.push(arg)
208 self.history.push(node)