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)
164 def deserialize_stack(self, data):
165 for possibleNode in data:
166 for nodeValue in possibleNode:
167 if nodeValue in self.OPERATIONS:
168 Node = self.OPERATIONS[nodeValue]
169 self._apply_operation(Node)
171 node = self._parse_value(nodeValue)
172 self.history.push(node)
174 def _parse_value(self, userInput):
176 value, base = parse_number(userInput)
177 return operation.Value(value, base)
182 return self.CONSTANTS[userInput]
186 return operation.Variable(userInput)
188 def _apply_operation(self, Node):
189 numArgs = Node.argumentCount
191 if len(self.history) < numArgs:
193 "Not enough arguments. The stack has %d but %s needs %d" % (
194 len(self.history), Node.symbol, numArgs
198 args = [arg for arg in algorithms.func_repeat(numArgs, self.history.pop)]
203 except StandardError:
205 self.history.push(arg)
207 self.history.push(node)