-- | a 'Boomerang' library for working with '[String]'
{-# LANGUAGE DeriveDataTypeable, FlexibleContexts, FlexibleInstances, TemplateHaskell, TypeFamilies, TypeSynonymInstances, TypeOperators #-}
module Text.Boomerang.Strings
    (
    -- * Types
      StringsError
    -- * Combinators
    , (</>), alpha, anyChar, anyString, char, digit, eos, int
    , integer, lit, readshow, satisfy, satisfyStr, space
    -- * Running the 'Boomerang'
    , isComplete, parseStrings, unparseStrings

    )
    where

import Prelude                 hiding ((.), id, (/))
import Control.Category        (Category((.), id))
import Data.Char               (isAlpha, isDigit, isSpace)
import Data.Data               (Data, Typeable)
import Data.List               (stripPrefix)
import Data.String             (IsString(..))
import Numeric                    (readDec, readSigned)
import Text.Boomerang.Combinators (opt, rCons, rList1)
import Text.Boomerang.Error       (ParserError(..),ErrorMsg(..), (<?>), condenseErrors, mkParserError)
import Text.Boomerang.HStack       ((:-)(..))
import Text.Boomerang.Pos         (InitialPosition(..), MajorMinorPos(..), incMajor, incMinor)
import Text.Boomerang.Prim        (Parser(..), Boomerang(..), parse1, xmaph, unparse1, val)

type StringsError = ParserError MajorMinorPos

instance InitialPosition StringsError where
    initialPos :: Maybe StringsError -> Pos StringsError
initialPos Maybe StringsError
_ = Integer -> Integer -> MajorMinorPos
MajorMinorPos Integer
0 Integer
0

instance a ~ b => IsString (Boomerang StringsError [String] a b) where
    fromString :: String -> Boomerang StringsError [String] a b
fromString = String -> Boomerang StringsError [String] a b
forall r. String -> Boomerang StringsError [String] r r
lit

-- | a constant string
lit :: String -> Boomerang StringsError [String] r r
lit :: String -> Boomerang StringsError [String] r r
lit String
l = Parser StringsError [String] (r -> r)
-> (r -> [([String] -> [String], r)])
-> Boomerang StringsError [String] r r
forall e tok a b.
Parser e tok (a -> b)
-> (b -> [(tok -> tok, a)]) -> Boomerang e tok a b
Boomerang Parser StringsError [String] (r -> r)
pf r -> [([String] -> [String], r)]
sf
    where
      pf :: Parser StringsError [String] (r -> r)
pf = ([String]
 -> Pos StringsError
 -> [Either StringsError ((r -> r, [String]), Pos StringsError)])
-> Parser StringsError [String] (r -> r)
forall e tok a.
(tok -> Pos e -> [Either e ((a, tok), Pos e)]) -> Parser e tok a
Parser (([String]
  -> Pos StringsError
  -> [Either StringsError ((r -> r, [String]), Pos StringsError)])
 -> Parser StringsError [String] (r -> r))
-> ([String]
    -> Pos StringsError
    -> [Either StringsError ((r -> r, [String]), Pos StringsError)])
-> Parser StringsError [String] (r -> r)
forall a b. (a -> b) -> a -> b
$ \[String]
tok Pos StringsError
pos ->
           case [String]
tok of
             [] -> MajorMinorPos
-> [ErrorMsg]
-> [Either StringsError ((r -> r, [String]), MajorMinorPos)]
forall pos a. pos -> [ErrorMsg] -> [Either (ParserError pos) a]
mkParserError MajorMinorPos
Pos StringsError
pos [String -> ErrorMsg
EOI String
"input", String -> ErrorMsg
Expect (String -> String
forall a. Show a => a -> String
show String
l)]
             (String
"":[String]
_) | (Bool -> Bool
not (Bool -> Bool) -> Bool -> Bool
forall a b. (a -> b) -> a -> b
$ String -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null String
l) -> MajorMinorPos
-> [ErrorMsg]
-> [Either StringsError ((r -> r, [String]), MajorMinorPos)]
forall pos a. pos -> [ErrorMsg] -> [Either (ParserError pos) a]
mkParserError MajorMinorPos
Pos StringsError
pos [String -> ErrorMsg
EOI String
"segment", String -> ErrorMsg
Expect (String -> String
forall a. Show a => a -> String
show String
l)]
             (String
p:[String]
ps) ->
                 case String -> String -> Maybe String
forall a. Eq a => [a] -> [a] -> Maybe [a]
stripPrefix String
l String
p of
                   (Just String
p') ->
                       do [((r -> r, [String]), MajorMinorPos)
-> Either StringsError ((r -> r, [String]), MajorMinorPos)
forall a b. b -> Either a b
Right ((r -> r
forall k (cat :: k -> k -> *) (a :: k). Category cat => cat a a
id, String
p'String -> [String] -> [String]
forall a. a -> [a] -> [a]
:[String]
ps), Int -> MajorMinorPos -> MajorMinorPos
forall i. Integral i => i -> MajorMinorPos -> MajorMinorPos
incMinor (String -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length String
l) MajorMinorPos
Pos StringsError
pos)]
                   Maybe String
Nothing ->
                       MajorMinorPos
-> [ErrorMsg]
-> [Either StringsError ((r -> r, [String]), MajorMinorPos)]
forall pos a. pos -> [ErrorMsg] -> [Either (ParserError pos) a]
mkParserError MajorMinorPos
Pos StringsError
pos [String -> ErrorMsg
UnExpect (String -> String
forall a. Show a => a -> String
show String
p), String -> ErrorMsg
Expect (String -> String
forall a. Show a => a -> String
show String
l)]
      sf :: r -> [([String] -> [String], r)]
sf r
b = [ (\[String]
strings -> case [String]
strings of [] -> [String
l] ; (String
s:[String]
ss) -> ((String
l String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
s) String -> [String] -> [String]
forall a. a -> [a] -> [a]
: [String]
ss), r
b)]

infixr 9 </>
-- | equivalent to @f . eos . g@
(</>) :: Boomerang StringsError [String] b c -> Boomerang StringsError [String] a b -> Boomerang StringsError [String] a c
Boomerang StringsError [String] b c
f </> :: Boomerang StringsError [String] b c
-> Boomerang StringsError [String] a b
-> Boomerang StringsError [String] a c
</> Boomerang StringsError [String] a b
g = Boomerang StringsError [String] b c
f Boomerang StringsError [String] b c
-> Boomerang StringsError [String] a b
-> Boomerang StringsError [String] a c
forall k (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. Boomerang StringsError [String] b b
forall r. Boomerang StringsError [String] r r
eos Boomerang StringsError [String] b b
-> Boomerang StringsError [String] a b
-> Boomerang StringsError [String] a b
forall k (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. Boomerang StringsError [String] a b
g

-- | end of string
eos :: Boomerang StringsError [String] r r
eos :: Boomerang StringsError [String] r r
eos = Parser StringsError [String] (r -> r)
-> (r -> [([String] -> [String], r)])
-> Boomerang StringsError [String] r r
forall e tok a b.
Parser e tok (a -> b)
-> (b -> [(tok -> tok, a)]) -> Boomerang e tok a b
Boomerang
       (([String]
 -> Pos StringsError
 -> [Either StringsError ((r -> r, [String]), Pos StringsError)])
-> Parser StringsError [String] (r -> r)
forall e tok a.
(tok -> Pos e -> [Either e ((a, tok), Pos e)]) -> Parser e tok a
Parser (([String]
  -> Pos StringsError
  -> [Either StringsError ((r -> r, [String]), Pos StringsError)])
 -> Parser StringsError [String] (r -> r))
-> ([String]
    -> Pos StringsError
    -> [Either StringsError ((r -> r, [String]), Pos StringsError)])
-> Parser StringsError [String] (r -> r)
forall a b. (a -> b) -> a -> b
$ \[String]
path Pos StringsError
pos -> case [String]
path of
                   []      -> [((r -> r, [String]), MajorMinorPos)
-> Either StringsError ((r -> r, [String]), MajorMinorPos)
forall a b. b -> Either a b
Right ((r -> r
forall k (cat :: k -> k -> *) (a :: k). Category cat => cat a a
id, []), Integer -> MajorMinorPos -> MajorMinorPos
forall i. Integral i => i -> MajorMinorPos -> MajorMinorPos
incMajor Integer
1 MajorMinorPos
Pos StringsError
pos)]
--                   [] -> mkParserError pos [EOI "input"]
                   (String
"":[String]
ps) ->
                          [ ((r -> r, [String]), MajorMinorPos)
-> Either StringsError ((r -> r, [String]), MajorMinorPos)
forall a b. b -> Either a b
Right ((r -> r
forall k (cat :: k -> k -> *) (a :: k). Category cat => cat a a
id, [String]
ps), Integer -> MajorMinorPos -> MajorMinorPos
forall i. Integral i => i -> MajorMinorPos -> MajorMinorPos
incMajor Integer
1 MajorMinorPos
Pos StringsError
pos) ]
                   (String
p:[String]
_) -> MajorMinorPos
-> [ErrorMsg]
-> [Either StringsError ((r -> r, [String]), MajorMinorPos)]
forall pos a. pos -> [ErrorMsg] -> [Either (ParserError pos) a]
mkParserError MajorMinorPos
Pos StringsError
pos [String -> ErrorMsg
Message (String -> ErrorMsg) -> String -> ErrorMsg
forall a b. (a -> b) -> a -> b
$ String
"path-segment not entirely consumed: " String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
p])
       (\r
a -> [((String
"" String -> [String] -> [String]
forall a. a -> [a] -> [a]
:), r
a)])

-- | statisfy a 'Char' predicate
satisfy :: (Char -> Bool) -> Boomerang StringsError [String] r (Char :- r)
satisfy :: (Char -> Bool) -> Boomerang StringsError [String] r (Char :- r)
satisfy Char -> Bool
p = Parser StringsError [String] Char
-> (Char -> [[String] -> [String]])
-> Boomerang StringsError [String] r (Char :- r)
forall e tok a r.
Parser e tok a -> (a -> [tok -> tok]) -> Boomerang e tok r (a :- r)
val
  (([String]
 -> Pos StringsError
 -> [Either StringsError ((Char, [String]), Pos StringsError)])
-> Parser StringsError [String] Char
forall e tok a.
(tok -> Pos e -> [Either e ((a, tok), Pos e)]) -> Parser e tok a
Parser (([String]
  -> Pos StringsError
  -> [Either StringsError ((Char, [String]), Pos StringsError)])
 -> Parser StringsError [String] Char)
-> ([String]
    -> Pos StringsError
    -> [Either StringsError ((Char, [String]), Pos StringsError)])
-> Parser StringsError [String] Char
forall a b. (a -> b) -> a -> b
$ \[String]
tok Pos StringsError
pos ->
       case [String]
tok of
         []          -> MajorMinorPos
-> [ErrorMsg]
-> [Either StringsError ((Char, [String]), MajorMinorPos)]
forall pos a. pos -> [ErrorMsg] -> [Either (ParserError pos) a]
mkParserError MajorMinorPos
Pos StringsError
pos [String -> ErrorMsg
EOI String
"input"]
         (String
"":[String]
ss)     -> MajorMinorPos
-> [ErrorMsg]
-> [Either StringsError ((Char, [String]), MajorMinorPos)]
forall pos a. pos -> [ErrorMsg] -> [Either (ParserError pos) a]
mkParserError MajorMinorPos
Pos StringsError
pos [String -> ErrorMsg
EOI String
"segment"]
         ((Char
c:String
cs):[String]
ss)
             | Char -> Bool
p Char
c ->
                 do [((Char, [String]), MajorMinorPos)
-> Either StringsError ((Char, [String]), MajorMinorPos)
forall a b. b -> Either a b
Right ((Char
c, String
cs String -> [String] -> [String]
forall a. a -> [a] -> [a]
: [String]
ss), Integer -> MajorMinorPos -> MajorMinorPos
forall i. Integral i => i -> MajorMinorPos -> MajorMinorPos
incMinor Integer
1 MajorMinorPos
Pos StringsError
pos )]
             | Bool
otherwise ->
                 do MajorMinorPos
-> [ErrorMsg]
-> [Either StringsError ((Char, [String]), MajorMinorPos)]
forall pos a. pos -> [ErrorMsg] -> [Either (ParserError pos) a]
mkParserError MajorMinorPos
Pos StringsError
pos [String -> ErrorMsg
SysUnExpect (String -> ErrorMsg) -> String -> ErrorMsg
forall a b. (a -> b) -> a -> b
$ Char -> String
forall a. Show a => a -> String
show Char
c]
  )
  (\Char
c -> [ \[String]
paths -> case [String]
paths of [] -> [[Char
c]] ; (String
s:[String]
ss) -> ((Char
cChar -> String -> String
forall a. a -> [a] -> [a]
:String
s)String -> [String] -> [String]
forall a. a -> [a] -> [a]
:[String]
ss) | Char -> Bool
p Char
c ])


-- | satisfy a 'String' predicate.
--
-- Note: must match the entire remainder of the 'String' in this segment
satisfyStr :: (String -> Bool) -> Boomerang StringsError [String] r (String :- r)
satisfyStr :: (String -> Bool) -> Boomerang StringsError [String] r (String :- r)
satisfyStr String -> Bool
p = Parser StringsError [String] String
-> (String -> [[String] -> [String]])
-> Boomerang StringsError [String] r (String :- r)
forall e tok a r.
Parser e tok a -> (a -> [tok -> tok]) -> Boomerang e tok r (a :- r)
val
  (([String]
 -> Pos StringsError
 -> [Either StringsError ((String, [String]), Pos StringsError)])
-> Parser StringsError [String] String
forall e tok a.
(tok -> Pos e -> [Either e ((a, tok), Pos e)]) -> Parser e tok a
Parser (([String]
  -> Pos StringsError
  -> [Either StringsError ((String, [String]), Pos StringsError)])
 -> Parser StringsError [String] String)
-> ([String]
    -> Pos StringsError
    -> [Either StringsError ((String, [String]), Pos StringsError)])
-> Parser StringsError [String] String
forall a b. (a -> b) -> a -> b
$ \[String]
tok Pos StringsError
pos ->
       case [String]
tok of
         []          -> MajorMinorPos
-> [ErrorMsg]
-> [Either StringsError ((String, [String]), MajorMinorPos)]
forall pos a. pos -> [ErrorMsg] -> [Either (ParserError pos) a]
mkParserError MajorMinorPos
Pos StringsError
pos [String -> ErrorMsg
EOI String
"input"]
         (String
"":[String]
ss)     -> MajorMinorPos
-> [ErrorMsg]
-> [Either StringsError ((String, [String]), MajorMinorPos)]
forall pos a. pos -> [ErrorMsg] -> [Either (ParserError pos) a]
mkParserError MajorMinorPos
Pos StringsError
pos [String -> ErrorMsg
EOI String
"segment"]
         (String
s:[String]
ss)
             | String -> Bool
p String
s ->
                 do [((String, [String]), MajorMinorPos)
-> Either StringsError ((String, [String]), MajorMinorPos)
forall a b. b -> Either a b
Right ((String
s, String
""String -> [String] -> [String]
forall a. a -> [a] -> [a]
:[String]
ss), Integer -> MajorMinorPos -> MajorMinorPos
forall i. Integral i => i -> MajorMinorPos -> MajorMinorPos
incMajor Integer
1 MajorMinorPos
Pos StringsError
pos )]
             | Bool
otherwise ->
                 do MajorMinorPos
-> [ErrorMsg]
-> [Either StringsError ((String, [String]), MajorMinorPos)]
forall pos a. pos -> [ErrorMsg] -> [Either (ParserError pos) a]
mkParserError MajorMinorPos
Pos StringsError
pos [String -> ErrorMsg
SysUnExpect (String -> ErrorMsg) -> String -> ErrorMsg
forall a b. (a -> b) -> a -> b
$ String -> String
forall a. Show a => a -> String
show String
s]
  )
  (\String
str -> [ \[String]
strings -> case [String]
strings of [] -> [String
str] ; (String
s:[String]
ss) -> ((String
strString -> String -> String
forall a. [a] -> [a] -> [a]
++String
s)String -> [String] -> [String]
forall a. a -> [a] -> [a]
:[String]
ss) | String -> Bool
p String
str ])


-- | ascii digits @\'0\'..\'9\'@
digit :: Boomerang StringsError [String] r (Char :- r)
digit :: Boomerang StringsError [String] r (Char :- r)
digit = (Char -> Bool) -> Boomerang StringsError [String] r (Char :- r)
forall r.
(Char -> Bool) -> Boomerang StringsError [String] r (Char :- r)
satisfy Char -> Bool
isDigit Boomerang StringsError [String] r (Char :- r)
-> String -> Boomerang StringsError [String] r (Char :- r)
forall p tok a b.
Boomerang (ParserError p) tok a b
-> String -> Boomerang (ParserError p) tok a b
<?> String
"a digit 0-9"

-- | matches alphabetic Unicode characters (lower-case, upper-case and title-case letters,
-- plus letters of caseless scripts and modifiers letters).  (Uses 'isAlpha')
alpha :: Boomerang StringsError [String] r (Char :- r)
alpha :: Boomerang StringsError [String] r (Char :- r)
alpha = (Char -> Bool) -> Boomerang StringsError [String] r (Char :- r)
forall r.
(Char -> Bool) -> Boomerang StringsError [String] r (Char :- r)
satisfy Char -> Bool
isAlpha Boomerang StringsError [String] r (Char :- r)
-> String -> Boomerang StringsError [String] r (Char :- r)
forall p tok a b.
Boomerang (ParserError p) tok a b
-> String -> Boomerang (ParserError p) tok a b
<?> String
"an alphabetic Unicode character"

-- | matches white-space characters in the Latin-1 range. (Uses 'isSpace')
space :: Boomerang StringsError [String] r (Char :- r)
space :: Boomerang StringsError [String] r (Char :- r)
space = (Char -> Bool) -> Boomerang StringsError [String] r (Char :- r)
forall r.
(Char -> Bool) -> Boomerang StringsError [String] r (Char :- r)
satisfy Char -> Bool
isSpace Boomerang StringsError [String] r (Char :- r)
-> String -> Boomerang StringsError [String] r (Char :- r)
forall p tok a b.
Boomerang (ParserError p) tok a b
-> String -> Boomerang (ParserError p) tok a b
<?> String
"a white-space character"

-- | any character
anyChar :: Boomerang StringsError [String] r (Char :- r)
anyChar :: Boomerang StringsError [String] r (Char :- r)
anyChar = (Char -> Bool) -> Boomerang StringsError [String] r (Char :- r)
forall r.
(Char -> Bool) -> Boomerang StringsError [String] r (Char :- r)
satisfy (Bool -> Char -> Bool
forall a b. a -> b -> a
const Bool
True)

-- | matches the specified character
char :: Char -> Boomerang StringsError [String] r (Char :- r)
char :: Char -> Boomerang StringsError [String] r (Char :- r)
char Char
c = (Char -> Bool) -> Boomerang StringsError [String] r (Char :- r)
forall r.
(Char -> Bool) -> Boomerang StringsError [String] r (Char :- r)
satisfy (Char -> Char -> Bool
forall a. Eq a => a -> a -> Bool
== Char
c) Boomerang StringsError [String] r (Char :- r)
-> String -> Boomerang StringsError [String] r (Char :- r)
forall p tok a b.
Boomerang (ParserError p) tok a b
-> String -> Boomerang (ParserError p) tok a b
<?> String -> String
forall a. Show a => a -> String
show [Char
c]

-- | lift 'Read'/'Show' to a 'Boomerang'
--
-- There are a few restrictions here:
--
--  1. Error messages are a bit fuzzy. `Read` does not tell us where
--  or why a parse failed. So all we can do it use the the position
--  that we were at when we called read and say that it failed.
--
--  2. it is (currently) not safe to use 'readshow' on integral values
--  because the 'Read' instance for 'Int', 'Integer', etc,
readshow :: (Read a, Show a) => Boomerang StringsError [String] r (a :- r)
readshow :: Boomerang StringsError [String] r (a :- r)
readshow =
    Parser StringsError [String] a
-> (a -> [[String] -> [String]])
-> Boomerang StringsError [String] r (a :- r)
forall e tok a r.
Parser e tok a -> (a -> [tok -> tok]) -> Boomerang e tok r (a :- r)
val Parser StringsError [String] a
forall a. Read a => Parser StringsError [String] a
readParser a -> [[String] -> [String]]
forall a. Show a => a -> [[String] -> [String]]
s
    where
      s :: a -> [[String] -> [String]]
s a
a = [ \[String]
strings -> case [String]
strings of [] -> [a -> String
forall a. Show a => a -> String
show a
a] ; (String
s:[String]
ss) -> (((a -> String
forall a. Show a => a -> String
show a
a)String -> String -> String
forall a. [a] -> [a] -> [a]
++String
s)String -> [String] -> [String]
forall a. a -> [a] -> [a]
:[String]
ss) ]

readParser :: (Read a) => Parser StringsError [String] a
readParser :: Parser StringsError [String] a
readParser =
    ([String]
 -> Pos StringsError
 -> [Either StringsError ((a, [String]), Pos StringsError)])
-> Parser StringsError [String] a
forall e tok a.
(tok -> Pos e -> [Either e ((a, tok), Pos e)]) -> Parser e tok a
Parser (([String]
  -> Pos StringsError
  -> [Either StringsError ((a, [String]), Pos StringsError)])
 -> Parser StringsError [String] a)
-> ([String]
    -> Pos StringsError
    -> [Either StringsError ((a, [String]), Pos StringsError)])
-> Parser StringsError [String] a
forall a b. (a -> b) -> a -> b
$ \[String]
tok Pos StringsError
pos ->
        case [String]
tok of
          []     -> MajorMinorPos
-> [ErrorMsg]
-> [Either StringsError ((a, [String]), MajorMinorPos)]
forall pos a. pos -> [ErrorMsg] -> [Either (ParserError pos) a]
mkParserError MajorMinorPos
Pos StringsError
pos [String -> ErrorMsg
EOI String
"input"]
          (String
"":[String]
_) -> MajorMinorPos
-> [ErrorMsg]
-> [Either StringsError ((a, [String]), MajorMinorPos)]
forall pos a. pos -> [ErrorMsg] -> [Either (ParserError pos) a]
mkParserError MajorMinorPos
Pos StringsError
pos [String -> ErrorMsg
EOI String
"segment"]
          (String
p:[String]
ps) ->
            case ReadS a
forall a. Read a => ReadS a
reads String
p of
              [] -> MajorMinorPos
-> [ErrorMsg]
-> [Either StringsError ((a, [String]), MajorMinorPos)]
forall pos a. pos -> [ErrorMsg] -> [Either (ParserError pos) a]
mkParserError MajorMinorPos
Pos StringsError
pos [String -> ErrorMsg
SysUnExpect String
p, String -> ErrorMsg
Message (String -> ErrorMsg) -> String -> ErrorMsg
forall a b. (a -> b) -> a -> b
$ String
"decoding using 'read' failed."]
              [(a
a,String
r)] ->
                  [((a, [String]), MajorMinorPos)
-> Either StringsError ((a, [String]), MajorMinorPos)
forall a b. b -> Either a b
Right ((a
a, String
rString -> [String] -> [String]
forall a. a -> [a] -> [a]
:[String]
ps), Int -> MajorMinorPos -> MajorMinorPos
forall i. Integral i => i -> MajorMinorPos -> MajorMinorPos
incMinor ((String -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length String
p) Int -> Int -> Int
forall a. Num a => a -> a -> a
- (String -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length String
r)) MajorMinorPos
Pos StringsError
pos)]

readIntegral :: (Read a, Eq a, Num a, Real a) => String -> a
readIntegral :: String -> a
readIntegral String
s =
    case (ReadS a -> ReadS a
forall a. Real a => ReadS a -> ReadS a
readSigned ReadS a
forall a. (Eq a, Num a) => ReadS a
readDec) String
s of
      [(a
x, [])] -> a
x
      []  -> String -> a
forall a. HasCallStack => String -> a
error String
"readIntegral: no parse"
      [(a, String)]
_   -> String -> a
forall a. HasCallStack => String -> a
error String
"readIntegral: ambiguous parse"

-- | matches an 'Int'
--
-- Note that the combinator @(rPair . int . int)@ is ill-defined because the parse can not tell where it is supposed to split the sequence of digits to produced two ints.
int :: Boomerang StringsError [String] r (Int :- r)
int :: Boomerang StringsError [String] r (Int :- r)
int = (String -> Int)
-> (Int -> Maybe String)
-> Boomerang StringsError [String] r (String :- r)
-> Boomerang StringsError [String] r (Int :- r)
forall a b e tok i o.
(a -> b)
-> (b -> Maybe a)
-> Boomerang e tok i (a :- o)
-> Boomerang e tok i (b :- o)
xmaph String -> Int
forall a. (Read a, Eq a, Num a, Real a) => String -> a
readIntegral (String -> Maybe String
forall a. a -> Maybe a
Just (String -> Maybe String) -> (Int -> String) -> Int -> Maybe String
forall k (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. Int -> String
forall a. Show a => a -> String
show) (Boomerang StringsError [String] (String :- r) (String :- r)
-> Boomerang StringsError [String] (String :- r) (String :- r)
forall e tok r. Boomerang e tok r r -> Boomerang e tok r r
opt (Boomerang
  StringsError [String] (Char :- (String :- r)) (String :- r)
forall e tok a r. Boomerang e tok (a :- ([a] :- r)) ([a] :- r)
rCons Boomerang
  StringsError [String] (Char :- (String :- r)) (String :- r)
-> Boomerang
     StringsError [String] (String :- r) (Char :- (String :- r))
-> Boomerang StringsError [String] (String :- r) (String :- r)
forall k (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. Char
-> Boomerang
     StringsError [String] (String :- r) (Char :- (String :- r))
forall r. Char -> Boomerang StringsError [String] r (Char :- r)
char Char
'-') Boomerang StringsError [String] (String :- r) (String :- r)
-> Boomerang StringsError [String] r (String :- r)
-> Boomerang StringsError [String] r (String :- r)
forall k (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. (Boomerang StringsError [String] r (Char :- r)
-> Boomerang StringsError [String] r (String :- r)
forall e tok r a.
Boomerang e tok r (a :- r) -> Boomerang e tok r ([a] :- r)
rList1 Boomerang StringsError [String] r (Char :- r)
forall r. Boomerang StringsError [String] r (Char :- r)
digit))

-- | matches an 'Integer'
--
-- Note that the combinator @(rPair . integer . integer)@ is ill-defined because the parse can not tell where it is supposed to split the sequence of digits to produced two ints.
integer :: Boomerang StringsError [String] r (Integer :- r)
integer :: Boomerang StringsError [String] r (Integer :- r)
integer = (String -> Integer)
-> (Integer -> Maybe String)
-> Boomerang StringsError [String] r (String :- r)
-> Boomerang StringsError [String] r (Integer :- r)
forall a b e tok i o.
(a -> b)
-> (b -> Maybe a)
-> Boomerang e tok i (a :- o)
-> Boomerang e tok i (b :- o)
xmaph String -> Integer
forall a. (Read a, Eq a, Num a, Real a) => String -> a
readIntegral (String -> Maybe String
forall a. a -> Maybe a
Just (String -> Maybe String)
-> (Integer -> String) -> Integer -> Maybe String
forall k (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. Integer -> String
forall a. Show a => a -> String
show) (Boomerang StringsError [String] (String :- r) (String :- r)
-> Boomerang StringsError [String] (String :- r) (String :- r)
forall e tok r. Boomerang e tok r r -> Boomerang e tok r r
opt (Boomerang
  StringsError [String] (Char :- (String :- r)) (String :- r)
forall e tok a r. Boomerang e tok (a :- ([a] :- r)) ([a] :- r)
rCons Boomerang
  StringsError [String] (Char :- (String :- r)) (String :- r)
-> Boomerang
     StringsError [String] (String :- r) (Char :- (String :- r))
-> Boomerang StringsError [String] (String :- r) (String :- r)
forall k (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. Char
-> Boomerang
     StringsError [String] (String :- r) (Char :- (String :- r))
forall r. Char -> Boomerang StringsError [String] r (Char :- r)
char Char
'-') Boomerang StringsError [String] (String :- r) (String :- r)
-> Boomerang StringsError [String] r (String :- r)
-> Boomerang StringsError [String] r (String :- r)
forall k (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. (Boomerang StringsError [String] r (Char :- r)
-> Boomerang StringsError [String] r (String :- r)
forall e tok r a.
Boomerang e tok r (a :- r) -> Boomerang e tok r ([a] :- r)
rList1 Boomerang StringsError [String] r (Char :- r)
forall r. Boomerang StringsError [String] r (Char :- r)
digit))

-- | matches any 'String'
--
-- the parser returns the remainder of the current String segment, (but does not consume the 'end of segment'.
--
-- Note that the only combinator that should follow 'anyString' is
-- 'eos' or '</>'. Other combinators will lead to inconsistent
-- inversions.
--
-- For example, if we have:
--
-- > unparseStrings (rPair . anyString . anyString)  ("foo","bar")
--
-- That will unparse to @Just ["foobar"]@. But if we call
--
-- > parseStrings (rPair . anyString . anyString)  ["foobar"]
--
-- We will get @Right ("foobar","")@ instead of the original @Right ("foo","bar")@
anyString :: Boomerang StringsError [String] r (String :- r)
anyString :: Boomerang StringsError [String] r (String :- r)
anyString = Parser StringsError [String] String
-> (String -> [[String] -> [String]])
-> Boomerang StringsError [String] r (String :- r)
forall e tok a r.
Parser e tok a -> (a -> [tok -> tok]) -> Boomerang e tok r (a :- r)
val Parser StringsError [String] String
ps String -> [[String] -> [String]]
forall a. [a] -> [[[a]] -> [[a]]]
ss
    where
      ps :: Parser StringsError [String] String
ps = ([String]
 -> Pos StringsError
 -> [Either StringsError ((String, [String]), Pos StringsError)])
-> Parser StringsError [String] String
forall e tok a.
(tok -> Pos e -> [Either e ((a, tok), Pos e)]) -> Parser e tok a
Parser (([String]
  -> Pos StringsError
  -> [Either StringsError ((String, [String]), Pos StringsError)])
 -> Parser StringsError [String] String)
-> ([String]
    -> Pos StringsError
    -> [Either StringsError ((String, [String]), Pos StringsError)])
-> Parser StringsError [String] String
forall a b. (a -> b) -> a -> b
$ \[String]
tok Pos StringsError
pos ->
           case [String]
tok of
             []     -> MajorMinorPos
-> [ErrorMsg]
-> [Either StringsError ((String, [String]), MajorMinorPos)]
forall pos a. pos -> [ErrorMsg] -> [Either (ParserError pos) a]
mkParserError MajorMinorPos
Pos StringsError
pos [String -> ErrorMsg
EOI String
"input", String -> ErrorMsg
Expect String
"any string"]
--             ("":_) -> mkParserError pos [EOI "segment", Expect "any string"]
             (String
s:[String]
ss) -> [((String, [String]), MajorMinorPos)
-> Either StringsError ((String, [String]), MajorMinorPos)
forall a b. b -> Either a b
Right ((String
s, String
""String -> [String] -> [String]
forall a. a -> [a] -> [a]
:[String]
ss), Int -> MajorMinorPos -> MajorMinorPos
forall i. Integral i => i -> MajorMinorPos -> MajorMinorPos
incMinor (String -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length String
s) MajorMinorPos
Pos StringsError
pos)]
      ss :: [a] -> [[[a]] -> [[a]]]
ss [a]
str = [\[[a]]
ss -> case [[a]]
ss of
                         []      -> [[a]
str]
                         ([a]
s:[[a]]
ss') -> (([a]
str [a] -> [a] -> [a]
forall a. [a] -> [a] -> [a]
++ [a]
s) [a] -> [[a]] -> [[a]]
forall a. a -> [a] -> [a]
: [[a]]
ss')
               ]

-- | Predicate to test if we have parsed all the strings.
-- Typically used as argument to 'parse1'
--
-- see also: 'parseStrings'
isComplete :: [String] -> Bool
isComplete :: [String] -> Bool
isComplete []   = Bool
True
isComplete [String
""] = Bool
True
isComplete [String]
_    = Bool
False

-- | run the parser
--
-- Returns the first complete parse or a parse error.
--
-- > parseStrings (rUnit . lit "foo") ["foo"]
parseStrings :: Boomerang StringsError [String] () (r :- ())
             -> [String]
             -> Either StringsError r
parseStrings :: Boomerang StringsError [String] () (r :- ())
-> [String] -> Either StringsError r
parseStrings Boomerang StringsError [String] () (r :- ())
pp [String]
strs =
    ([StringsError] -> Either StringsError r)
-> (r -> Either StringsError r)
-> Either [StringsError] r
-> Either StringsError r
forall a c b. (a -> c) -> (b -> c) -> Either a b -> c
either (StringsError -> Either StringsError r
forall a b. a -> Either a b
Left (StringsError -> Either StringsError r)
-> ([StringsError] -> StringsError)
-> [StringsError]
-> Either StringsError r
forall k (cat :: k -> k -> *) (b :: k) (c :: k) (a :: k).
Category cat =>
cat b c -> cat a b -> cat a c
. [StringsError] -> StringsError
forall pos. Ord pos => [ParserError pos] -> ParserError pos
condenseErrors) r -> Either StringsError r
forall a b. b -> Either a b
Right (Either [StringsError] r -> Either StringsError r)
-> Either [StringsError] r -> Either StringsError r
forall a b. (a -> b) -> a -> b
$ ([String] -> Bool)
-> Boomerang StringsError [String] () (r :- ())
-> [String]
-> Either [StringsError] r
forall e tok a.
(ErrorPosition e, InitialPosition e, Show e, Ord (Pos e)) =>
(tok -> Bool)
-> Boomerang e tok () (a :- ()) -> tok -> Either [e] a
parse1 [String] -> Bool
isComplete Boomerang StringsError [String] () (r :- ())
pp [String]
strs

-- | run the printer
--
-- > unparseStrings (rUnit . lit "foo") ()
unparseStrings :: Boomerang e [String] () (r :- ()) -> r -> Maybe [String]
unparseStrings :: Boomerang e [String] () (r :- ()) -> r -> Maybe [String]
unparseStrings Boomerang e [String] () (r :- ())
pp r
r = [String]
-> Boomerang e [String] () (r :- ()) -> r -> Maybe [String]
forall tok e a.
tok -> Boomerang e tok () (a :- ()) -> a -> Maybe tok
unparse1 [] Boomerang e [String] () (r :- ())
pp r
r