RPN Calculator

From awesome
Jump to: navigation, search

RPN module in Lua[edit]

First, copy this to ~/.config/awesome/stack.lua

-- Stack Table
-- Uses a table as stack, use <table>:push(value) and <table>:pop()
-- Lua 5.1 compatible

-- GLOBAL
Stack = {}

-- Create a Table with stack functions
function Stack:Create()

  -- stack table
  local t = {}
  -- entry table
  t._et = {}

  -- push a value on to the stack
  function t:push(...)
    if ... then
      local targs = {...}
      -- add values
      for _,v in pairs(targs) do
        table.insert(self._et, v)
      end
    end
  end

  -- pop a value from the stack
  function t:pop(num)

    -- get num values from stack
    local num = num or 1

    -- return table
    local entries = {}

    -- get values into entries
    for i = 1, num do
      -- get last entry
      if #self._et ~= 0 then
        table.insert(entries, self._et[#self._et])
        -- remove last value
        table.remove(self._et)
      else
        break
      end
    end
    -- return unpacked entries
    return unpack(entries)
  end

  -- get entries
  function t:getn()
    return #self._et
  end

  -- list values
  function t:list()
    for i,v in pairs(self._et) do
      print(i, v)
    end
  end
  return t
end

-- CHILLCODE™

(from http://lua-users.org/wiki/SimpleStack )

Then copy this to ~/.config/awesome/rpn.lua

require("stack")

local Stack = Stack
local pairs = pairs
-- local print = print
local tonumber = tonumber

module("rpn")

local operators = { 
    { symbol = " ",
      operation = function(s) end },
    { symbol = "+",
      operation = function(s)
                    local a, b = s:pop(2)
                    s:push(a+b)
                  end },
    { symbol = "-",
      operation = function(s)
                    local a, b = s:pop(2)
                    s:push(b-a)
                  end },
    { symbol = "*",
      operation = function(s)
                    local a, b = s:pop(2)
                    s:push(a*b)
                  end },
    { symbol = "/",
      operation = function(s)
                    local a, b = s:pop(2)
                    s:push(b/a)
                  end },
}

function parseRPN(expr)
    stack = Stack:Create()
    tempNumber = ""
    for c in expr:gmatch"." do
        local found = false
        for _,op in pairs(operators) do
            if c == op.symbol then
                if tempNumber ~= "" then
                    stack:push(tonumber(tempNumber..c))
                    tempNumber = ""
                end
                op.operation(stack)
                found = true
                break
            end
        end
        if found == false then
            tempNumber = tempNumber..c
        end
    end
    return stack:pop(1)
end

Then you just need to include it in your rc.lua:

require("rpn")

To use it, just call rpn.parseRPN() passing the RPN expression as a string. It'll return the result as a number. Suggestion of use: use the promptbox, like in the following example

    -- RPN prompt
    awful.key({ modkey }, "c",
              function ()
                  awful.prompt.run({ prompt = "RPN: " },
                  mypromptbox[mouse.screen].widget,
                  function(expr) 
                    mypromptbox[mouse.screen].widget.text = "Result: "..rpn.parseRPN(expr)
                  end, nil,
                  awful.util.getdir("cache") .. "/history_rpn")
              end)