diff --git a/JustParse.cabal b/JustParse.cabal
--- a/JustParse.cabal
+++ b/JustParse.cabal
@@ -1,5 +1,5 @@
 name:                JustParse
-version:             1.0
+version:             2.0
 synopsis:            A simple and comprehensive Haskell parsing library
 description:         A simple and comprehensive Haskell parsing library
 homepage:            https://github.com/grantslatton/JustParse
@@ -13,8 +13,16 @@
 cabal-version:       >=1.8
 
 library
-   exposed-modules: Data.JustParse
-   other-modules: Data.JustParse.Internal, Data.JustParse.Language, Data.JustParse.Common
-  build-depends:       base ==4.6.*
-  hs-source-dirs: src
-  extensions: MultiParamTypeClasses, Rank2Types, FlexibleInstances, FlexibleContexts, Safe
+    exposed-modules: 
+        Data.JustParse,
+        Data.JustParse.Combinator,
+        Data.JustParse.Numeric,
+        Data.JustParse.Language,
+        Data.JustParse.Char
+    other-modules: 
+        Data.JustParse.Internal
+    build-depends:
+        base >= 4.2 && < 5
+    hs-source-dirs: src
+    extensions: MultiParamTypeClasses, Rank2Types, FlexibleInstances, FlexibleContexts, Safe, TupleSections, UndecidableInstances
+    ghc-options: -O2 -Wall
diff --git a/src/Data/JustParse.hs b/src/Data/JustParse.hs
--- a/src/Data/JustParse.hs
+++ b/src/Data/JustParse.hs
@@ -1,16 +1,14 @@
 {-|
 Module      : Data.JustParse
-Description : The one-stop import for the library
+Description : Parsing functions and types
 Copyright   : Copyright Waived
 License     : PublicDomain
 Maintainer  : grantslatton@gmail.com
 Stability   : experimental
 Portability : portable
-
-A simple and comprehensive Haskell parsing library.
 -} 
 
