diff --git a/LICENSE b/LICENSE
new file mode 100644
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,101 @@
+                    GNU GENERAL PUBLIC LICENSE
+                       Version 3, 29 June 2007
+
+ Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+                            Preamble
+
+  The GNU General Public License is a free, copyleft license for
+software and other kinds of works.
+
+  The licenses for most software and other practical works are designed
+to take away your freedom to share and change the works.  By contrast,
+the GNU General Public License is intended to guarantee your freedom to
+share and change all versions of a program--to make sure it remains free
+software for all its users.  We, the Free Software Foundation, use the
+GNU General Public License for most of our software; it applies also to
+any other work released this way by its authors.  You can apply it to
+your programs, too.
+
+  When we speak of free software, we are referring to freedom, not
+price.  Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+them if you wish), that you receive source code or can get it if you
+want it, that you can change the software or use pieces of it in new
+free programs, and that you know you can do these things.
+
+  To protect your rights, we need to prevent others from denying you
+these rights or asking you to surrender the rights.  Therefore, you have
+certain responsibilities if you distribute copies of the software, or if
+you modify it: responsibilities to respect the freedom of others.
+
+  For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must pass on to the recipients the same
+freedoms that you received.  You must make sure that they, too, receive
+or can get the source code.  And you must show them these terms so they
+know their rights.
+
+  Developers that use the GNU GPL protect your rights with two steps:
+(1) assert copyright on the software, and (2) offer you this License
+giving you legal permission to copy, distribute and/or modify it.
+
+  For the developers' and authors' protection, the GPL clearly explains
+that there is no warranty for this free software.  For both users' and
+authors' sake, the GPL requires that modified versions be marked as
+changed, so that their problems will not be attributed erroneously to
+authors of previous versions.
+
+  Some devices are designed to deny users access to install or run
+modified versions of the software inside them, although the manufacturer
+can do so.  This is fundamentally incompatible with the aim of
+protecting users' freedom to change the software.  The systematic
+pattern of such abuse occurs in the area of products for individuals to
+use, which is precisely where it is most unacceptable.  Therefore, we
+have designed this version of the GPL to prohibit the practice for those
+products.  If such problems arise substantially in other domains, we
+stand ready to extend this provision to those domains in future versions
+of the GPL, as needed to protect the freedom of users.
+
+  Finally, every program is threatened constantly by software patents.
+States should not allow patents to restrict development and use of
+software on general-purpose computers, but in those that do, we wish to
+avoid the special danger that patents applied to a free program could
+make it effectively proprietary.  To prevent this, the GPL assures that
+patents cannot be used to render the program non-free.
+
+  The precise terms and conditions for copying, distribution and
+modification follow.
+
+                       TERMS AND CONDITIONS
+
+  0. Definitions.
+
+  "This License" refers to version 3 of the GNU General Public License.
+
+  "Copyright" also means copyright-like laws that apply to other kinds of
+works, such as semiconductor masks.
+
+  "The Program" refers to any copyrightable work licensed under this
+License.  Each licensee is addressed as "you".  "Licensees" and
+"recipients" may be individuals or organizations.
+
+  To "modify" a work means to copy from or adapt all or part of the work
+in a fashion requiring copyright permission, other than the making of an
+exact copy.  The resulting work is called a "modified version" of the
+earlier work or a work "based on" the earlier work.
+
+  A "covered work" means either the unmodified Program or a work based
+on the Program.
+
+  To "propagate" a work means to do anything with it that, without
+permission, would make you directly or secondarily liable for
+infringement under applicable copyright law, except executing it on a
+computer or modifying a private copy.  Propagation includes copying,
+distribution (with or without modification), making available to the
+public, and in some countries other activities as well.
+
+  To "convey" a work means any kind of propagation that enables other
+parties to make or receive copies.  Mere interaction with a user through
+a computer network, with no transfer of a copy, 
diff --git a/Setup.hs b/Setup.hs
new file mode 100644
--- /dev/null
+++ b/Setup.hs
@@ -0,0 +1,2 @@
+import Distribution.Simple
+main = defaultMain
diff --git a/mathexpr.cabal b/mathexpr.cabal
new file mode 100644
--- /dev/null
+++ b/mathexpr.cabal
@@ -0,0 +1,25 @@
+name:                mathexpr
+version:             0.1.0.0
+synopsis:            Parse and evaluate math expressions with variables and functions
+description:         A simple tool to evaluate math expressions as strings with support for custom functions and operators
+homepage:            https://github.com/mdibaiee/mathexpr
+license:             GPL-3
+license-file:        LICENSE
+author:              Mahdi Dibaiee
+maintainer:          mdibaiee@aol.com
+copyright:           2016 Mahdi Dibaiee
+category:            Math
+build-type:          Simple
+-- extra-source-files:
+cabal-version:       >=1.10
+
+library
+  hs-source-dirs:      src
+  exposed-modules:     Data.MathExpr
+  build-depends:       base >= 4.7 && < 5,
+                       data-default-class
+  default-language:    Haskell2010
+
+source-repository head
+  type:     git
+  location: https://github.com/mdibaiee/mathexpr
diff --git a/src/Data/MathExpr.hs b/src/Data/MathExpr.hs
new file mode 100644
--- /dev/null
+++ b/src/Data/MathExpr.hs
@@ -0,0 +1,108 @@
+module Data.MathExpr
+    ( evaluate
+    , Settings (..)
+    , defaultFunctions
+    , defaultOperators
+    ) where
+      import Data.Default.Class
+      import Data.Maybe (isJust, fromJust)
+      import Debug.Trace
+      import Data.List (find)
+
+      data Settings = Settings { operators :: [(Char, Int, Double -> Double -> Double)]
+                               , functions :: [(String, Double -> Double)]
+                               }
+
+      defaultOperators = [
+          ('+', 0, (+)), ('-', 0, (-)),
+          ('*', 1, (*)), ('/', 1, (/)),
+          ('^', 2, (**))
+        ]
+      defaultFunctions = [("ln", log), ("sin", sin), ("cos", cos)]
+
+      instance Default Settings where
+        def = Settings { operators = defaultOperators
+                       , functions = defaultFunctions
+                       }
+      toPostfix :: Settings -> String -> String
+      toPostfix settings s = helper (tokenize s) [] []
+        where
+          ops = operators settings
+          fns = functions settings
+
+          helper :: [String] -> [String] -> String -> String
+          helper [] os out = out ++ concat os
+          helper (c:cs) os out
+            | head c == '(' = helper cs (c:os) out
+            | head c == ')' && head os == "(" = helper cs (tail os) out
+            | head c == ')' = helper (c:cs) (tail os) (out ++ pad (head os))
+            | isOperator c && (null os || precedence c > precedence (head os)) = helper cs (c:os) out
+            | isOperator c = helper (c:cs) (tail os) (out ++ pad (head os))
+            | otherwise = helper cs os (out ++ pad c)
+
+          isOperator cs = isOp cs || isFunction cs
+          isOp cs = isJust $ (head cs) `triLookup` ops
+          isFunction cs = isJust $ cs `lookup` fns
+          precedence cs
+            | isFunction cs = Just 999
+            | otherwise = (head cs) `triLookup` ops
+
+      tokenize :: String -> [String]
+      tokenize str = words $ helper str
+        where
+          helper :: String -> String
+          helper [] = []
+          helper (c:cs)
+            | isAlphanumeric c = c : helper cs
+            | isSymbol c = pad [c] ++ helper cs
+
+      replaceVariables :: String -> [(String, Double)] -> String
+      replaceVariables str [] = str
+      replaceVariables str vars = concatMap replace (tokenize str)
+        where
+          replace c
+            | isVariable c = pad $ show $ fromJust $ c `lookup` vars
+            | otherwise = c
+
+          isVariable c = isJust $ c `lookup` vars
+
+      -- | Evaluate an expression
+      -- Example: `evaluate def "x + y ^ 2" [("x", 1), ("y", 2)]
+      evaluate :: Settings -> String -> [(String, Double)] -> Double
+      evaluate settings expr vars =
+        let postfix = toPostfix settings expr
+            replaced = replaceVariables postfix vars
+        in helper (tokenize replaced) []
+        where
+          ops = operators settings
+          fns = functions settings
+
+          helper :: [String] -> [String] -> Double
+          helper [] [o] = read o
+          helper (c:cs) os
+            | isOperator c =
+                let result = (operatorFunction c) (read . head . tail $ os) (read . head $ os) 
+                in helper cs $ (show result) : drop 2 os
+            | isFunction c =
+                let result = (function c) (read . head $ os)
+                in helper cs $ (show result) : tail os
+            | otherwise = helper cs (c:os)
+
+          isOperator cs = isJust $ (head cs) `triLookup` ops
+          isFunction cs = isJust $ cs `lookup` fns
+
+          function cs = fromJust $ cs `lookup` fns
+          operatorFunction cs = case find (\(a, _, _) -> a == head cs) ops of
+                                  Just (_, _, c) -> c
+                                  Nothing -> const (const 0)
+          isParen cs = head cs `elem` ['(', ')']
+
+      alphanumeric = '.' : ['a'..'z'] ++ ['0'..'9']
+      isAlphanumeric = (`elem` alphanumeric)
+      isSymbol = not . (`elem` alphanumeric)  
+
+      triLookup :: (Eq a) => a -> [(a, b, c)] -> Maybe b
+      triLookup a x = lookup a $ map (\(a, b, _) -> (a, b)) x
+
+      pad :: String -> String
+      pad x = ' ' : x ++ [' ']
