diff --git a/LICENSE b/LICENSE
--- a/LICENSE
+++ b/LICENSE
@@ -1,4 +1,5 @@
 Copyright 2011 Edward Kmett
+Copyright 2007 Paolo Martini
 Copyright 1999-2000 Daan Leijen
 
 All rights reserved.
diff --git a/Text/Trifecta.hs b/Text/Trifecta.hs
--- a/Text/Trifecta.hs
+++ b/Text/Trifecta.hs
@@ -18,6 +18,7 @@
   , module Text.Trifecta.Parser.Step
   , module Text.Trifecta.Parser.Token
   , module Text.Trifecta.Parser.Token.Class
+  , module Text.Trifecta.Parser.Expr
   , module Text.Trifecta.Path
   , module Text.Trifecta.Render.Caret
   , module Text.Trifecta.Render.Fixit
@@ -44,6 +45,7 @@
 import Text.Trifecta.Parser.Step
 import Text.Trifecta.Parser.Token
 import Text.Trifecta.Parser.Token.Class
+import Text.Trifecta.Parser.Expr
 import Text.Trifecta.Path
 import Text.Trifecta.Render.Caret
 import Text.Trifecta.Render.Fixit
diff --git a/Text/Trifecta/Parser/Expr.hs b/Text/Trifecta/Parser/Expr.hs
new file mode 100644
--- /dev/null
+++ b/Text/Trifecta/Parser/Expr.hs
@@ -0,0 +1,167 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module      :  Text.Trifecta.Parser.Expr
+-- Copyright   :  (c) Edward Kmett
+--                (c) Paolo Martini 2007
+--                (c) Daan Leijen 1999-2001, 
+-- License     :  BSD-style (see the LICENSE file)
+-- 
+-- Maintainer  :  ekmett@gmail.com
+-- Stability   :  experimental
+-- Portability :  non-portable
+-- 
+-- A helper module to parse \"expressions\".
+-- Builds a parser given a table of operators and associativities.
+-- 
+-----------------------------------------------------------------------------
+
+module Text.Trifecta.Parser.Expr
+    ( Assoc(..), Operator(..), OperatorTable
+    , buildExpressionParser
+    ) where
+
+import Control.Applicative
+import Text.Trifecta.Parser.Class
+import Text.Trifecta.Parser.Combinators
+
+-----------------------------------------------------------
+-- Assoc and OperatorTable
+-----------------------------------------------------------
+
+-- |  This data type specifies the associativity of operators: left, right
+-- or none.
+
+data Assoc 
+  = AssocNone
+  | AssocLeft
+  | AssocRight
+
+-- | This data type specifies operators that work on values of type @a@.
+-- An operator is either binary infix or unary prefix or postfix. A
+-- binary operator has also an associated associativity.
+
+data Operator m a 
+  = Infix (m (a -> a -> a)) Assoc
+  | Prefix (m (a -> a))
+  | Postfix (m (a -> a))
+
+-- | An @OperatorTable m a@ is a list of @Operator m a@
+-- lists. The list is ordered in descending
+-- precedence. All operators in one list have the same precedence (but
+-- may have a different associativity).
+
+type OperatorTable m a = [[Operator m a]]
+
+-----------------------------------------------------------
+-- Convert an OperatorTable and basic term parser into
+-- a full fledged expression parser
+-----------------------------------------------------------
+
+-- | @buildExpressionParser table term@ builds an expression parser for
+-- terms @term@ with operators from @table@, taking the associativity
+-- and precedence specified in @table@ into account. Prefix and postfix
+-- operators of the same precedence can only occur once (i.e. @--2@ is
+-- not allowed if @-@ is prefix negate). Prefix and postfix operators
+-- of the same precedence associate to the left (i.e. if @++@ is
+-- postfix increment, than @-2++@ equals @-1@, not @-3@).
+--
+-- The @buildExpressionParser@ takes care of all the complexity
+-- involved in building expression parser. Here is an example of an
+-- expression parser that handles prefix signs, postfix increment and
+-- basic arithmetic.
+--
+-- >  expr    = buildExpressionParser table term
+-- >          <?> "expression"
+-- >
+-- >  term    =  parens expr 
+-- >          <|> natural
+-- >          <?> "simple expression"
+-- >
+-- >  table   = [ [prefix "-" negate, prefix "+" id ]
+-- >            , [postfix "++" (+1)]
+-- >            , [binary "*" (*) AssocLeft, binary "/" (div) AssocLeft ]
+-- >            , [binary "+" (+) AssocLeft, binary "-" (-)   AssocLeft ]
+-- >            ]
+-- >          
+-- >  binary  name fun assoc = Infix (do{ reservedOp name; return fun }) assoc
+-- >  prefix  name fun       = Prefix (do{ reservedOp name; return fun })
+-- >  postfix name fun       = Postfix (do{ reservedOp name; return fun })
+
+buildExpressionParser :: MonadParser m
+                      => OperatorTable m a
+                      -> m a
+                      -> m a
+buildExpressionParser operators simpleExpr
+    = foldl (makeParser) simpleExpr operators
+    where
+      makeParser term ops
+        = let (rassoc,lassoc,nassoc,prefix,postfix) = foldr splitOp ([],[],[],[],[]) ops
+
+              rassocOp   = choice rassoc
+              lassocOp   = choice lassoc
+              nassocOp   = choice nassoc
+              prefixOp   = choice prefix  <?> ""
+              postfixOp  = choice postfix <?> ""
+
+              ambigious assoc op= try $ op *> fail ("ambiguous use of a " ++ assoc ++ " associative operator")
+
+              ambigiousRight    = ambigious "right" rassocOp
+              ambigiousLeft     = ambigious "left" lassocOp
+              ambigiousNon      = ambigious "non" nassocOp
+
+              termP      = do{ pre  <- prefixP
+                             ; x    <- term
+                             ; post <- postfixP
+                             ; return (post (pre x))
+                             }
+
+              postfixP   = postfixOp <|> return id
+
+              prefixP    = prefixOp <|> return id
+
+              rassocP x  = do{ f <- rassocOp
+                             ; y <- termP >>= rassocP1
+                             ; return (f x y)
+                             }
+                           <|> ambigiousLeft
+                           <|> ambigiousNon
+                           -- <|> return x
+
+              rassocP1 x = rassocP x <|> return x
+
+              lassocP x  = do{ f <- lassocOp
+                             ; y <- termP
+                             ; lassocP1 (f x y)
+                             }
+                           <|> ambigiousRight
+                           <|> ambigiousNon
+                           -- <|> return x
+
+              lassocP1 x = lassocP x <|> return x
+
+              nassocP x  = do{ f <- nassocOp
+                             ; y <- termP
+                             ;    ambigiousRight
+                              <|> ambigiousLeft
+                              <|> ambigiousNon
+                              <|> return (f x y)
+                             }
+                           -- <|> return x
+
+           in  do{ x <- termP
+                 ; rassocP x <|> lassocP  x <|> nassocP x <|> return x
+                   <?> "operator"
+                 }
+
+
+      splitOp (Infix op assoc) (rassoc,lassoc,nassoc,prefix,postfix)
+        = case assoc of
+            AssocNone  -> (rassoc,lassoc,op:nassoc,prefix,postfix)
+            AssocLeft  -> (rassoc,op:lassoc,nassoc,prefix,postfix)
+            AssocRight -> (op:rassoc,lassoc,nassoc,prefix,postfix)
+
+      splitOp (Prefix op) (rassoc,lassoc,nassoc,prefix,postfix)
+        = (rassoc,lassoc,nassoc,op:prefix,postfix)
+
+      splitOp (Postfix op) (rassoc,lassoc,nassoc,prefix,postfix)
+        = (rassoc,lassoc,nassoc,prefix,op:postfix)
diff --git a/trifecta.cabal b/trifecta.cabal
--- a/trifecta.cabal
+++ b/trifecta.cabal
@@ -1,6 +1,6 @@
 name:          trifecta
 category:      Text, Parsing, Diagnostics, Pretty Printer, Logging
-version:       0.15
+version:       0.15.1
 license:       BSD3
 cabal-version: >= 1.6
 license-file:  LICENSE
@@ -36,6 +36,7 @@
     Text.Trifecta.Parser.Step
     Text.Trifecta.Parser.Token
     Text.Trifecta.Parser.Token.Class
+    Text.Trifecta.Parser.Expr
     Text.Trifecta.Path
     Text.Trifecta.Render.Prim
     Text.Trifecta.Render.Caret
