1. #!/usr/bin/python
  2.  
  3. """
  4. From wikipedia: http://en.wikipedia.org/wiki/Reverse_Polish_notation
  5.  
  6. In reverse Polish notation the operators follow their operands; for
  7. instance, to add 3 and 4, one would write '3 4 +' rather than '3 + 4'.
  8.  
  9. If there are multiple operations, the operator is given immediately
  10. after its second operand; so the expression written '3 - 4 + 5' in
  11. conventional notation would be written '3 4 - 5 +' in RPN: first
  12. subtract 4 from 3, then add 5 to that.
  13.  
  14. An advantage of RPN is that it obviates the need for parentheses that
  15. are required by infix. While '3 - 4 * 5' can also be written
  16. '3 - (4 * 5)', that means something quite different from'(3 - 4) * 5'. In
  17. postfix, the former could be written '3 4 5 * -', which unambiguously
  18. means '3 (4 5 *) -' which reduces to '3 20 -'; the latter could be
  19. written '3 4 - 5 *' (or 5 3 4 - *, if you wish to keep similar
  20. formatting), which unambiguously means '(3 4 -) 5 *'.
  21.  
  22. The reverse Polish scheme was proposed in 1954 by Burks, Warren, and
  23. Wright[1] and was independently reinvented by F. L. Bauer and
  24. E. W. Dijkstra in the early 1960s to reduce computer memory access and
  25. utilize the stack to evaluate expressions. The algorithms and notation
  26. for this scheme were extended by Australian philosopher and computer
  27. scientist Charles Hamblin in the mid-1950s.[2][3]
  28.  
  29. During the 1970s and 1980s, RPN was known to many calculator users, as
  30. it was used in some handheld calculators of the time designed for
  31. advanced users: for example, the HP-10C series and Sinclair Scientific
  32. calculators.
  33.  
  34. In computer science, postfix notation is often used in stack-based and
  35. concatenative programming languages.
  36.  
  37. """
  38.  
  39. from go import *
  40.  
  41. #---| lib stuff |------
  42.  
  43. import sys
  44. def say(x):
  45. sys.stdout.write(x)
  46.  
  47. #--- interpreter for reverse polish notation
  48.  
  49. def postorder(x):
  50. return postorder1(x,[])
  51.  
  52. def postorder1(x,out):
  53. leaf = lambda y: not isinstance(y,list)
  54. left = lambda y: y[0]
  55. head = lambda y: y[1]
  56. right = lambda y: y[2]
  57. if leaf(x):
  58. out += [x]
  59. else:
  60. postorder1(left(x), out)
  61. postorder1(right(x),out)
  62. postorder1(head(x), out)
  63. return out
  64.  
  65. #@go
  66. def _postorder():
  67. print postorder( [[1, "+",2],
  68. "*",
  69. [2, "-", 3]] )
  70.  
  71. #-----------------------------------------
  72. # evaluator for rpn
  73. def rpn(input):
  74. minus = lambda x,y : float(x) - float(y)
  75. plus = lambda x,y : float(x) + float(y)
  76. mult = lambda x,y : float(x) * float(y)
  77. args = {"+" : plus,
  78. "*" : mult,
  79. "-" : minus}
  80. operator = lambda x: x in args
  81. stack = []
  82. while input:
  83. token = input.pop(0)
  84. if not operator(token):
  85. stack += [token]
  86. else:
  87. two = stack.pop()
  88. one = stack.pop()
  89. f= args[token]
  90. stack += [f(one,two)]
  91. return stack[0]
  92.  
  93. @go
  94. def _shunt():
  95. say("5 + ((1 + 2) * 4) - 3 = " )
  96. print rpn([5,1,2,"+",4,"*","+",3,"-"])
  97.  
  98. # -------------------------------------------
  99. # infix to rpn translator
  100.  
  101. # class stuff definitions
  102.  
  103. class Op:
  104. all = []
  105. def __init__(i,name,precedence=100):
  106. i.name=name
  107. i.precedence = precedence
  108. Op.all += [i]
  109. def __repr__(i):
  110. return i.name + '{' + str(i.precedence) + '}'
  111. # parsing utils
  112. def isa(x):
  113. "Try to find the operator names 'x'. Else fail."
  114. for y in Op.all:
  115. if x == y.name: return y
  116. return None
  117. def isNum(x):
  118. "Let Python do the heavy lifting"
  119. try: return int(x)
  120. except ValueError:
  121. try: return float(x)
  122. except ValueError:
  123. return None
  124.  
  125. # main engine
  126. import re
  127. class Shunt:
  128. """ Simple version of Edsger Dijkstra's shunting yard algorithm.
  129. No associativity, brackets, function symbols, arguments.
  130. No error checking.
  131. For full version, see http://goo.gl/pakbVu
  132. """
  133. def __init__(i,str):
  134. say(str + ' : ')
  135. i.out = []
  136. i.stack = []
  137. for token in i.tokens(str):
  138. i.shunt(token)
  139. # tidy up
  140. while i.stack: i.up()
  141. def __repr__(i) : return str(i.out)
  142. def over(i,token) : say("o"); i.out += token
  143. def down(i,op) : say("d"); i.stack += [op]
  144. def up(i) : say("u"); i.out += [i.stack.pop()]
  145. def somethingIsMoreImportant(i,op):
  146. return i.stack and op.precedence <= i.stack[-1].precedence
  147. def tokens(i,str):
  148. "dumb tokenizer: assumes tokens one char wide)"
  149. return list(re.sub("[ \t]*","",str))
  150. def shunt(i,token):
  151. op = isa(token)
  152. if not op:
  153. i.over(token)
  154. else:
  155. while i.somethingIsMoreImportant(op):
  156. i.up()
  157. i.down(op)
  158. # demos
  159. @go
  160. def _shunt():
  161. Op.all = []
  162. Op('+',1)
  163. Op('*',2)
  164. Op('/',2)
  165. print Shunt("1 + 2")
  166. print Shunt("1 + 2 + 3")
  167. print Shunt("1 + 2 / 3")
  168. print Shunt("a * b + c / d")
  169. print Shunt("a * b + c * d")