Kouksi44

Calc Beta

Aug 2nd, 2015
249
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 5.77 KB | None | 0 0
  1. dofile("Class.lua")   --Load Class API for OOP
  2. import("Classes.lua") -- Import Stack and Queue class
  3.  
  4.  
  5. local opOrder={} -- table that holds the operators , the rank of the operator ( * before + )
  6. opOrder["*"]={rank=2,isLeft=true }
  7. opOrder["/"]={rank=2,isLeft=true }
  8. opOrder["+"]={rank=1,isLeft=false}
  9. opOrder["-"]={rank=1,isLeft=true }
  10. opOrder["^"]={rank=3,isLeft=false}
  11. opOrder["%"]={rank=2,isLeft=true }
  12.  
  13.  
  14. local action={} -- the actions for all standart math operators
  15.  
  16. action["+"]=function(l,r)
  17.         return l+r
  18. end
  19.  
  20. action["-"]=function(l,r)
  21.         return l-r
  22. end
  23.  
  24. action["*"]=function(l,r)
  25.         return l*r
  26. end
  27.  
  28. action["/"]=function(l,r)
  29.         return l/r
  30. end
  31.  
  32. action["^"]=function(l,r)
  33.         return math.pow(l,r)
  34. end
  35.  
  36. action["%"]=function(l,r)
  37.         return math.fmod(l,r)
  38. end
  39.  
  40. -- /**
  41. --  * shuntingYard turns a Queue of tokens(infix expression) and turns it into a (RPN expression)
  42. --  * @param  [Queue] exp Queue representing the infix expression
  43. --  * @return [Queue] Queue representing the RPN expression
  44. --  */
  45. local function shuntingYard(exp)
  46.         local input=exp
  47.         local output=Queue()
  48.         local op=Stack()
  49.         while not input.isEmpty do
  50.                 local token=input:dequeue()
  51.                 if tonumber(token) then
  52.                         output:enqueue(token)
  53.                 elseif opOrder[token] then
  54.                         local top=op:peek()
  55.                        
  56.                         while op.isEmpty==false and opOrder[top]~=nil and ((opOrder[token].isLeft and opOrder[token].rank<opOrder[top].rank) or opOrder[token].rank<=opOrder[top].rank)  do
  57.                                 output:enqueue(op:pop())
  58.                                 top=op:peek()
  59.                         end
  60.                        
  61.                         op:push(token)
  62.                        
  63.                 elseif token=="(" then
  64.                         op:push(token)
  65.                 elseif token==")" then
  66.                         while op:peek()~="(" do
  67.                                 if op.isEmpty then
  68.                                         return("[ERROR]:The closing bracket is not preceeded by an opening bracket")
  69.                                 end
  70.                                 output:enqueue(op:pop())
  71.                         end
  72.                         op:pop()
  73.                 end
  74.         end
  75.         while not op.isEmpty do
  76.                 if op:peek()=="(" then
  77.                         return("[ERROR]:More opening brackets than closing brackets")
  78.                 end
  79.                 output:enqueue(op:pop())
  80.         end
  81.         return output
  82. end
  83.  
  84. -- /**
  85. --  * toTokenStream turns a string expression into a Queue of Tokens that represent numbers, operators and brackets
  86. --  * @param  [string] sExpression the string that holds the math expression in infix notation
  87. --  * @return [Queue]  the token Queue
  88. --  */
  89. local function toTokenStream(sExpression)
  90.         local _tokens=Queue()
  91.          pos=1
  92.         while pos<=#sExpression do
  93.                 local e=sExpression:sub(pos,pos)
  94.                 if tonumber(e) then
  95.                         local notNum=false
  96.                         local number=e
  97.                         local p=pos+1
  98.                         while notNum==false do
  99.                                 if tonumber(sExpression:sub(p,p)) then
  100.                                         number=number..sExpression:sub(p,p)
  101.                                         p=p+1
  102.                                 else
  103.                                         notNum=true
  104.                                 end
  105.                         end
  106.                         number=tonumber(number)
  107.                         _tokens:enqueue(number)
  108.                         pos=p
  109.                 elseif e~=" " then
  110.                         _tokens:enqueue(e)
  111.                         pos=pos+1
  112.                 elseif e:match("%a")~=nil then
  113.                         local f=e
  114.                         local notFunc=false
  115.                         local p=pos+1
  116.                         while notFunc==false do
  117.                                 if sExpression:sub(p,p):match("%a") then
  118.                                         f=f..sExpression:sub(p,p)
  119.                                         p=p+1
  120.                                 else
  121.                                         notFunc=true
  122.                                 end
  123.                         end
  124.                         _tokens:enqueue(f)
  125.                         pos=p
  126.                 end
  127.         end
  128.         return _tokens
  129. end
  130.  
  131. -- /**
  132. --  * evaluateRPN evaluates a RPN expression
  133. --  * @param  [Queue]   reverse the Queue that holds the RPN expression
  134. --  * @return [number]  the result of the expression
  135. --  */
  136. local function evaluateRPN(reverse)
  137.         local op=Stack()
  138.         while not reverse.isEmpty do
  139.                 local val=reverse:dequeue()
  140.                 if tonumber(val) then
  141.                         op:push(val)
  142.                 elseif opOrder[val] then
  143.                         local r=op:pop()
  144.                         local l=op:pop()
  145.                         op:push(action[val](tonumber(l),tonumber(r)))
  146.                 end
  147.         end
  148.         return op:pop()
  149. end
  150.  
  151. local expression = table.concat({ ... }, " ")
  152.  
  153.  
  154. if #expression==0 then
  155.         print("Enter your expression: ")
  156.         expression=io.read()
  157. else
  158.         local TOKENSTREAM=toTokenStream(expression)
  159.         local reverse=shuntingYard(TOKENSTREAM)
  160.         local result=evaluateRPN(reverse)
  161.         print(result)
  162.         return
  163.        
  164. end
  165.        
  166.  
  167.  
  168.  
  169. local TOKENSTREAM=toTokenStream(expression)
  170.  
  171. local reverse=shuntingYard(TOKENSTREAM)
  172.  
  173.  
  174. if type(reverse)=="string" then
  175.         print(reverse)
  176. else
  177.         print("Your result is :"..evaluateRPN(reverse))
  178. end
Advertisement
Add Comment
Please, Sign In to add comment