Advertisement
RobotBubble

Calculator

Oct 24th, 2017
178
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. -- This program is public domain. Do whatever you want with it.
  2. os.pullEvent = os.pullEventRaw
  3.  
  4. local expr
  5.  
  6. local spacechars = " \t\n\r"
  7.  
  8. local function skipspaces()
  9. while spacechars:find(expr:sub(1, 1),1,true) ~= nil and expr:len() > 0 do
  10. expr = expr:sub(2)
  11. end
  12. end
  13.  
  14. local function acceptch(ch)
  15. skipspaces()
  16. if expr:sub(1,1) == ch then
  17. expr = expr:sub(2)
  18. return true
  19. else
  20. return false
  21. end
  22. end
  23.  
  24. local function acceptnum()
  25. skipspaces()
  26. -- I'm sure there's a better way
  27. for len = expr:len(), 1, -1 do
  28. local success, n = pcall(tonumber, expr:sub(1, len))
  29. if success and n ~= nil then
  30. expr = expr:sub(len + 1)
  31. return n
  32. end
  33. end
  34. return nil
  35. end
  36.  
  37. local alpha = "_abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
  38. local alnum = alpha .. "0123456789"
  39.  
  40. local function acceptident()
  41. local n = 0
  42. skipspaces()
  43. if alpha:find(expr:sub(1, 1),1,true) == nil then return nil end
  44. while alnum:find(expr:sub(n+1, n+1),1,true) ~= nil and expr:len() > n do
  45. n = n + 1
  46. end
  47. local ident = expr:sub(1, n)
  48. expr = expr:sub(n+1)
  49. return ident
  50. end
  51.  
  52. local function parse_error(s)
  53. error(s and ("parse error: " .. s) or "parse error")
  54. end
  55.  
  56. local expression_root
  57.  
  58. local math_functions = {
  59. abs = math.abs,
  60. acos = math.acos,
  61. asin = math.asin,
  62. atan = math.atan,
  63. atan2 = math.atan2,
  64. ceil = math.ceil,
  65. floor = math.floor,
  66. cos = math.cos,
  67. sin = math.sin,
  68. tan = math.tan,
  69. cosh = math.cosh,
  70. sinh = math.sinh,
  71. tanh = math.tanh,
  72. -- math.deg, math.rad
  73. exp = math.exp,
  74. ln = math.log,
  75. log = math.log10,
  76. pow = math.pow,
  77. min = math.min,
  78. max = math.max,
  79. sqrt = math.sqrt,
  80. random = math.random
  81. }
  82.  
  83. local math_constants = {
  84. pi = math.pi,
  85. e = math.exp(1),
  86. inf = math.huge,
  87. nan = math.huge - math.huge
  88. }
  89.  
  90. local function call_function(id, arglist)
  91. if math_functions[id] == nil then
  92. error("no such function: " .. id)
  93. end
  94. return math_functions[id](unpack(arglist))
  95. end
  96.  
  97. local function get_constant(id)
  98. return math_constants[id] or error("no such constant: "..id)
  99. end
  100.  
  101. local function num_or_brackets()
  102. if acceptch("(") then
  103. local n = expression_root()
  104. if not acceptch(")") then parse_error("non-matching parentheses") end
  105. return n
  106. elseif acceptch("-") then
  107. return -expression_root()
  108. else
  109. local id = acceptident()
  110. if id ~= nil then
  111. if not acceptch("(") then
  112. return get_constant(id)
  113. elseif acceptch(")") then
  114. return call_function(id, {})
  115. else
  116. local arglist = {}
  117. local done = false
  118. while not done do
  119. table.insert(arglist, expression_root())
  120. if acceptch(")") then
  121. done = true
  122. elseif not acceptch(",") then
  123. parse_error("expected , or )")
  124. end
  125. end
  126. return call_function(id, arglist)
  127. end
  128. else
  129. local n = acceptnum()
  130. if n == nil then parse_error("expected number or bracketed expression") end
  131. return n
  132. end
  133. end
  134. end
  135.  
  136. local function division()
  137. local n1 = num_or_brackets()
  138. while acceptch("/") do
  139. n1 = n1 / num_or_brackets()
  140. end
  141. return n1
  142. end
  143.  
  144. local function multiplication()
  145. local n1 = division()
  146. while acceptch("*") do
  147. n1 = n1 * division()
  148. end
  149. return n1
  150. end
  151. local function subtraction()
  152. local n1 = multiplication()
  153. while acceptch("-") do
  154. n1 = n1 - multiplication()
  155. end
  156. return n1
  157. end
  158. local function addition()
  159. local n1 = subtraction()
  160. while acceptch("+") do
  161. n1 = n1 + subtraction()
  162. end
  163. return n1
  164. end
  165. expression_root = addition
  166.  
  167. local function parse(e)
  168. expr = e
  169. local success, result = pcall(expression_root)
  170. if success and expr ~= "" then
  171. print("Garbage after expression?")
  172. end
  173. if success then
  174. print("Answer: " .. tostring(result))
  175. else
  176. print(result)
  177. print("Near: " .. (expr == "" and "end of expression" or expr))
  178. end
  179. end
  180.  
  181. local function mainloop()
  182. local quitting = false
  183. print("")
  184. print("Welcome to immicalc.")
  185. print("This software is public domain.")
  186. print("")
  187. print("Enter expressions, one per line.")
  188. print("Enter 'quit' to quit.")
  189. print("")
  190. while not quitting do
  191. local line = io.read()
  192. if line == "quit" then
  193. os.reboot()
  194. else
  195. parse(line)
  196. print("")
  197. end
  198. end
  199. end
  200.  
  201. mainloop()
Advertisement
RAW Paste Data Copied
Advertisement