{-# LANGUAGE CPP #-}
{-# LANGUAGE OverloadedStrings #-}
module Swish.RDF.Parser.Utils
( SpecialMap
, prefixTable, specialTable
, runParserWithError
, ParseResult
, ignore
, char
, ichar
, string
, stringT
, symbol
, isymbol
, lexeme
, notFollowedBy
, whiteSpace
, skipMany
, skipMany1
, endBy
, sepEndBy
, sepEndBy1
, manyTill
, noneOf
, eoln
, fullStop
, hex4
, hex8
, appendURIs
)
where
import Swish.Namespace (Namespace, makeNamespace, ScopedName)
import Swish.RDF.Graph (RDFGraph)
import Swish.RDF.Vocabulary
( namespaceRDF
, namespaceRDFS
, namespaceRDFD
, namespaceOWL
, namespaceLOG
, rdfType
, rdfFirst, rdfRest, rdfNil
, owlSameAs, logImplies
, defaultBase
)
import Data.Char (isSpace, isHexDigit, chr)
#if MIN_VERSION_base(4, 7, 0)
import Data.Functor (($>))
#endif
import Data.Maybe (fromMaybe, fromJust)
import Network.URI (URI(..), relativeTo, parseURIReference)
import Text.ParserCombinators.Poly.StateText
import qualified Data.Map as M
import qualified Data.Text as T
import qualified Data.Text.Lazy as L
import qualified Data.Text.Read as R
#if !MIN_VERSION_base(4, 7, 0)
($>) :: Functor f => f a -> b -> f b
($>) = flip (<$)
#endif
appendURIs ::
URI
-> URI
-> Either String URI
appendURIs :: URI -> URI -> Either String URI
appendURIs URI
base URI
uri =
case URI -> String
uriScheme URI
uri of
String
"" -> forall a b. b -> Either a b
Right forall a b. (a -> b) -> a -> b
$ URI
uri URI -> URI -> URI
`relativeTo` URI
base
String
_ -> forall a b. b -> Either a b
Right URI
uri
type SpecialMap = M.Map String ScopedName
prefixTable :: [Namespace]
prefixTable :: [Namespace]
prefixTable = [ Namespace
namespaceRDF
, Namespace
namespaceRDFS
, Namespace
namespaceRDFD
, Namespace
namespaceOWL
, Namespace
namespaceLOG
, Maybe Text -> URI -> Namespace
makeNamespace forall a. Maybe a
Nothing forall a b. (a -> b) -> a -> b
$ forall a. HasCallStack => Maybe a -> a
fromJust (String -> Maybe URI
parseURIReference String
"#")
]
specialTable ::
Maybe ScopedName
-> [(String,ScopedName)]
specialTable :: Maybe ScopedName -> [(String, ScopedName)]
specialTable Maybe ScopedName
mbase =
[ (String
"a", ScopedName
rdfType ),
(String
"equals", ScopedName
owlSameAs ),
(String
"implies", ScopedName
logImplies ),
(String
"listfirst", ScopedName
rdfFirst ),
(String
"listrest", ScopedName
rdfRest ),
(String
"listnull", ScopedName
rdfNil ),
(String
"base", forall a. a -> Maybe a -> a
fromMaybe ScopedName
defaultBase Maybe ScopedName
mbase )
]
runParserWithError ::
Parser a b
-> a
-> L.Text
-> Either String b
runParserWithError :: forall a b. Parser a b -> a -> Text -> Either String b
runParserWithError Parser a b
parser a
state0 Text
input =
let (Either String b
result, a
_, Text
unparsed) = forall s a. Parser s a -> s -> Text -> (Either String a, s, Text)
runParser Parser a b
parser a
state0 Text
input
econtext :: String
econtext = if Text -> Bool
L.null Text
unparsed
then String
"\n(at end of the text)\n"
else String
"\nRemaining input:\n" forall a. [a] -> [a] -> [a]
++
case Text -> Int64 -> Ordering
L.compareLength Text
unparsed Int64
40 of
Ordering
GT -> Text -> String
L.unpack (Int64 -> Text -> Text
L.take Int64
40 Text
unparsed) forall a. [a] -> [a] -> [a]
++ String
"..."
Ordering
_ -> Text -> String
L.unpack Text
unparsed
in case Either String b
result of
Left String
emsg -> forall a b. a -> Either a b
Left forall a b. (a -> b) -> a -> b
$ String
emsg forall a. [a] -> [a] -> [a]
++ String
econtext
Either String b
_ -> Either String b
result
type ParseResult = Either String RDFGraph
ignore :: (Applicative f) => f a -> f ()
ignore :: forall (f :: * -> *) a. Applicative f => f a -> f ()
ignore f a
f = f a
f forall (f :: * -> *) a b. Functor f => f a -> b -> f b
$> ()
char :: Char -> Parser s Char
char :: forall s. Char -> Parser s Char
char Char
c = forall s. (Char -> Bool) -> Parser s Char
satisfy (forall a. Eq a => a -> a -> Bool
== Char
c)
ichar :: Char -> Parser s ()
ichar :: forall s. Char -> Parser s ()
ichar = forall (f :: * -> *) a. Applicative f => f a -> f ()
ignore forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall s. Char -> Parser s Char
char
string :: String -> Parser s String
string :: forall s. String -> Parser s String
string = forall (t :: * -> *) (m :: * -> *) a b.
(Traversable t, Monad m) =>
(a -> m b) -> t a -> m (t b)
mapM forall s. Char -> Parser s Char
char
stringT :: T.Text -> Parser s T.Text
stringT :: forall s. Text -> Parser s Text
stringT Text
s = forall s. String -> Parser s String
string (Text -> String
T.unpack Text
s) forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> forall (m :: * -> *) a. Monad m => a -> m a
return Text
s
skipMany :: Parser s a -> Parser s ()
skipMany :: forall s a. Parser s a -> Parser s ()
skipMany = forall (f :: * -> *) a. Applicative f => f a -> f ()
ignore forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall (f :: * -> *) a. Alternative f => f a -> f [a]
many
skipMany1 :: Parser s a -> Parser s ()
skipMany1 :: forall s a. Parser s a -> Parser s ()
skipMany1 = forall (f :: * -> *) a. Applicative f => f a -> f ()
ignore forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall (p :: * -> *) a. PolyParse p => p a -> p [a]
many1
endBy ::
Parser s a
-> Parser s b
-> Parser s [a]
endBy :: forall s a b. Parser s a -> Parser s b -> Parser s [a]
endBy Parser s a
p Parser s b
sep = forall (f :: * -> *) a. Alternative f => f a -> f [a]
many (Parser s a
p forall (f :: * -> *) a b. Applicative f => f a -> f b -> f a
<* Parser s b
sep)
sepEndBy ::
Parser s a
-> Parser s b
-> Parser s [a]
sepEndBy :: forall s a b. Parser s a -> Parser s b -> Parser s [a]
sepEndBy Parser s a
p Parser s b
sep = forall s a b. Parser s a -> Parser s b -> Parser s [a]
sepEndBy1 Parser s a
p Parser s b
sep forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> forall (f :: * -> *) a. Applicative f => a -> f a
pure []
sepEndBy1 ::
Parser s a
-> Parser s b
-> Parser s [a]
sepEndBy1 :: forall s a b. Parser s a -> Parser s b -> Parser s [a]
sepEndBy1 Parser s a
p Parser s b
sep = do
a
x <- Parser s a
p
(Parser s b
sep forall (f :: * -> *) a b. Applicative f => f a -> f b -> f b
*> ((a
xforall a. a -> [a] -> [a]
:) forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> forall s a b. Parser s a -> Parser s b -> Parser s [a]
sepEndBy Parser s a
p Parser s b
sep)) forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> forall (m :: * -> *) a. Monad m => a -> m a
return [a
x]
manyTill ::
Parser s a
-> Parser s b
-> Parser s [a]
manyTill :: forall s a b. Parser s a -> Parser s b -> Parser s [a]
manyTill Parser s a
p Parser s b
end = Parser s [a]
go
where
go :: Parser s [a]
go = (Parser s b
end forall (f :: * -> *) a b. Functor f => f a -> b -> f b
$> [])
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|>
((:) forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Parser s a
p forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Parser s [a]
go)
noneOf :: String -> Parser s Char
noneOf :: forall s. String -> Parser s Char
noneOf String
istr = forall s. (Char -> Bool) -> Parser s Char
satisfy (forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`notElem` String
istr)
fullStop :: Parser s ()
fullStop :: forall s. Parser s ()
fullStop = forall s. Char -> Parser s ()
ichar Char
'.'
eoln :: Parser s ()
eoln :: forall s. Parser s ()
eoln = forall (f :: * -> *) a. Applicative f => f a -> f ()
ignore (forall (p :: * -> *) a. PolyParse p => [p a] -> p a
oneOf [forall s. String -> Parser s String
string String
"\r\n", forall s. String -> Parser s String
string String
"\r", forall s. String -> Parser s String
string String
"\n"])
notFollowedBy :: (Char -> Bool) -> Parser s ()
notFollowedBy :: forall s. (Char -> Bool) -> Parser s ()
notFollowedBy Char -> Bool
p = do
Char
c <- forall s. Parser s Char
next
if Char -> Bool
p Char
c
then forall (m :: * -> *) a. MonadFail m => String -> m a
fail forall a b. (a -> b) -> a -> b
$ String
"Unexpected character: " forall a. [a] -> [a] -> [a]
++ forall a. Show a => a -> String
show [Char
c]
else forall s. Text -> Parser s ()
reparse forall a b. (a -> b) -> a -> b
$ Char -> Text
L.singleton Char
c
symbol :: String -> Parser s String
symbol :: forall s. String -> Parser s String
symbol = forall s a. Parser s a -> Parser s a
lexeme forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall s. String -> Parser s String
string
isymbol :: String -> Parser s ()
isymbol :: forall s. String -> Parser s ()
isymbol = forall (f :: * -> *) a. Applicative f => f a -> f ()
ignore forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall s. String -> Parser s String
symbol
lexeme :: Parser s a -> Parser s a
lexeme :: forall s a. Parser s a -> Parser s a
lexeme Parser s a
p = Parser s a
p forall (f :: * -> *) a b. Applicative f => f a -> f b -> f a
<* forall s. Parser s ()
whiteSpace
whiteSpace :: Parser s ()
whiteSpace :: forall s. Parser s ()
whiteSpace = forall s a. Parser s a -> Parser s ()
skipMany (forall s. Parser s ()
simpleSpace forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> forall s. Parser s ()
oneLineComment)
simpleSpace :: Parser s ()
simpleSpace :: forall s. Parser s ()
simpleSpace = forall (f :: * -> *) a. Applicative f => f a -> f ()
ignore forall a b. (a -> b) -> a -> b
$ forall s. (Char -> Bool) -> Parser s Text
many1Satisfy Char -> Bool
isSpace
oneLineComment :: Parser s ()
= (forall s. Char -> Parser s ()
ichar Char
'#' forall (f :: * -> *) a b. Applicative f => f a -> f b -> f b
*> forall s. (Char -> Bool) -> Parser s Text
manySatisfy (forall a. Eq a => a -> a -> Bool
/= Char
'\n')) forall (f :: * -> *) a b. Functor f => f a -> b -> f b
$> ()
hexDigit :: Parser a Char
hexDigit :: forall s. Parser s Char
hexDigit = forall s. (Char -> Bool) -> Parser s Char
satisfy Char -> Bool
isHexDigit
hex4 :: Parser a Char
hex4 :: forall s. Parser s Char
hex4 = do
String
digs <- forall (p :: * -> *) a. PolyParse p => Int -> p a -> p [a]
exactly Int
4 forall s. Parser s Char
hexDigit
let mhex :: Either String (Int, Text)
mhex = forall a. Integral a => Reader a
R.hexadecimal (String -> Text
T.pack String
digs)
case Either String (Int, Text)
mhex of
Left String
emsg -> forall (p :: * -> *) a. PolyParse p => String -> p a
failBad forall a b. (a -> b) -> a -> b
$ String
"Internal error: unable to parse hex4: " forall a. [a] -> [a] -> [a]
++ String
emsg
Right (Int
v, Text
"") -> forall (m :: * -> *) a. Monad m => a -> m a
return forall a b. (a -> b) -> a -> b
$ Int -> Char
chr Int
v
Right (Int
_, Text
vs) -> forall (p :: * -> *) a. PolyParse p => String -> p a
failBad forall a b. (a -> b) -> a -> b
$ String
"Internal error: hex4 remainder = " forall a. [a] -> [a] -> [a]
++ Text -> String
T.unpack Text
vs
hex8 :: Parser a Char
hex8 :: forall s. Parser s Char
hex8 = do
String
digs <- forall (p :: * -> *) a. PolyParse p => Int -> p a -> p [a]
exactly Int
8 forall s. Parser s Char
hexDigit
let mhex :: Either String (Int, Text)
mhex = forall a. Integral a => Reader a
R.hexadecimal (String -> Text
T.pack String
digs)
case Either String (Int, Text)
mhex of
Left String
emsg -> forall (p :: * -> *) a. PolyParse p => String -> p a
failBad forall a b. (a -> b) -> a -> b
$ String
"Internal error: unable to parse hex8: " forall a. [a] -> [a] -> [a]
++ String
emsg
Right (Int
v, Text
"") -> if Int
v forall a. Ord a => a -> a -> Bool
<= Int
0x10FFFF
then forall (m :: * -> *) a. Monad m => a -> m a
return forall a b. (a -> b) -> a -> b
$ Int -> Char
chr Int
v
else forall (p :: * -> *) a. PolyParse p => String -> p a
failBad String
"\\UHHHHHHHH format is limited to a maximum of \\U0010FFFF"
Right (Int
_, Text
vs) -> forall (p :: * -> *) a. PolyParse p => String -> p a
failBad forall a b. (a -> b) -> a -> b
$ String
"Internal error: hex8 remainder = " forall a. [a] -> [a] -> [a]
++ Text -> String
T.unpack Text
vs