-{-# LANGUAGE Safe #-}
+--{-# LANGUAGE Safe #-}
 module Data.JustParse (
     -- * Overview
     -- $overview
@@ -24,67 +22,17 @@
 
     -- *** Recursive combinatorial parsing
     -- $quickstart3
-
-    -- * General Parsing
-    C.Stream(..),
-    C.Result(..),
-    C.Parser( parse ),
-    C.justParse,
-    C.runParser,
-    C.finalize,
-    C.extend,
-    C.isDone,
-    C.isFail,
-    C.isPartial,
-    C.rename,
-    (C.<?>),
-
-    -- * Generic Parsers
-    C.test,
-    C.greedy,
-    C.option,
-    C.satisfy,
-    C.mN,
-    C.many,
-    C.many1,
-    C.manyN,
-    C.atLeast,
-    C.exactly,
-    C.eof,
-    C.oneOf,
-    C.noneOf,
-    C.anyToken,
-    C.lookAhead,
-
-    -- * Char Parsers
-    C.char,
-    C.anyChar,
-    C.ascii,
-    C.latin1,
-    C.control,
-    C.space,
-    C.lower,
-    C.upper,
-    C.alpha,
-    C.alphaNum,
-    C.print,
-    C.digit,
-    C.octDigit,
-    C.hexDigit,
-    C.eol,
-
-    -- * String Parsers
-    C.string,
-
-    -- * Regex Parsers
-    L.regex,
-    L.regex',
-    L.Match(..)
-
+    runParser,
+    parseOnly,
+    extend,
+    finalize,
+    Parser,
+    Result(..),
+    Stream(..)
 ) where
 
-import Data.JustParse.Language as L
-import Data.JustParse.Common as C
+import Data.JustParse.Internal
+import Data.JustParse.Combinator
 
 -- $overview
 -- 
@@ -92,13 +40,7 @@
 -- 
 -- * Makes extensive use of combinators
 -- 
--- * Returns relatively verbose 'Fail'ure messages.
--- 
--- * Allows one to 'rename' a 'Parser'. 
--- 
--- * Allows for a parser to return a 'Partial' 'Result'
--- 
--- * Non-greedy parsing
+-- * Allows for a parser to return a 'Partial' result
 -- 
 -- * Returns a list of all possible parses
 -- 
@@ -112,8 +54,8 @@
 --p = do                
 --    h \<- char \'h\'                   \-\-Parses the character \'h\'
 --    rest \<- string \"ello world\"     \-\-Parses the string \"ello world\"
---    exp \<- char \'!\'                 \-\-Parses the character \'!\'
---    return ([h]++rest++[exp])       \-\-Returns all of the above concatenated together
+--    ex \<- char \'!\'                  \-\-Parses the character \'!\'
+--    return ([h]++rest++[ex])        \-\-Returns all of the above concatenated together
 -- @
 
 -- $quickstart2
@@ -123,19 +65,37 @@
 --
 -- @
 --p = do
---    first \<- string \"hello w\"         \-\-Parses the string \"hello w\"
---    os \<- many1 (char \'o\')            \-\-Applies the parser \"char \'o\'\" one or more times
---    second \<- string \"rld\"            \-\-Parses the string \"rld\"
---    return (length os)                \-\-Return the number of o\'s parsed
+--    string \"hello w\"         \-\-Parses the string \"hello w\"
+--    os \<- many1 (char \'o\')   \-\-Applies the parser \"char \'o\'\" one or more times
+--    string \"rld\"             \-\-Parses the string \"rld\"
+--    return (length os)       \-\-Return the number of o\'s parsed
 -- @
 
 -- $quickstart3
 -- 
--- This parser will turn a string of comma separated values into a list of them
+-- This parser will turn a string of comma separated values into a list of 
+-- them. Note that we could use the 'sepBy' parser, but this demonstrates a 
+-- recursive parser.
 --
 -- @
 --csv = do  
---    v \<- greedy (many (noneOf \",\"))       \-\-Parses as many non-comma characters as possible
+--    v \<- many (noneOf \",\")                \-\-Parses as many non-comma characters as possible
 --    vs \<- option [] (char \',\' >> csv)     \-\-Optionally parses a comma and a csv, returning the empty list upon failure
 --    return (v:vs)                         \-\-Concatenates and returns the full list
 -- @
+
+-- | Supplies the input to the 'Parser'. Returns all 'Result' types, 
+-- including 'Partial' results.
+runParser :: Parser s a -> s -> [Result s a]
+runParser p = parse p . Just
+
+-- | This runs the 'Parser' greedily over the input, 'finalize's all the 
+-- results, and returns the first successful result. If there are no 
+-- successful results, it returns 'Nothing'. This is useful when you are
+-- parsing something that you know will have no 'Partial's and you just
+-- want an answer.
+parseOnly :: Stream s t => Parser s a -> s -> Maybe a
+parseOnly p s = 
+    case finalize (parse (greedy p) (Just s)) of
+        [] -> Nothing
+        (Done v _:_) -> Just v
diff --git a/src/Data/JustParse/Char.hs b/src/Data/JustParse/Char.hs
new file mode 100644
--- /dev/null
+++ b/src/Data/JustParse/Char.hs
@@ -0,0 +1,115 @@
+{-|
+Module      : Data.JustParse.Common
+Description : Common char parsers
+Copyright   : Copyright Waived
+License     : PublicDomain
+Maintainer  : grantslatton@gmail.com
+Stability   : experimental
+Portability : portable
+
+Several useful parsers for dealing with 'String's.
+-}
+
+--{-# LANGUAGE Safe #-}
+module Data.JustParse.Char (
+    char,
+    anyChar,
+    caseInsensitiveChar,
+    ascii,
+    latin1,
+    control,
+    space,
+    lower,
+    upper,
+    alpha,
+    alphaNum,
+    print,
+    digit,
+    octDigit,
+    hexDigit,
+    string,
+    caseInsensitiveString,
+    eol
+) where
+
+import Prelude hiding (print)
+import Data.Char
+import Data.JustParse.Internal
+import Data.JustParse.Combinator
+
+-- | Parse a specic char.
+char :: Stream s Char => Char -> Parser s Char
+char = token
+
+-- | Parse any char.
+anyChar :: Stream s Char =>  Parser s Char
+anyChar = anyToken
+
+-- | Parse a specific char, ignoring case.
+caseInsensitiveChar :: Stream s Char => Char -> Parser s Char
+caseInsensitiveChar c = char (toUpper c) <|> char (toLower c)
+
+-- | Parse any char that is ASCII.
+ascii :: Stream s Char =>  Parser s Char
+ascii = satisfy isAscii
+
+-- | Parse any char that is Latin-1.
+latin1 :: Stream s Char =>  Parser s Char
+latin1 = satisfy isLatin1
+
+-- | Parse a control character.
+control :: Stream s Char =>  Parser s Char
+control = satisfy isControl
+
+-- | Parse a space.
+space :: Stream s Char =>  Parser s Char
+space = satisfy isSpace
+
+-- | Parse a lowercase character.
+lower :: Stream s Char =>  Parser s Char
+lower = satisfy isLower
+
+-- | Parse an uppercase character.
+upper :: Stream s Char =>  Parser s Char
+upper = satisfy isUpper
+
+-- | Parse an alphabetic character.
+alpha :: Stream s Char =>  Parser s Char
+alpha = satisfy isAlpha
+
+-- | Parse an alphanumeric character.
+alphaNum :: Stream s Char =>  Parser s Char
+alphaNum = satisfy isAlphaNum
+
+-- | Parse a printable (non-control) character.
+print :: Stream s Char =>  Parser s Char
+print = satisfy isPrint
+
+-- | Parse a digit.
+digit :: Stream s Char =>  Parser s Char
+digit = satisfy isDigit
+
+-- | Parse an octal digit.
+octDigit :: Stream s Char =>  Parser s Char
+octDigit = satisfy isOctDigit
+
+-- | Parse a hexadeciaml digit.
+hexDigit :: Stream s Char =>  Parser s Char
+hexDigit = satisfy isHexDigit
+
+-- | Parse a specific string.
+string :: Stream s Char => String -> Parser s String
+string = mapM char 
+
+-- | Parse a specfic string, ignoring case.
+caseInsensitiveString :: Stream s Char => String -> Parser s String
+caseInsensitiveString = mapM caseInsensitiveChar 
+
+-- | Parses until a newline, carriage return + newline, or newline + carriage return.
+eol :: Stream s Char => Parser s String
+eol = choice [string "\r\n", string "\n\r", string "\n"]
+
+-- | Makes common types such as 'String's into a Stream.
+instance Eq t => Stream [t] t where
+    uncons [] = Nothing
+    uncons (x:xs) = Just (x, xs)
diff --git a/src/Data/JustParse/Combinator.hs b/src/Data/JustParse/Combinator.hs
new file mode 100644
--- /dev/null
+++ b/src/Data/JustParse/Combinator.hs
@@ -0,0 +1,478 @@
+{-|
+Module      : Data.JustParse.Common
+Description : Common parser combinators
+Copyright   : Copyright Waived
+License     : PublicDomain
+Maintainer  : grantslatton@gmail.com
+Stability   : experimental
+Portability : portable
+
+The bread and butter of combinatory parsing.
+-}
+
+--{-# LANGUAGE Safe #-}
+--{-# LANGUAGE TupleSections #-}
+module Data.JustParse.Combinator (
+    -- * Utility Parsers
+    assert,
+    eof,
+    eitherP,
+    greedy,
+    guard,
+    lookAhead,
+    notFollowedBy,
+    option,
+    optional,
+    test,
+    (<|>),
+
+    -- * Token Parsers
+    anyToken,
+    noneOf,
+    oneOf,
+    satisfy,
+    token,
+
+    -- * Repetetive Parsers
+    chainl,
+    chainl1,
+    chainr,
+    chainr1,
+    count,
+    endBy,
+    endBy1,
+    exactly,
+    many,
+    many1,
+    mN,
+    sepBy,
+    sepBy1,
+    skipMany,
+    skipMany1,
+    sepEndBy,
+    sepEndBy1,
+    takeWhile,
+
+    -- * Group Parsers
+    choice,
+    perm,
+    select,
+
+    -- * Branching Parsers
+    branch,
+    (<||>),
+    chainl_,
+    chainr_,
+    chainl1_,
+    chainr1_,
+    choice_,
+    eitherP_,
+    endBy_,
+    endBy1_,
+    many_,
+    many1_,
+    mN_,
+    option_,
+    optional_,
+    perm_,
+    select_,
+    sepBy_,
+    sepBy1_,
+    sepEndBy_,
+    sepEndBy1_,
+    skipMany_,
+    skipMany1_,
+    takeWhile_
+) where
+
+import Prelude hiding ( print, length, takeWhile )
+import Data.JustParse.Internal ( 
+    Stream(..), Parser(..), Result(..), extend, finalize, isDone, 
+    isPartial, toPartial, streamAppend )
+import Data.Monoid ( mempty, Monoid, mappend )
+import Data.Maybe ( fromMaybe )
+import Data.List ( minimumBy, foldl1', foldl' )
+import Data.Ord ( comparing )
+import qualified Control.Monad as M
+import qualified Control.Applicative as A
+
+-- | Parse a token that satisfies a predicate.
+satisfy :: Stream s t => (t -> Bool) -> Parser s t
+satisfy f = Parser $ \s -> 
+    case s of
+        Nothing -> []
+        Just s' -> case uncons s' of
+            Nothing -> [Partial $ parse (satisfy f)]
+            Just (x, xs) -> [Done x (Just xs) | f x]
+
+-- | A parser that succeeds on 'True' and fails on 'False'. 
+guard :: Stream s t => Bool -> Parser s ()
+guard = M.guard
+
+-- | Synonym of 'guard'.
+assert :: Stream s t => Bool -> Parser s ()
+assert = guard
+
+-- | Only succeeds when supplied with 'Nothing'.
+eof :: Stream s t => Parser s ()
+eof = notFollowedBy anyToken
+
+-- | Parse a token that is a member of the list of tokens.
+oneOf :: (Eq t, Stream s t) => [t] -> Parser s t
+oneOf ts = satisfy (`elem` ts)
+
+-- | Parse a token that is not a member of the list of tokens.
+noneOf :: (Eq t, Stream s t) => [t] -> Parser s t
+noneOf ts = satisfy (`notElem` ts)
+
+-- | Parse a specific token.
+token :: (Eq t, Stream s t) => t -> Parser s t
+token t = satisfy (==t)
+
+-- | Parse any token.
+anyToken :: Stream s t => Parser s t
+anyToken = satisfy (const True)
+
+-- | Parse tokens while a predicate remains true.
+takeWhile :: Stream s t => (t -> Bool) -> Parser s [t]
+takeWhile = many . satisfy
+
+-- | Branches every iteration where one branch stops and one branch 
+-- continues.
+takeWhile_ :: Stream s t => (t -> Bool) -> Parser s [t]
+takeWhile_ = many_ . satisfy
+
+-- | Splits the current parse branch between the two parsers.
+branch :: Parser s a -> Parser s a -> Parser s a
+branch a b = Parser $ \s -> parse a s ++ parse b s
+
+infixr 1 <||>
+-- | Infix version of 'branch'.
+(<||>) :: Parser s a -> Parser s a -> Parser s a
+(<||>) = branch
+
+-- | @mN m n p@ parses between @m@ and @n@ occurences of @p@, inclusive.
+mN :: Stream s t => Int -> Int -> Parser s a -> Parser s [a]
+mN _ 0 _ = Parser $ \s -> [Done [] s]
+mN 0 n p = M.liftM2 (:) p (mN 0 (n-1) p) A.<|> return []
+mN m n p = M.liftM2 (:) p (mN (m-1) (n-1) p)
+
+-- | Branches every iteration where one branch stops and one branch 
+-- continues.
+mN_ :: Stream s t => Int -> Int -> Parser s a -> Parser s [a]
+mN_ _ 0 _ = Parser $ \s -> [Done [] s]
+mN_ 0 n p = M.liftM2 (:) p (mN 0 (n-1) p) <||> return []
+mN_ m n p = M.liftM2 (:) p (mN (m-1) (n-1) p)
+
+-- | Synonym of 'count'.
+exactly :: Stream s t => Int -> Parser s a -> Parser s [a]
+exactly n = mN n n
+
+-- | Applies a parser at least @n@ times.
+atLeast :: Stream s t => Int -> Parser s a -> Parser s [a]
+atLeast n = mN n (-1)
+
+-- | Branches every iteration where one branch stops and one branch 
+-- continues.
+atLeast_ :: Stream s t => Int -> Parser s a -> Parser s [a]
+atLeast_ n = mN_ n (-1)
+
+-- | Applies a parser at most @n@ times.
+atMost :: Stream s t => Int -> Parser s a -> Parser s [a]
+atMost  = mN 0
+
+-- | Branches every iteration where one branch stops and one branch 
+-- continues.
+atMost_ :: Stream s t => Int -> Parser s a -> Parser s [a]
+atMost_ = mN 0
+
+-- | Applies a parser zero or more times.
+many :: Stream s t => Parser s a -> Parser s [a]
+many = A.many
+
+-- | Branches every iteration where one branch stops and one branch 
+-- continues.
+many_ :: Parser s a -> Parser s [a]
+many_ p = return [] <||> M.liftM2 (:) p (many_ p)
+
+-- | Applies a parser one or more times.
+many1 :: Stream s t => Parser s a -> Parser s [a]
+many1 p = M.liftM2 (:) p (many p)
+
+-- | Branches every iteration where one branch stops and one branch 
+-- continues.
+many1_ :: Parser s a -> Parser s [a]
+many1_ p = M.liftM2 (:) p (many_ p)
+
+-- | Return 'True' if the parser would succeed if one were to apply it,
+-- otherwise, it returns 'False'. It does not consume input.
+test :: Stream s t => Parser s a -> Parser s Bool
+test p = 
+    do 
+        a <- optional (lookAhead p)
+        case a of
+            Nothing -> return False
+            _ -> return True
+
+infixr 1 <|>
+-- | @a \<|\> b@ is equivalent to @'choice' [a,b]@. That is, first @a@ is
+-- tried, and if it yields no results, @b@ is tried.
+(<|>) :: Stream s t => Parser s a -> Parser s a -> Parser s a
+(<|>) = (A.<|>)
+
+-- | Attempt to apply each parser in the list in order until one succeeds.
+choice :: Stream s t => [Parser s a] -> Parser s a
+choice = foldl1' (A.<|>) 
+
+-- | Given a list of parsers, split off a branch for each one.
+choice_ :: Stream s t => [Parser s a] -> Parser s a
+choice_ = foldl1' (<||>)
+
+-- | Like 'choice', but returns the index of the successful parser as well
+-- as the result.
+select :: Stream s t => [Parser s a] -> Parser s (Int, a)
+select [] = M.mzero
+select (p:ps) = M.liftM (0,) p <|> M.liftM (\(x,y) -> (x+1,y)) (select ps)
+
+-- | Like 'choice_', but returns the index of the successful parser.
+select_ :: Stream s t => [Parser s a] -> Parser s (Int, a)
+select_ [] = M.mzero
+select_ (p:ps) = M.liftM (0,) p <||> M.liftM (\(x,y) -> (x+1,y)) (select_ ps)
+
+-- | Modifies a parser so that it will ony return the most consumptive
+-- succesful results. 
+greedy :: Stream s t => Parser s a -> Parser s a
+greedy (Parser p) = Parser $ \s -> g (p s) 
+    where
+        f Nothing = 0
+        f (Just s) = length s
+        g [] = []
+        g xs 
+            | all isDone xs = [minimumBy (comparing (f . leftover)) xs]
+            | otherwise = [Partial $ \s -> g $ extend s xs] 
+
+-- | Attempts to apply a parser and returns a default value if it fails.
+option :: Stream s t => a -> Parser s a -> Parser s a
+option v p = 
+    do
+        r <- A.optional p
+        case r of
+            Nothing -> return v
+            Just v' -> return v'
+
+-- | Splits off two branches, one where the parse is attempted, and one 
+-- where it is not.
+option_ :: Stream s t => a -> Parser s a -> Parser s a
+option_ v p = option v p <||> return v
+
+-- | Attempts to apply the parser, returning 'Nothing' upon failure, or
+-- the result wrapped in a 'Just'.
+optional :: Stream s t => Parser s a -> Parser s (Maybe a)
+optional = A.optional
+
+-- | Splits off two branches, one where the parse is attempted, and one 
+-- where it is not.
+optional_ :: Stream s t => Parser s a -> Parser s (Maybe a)
+optional_ p = M.liftM Just p <||> return Nothing
+
+-- | @sepBy1 p s@ parses many  occurences of @p@ separated by @s@.
+sepBy :: Stream s t => Parser s a -> Parser s b -> Parser s [a]
+sepBy p s = sepBy1 p s A.<|> return []
+
+-- | Branches every iteration where one branch stops and one branch 
+-- continues.
+sepBy_ :: Stream s t => Parser s a -> Parser s b -> Parser s [a]
+sepBy_ p s = sepBy1_ p s <||> return []
+
+-- | @sepBy1 p s@ parses one or more occurences of @p@ separated by @s@.
+sepBy1 :: Stream s t => Parser s a -> Parser s b -> Parser s [a]
+sepBy1 p s = M.liftM2 (:) p (many (s >> p))
+
+-- | Branches every iteration where one branch stops and one branch 
+-- continues.
+sepBy1_ :: Stream s t => Parser s a -> Parser s b -> Parser s [a]
+sepBy1_ p s = M.liftM2 (:) p (many_ (s >> p))
+
+-- | Applies the parser and returns its result, but resets
+-- the 'Stream' as if it consumed nothing.
+lookAhead :: Stream s t => Parser s a -> Parser s a
+lookAhead v@(Parser p) = Parser $ \s -> 
+    let 
+        g (Done a _) = Done a s
+        g (Partial p') = Partial $ \s' -> 
+            case s' of
+                Nothing -> finalize (p' s)
+                _ -> parse (lookAhead v) (streamAppend s s')
+    in
+        map g (p s)
+
+-- | @count n p@ parses exactly @n@ occurences of @p@.
+count :: Stream s t => Int -> Parser s a -> Parser s [a]
+count = exactly
+
+-- | Identical to 'many' except the result is discarded.
+skipMany :: Stream s t => Parser s a -> Parser s ()
+skipMany = M.void . many
+
+-- | Branches every iteration where one branch stops and one branch 
+-- continues.
+skipMany_ :: Stream s t => Parser s a -> Parser s ()
+skipMany_ = M.void . many_
+
+-- | Identical to 'many1' except the result is discarded.
+skipMany1 :: Stream s t => Parser s a -> Parser s ()
+skipMany1 = M.void . many1
+
+-- | Branches every iteration where one branch stops and one branch 
+-- continues.
+skipMany1_ :: Stream s t => Parser s a -> Parser s ()
+skipMany1_ = M.void . many1_
+
+-- | @endBy p s@ parses multiple occurences of @p@ separated and ended by
+-- @s@.
+endBy :: Stream s t => Parser s a -> Parser s b -> Parser s [a]
+endBy p s = many (p A.<* s)
+
+-- | Branches every iteration where one branch stops and one branch 
+-- continues.
+endBy_ :: Stream s t => Parser s a -> Parser s b -> Parser s [a]
+endBy_ p s = many_ (p A.<* s)
+
+-- | @endBy1 p s@ parses one or more occurences of @p@ separated and ended 
+-- by @s@.
+endBy1 :: Stream s t => Parser s a -> Parser s b -> Parser s [a]
+endBy1 p s = many1 (p A.<* s)
+
+-- | Branches every iteration where one branch stops and one branch 
+-- continues.
+endBy1_ :: Stream s t => Parser s a -> Parser s b -> Parser s [a]
+endBy1_ p s = many1_ (p A.<* s)
+
+-- | @sepEndBy p s@ parses multiple occurences of @p@ separated and 
+-- optionally ended by @s@.
+sepEndBy :: Stream s t => Parser s a -> Parser s b -> Parser s [a]
+sepEndBy p s = sepBy p s A.<* optional s
+
+-- | Branches every iteration where one branch stops and one branch 
+-- continues.
+sepEndBy_ :: Stream s t => Parser s a -> Parser s b -> Parser s [a]
+sepEndBy_ p s = sepBy_ p s A.<* optional s
+
+-- | @sepEndBy p s@ parses one or more occurences of @p@ separated and 
+-- optionally ended by @s@.
+sepEndBy1 :: Stream s t => Parser s a -> Parser s b -> Parser s [a]
+sepEndBy1 p s = sepBy1 p s A.<* optional s
+
+-- | Branches every iteration where one branch stops and one branch 
+-- continues.
+sepEndBy1_ :: Stream s t => Parser s a -> Parser s b -> Parser s [a]
+sepEndBy1_ p s = sepBy1_ p s A.<* optional s
+
+-- | @chainr p o x@ parses zero or more occurences of @p@ separated by @o@. 
+-- The result is the left associative application of the functions to the
+-- values. If @p@ succeeds zero times, @x@ is returned.
+chainl :: Stream s t => Parser s a -> Parser s (a -> a -> a) -> a -> Parser s a
+chainl p o x = chainl1 p o <|> return x
+
+-- | Branches every iteration where one branch stops and one branch 
+-- continues.
+chainl_ :: Stream s t => Parser s a -> Parser s (a -> a -> a) -> a -> Parser s a
+chainl_ p o x = chainl1_ p o <||> return x
+
+-- | Like 'chainl', but a minimum of one occurence of @p@ must be parsed.
+chainl1 :: Stream s t => Parser s a -> Parser s (a -> a -> a) -> Parser s a
+chainl1 p o = p >>= f
+    where
+        f x =
+            do
+                g <- o
+                y <- p
+                f (g x y)
+            <|> return x
+
+-- | Branches every iteration where one branch stops and one branch 
+-- continues.
+chainl1_ :: Stream s t => Parser s a -> Parser s (a -> a -> a) -> Parser s a
+chainl1_ p o = p >>= f
+    where
+        f x =
+            do
+                g <- o
+                y <- p
+                f (g x y)
+            <||> return x
+
+-- | Like 'chainl', but right associative.
+chainr :: Stream s t => Parser s a -> Parser s (a -> a -> a) -> a -> Parser s a
+chainr p o x = chainr1 p o <|> return x
+
+-- | Branches every iteration where one branch stops and one branch 
+-- continues.
+chainr_ :: Stream s t => Parser s a -> Parser s (a -> a -> a) -> a -> Parser s a
+chainr_ p o x = chainr1_ p o <||> return x
+
+-- | Like 'chainl1', but right associative.
+chainr1 :: Stream s t => Parser s a -> Parser s (a -> a -> a) -> Parser s a
+chainr1 p o = p >>= f
+    where
+        f x = 
+            do
+                g <- o
+                y <- chainr1 p o
+                return (g x y)
+            <|> return x
+
+-- | Branches every iteration where one branch stops and one branch 
+-- continues.
+chainr1_ :: Stream s t => Parser s a -> Parser s (a -> a -> a) -> Parser s a
+chainr1_ p o = p >>= f
+    where
+        f x = 
+            do
+                g <- o
+                y <- chainr1_ p o
+                return (g x y)
+            <||> return x
+
+-- | Only succeeds when the given parser fails. Consumes no input.
+notFollowedBy :: Stream s t => Parser s a -> Parser s ()
+notFollowedBy p = test p >>= assert . not
+
+-- | @manyTill a b@ parses multiple occurences of @a@ until @b@ would 
+-- succeed if tried.
+manyTill :: Stream s t => Parser s a -> Parser s b -> Parser s [a]
+manyTill p e = 
+    do
+        b <- test e
+        if b 
+            then return []
+            else M.liftM2 (:) p (manyTill p e)
+
+-- | Does nothing -- only used for @Parsec@ compatability.
+try :: Stream s t => Parser s a -> Parser s a
+try = id
+
+-- | @eitherP a b@ returns the result wrapped in a 'Left' if @a@ succeeds or
+-- a 'Right' if @b@ succeeds
+eitherP :: Stream s t => Parser s a -> Parser s b -> Parser s (Either a b)
+eitherP a b = M.liftM Left a <|> M.liftM Right b
+
+-- | Like 'eitherP', but tries both @a@ and @b@.
+eitherP_ :: Stream s t => Parser s a -> Parser s b -> Parser s (Either a b)
+eitherP_ a b = M.liftM Left a <||> M.liftM Right b
+
+-- | Parses a sequence of parsers in any order.
+perm :: Stream s t => [Parser s a] -> Parser s [a]
+perm [] = return []
+perm ps = 
+    do
+        (i, r) <- select ps
+        M.liftM (r:) (perm (let (a,b) = splitAt i ps in a ++ tail b)) 
+
+-- | Parses a sequence of parsers in all possible orders.
+perm_ :: Stream s t => [Parser s a] -> Parser s [a]
+perm_ [] = return []
+perm_ ps = 
+    do
+        (i, r) <- select_ ps
+        M.liftM (r:) (perm_ (let (a,b) = splitAt i ps in a ++ tail b)) 
diff --git a/src/Data/JustParse/Common.hs b/src/Data/JustParse/Common.hs
deleted file mode 100644
--- a/src/Data/JustParse/Common.hs
+++ /dev/null
@@ -1,284 +0,0 @@
-{-|
-Module      : Data.JustParse.Common
-Description : Common Parser Combinators
-Copyright   : Copyright Waived
-License     : PublicDomain
-Maintainer  : grantslatton@gmail.com
-Stability   : experimental
-Portability : portable
-
-Many common parsing needs in one place.
--}
-
-{-# LANGUAGE Safe #-}
-module Data.JustParse.Common (
--- Parsing
-    Stream(..),
-    Result(..),
-    Parser( parse ),
-    finalize,
-    extend,
-    justParse,
-    runParser,
-    isDone,
-    isFail,
-    isPartial,
-    rename,
-    (<?>),
-
--- Primitive parsers
-    satisfy,
-    mN,
-
--- Derived Parsers
-
--- Generic Parsers
-    test,
-    greedy,
-    option,
-    many,
-    many1,
-    manyN,
-    atLeast,
-    exactly,
-    eof,
-    oneOf,
-    noneOf,
-    anyToken,
-    lookAhead,
-
--- Char Parsers
-    char,
-    anyChar,
-    ascii,
-    latin1,
-    control,
-    space,
-    lower,
-    upper,
-    alpha,
-    alphaNum,
-    print,
-    digit,
-    octDigit,
-    hexDigit,
-    eol,
-
--- String Parsers
-    string,
-
-) where
-
-import Prelude hiding ( print, length )
-import Data.JustParse.Internal ( Stream(..), Parser(..), Result(..), extend, finalize, isDone, isPartial, isFail, rename, (<?>) )
-import Data.Monoid ( mempty, Monoid )
-import Data.Maybe ( fromMaybe )
-import Data.List ( minimumBy )
-import Data.Char ( isControl, isSpace, isLower, isUpper, isAlpha, isAlphaNum, isPrint, 
-                   isDigit, isOctDigit, isHexDigit, isLetter, isMark, isNumber, isPunctuation, 
-                   isSymbol, isSeparator, isAscii, isLatin1, isAsciiUpper, isAsciiLower )
-import Data.Ord ( comparing )
-import Control.Monad ( void, (>=>), liftM )
-import Control.Applicative ( (<|>), optional, (<*) )
-
--- | Supplies the input to the 'Parser'. Returns all 'Result' types, 
--- including 'Partial' and 'Fail' types.
-runParser :: Parser s a -> s -> [Result s a]
-runParser p = parse p . Just
-
--- | This is a \"newbie\" command that one should probably only use out of frustration.
--- It runs the 'Parser' greedily over the input, 'finalize's all the results, and returns
--- the first successful result. If there are no successful results, it returns Nothing.
-justParse :: Stream s t => Parser s a -> s -> Maybe a
-justParse p s = 
-    case finalize (parse (greedy p) (Just s)) of
-        [] -> Nothing
-        (Done v _:_) -> Just v
-        (Fail m _:_) -> Nothing
-
--- | Parse a token that satisfies a predicate.
-satisfy :: Stream s t => (t -> Bool) -> Parser s t
-satisfy f = Parser $ \s -> 
-    case s of
-        Nothing -> [Fail ["satisfy"] s]
-        Just s' -> case uncons s' of
-            Nothing -> [Partial $ parse (satisfy f)]
-            Just (x, xs) -> 
-                if f x 
-                    then [Done x (Just xs)]
-                    else [Fail ["satisfy"] s]
-
--- | Parse from @m@ to @n@ occurences of a 'Parser'. Let @n@ be negative
--- if one wishes for no upper bound.
-mN :: Int -> Int -> Parser s a -> Parser s [a]
-mN m n p = mN' m n p <?> "mN"
-
-mN' :: Int -> Int -> Parser s a -> Parser s [a]
-mN' _ 0 _ = Parser $ \s -> [Done [] s] 
-mN' m n p = Parser $ \s -> 
-    if m == 0 
-        then Done [] s : (parse p s >>= g)
-        else             parse p s >>= g
-    where
-        m' = if m == 0 then 0 else m-1
-        g (Done a s) = parse (mN' m' (n-1) p) s >>= h a
-        g (Partial p') = [Partial $ p' >=> g]
-        g (Fail m l) = [Fail m l]
-        h a (Done as s) = [Done (a:as) s]
-        h a (Partial p') = [Partial $ p' >=> h a]
-        h a (Fail m l) = [Fail m l]
-
--- | Return @True@ if the 'Parser' would succeed if one were to apply it,
--- otherwise, @False@.
-test :: Parser s a -> Parser s Bool
-test p = 
-    do 
-        a <- optional (lookAhead p)
-        case a of
-            Nothing -> return False
-            _ -> return True
-
--- | Modifies a 'Parser' so that it will ony return the most consumptive
--- succesful results. If there are no successful results, it will only
--- return the most consumptive failures. One can use @greedy@ to emulate
--- parsers from @Parsec@ or @attoparsec@.
-greedy :: Stream s t => Parser s a -> Parser s a
-greedy (Parser p) = Parser $ \s -> g (p s) 
-    where
-        b (Done _ _) = True
-        b (Fail _ _) = True
-        b _ = False
-        f Nothing = 0
-        f (Just s) = length s
-        g [] = []
-        g xs 
-            | all b xs = 
-                let
-                    ds = filter isDone xs
-                    dm = minimum (map (f . leftover) ds)
-                    fs = filter isFail xs
-                    fm = minimum (map (f . leftover) fs)
-                in
-                    if not (null ds)
-                        then filter ((dm==) . f . leftover) ds
-                        else filter ((fm==) . f . leftover) fs
-            | otherwise = [Partial $ \s -> g $ extend s xs] 
-
--- | Attempts to apply a parser and returns a default value if it fails.
-option :: a -> Parser s a -> Parser s a
-option v p = 
-    do
-        r <- optional p
-        case r of
-            Nothing -> return v
-            Just v' -> return v'
-
--- | Parse any number of occurences of the 'Parser'. Equivalent to @'mN' 0 (-1)@.
-many :: Parser s a -> Parser s [a]
-many p = rename "many" (mN 0 (-1) p)
-
--- | Parse one or more occurence of the 'Parser'. Equivalent to @'mN' 1 (-1)@.
-many1 :: Parser s a -> Parser s [a]
-many1 p = rename "many1" (mN 1 (-1) p)
-
--- | Parse at least @n@ occurences of the 'Parser'. Equivalent to @'mN' n (-1)@.
-manyN :: Int -> Parser s a -> Parser s [a]
-manyN n p = rename "manyN" (mN n (-1) p)
-
--- | Identical to 'manyN', just a more intuitive name.
-atLeast :: Int -> Parser s a -> Parser s [a]
-atLeast n p = rename "atLeast" (mN n (-1) p)
-
--- | Parse exactly @n@ occurences of the 'Parser'. Equivalent to @'mN' n n@.
-exactly :: Int -> Parser s a -> Parser s [a]
-exactly n p = rename "exactly" (mN n n p)
-
--- | Only succeeds when supplied with @Nothing@.
-eof :: (Eq s, Monoid s) => Parser s ()
-eof = Parser $ \s ->
-    case s of
-        Nothing -> [Done () s]
-        Just s' -> 
-            if s' == mempty
-                then [Partial $ parse eof]
-                else [Fail ["eof"] (Just s')]
-
-oneOf :: (Eq t, Stream s t) => [t] -> Parser s t
-oneOf ts = rename "oneOf" (satisfy (`elem` ts))
-
-noneOf :: (Eq t, Stream s t) => [t] -> Parser s t
-noneOf ts = rename "noneOf" (satisfy (not . (`elem` ts)))
-
--- | Parse a specific token.
-token :: (Eq t, Stream s t) => t -> Parser s t
-token t = rename "token" (satisfy (==t))
-
-anyToken :: Stream s t => Parser s t
-anyToken = rename "anyToken" (satisfy (const True))
-
--- | Applies the parser and returns its result, but resets
--- the leftovers as if it consumed nothing.
-lookAhead :: Parser s a -> Parser s a
-lookAhead (Parser p) = rename "lookAhead" $ Parser $ \s -> 
-    let 
-        g (Done a _) = [Done a s]
-        g (Partial p') = [Partial $ p' >=> g]
-        g (Fail m _) = [Fail m s]
-    in
-        p s >>= g
-
--- | Parse a specic char.
-char :: Stream s Char => Char -> Parser s Char
-char c = rename ("char "++[c]) (token c)
-
-anyChar :: Stream s Char =>  Parser s Char
-anyChar = rename "anyChar" anyToken
-
-ascii :: Stream s Char =>  Parser s Char
-ascii = rename "ascii" (satisfy isAscii)
-
-latin1 :: Stream s Char =>  Parser s Char
-latin1 = rename "latin1" (satisfy isLatin1)
-
-control :: Stream s Char =>  Parser s Char
-control = rename "control" (satisfy isControl)
-
-space :: Stream s Char =>  Parser s Char
-space = rename "space" (satisfy isSpace)
-
-lower :: Stream s Char =>  Parser s Char
-lower = rename "lower" (satisfy isLower)
-
-upper :: Stream s Char =>  Parser s Char
-upper = rename "upper" (satisfy isUpper)
-
-alpha :: Stream s Char =>  Parser s Char
-alpha = rename "alpha" (satisfy isAlpha)
-
-alphaNum :: Stream s Char =>  Parser s Char
-alphaNum = rename "alphaNum" (satisfy isAlphaNum)
-
-print :: Stream s Char =>  Parser s Char
-print = rename "print" (satisfy isPrint)
-
-digit :: Stream s Char =>  Parser s Char
-digit = rename "digit" (satisfy isDigit)
-
-octDigit :: Stream s Char =>  Parser s Char
-octDigit = rename "octDigit" (satisfy isOctDigit)
-
-hexDigit :: Stream s Char =>  Parser s Char
-hexDigit = rename "hexDigit" (satisfy isHexDigit)
-
--- | Parse a specific string.
-string :: Stream s Char => String -> Parser s String
-string s = rename ("string "++s) (mapM char s)
-
--- | Parses until a newline, carriage return + newline, or newline + carriage return.
-eol :: Stream s Char => Parser s String
-eol = rename "eol" (string "\r\n" <|> string "\n\r" <|> string "\n")
-
--- | Makes common types such as Strings into a Stream.
-instance (Eq t) => Stream [t] t where
-    uncons [] = Nothing
-    uncons (x:xs) = Just (x, xs)
diff --git a/src/Data/JustParse/Internal.hs b/src/Data/JustParse/Internal.hs
--- a/src/Data/JustParse/Internal.hs
+++ b/src/Data/JustParse/Internal.hs
@@ -11,21 +11,21 @@
 {-# LANGUAGE MultiParamTypeClasses #-}
 {-# LANGUAGE Rank2Types #-}
 {-# LANGUAGE FlexibleInstances #-}
+{-# LANGUAGE UndecidableInstances #-}
 {-# LANGUAGE FlexibleContexts #-}
 {-# LANGUAGE FunctionalDependencies #-}
-{-# LANGUAGE Safe #-}
+--{-# LANGUAGE Safe #-}
 
 module Data.JustParse.Internal (
-    finalize,
-    extend,
     Stream (..),
     Parser (..),
     Result (..),
     isDone,
-    isFail,
     isPartial,
-    rename,
-    (<?>)
+    toPartial,
+    finalize,
+    extend,
+    streamAppend
 ) where
 
 import Prelude hiding ( length )
@@ -35,15 +35,17 @@
 import Data.List ( intercalate )
 
 -- | A @Stream@ instance has a stream of type @s@, made up of tokens of 
--- type @t@, which must be determinable by the stream.
+-- type @t@, which must be determinable by the stream. A minimal complete
+-- definition only needs to define @uncons@.
 class (Eq s, Monoid s) => Stream s t | s -> t where
-    -- | @uncons@ returns @Nothing@ if the @Stream@ is empty, otherwise it
+    -- | @uncons@ returns 'Nothing' if the @Stream@ is empty, otherwise it
     -- returns the first token of the stream, followed by the remainder
-    -- of the stream, wrapped in a @Just@.
+    -- of the stream, wrapped in a 'Just'.
     uncons :: Stream s t => s -> Maybe (t, s)
-    -- | The default @length@ implementation is O(n). If your stream provides
-    -- a more efficient method for determining the length, it is wise to
-    -- override this. The @length@ method is only used by the 'greedy' parser.
+    -- | The default @length@ implementation is @O(n)@. If your stream 
+    -- provides a more efficient method for determining the length, it is 
+    -- wise to override this. The @length@ method is only used by the 
+    -- 'greedy' parser.
     length :: Stream s t => s -> Int
     length s = 
         case uncons s of
@@ -55,18 +57,18 @@
         parse :: Maybe s -> [Result s a]
     }
 
-instance Monoid (Parser s a) where
+instance Stream s t => Monoid (Parser s a) where
     mempty = mzero
     mappend = mplus
 
 instance Functor (Parser s) where
-    fmap f (Parser p) = Parser $ \s -> map (fmap f) (p s)
+    fmap f (Parser p) = Parser $ map (fmap f) . p 
 
 instance Applicative (Parser s) where
     pure = return 
     (<*>) = ap
 
-instance Alternative (Parser s) where
+instance Stream s t => Alternative (Parser s) where
     empty = mzero
     (<|>) = mplus
 
@@ -74,31 +76,47 @@
     return v = Parser $ \s -> [Done v s] 
     (Parser p) >>= f = Parser $ p >=> g
         where
-            g (Fail m l) = [Fail m l]
             g (Done a s) = parse (f a) s 
             g (Partial p) = [Partial $ p >=> g] 
 
-instance MonadPlus (Parser s) where
+instance Stream s t => MonadPlus (Parser s) where
     mzero = Parser $ const []
-    mplus (Parser p1) (Parser p2) = Parser (\s -> p1 s ++ p2 s)
+    mplus a b = Parser $ \s ->
+        let
+            g [] = parse b s
+            g xs 
+                | any isDone xs = xs
+                | otherwise = [Partial $ \s' -> 
+                    -- case needed for proper finalization
+                    case s' of
+                        -- if finalized
+                        Nothing -> 
+                            case finalize (parse a s) of
+                                -- if parser a doesn't yield, try b
+                                [] -> finalize (parse b s)
+                                -- otherwise give what a yielded
+                                r -> r
+                        -- if not finalized
+                        _ -> parse (mplus a b) (streamAppend s s')]
 
+        in
+            g (parse a s) 
+
 data Result s a 
-    -- | A @Partial@ wraps the same function as a Parser. Supply it with a @Just@
-    -- and it will continue parsing, or with a @Nothing@ and it will terminate.
+    -- | A @Partial@ wraps the same function as a Parser. Supply it with 
+    -- a 'Just'
+    -- and it will continue parsing, or with a 'Nothing' and it will 
+    -- terminate.
     =
     Partial {
         continue    :: Maybe s -> [Result s a]
     } |
-    -- | A @Done@ contains the resultant @value@, and the @leftover@ stream, if any.
+    -- | A @Done@ contains the resultant @value@, and the @leftover@ 
+    -- stream, if any.
     Done {
         value       :: a,
         leftover    :: Maybe s
-    } |
-    -- | A @Fail@ contains a stack of error messages, and the @lftover@ stream, if any.
-    Fail {
-        messages    :: [String],
-        leftover    :: Maybe s
-    }
+    } 
 
 isDone :: Result s a -> Bool
 isDone (Done _ _) = True
@@ -108,50 +126,35 @@
 isPartial (Partial _) = True
 isPartial _ = False
 
-isFail :: Result s a -> Bool
-isFail (Fail _ _) = True
-isFail _ = False
+-- | Lifts a parser into the result space
+toPartial :: Parser s a -> [Result s a]
+toPartial (Parser p) = [Partial p]
 
 instance Functor (Result s) where
     fmap f (Partial p) = Partial $ map (fmap f) . p
     fmap f (Done a s) = Done (f a) s
-    fmap f (Fail m l) = Fail m l
 
 instance Show a => Show (Result s a) where
     show (Partial _) = "Partial"
     show (Done a _) = show a
-    show (Fail m l) = "Fail: \nIn: " ++ intercalate "\nIn: " m
 
--- | @finalize@ takes a list of results (presumably returned from a 'Parser' or 'Partial',
--- and supplies @Nothing@ to any remaining @Partial@ values, so that only 'Fail' and 'Done'
--- values remain.
+-- | @finalize@ takes a list of results (presumably returned from a 
+-- 'Parser' or 'Partial', and supplies 'Nothing' to any remaining 'Partial' 
+-- values, so that only 'Done' values remain.
 finalize :: (Eq s, Monoid s) => [Result s a] -> [Result s a]
 finalize = extend Nothing
 
--- | @extend@ takes a @Maybe s@ as input, and supplies the input to all values
--- in the 'Result' list. For 'Done' and 'Fail' values, it appends the @stream@ 
--- to the 'leftover' portion, and for 'Partial' values, it runs the continuation,
--- adding in any new 'Result' values to the output.
+-- | @extend@ takes a @'Maybe' s@ as input, and supplies the input to all 
+-- values  in the 'Result' list. For 'Done' values, it appends 
+-- the 'Stream'  to the 'leftover' portion, and for 'Partial' values, it 
+-- runs the continuation, adding in any new 'Result' values to the output.
 extend :: (Eq s, Monoid s) => Maybe s -> [Result s a] -> [Result s a]
-extend s rs = rs >>= g --`prnt` (show (map i rs, map i (rs >>= g), h s))
+extend s rs = rs >>= g 
     where
-        g (Fail m l) = [Fail m (f l s)]
         g (Partial p) = p s
-        g (Done a s') = [Done a (f s' s)]
-        f Nothing _ = Nothing
-        f (Just s) Nothing = if s == mempty then Nothing else Just s
-        f s s' = mappend s s'
-
--- | @rename@ pushes a new error message onto the stack in case of failure.
--- This is particularly useful when debugging a complex 'Parser'.
-rename :: String -> Parser s a -> Parser s a
-rename s p = Parser (map g . parse p)
-    where
-        g v@(Fail m l) = Fail (s:m) l
-        g v = v
-
+        g (Done a s') = [Done a (streamAppend s' s)]
 
-infixl 0 <?>
--- | The infix version of 'rename'
-(<?>) :: Parser s a -> String -> Parser s a
-p <?> s = rename s p
+streamAppend :: (Eq s, Monoid s) => Maybe s -> Maybe s -> Maybe s
+streamAppend Nothing _ = Nothing 
+streamAppend (Just s) Nothing = if s == mempty then Nothing else Just s 
+streamAppend s s' = mappend s s'
diff --git a/src/Data/JustParse/Language.hs b/src/Data/JustParse/Language.hs
--- a/src/Data/JustParse/Language.hs
+++ b/src/Data/JustParse/Language.hs
@@ -1,47 +1,55 @@
 {-|
 Module      : Data.JustParse.Language
-Description : Regular Expressions and Grammars in JustParse
+Description : Regular expressions
 Copyright   : Copyright Waived
 License     : PublicDomain
 Maintainer  : grantslatton@gmail.com
 Stability   : experimental
 Portability : portable
 
-Takes ideas from the field of Formal Languages and imports them into the parsing library.
+Allows for conversion from a regular expression and a 'Parser'.
 -}
 
 {-# LANGUAGE Safe #-}
 module Data.JustParse.Language (
     Match (..),
     regex,
-    regex'
+    regex_,
+    regex',
+    regex_'
 ) where
 
-import Data.JustParse.Common ( char, string, many1, digit, Stream, noneOf, oneOf, greedy, many, mN, anyChar, leftover, value, finalize, parse, Result(..), justParse, isFail )
-import Data.JustParse.Internal( Parser (..) )
-import Control.Applicative ( (<|>), optional )
+import Data.JustParse
+import Data.JustParse.Internal
+import Data.JustParse.Combinator
+import Data.JustParse.Numeric
+import Data.JustParse.Char
+
 import Control.Monad ( liftM, mzero )
 import Data.Monoid ( Monoid, mconcat, mempty, mappend )
-import Data.Maybe ( isJust )
+import Data.Maybe ( isJust, fromMaybe )
 import Data.List ( intercalate )
 
 -- | @regex@ takes a regular expression in the form of a 'String' and,
 -- if the regex is valid, returns a 'Parser' that parses that regex.
--- If the regex is invalid, it returns a Parser that will only return
--- 'Fail' with an \"Invalid Regex\" message.
+-- If the regex is invalid, it returns a Parser that will always fail.
+-- The returned parser is greedy.
 regex :: Stream s Char => String -> Parser s Match
-regex s 
-    | null r = Parser $ \s -> [Fail ["Invalid Regex"] s]
-    | isFail $ head r = Parser $ \s -> [Fail ["Invalid Regex"] s]
-    | isJust $ leftover $ head r = Parser $ \s -> [Fail ["Invalid Regex"] s]
-    | otherwise = value $ head r
-    where
-        r = finalize (parse (greedy regular) (Just s))
+regex = greedy . fromMaybe mzero . parseOnly regular
 
+-- | Like 'regex', but returns a branching (non-greedy) parser.
+regex_ :: Stream s Char => String -> Parser s Match
+regex_ = fromMaybe mzero . parseOnly regular
+
 -- | The same as 'regex', but only returns the full matched text.
 regex' :: Stream s Char => String -> Parser s String
 regex' = liftM matched . regex 
 
+-- | The same as 'regex_', but only returns the full matched text.
+regex_' :: Stream s Char => String -> Parser s String
+regex_' = liftM matched . regex_
+
+
 -- | The result of a 'regex'
 data Match = 
     Match {
@@ -67,19 +75,48 @@
         }
 
 regular :: (Stream s0 Char, Stream s1 Char) => Parser s0 (Parser s1 Match)
-regular = liftM (liftM mconcat . sequence) (greedy $ many parser)
+regular = liftM (liftM mconcat . sequence) (many parser)
 
 parser :: (Stream s0 Char, Stream s1 Char) => Parser s0 (Parser s1 Match)
-parser = character <|> charClass <|> negCharClass <|> question <|> group <|> asterisk <|> plus <|> mn <|> period <|> pipe
+parser = choice [
+    asterisk,
+    mn,
+    pipe,
+    plus,
+    question,
+    group,
+    character,
+    charClass,
+    negCharClass,
+    period
+    ]
 
 parserNP :: (Stream s0 Char, Stream s1 Char) => Parser s0 (Parser s1 Match)
-parserNP = character <|> charClass <|> negCharClass <|> question <|> group <|> asterisk <|> plus <|> mn <|> period 
+parserNP = choice [
+    asterisk,
+    mn,
+    plus,
+    question,
+    group,
+    character,
+    charClass,
+    negCharClass,
+    period
+    ]
 
+
+
 restricted :: (Stream s0 Char, Stream s1 Char) => Parser s0 (Parser s1 Match)
-restricted = character <|> charClass <|> negCharClass <|> group <|> period
+restricted = choice [
+    character,
+    charClass,
+    negCharClass,
+    group,
+    period
+    ]
 
 unreserved :: Stream s Char => Parser s Char 
-unreserved = (char '\\' >> anyChar ) <|> noneOf "()[]\\*+{}^?:<>|."
+unreserved = (char '\\' >> anyChar ) <|> noneOf "()[]\\*+{}^?|."
 
 character :: (Stream s0 Char, Stream s1 Char) => Parser s0 (Parser s1 Match)
 character = 
@@ -93,7 +130,7 @@
 charClass = 
     do
         char '['
-        c <- greedy (many1 unreserved)
+        c <- many1 unreserved
         char ']'
         return $ do
             c' <- oneOf c
@@ -103,7 +140,7 @@
 negCharClass = 
     do
         string "[^"
-        c <- greedy (many1 unreserved)
+        c <- many1 unreserved
         char ']'
         return $ do
             c' <- noneOf c
@@ -123,12 +160,12 @@
     do
         p <- restricted
         char '?'
-        return $ liftM mconcat (mN 0 1 p)
+        return $ liftM mconcat (mN_ 0 1 p)
 
 group :: (Stream s0 Char, Stream s1 Char) => Parser s0 (Parser s1 Match)
 group = 
     do
-        string "("
+        char '('
         p <- regular
         char ')'
         return $ do
@@ -140,25 +177,25 @@
     do
         p <- restricted
         char '*'
-        return $ liftM mconcat (many p)
+        return $ liftM mconcat (many_ p)
 
 plus :: (Stream s0 Char, Stream s1 Char) => Parser s0 (Parser s1 Match)
 plus = 
     do
         p <- restricted
         char '+'
-        return $ liftM mconcat (many1 p)
+        return $ liftM mconcat (many1_ p)
 
 mn :: (Stream s0 Char, Stream s1 Char) => Parser s0 (Parser s1 Match)
 mn = 
     do
         p <- restricted
         char '{'
-        l <- optional (many1 digit)
+        l <- option 0 decInt
         char ','
-        r <- optional (many1 digit)
+        r <- option (-1) decInt
         char '}'
-        return $ liftM mconcat (mN (maybe 0 read l) (maybe (-1) read r) p)
+        return $ liftM mconcat (mN_ l r p)
 
 pipe :: (Stream s0 Char, Stream s1 Char) => Parser s0 (Parser s1 Match)
 pipe = 
@@ -166,4 +203,4 @@
         p <- parserNP
         char '|'
         p' <- parser
-        return $ p <|> p'
+        return $ p <||> p'
diff --git a/src/Data/JustParse/Numeric.hs b/src/Data/JustParse/Numeric.hs
new file mode 100644
--- /dev/null
+++ b/src/Data/JustParse/Numeric.hs
@@ -0,0 +1,101 @@
+{-|
+Module      : Data.JustParse.Numeric
+Description : Numeric parsing
+Copyright   : Copyright Waived
+License     : PublicDomain
+Maintainer  : grantslatton@gmail.com
+Stability   : experimental
+Portability : portable
+
+Parsers for dealing with signed and unsigned 'Int's and 'Float's.
+-}
+
+module Data.JustParse.Numeric (
+    decFloat,
+    decFloat_,
+    decInt,
+    decInt_,
+    hexInt,
+    hexInt_
+) where
+
+--{-# LANGUAGE Safe #-}
+import Data.JustParse.Combinator
+import Data.JustParse.Internal
+import Data.JustParse.Char
+import Control.Monad ( liftM, liftM2 )
+import Data.Char ( ord, digitToInt, toUpper, isDigit, isHexDigit )
+
+-- | Reads many decimal digits and returns them as an @Int@.
+decInt :: Stream s Char => Parser s Int
+decInt = 
+    do
+        sign <- optional (oneOf "-+")
+        num <- liftM read (many1 digit)
+        case sign of
+            Just '-' -> return (-num)
+            _ -> return num
+
+-- | Branching version of decInt.
+decInt_ :: Stream s Char => Parser s Int
+decInt_ = 
+    do
+        sign <- optional (oneOf "-+")
+        num <- liftM read (many1_ digit)
+        case sign of
+            Just '-' -> return (-num)
+            _ -> return num
+
+-- | Parse a float. If a decimal point is present, it must have at 
+-- least one digit before and after the decimal point.
+decFloat :: Stream s Char => Parser s Float
+decFloat = 
+    do
+        sign <- optional (oneOf "-+")
+        whole <- many1 digit
+        fractional <- option ".0" (liftM2 (:) (char '.') (many1 digit))
+        case sign of
+            Just '-' -> return (-(read (whole ++ fractional)))
+            _ -> return (read (whole ++ fractional))
+
+-- | Branching version of decFloat.
+decFloat_ :: Stream s Char => Parser s Float
+decFloat_ = 
+    do
+        sign <- optional (oneOf "-+")
+        whole <- many1_ digit
+        fractional <- option_ ".0" (liftM2 (:) (char '.') (many1_ digit))
+        case sign of
+            Just '-' -> return (-(read (whole ++ fractional)))
+            _ -> return (read (whole ++ fractional))
+
+
+-- | Reads many hexidecimal digits and returns them as an @Int@.
+hexInt :: Stream s Char => Parser s Int
+hexInt = 
+    do
+        sign <- optional (oneOf "-+")
+        num <- liftM (f . reverse) (many1 hexDigit)
+        case sign of
+            Just '-' -> return (-num)
+            _ -> return num
+    where
+        f [] = 0
+        f (x:xs) 
+            | isDigit x = digitToInt x + 16 * f xs 
+            | otherwise = ord (toUpper x) - ord 'A' + 16 * f xs
+
+-- | Branching versino of 'hexInt'.
+hexInt_ :: Stream s Char => Parser s Int
+hexInt_ = 
+    do
+        sign <- optional (oneOf "-+")
+        num <- liftM (f . reverse) (many1_ hexDigit)
+        case sign of
+            Just '-' -> return (-num)
+            _ -> return num
+    where
+        f [] = 0
+        f (x:xs) 
+            | isDigit x = digitToInt x + 16 * f xs 
+            | otherwise = ord (toUpper x) - ord 'A' + 16 * f xs
