{-# LANGUAGE CPP #-}

-- | A parser for RDF in N-Triples format
--  <http://www.w3.org/TR/rdf-testcases/#ntriples>.
module Text.RDF.RDF4H.NTriplesParser
  ( NTriplesParser (NTriplesParser),
    NTriplesParserCustom (NTriplesParserCustom),
    ParseFailure,
    nt_echar,
    nt_uchar,
    nt_langtag,
    string_literal_quote,
    nt_string_literal_quote,
    nt_pn_chars_base,
    nt_comment,
    readFile,
  )
where

#if MIN_VERSION_base(4,9,0)
#if !MIN_VERSION_base(4,11,0)
import Data.Semigroup ((<>))
#else
#endif
#else
#endif

import Control.Applicative
import Control.Monad (void)
import Data.Attoparsec.ByteString (IResult (..), parse)
import Data.Char (isAlphaNum, isAsciiLower, isAsciiUpper, isDigit, isLetter)
import Data.RDF.IRI
import Data.RDF.Types hiding (empty)
import qualified Data.Text as T
import qualified Data.Text.Encoding as T
import qualified Data.Text.IO as T
import System.IO (IOMode (..), hSetEncoding, hSetNewlineMode, noNewlineTranslation, utf8, withFile)
import Text.Parsec (ParseError, runParser)
import Text.Parser.Char
import Text.Parser.Combinators
import Text.Parser.LookAhead
import Text.RDF.RDF4H.ParserUtils
import Prelude hiding (readFile)

-- | NTriplesParser is an 'RdfParser' implementation for parsing RDF in the
--  NTriples format. It requires no configuration options. To use this parser,
--  pass an 'NTriplesParser' value as the first argument to any of the
--  'parseString', 'parseFile', or 'parseURL' methods of the 'RdfParser' type
--  class.
data NTriplesParser = NTriplesParser

newtype NTriplesParserCustom = NTriplesParserCustom Parser

-- | 'NTriplesParser' is an instance of 'RdfParser' using parsec based parsers.
instance RdfParser NTriplesParser where
  parseString :: NTriplesParser -> Text -> Either ParseFailure (RDF a)
parseString NTriplesParser
_ = Text -> Either ParseFailure (RDF a)
forall a. Rdf a => Text -> Either ParseFailure (RDF a)
parseStringParsec
  parseFile :: NTriplesParser -> String -> IO (Either ParseFailure (RDF a))
parseFile NTriplesParser
_ = String -> IO (Either ParseFailure (RDF a))
forall a. Rdf a => String -> IO (Either ParseFailure (RDF a))
parseFileParsec
  parseURL :: NTriplesParser -> String -> IO (Either ParseFailure (RDF a))
parseURL NTriplesParser
_ = String -> IO (Either ParseFailure (RDF a))
forall a. Rdf a => String -> IO (Either ParseFailure (RDF a))
parseURLParsec

-- | 'NTriplesParser' is an instance of 'RdfParser'.
instance RdfParser NTriplesParserCustom where
  parseString :: NTriplesParserCustom -> Text -> Either ParseFailure (RDF a)
parseString (NTriplesParserCustom Parser
Parsec) = Text -> Either ParseFailure (RDF a)
forall a. Rdf a => Text -> Either ParseFailure (RDF a)
parseStringParsec
  parseString (NTriplesParserCustom Parser
Attoparsec) = Text -> Either ParseFailure (RDF a)
forall a. Rdf a => Text -> Either ParseFailure (RDF a)
parseStringAttoparsec
  parseFile :: NTriplesParserCustom -> String -> IO (Either ParseFailure (RDF a))
parseFile (NTriplesParserCustom Parser
Parsec) = String -> IO (Either ParseFailure (RDF a))
forall a. Rdf a => String -> IO (Either ParseFailure (RDF a))
parseFileParsec
  parseFile (NTriplesParserCustom Parser
Attoparsec) = String -> IO (Either ParseFailure (RDF a))
forall a. Rdf a => String -> IO (Either ParseFailure (RDF a))
parseFileAttoparsec
  parseURL :: NTriplesParserCustom -> String -> IO (Either ParseFailure (RDF a))
parseURL (NTriplesParserCustom Parser
Parsec) = String -> IO (Either ParseFailure (RDF a))
forall a. Rdf a => String -> IO (Either ParseFailure (RDF a))
parseURLParsec
  parseURL (NTriplesParserCustom Parser
Attoparsec) = String -> IO (Either ParseFailure (RDF a))
forall a. Rdf a => String -> IO (Either ParseFailure (RDF a))
parseURLAttoparsec

-- We define or redefine all here using same names as the spec, but with an
-- 'nt_' prefix in order to avoid name clashes (e.g., ntripleDoc becomes
-- nt_ntripleDoc).

-- | nt_ntripleDoc is simply zero or more lines.
--  grammar [1] ntriplesDoc ::= triple? (EOL triple)* EOL?
nt_ntripleDoc :: (CharParsing m, LookAheadParsing m, Monad m) => m [Triple]
nt_ntripleDoc :: m [Triple]
nt_ntripleDoc = m [()] -> m [[()]]
forall (f :: * -> *) a. Alternative f => f a -> f [a]
many m [()]
sep m [[()]] -> m [Triple] -> m [Triple]
forall (f :: * -> *) a b. Applicative f => f a -> f b -> f b
*> m Triple -> m [[()]] -> m [Triple]
forall (m :: * -> *) a sep. Alternative m => m a -> m sep -> m [a]
sepEndBy (m Triple -> m Triple
forall (m :: * -> *) a. Parsing m => m a -> m a
try m Triple
forall (m :: * -> *).
(CharParsing m, LookAheadParsing m, Monad m) =>
m Triple
nt_triple) (m [()] -> m [[()]]
forall (f :: * -> *) a. Alternative f => f a -> f [a]
many m [()]
sep) m [Triple] -> m () -> m [Triple]
forall (f :: * -> *) a b. Applicative f => f a -> f b -> f a
<* m ()
forall (m :: * -> *). Parsing m => m ()
eof
  where
    sep :: m [()]
sep = m () -> m [()]
forall (f :: * -> *) a. Alternative f => f a -> f [a]
many m ()
forall (m :: * -> *). CharParsing m => m ()
nt_space m [()] -> m () -> m ()
forall (f :: * -> *) a b. Applicative f => f a -> f b -> f b
*> (m () -> m ()
forall (m :: * -> *) a. Parsing m => m a -> m a
try m ()
forall (m :: * -> *). CharParsing m => m ()
nt_comment m () -> m () -> m ()
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> m () -> m ()
forall (m :: * -> *) a. Parsing m => m a -> m a
try m ()
forall (m :: * -> *). CharParsing m => m ()
nt_eoln) m () -> m [()] -> m [()]
forall (f :: * -> *) a b. Applicative f => f a -> f b -> f b
*> m () -> m [()]
forall (f :: * -> *) a. Alternative f => f a -> f [a]
many m ()
forall (m :: * -> *). CharParsing m => m ()
nt_space

-- A triple consists of whitespace-delimited subject, predicate, and object,
-- followed by optional whitespace and a period, and possibly more
-- whitespace.
--
-- NTriples W3C test "minimal_whitespace" proposes no space:
--
-- "tests absense of whitespace between subject, predicate, object and
-- end-of-statement"
--
-- `optional` lets this nt_triple parser succeed even if there is not
-- a space or tab character between resources or the object and the '.'.
-- Grammar [2] triple ::= subject predicate object '.'
nt_triple :: (CharParsing m, LookAheadParsing m, Monad m) => m Triple
nt_triple :: m Triple
nt_triple =
  Node -> Node -> Node -> Triple
Triple
    (Node -> Node -> Node -> Triple)
-> m Node -> m (Node -> Node -> Triple)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> (m Node
forall (m :: * -> *).
(CharParsing m, LookAheadParsing m, Monad m) =>
m Node
nt_subject m Node -> m (Maybe ()) -> m Node
forall (f :: * -> *) a b. Applicative f => f a -> f b -> f a
<* m () -> m (Maybe ())
forall (f :: * -> *) a. Alternative f => f a -> f (Maybe a)
optional (m () -> m ()
forall (m :: * -> *) a. Parsing m => m a -> m ()
skipSome m ()
forall (m :: * -> *). CharParsing m => m ()
nt_space))
    m (Node -> Node -> Triple) -> m Node -> m (Node -> Triple)
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> (m Node
forall (m :: * -> *). (CharParsing m, Monad m) => m Node
nt_predicate m Node -> m (Maybe ()) -> m Node
forall (f :: * -> *) a b. Applicative f => f a -> f b -> f a
<* m () -> m (Maybe ())
forall (f :: * -> *) a. Alternative f => f a -> f (Maybe a)
optional (m () -> m ()
forall (m :: * -> *) a. Parsing m => m a -> m ()
skipSome m ()
forall (m :: * -> *). CharParsing m => m ()
nt_space))
    m (Node -> Triple) -> m Node -> m Triple
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> (m Node
forall (m :: * -> *).
(CharParsing m, LookAheadParsing m, Monad m) =>
m Node
nt_object m Node -> m (Maybe ()) -> m Node
forall (f :: * -> *) a b. Applicative f => f a -> f b -> f a
<* m () -> m (Maybe ())
forall (f :: * -> *) a. Alternative f => f a -> f (Maybe a)
optional (m () -> m ()
forall (m :: * -> *) a. Parsing m => m a -> m ()
skipSome m ()
forall (m :: * -> *). CharParsing m => m ()
nt_space) m Node -> m Char -> m Node
forall (f :: * -> *) a b. Applicative f => f a -> f b -> f a
<* Char -> m Char
forall (m :: * -> *). CharParsing m => Char -> m Char
char Char
'.' m Node -> m [()] -> m Node
forall (f :: * -> *) a b. Applicative f => f a -> f b -> f a
<* m () -> m [()]
forall (f :: * -> *) a. Alternative f => f a -> f [a]
many m ()
forall (m :: * -> *). CharParsing m => m ()
nt_space)

-- Grammar [6] literal ::= STRING_LITERAL_QUOTE ('^^' IRIREF | LANGTAG)?
nt_literal :: (CharParsing m, Monad m) => m LValue
nt_literal :: m LValue
nt_literal = do
  Text
str <- m Text
forall (m :: * -> *). (CharParsing m, Monad m) => m Text
nt_string_literal_quote
  LValue -> m LValue -> m LValue
forall (m :: * -> *) a. Alternative m => a -> m a -> m a
option (Text -> LValue
plainL Text
str) (Text -> m LValue
forall (f :: * -> *). (CharParsing f, Monad f) => Text -> f LValue
langTag Text
str m LValue -> m LValue -> m LValue
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> Text -> m LValue
forall (f :: * -> *). (CharParsing f, Monad f) => Text -> f LValue
typeIRI Text
str)
  where
    langTag :: Text -> f LValue
langTag Text
str = Text -> Text -> LValue
plainLL Text
str (Text -> LValue) -> f Text -> f LValue
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> f Text -> f Text
forall (m :: * -> *) a. Parsing m => m a -> m a
try f Text
forall (m :: * -> *). (CharParsing m, Monad m) => m Text
nt_langtag
    typeIRI :: Text -> f LValue
typeIRI Text
str = Text -> Text -> LValue
typedL Text
str (Text -> LValue) -> f Text -> f LValue
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> f Text -> f Text
forall (m :: * -> *) a. Parsing m => m a -> m a
try (Int -> f Char -> f String
forall (m :: * -> *) a. Applicative m => Int -> m a -> m [a]
count Int
2 (Char -> f Char
forall (m :: * -> *). CharParsing m => Char -> m Char
char Char
'^') f String -> f Text -> f Text
forall (f :: * -> *) a b. Applicative f => f a -> f b -> f b
*> f Text
forall (m :: * -> *). (CharParsing m, Monad m) => m Text
nt_iriref)

-- Grammar [9] STRING_LITERAL_QUOTE ::= '"' ([^#x22#x5C#xA#xD] | ECHAR | UCHAR)* '"'
nt_string_literal_quote :: (CharParsing m, Monad m) => m T.Text
nt_string_literal_quote :: m Text
nt_string_literal_quote = Char -> m Text
forall (m :: * -> *). (CharParsing m, Monad m) => Char -> m Text
string_literal_quote Char
'"'

string_literal_quote :: (CharParsing m, Monad m) => Char -> m T.Text
string_literal_quote :: Char -> m Text
string_literal_quote Char
d = m Char -> m Char -> m Text -> m Text
forall (m :: * -> *) bra ket a.
Applicative m =>
m bra -> m ket -> m a -> m a
between (Char -> m Char
forall (m :: * -> *). CharParsing m => Char -> m Char
char Char
d) (Char -> m Char
forall (m :: * -> *). CharParsing m => Char -> m Char
char Char
d) m Text
string_literal
  where
    string_literal :: m Text
string_literal = String -> Text
T.pack (String -> Text) -> m String -> m Text
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> m Char -> m String
forall (f :: * -> *) a. Alternative f => f a -> f [a]
many (m Char -> m Char
forall (m :: * -> *) a. Parsing m => m a -> m a
try m Char
validLiteralChar)
    validLiteralChar :: m Char
validLiteralChar =
      String -> m Char
forall (m :: * -> *). CharParsing m => String -> m Char
noneOf [Char
d, Char
'\x5C', Char
'\xA', Char
'\xD']
        m Char -> m Char -> m Char
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> m Char
forall (m :: * -> *). (CharParsing m, Monad m) => m Char
nt_echar
        m Char -> m Char -> m Char
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> m Char
forall (m :: * -> *). (CharParsing m, Monad m) => m Char
nt_uchar

-- Grammar [144s] LANGTAG ::= '@' [a-zA-Z]+ ('-' [a-zA-Z0-9]+)*
nt_langtag :: (CharParsing m, Monad m) => m T.Text
nt_langtag :: m Text
nt_langtag = do
  String
ss <- Char -> m Char
forall (m :: * -> *). CharParsing m => Char -> m Char
char Char
'@' m Char -> m String -> m String
forall (f :: * -> *) a b. Applicative f => f a -> f b -> f b
*> m Char -> m String
forall (f :: * -> *) a. Alternative f => f a -> f [a]
some ((Char -> Bool) -> m Char
forall (m :: * -> *). CharParsing m => (Char -> Bool) -> m Char
satisfy Char -> Bool
isLetter)
  String
rest <- [String] -> String
forall (t :: * -> *) a. Foldable t => t [a] -> [a]
concat ([String] -> String) -> m [String] -> m String
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> m String -> m [String]
forall (f :: * -> *) a. Alternative f => f a -> f [a]
many (Char -> m Char
forall (m :: * -> *). CharParsing m => Char -> m Char
char Char
'-' m Char -> m String -> m String
forall (f :: * -> *) a b. Applicative f => f a -> f b -> f b
*> m Char -> m String
forall (f :: * -> *) a. Alternative f => f a -> f [a]
some ((Char -> Bool) -> m Char
forall (m :: * -> *). CharParsing m => (Char -> Bool) -> m Char
satisfy Char -> Bool
isAlphaNum) m String -> (String -> m String) -> m String
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= \String
lang_str -> String -> m String
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Char
'-' Char -> String -> String
forall a. a -> [a] -> [a]
: String
lang_str))
  Text -> m Text
forall (f :: * -> *) a. Applicative f => a -> f a
pure (String -> Text
T.pack (String
ss String -> String -> String
forall a. Semigroup a => a -> a -> a
<> String
rest))

-- [8] IRIREF
nt_iriref :: (CharParsing m, Monad m) => m T.Text
nt_iriref :: m Text
nt_iriref = m Char -> m Char -> m Text -> m Text
forall (m :: * -> *) bra ket a.
Applicative m =>
m bra -> m ket -> m a -> m a
between (Char -> m Char
forall (m :: * -> *). CharParsing m => Char -> m Char
char Char
'<') (Char -> m Char
forall (m :: * -> *). CharParsing m => Char -> m Char
char Char
'>') (m Text -> m Text) -> m Text -> m Text
forall a b. (a -> b) -> a -> b
$ do
  Text
raw_iri <- m Text
forall (m :: * -> *). (CharParsing m, Monad m) => m Text
iriFragment
  (String -> m Text)
-> (Text -> m Text) -> Either String Text -> m Text
forall a c b. (a -> c) -> (b -> c) -> Either a b -> c
either (m Text -> String -> m Text
forall a b. a -> b -> a
const m Text
forall (f :: * -> *) a. Alternative f => f a
empty) Text -> m Text
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Text -> Either String Text
validateIRI Text
raw_iri) m Text -> String -> m Text
forall (m :: * -> *) a. Parsing m => m a -> String -> m a
<?> String
"Only absolute IRIs allowed in NTriples format, which this isn't: " String -> String -> String
forall a. Semigroup a => a -> a -> a
<> Text -> String
forall a. Show a => a -> String
show Text
raw_iri

-- [153s] ECHAR
nt_echar :: (CharParsing m, Monad m) => m Char
nt_echar :: m Char
nt_echar = m Char -> m Char
forall (m :: * -> *) a. Parsing m => m a -> m a
try (m Char -> m Char) -> m Char -> m Char
forall a b. (a -> b) -> a -> b
$ do
  Char
c2 <- Char -> m Char
forall (m :: * -> *). CharParsing m => Char -> m Char
char Char
'\\' m Char -> m Char -> m Char
forall (f :: * -> *) a b. Applicative f => f a -> f b -> f b
*> m Char
forall (m :: * -> *). CharParsing m => m Char
anyChar
  case Char
c2 of
    Char
't' -> Char -> m Char
forall (f :: * -> *) a. Applicative f => a -> f a
pure Char
'\t'
    Char
'b' -> Char -> m Char
forall (f :: * -> *) a. Applicative f => a -> f a
pure Char
'\b'
    Char
'n' -> Char -> m Char
forall (f :: * -> *) a. Applicative f => a -> f a
pure Char
'\n'
    Char
'r' -> Char -> m Char
forall (f :: * -> *) a. Applicative f => a -> f a
pure Char
'\r'
    Char
'f' -> Char -> m Char
forall (f :: * -> *) a. Applicative f => a -> f a
pure Char
'\f'
    Char
'"' -> Char -> m Char
forall (f :: * -> *) a. Applicative f => a -> f a
pure Char
'\"'
    Char
'\'' -> Char -> m Char
forall (f :: * -> *) a. Applicative f => a -> f a
pure Char
'\''
    Char
'\\' -> Char -> m Char
forall (f :: * -> *) a. Applicative f => a -> f a
pure Char
'\\'
    Char
_ -> m Char
forall (f :: * -> *) a. Alternative f => f a
empty

-- [10] UCHAR ::= '\u' HEX HEX HEX HEX | '\U' HEX HEX HEX HEX HEX HEX HEX HEX
nt_uchar :: (CharParsing m, Monad m) => m Char
nt_uchar :: m Char
nt_uchar = m Char
forall (m :: * -> *). (CharParsing m, Monad m) => m Char
uchar

-- A subject is either a URI reference for a resource or a node id for a
-- blank node.
nt_subject :: (CharParsing m, LookAheadParsing m, Monad m) => m Node
nt_subject :: m Node
nt_subject =
  Text -> Node
unode (Text -> Node) -> m Text -> m Node
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> m Text -> m Text
forall (m :: * -> *) a. Parsing m => m a -> m a
try m Text
forall (m :: * -> *). (CharParsing m, Monad m) => m Text
nt_iriref
    m Node -> m Node -> m Node
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> Text -> Node
bnodeUnsafe (Text -> Node) -> m Text -> m Node
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> m Text
forall (m :: * -> *).
(CharParsing m, LookAheadParsing m, Monad m) =>
m Text
nt_blank_node_label

-- A predicate may only be a URI reference to a resource.
nt_predicate :: (CharParsing m, Monad m) => m Node
nt_predicate :: m Node
nt_predicate = Text -> Node
unode (Text -> Node) -> m Text -> m Node
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> m Text
forall (m :: * -> *). (CharParsing m, Monad m) => m Text
nt_iriref

-- An object may be either a resource (represented by a URI reference),
-- a blank node (represented by a node id), or an object literal.
nt_object :: (CharParsing m, LookAheadParsing m, Monad m) => m Node
nt_object :: m Node
nt_object =
  Text -> Node
unode (Text -> Node) -> m Text -> m Node
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> m Text -> m Text
forall (m :: * -> *) a. Parsing m => m a -> m a
try m Text
forall (m :: * -> *). (CharParsing m, Monad m) => m Text
nt_iriref
    m Node -> m Node -> m Node
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> Text -> Node
bnodeUnsafe (Text -> Node) -> m Text -> m Node
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> m Text -> m Text
forall (m :: * -> *) a. Parsing m => m a -> m a
try m Text
forall (m :: * -> *).
(CharParsing m, LookAheadParsing m, Monad m) =>
m Text
nt_blank_node_label
    m Node -> m Node -> m Node
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> LValue -> Node
LNode (LValue -> Node) -> m LValue -> m Node
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> m LValue
forall (m :: * -> *). (CharParsing m, Monad m) => m LValue
nt_literal

-- [141s] BLANK_NODE_LABEL ::= '_:' (PN_CHARS_U | [0-9]) ((PN_CHARS | '.')* PN_CHARS)?
nt_blank_node_label :: (CharParsing m, LookAheadParsing m, Monad m) => m T.Text
nt_blank_node_label :: m Text
nt_blank_node_label = do
  m String -> m ()
forall (f :: * -> *) a. Functor f => f a -> f ()
void (String -> m String
forall (m :: * -> *). CharParsing m => String -> m String
string String
"_:")
  Char
firstChar <- m Char
forall (m :: * -> *). CharParsing m => m Char
nt_pn_chars_u m Char -> m Char -> m Char
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> (Char -> Bool) -> m Char
forall (m :: * -> *). CharParsing m => (Char -> Bool) -> m Char
satisfy Char -> Bool
isDigit
  String
otherChars <-
    String -> m String -> m String
forall (m :: * -> *) a. Alternative m => a -> m a -> m a
option String
"" (m String -> m String) -> m String -> m String
forall a b. (a -> b) -> a -> b
$
      m String -> m String
forall (m :: * -> *) a. Parsing m => m a -> m a
try (m String -> m String) -> m String -> m String
forall a b. (a -> b) -> a -> b
$
        m Char -> m String
forall (f :: * -> *) a. Alternative f => f a -> f [a]
many (m Char
forall (m :: * -> *). CharParsing m => m Char
nt_pn_chars m Char -> m Char -> m Char
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> m Char -> m Char
forall (m :: * -> *) a. Parsing m => m a -> m a
try (Char -> m Char
forall (m :: * -> *). CharParsing m => Char -> m Char
char Char
'.' m Char -> m Char -> m Char
forall (f :: * -> *) a b. Applicative f => f a -> f b -> f a
<* m Char -> m Char
forall (m :: * -> *) a. LookAheadParsing m => m a -> m a
lookAhead (m Char -> m Char
forall (m :: * -> *) a. Parsing m => m a -> m a
try m Char
forall (m :: * -> *). CharParsing m => m Char
nt_pn_chars)))
  Text -> m Text
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Text -> m Text) -> Text -> m Text
forall a b. (a -> b) -> a -> b
$ String -> Text
T.pack (Char
firstChar Char -> String -> String
forall a. a -> [a] -> [a]
: String
otherChars)

-- [157s] PN_CHARS_BASE ::= [A-Z] | [a-z] | [#x00C0-#x00D6] | [#x00D8-#x00F6] | [#x00F8-#x02FF] | [#x0370-#x037D] | [#x037F-#x1FFF] | [#x200C-#x200D] | [#x2070-#x218F] | [#x2C00-#x2FEF] | [#x3001-#xD7FF] | [#xF900-#xFDCF] | [#xFDF0-#xFFFD] | [#x10000-#xEFFFF]
nt_pn_chars_base :: CharParsing m => m Char
nt_pn_chars_base :: m Char
nt_pn_chars_base = m Char -> m Char
forall (m :: * -> *) a. Parsing m => m a -> m a
try (m Char -> m Char) -> m Char -> m Char
forall a b. (a -> b) -> a -> b
$ (Char -> Bool) -> m Char
forall (m :: * -> *). CharParsing m => (Char -> Bool) -> m Char
satisfy Char -> Bool
isBaseChar
  where
    isBaseChar :: Char -> Bool
isBaseChar Char
c =
      (Char -> Bool
isAsciiUpper Char
c)
        Bool -> Bool -> Bool
|| (Char -> Bool
isAsciiLower Char
c)
        Bool -> Bool -> Bool
|| (Char
c Char -> Char -> Bool
forall a. Ord a => a -> a -> Bool
>= Char
'\x00C0' Bool -> Bool -> Bool
&& Char
c Char -> Char -> Bool
forall a. Ord a => a -> a -> Bool
<= Char
'\x00D6')
        Bool -> Bool -> Bool
|| (Char
c Char -> Char -> Bool
forall a. Ord a => a -> a -> Bool
>= Char
'\x00D8' Bool -> Bool -> Bool
&& Char
c Char -> Char -> Bool
forall a. Ord a => a -> a -> Bool
<= Char
'\x00F6')
        Bool -> Bool -> Bool
|| (Char
c Char -> Char -> Bool
forall a. Ord a => a -> a -> Bool
>= Char
'\x00F8' Bool -> Bool -> Bool
&& Char
c Char -> Char -> Bool
forall a. Ord a => a -> a -> Bool
<= Char
'\x02FF')
        Bool -> Bool -> Bool
|| (Char
c Char -> Char -> Bool
forall a. Ord a => a -> a -> Bool
>= Char
'\x0370' Bool -> Bool -> Bool
&& Char
c Char -> Char -> Bool
forall a. Ord a => a -> a -> Bool
<= Char
'\x037D')
        Bool -> Bool -> Bool
|| (Char
c Char -> Char -> Bool
forall a. Ord a => a -> a -> Bool
>= Char
'\x037F' Bool -> Bool -> Bool
&& Char
c Char -> Char -> Bool
forall a. Ord a => a -> a -> Bool
<= Char
'\x1FFF')
        Bool -> Bool -> Bool
|| (Char
c Char -> Char -> Bool
forall a. Ord a => a -> a -> Bool
>= Char
'\x200C' Bool -> Bool -> Bool
&& Char
c Char -> Char -> Bool
forall a. Ord a => a -> a -> Bool
<= Char
'\x200D')
        Bool -> Bool -> Bool
|| (Char
c Char -> Char -> Bool
forall a. Ord a => a -> a -> Bool
>= Char
'\x2070' Bool -> Bool -> Bool
&& Char
c Char -> Char -> Bool
forall a. Ord a => a -> a -> Bool
<= Char
'\x218F')
        Bool -> Bool -> Bool
|| (Char
c Char -> Char -> Bool
forall a. Ord a => a -> a -> Bool
>= Char
'\x2C00' Bool -> Bool -> Bool
&& Char
c Char -> Char -> Bool
forall a. Ord a => a -> a -> Bool
<= Char
'\x2FEF')
        Bool -> Bool -> Bool
|| (Char
c Char -> Char -> Bool
forall a. Ord a => a -> a -> Bool
>= Char
'\x3001' Bool -> Bool -> Bool
&& Char
c Char -> Char -> Bool
forall a. Ord a => a -> a -> Bool
<= Char
'\xD7FF')
        Bool -> Bool -> Bool
|| (Char
c Char -> Char -> Bool
forall a. Ord a => a -> a -> Bool
>= Char
'\xF900' Bool -> Bool -> Bool
&& Char
c Char -> Char -> Bool
forall a. Ord a => a -> a -> Bool
<= Char
'\xFDCF')
        Bool -> Bool -> Bool
|| (Char
c Char -> Char -> Bool
forall a. Ord a => a -> a -> Bool
>= Char
'\xFDF0' Bool -> Bool -> Bool
&& Char
c Char -> Char -> Bool
forall a. Ord a => a -> a -> Bool
<= Char
'\xFFFD')
        Bool -> Bool -> Bool
|| (Char
c Char -> Char -> Bool
forall a. Ord a => a -> a -> Bool
>= Char
'\x10000' Bool -> Bool -> Bool
&& Char
c Char -> Char -> Bool
forall a. Ord a => a -> a -> Bool
<= Char
'\xEFFFF')

-- [158s] PN_CHARS_U
nt_pn_chars_u :: CharParsing m => m Char
nt_pn_chars_u :: m Char
nt_pn_chars_u = m Char
forall (m :: * -> *). CharParsing m => m Char
nt_pn_chars_base m Char -> m Char -> m Char
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> m Char -> m Char
forall (m :: * -> *) a. Parsing m => m a -> m a
try (Char -> m Char
forall (m :: * -> *). CharParsing m => Char -> m Char
char Char
'_') m Char -> m Char -> m Char
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> m Char -> m Char
forall (m :: * -> *) a. Parsing m => m a -> m a
try (Char -> m Char
forall (m :: * -> *). CharParsing m => Char -> m Char
char Char
':')

-- [160s] PN_CHARS
nt_pn_chars :: CharParsing m => m Char
nt_pn_chars :: m Char
nt_pn_chars =
  m Char
forall (m :: * -> *). CharParsing m => m Char
nt_pn_chars_u
    m Char -> m Char -> m Char
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> m Char -> m Char
forall (m :: * -> *) a. Parsing m => m a -> m a
try (Char -> m Char
forall (m :: * -> *). CharParsing m => Char -> m Char
char Char
'-')
    m Char -> m Char -> m Char
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> m Char -> m Char
forall (m :: * -> *) a. Parsing m => m a -> m a
try (Char -> m Char
forall (m :: * -> *). CharParsing m => Char -> m Char
char Char
'\x00B7')
    m Char -> m Char -> m Char
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> m Char -> m Char
forall (m :: * -> *) a. Parsing m => m a -> m a
try ((Char -> Bool) -> m Char
forall (m :: * -> *). CharParsing m => (Char -> Bool) -> m Char
satisfy Char -> Bool
f)
  where
    f :: Char -> Bool
f Char
c =
      Char -> Bool
isDigit Char
c
        Bool -> Bool -> Bool
|| (Char
c Char -> Char -> Bool
forall a. Ord a => a -> a -> Bool
>= Char
'\x0300' Bool -> Bool -> Bool
&& Char
c Char -> Char -> Bool
forall a. Ord a => a -> a -> Bool
<= Char
'\x036F')
        Bool -> Bool -> Bool
|| (Char
c Char -> Char -> Bool
forall a. Ord a => a -> a -> Bool
>= Char
'\x203F' Bool -> Bool -> Bool
&& Char
c Char -> Char -> Bool
forall a. Ord a => a -> a -> Bool
<= Char
'\x2040')

-- End-of-line consists of either lf or crlf.
-- We also test for eof and consider that to match as well.
nt_eoln :: CharParsing m => m ()
nt_eoln :: m ()
nt_eoln = m () -> m ()
forall (m :: * -> *) a. Parsing m => m a -> m a
try (m String -> m ()
forall (f :: * -> *) a. Functor f => f a -> f ()
void (String -> m String
forall (m :: * -> *). CharParsing m => String -> m String
string String
"\r\n")) m () -> m () -> m ()
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> m Char -> m ()
forall (f :: * -> *) a. Functor f => f a -> f ()
void (Char -> m Char
forall (m :: * -> *). CharParsing m => Char -> m Char
char Char
'\n')

-- Whitespace is either a space or a tabulation.
-- The built-in space combinator must be avoided here, because it includes newline.
nt_space :: CharParsing m => m ()
nt_space :: m ()
nt_space = m Char -> m ()
forall (f :: * -> *) a. Functor f => f a -> f ()
void (m Char -> m Char
forall (m :: * -> *) a. Parsing m => m a -> m a
try (Char -> m Char
forall (m :: * -> *). CharParsing m => Char -> m Char
char Char
' ') m Char -> m Char -> m Char
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> m Char -> m Char
forall (m :: * -> *) a. Parsing m => m a -> m a
try (Char -> m Char
forall (m :: * -> *). CharParsing m => Char -> m Char
char Char
'\t'))

nt_comment :: CharParsing m => m ()
nt_comment :: m ()
nt_comment = m String -> m ()
forall (f :: * -> *) a. Functor f => f a -> f ()
void (Char -> m Char
forall (m :: * -> *). CharParsing m => Char -> m Char
char Char
'#' m Char -> m String -> m String
forall (f :: * -> *) a b. Applicative f => f a -> f b -> f b
*> m Char -> m () -> m String
forall (m :: * -> *) a sep. Alternative m => m a -> m sep -> m [a]
manyTill m Char
forall (m :: * -> *). CharParsing m => m Char
anyChar (m () -> m ()
forall (m :: * -> *) a. Parsing m => m a -> m a
try m ()
forall (m :: * -> *). CharParsing m => m ()
nt_eoln))

---------------------------------
-- parsec based parsers

parseStringParsec :: (Rdf a) => T.Text -> Either ParseFailure (RDF a)
parseStringParsec :: Text -> Either ParseFailure (RDF a)
parseStringParsec Text
bs = ([Triple] -> Maybe BaseUrl -> PrefixMappings -> RDF a)
-> Either ParseError [Triple] -> Either ParseFailure (RDF a)
forall a.
([Triple] -> Maybe BaseUrl -> PrefixMappings -> RDF a)
-> Either ParseError [Triple] -> Either ParseFailure (RDF a)
handleParsec [Triple] -> Maybe BaseUrl -> PrefixMappings -> RDF a
forall rdfImpl.
Rdf rdfImpl =>
[Triple] -> Maybe BaseUrl -> PrefixMappings -> RDF rdfImpl
mkRdf (Parsec Text () [Triple]
-> () -> String -> Text -> Either ParseError [Triple]
forall s t u a.
Stream s Identity t =>
Parsec s u a -> u -> String -> s -> Either ParseError a
runParser Parsec Text () [Triple]
forall (m :: * -> *).
(CharParsing m, LookAheadParsing m, Monad m) =>
m [Triple]
nt_ntripleDoc () String
"" Text
bs)

parseFileParsec :: (Rdf a) => String -> IO (Either ParseFailure (RDF a))
parseFileParsec :: String -> IO (Either ParseFailure (RDF a))
parseFileParsec String
path =
  ([Triple] -> Maybe BaseUrl -> PrefixMappings -> RDF a)
-> Either ParseError [Triple] -> Either ParseFailure (RDF a)
forall a.
([Triple] -> Maybe BaseUrl -> PrefixMappings -> RDF a)
-> Either ParseError [Triple] -> Either ParseFailure (RDF a)
handleParsec [Triple] -> Maybe BaseUrl -> PrefixMappings -> RDF a
forall rdfImpl.
Rdf rdfImpl =>
[Triple] -> Maybe BaseUrl -> PrefixMappings -> RDF rdfImpl
mkRdf (Either ParseError [Triple] -> Either ParseFailure (RDF a))
-> (Text -> Either ParseError [Triple])
-> Text
-> Either ParseFailure (RDF a)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Parsec Text () [Triple]
-> () -> String -> Text -> Either ParseError [Triple]
forall s t u a.
Stream s Identity t =>
Parsec s u a -> u -> String -> s -> Either ParseError a
runParser Parsec Text () [Triple]
forall (m :: * -> *).
(CharParsing m, LookAheadParsing m, Monad m) =>
m [Triple]
nt_ntripleDoc () String
path
    (Text -> Either ParseFailure (RDF a))
-> IO Text -> IO (Either ParseFailure (RDF a))
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> String -> IO Text
readFile String
path

readFile :: FilePath -> IO T.Text
readFile :: String -> IO Text
readFile String
fpath = String -> IOMode -> (Handle -> IO Text) -> IO Text
forall r. String -> IOMode -> (Handle -> IO r) -> IO r
withFile String
fpath IOMode
ReadMode ((Handle -> IO Text) -> IO Text) -> (Handle -> IO Text) -> IO Text
forall a b. (a -> b) -> a -> b
$ \Handle
h -> do
  Handle -> NewlineMode -> IO ()
hSetNewlineMode Handle
h NewlineMode
noNewlineTranslation
  Handle -> TextEncoding -> IO ()
hSetEncoding Handle
h TextEncoding
utf8
  Handle -> IO Text
T.hGetContents Handle
h

parseURLParsec :: (Rdf a) => String -> IO (Either ParseFailure (RDF a))
parseURLParsec :: String -> IO (Either ParseFailure (RDF a))
parseURLParsec = (Text -> Either ParseFailure (RDF a))
-> String -> IO (Either ParseFailure (RDF a))
forall rdfImpl.
(Text -> Either ParseFailure (RDF rdfImpl))
-> String -> IO (Either ParseFailure (RDF rdfImpl))
parseFromURL Text -> Either ParseFailure (RDF a)
forall a. Rdf a => Text -> Either ParseFailure (RDF a)
parseStringParsec

handleParsec ::
  (Triples -> Maybe BaseUrl -> PrefixMappings -> RDF a) ->
  Either ParseError [Triple] ->
  Either ParseFailure (RDF a)
handleParsec :: ([Triple] -> Maybe BaseUrl -> PrefixMappings -> RDF a)
-> Either ParseError [Triple] -> Either ParseFailure (RDF a)
handleParsec [Triple] -> Maybe BaseUrl -> PrefixMappings -> RDF a
_mkRdf Either ParseError [Triple]
result = case Either ParseError [Triple]
result of
  Left ParseError
err -> ParseFailure -> Either ParseFailure (RDF a)
forall a b. a -> Either a b
Left (ParseFailure -> Either ParseFailure (RDF a))
-> ParseFailure -> Either ParseFailure (RDF a)
forall a b. (a -> b) -> a -> b
$ String -> ParseFailure
ParseFailure (String -> ParseFailure) -> String -> ParseFailure
forall a b. (a -> b) -> a -> b
$ String
"Parse failure: \n" String -> String -> String
forall a. Semigroup a => a -> a -> a
<> ParseError -> String
forall a. Show a => a -> String
show ParseError
err
  Right [Triple]
ts -> RDF a -> Either ParseFailure (RDF a)
forall a b. b -> Either a b
Right (RDF a -> Either ParseFailure (RDF a))
-> RDF a -> Either ParseFailure (RDF a)
forall a b. (a -> b) -> a -> b
$ [Triple] -> Maybe BaseUrl -> PrefixMappings -> RDF a
_mkRdf [Triple]
ts Maybe BaseUrl
forall a. Maybe a
Nothing (Map Text Text -> PrefixMappings
PrefixMappings Map Text Text
forall a. Monoid a => a
mempty)

---------------------------------

---------------------------------
-- attoparsec based parsers

parseFileAttoparsec :: (Rdf a) => String -> IO (Either ParseFailure (RDF a))
parseFileAttoparsec :: String -> IO (Either ParseFailure (RDF a))
parseFileAttoparsec String
path = Text -> Either ParseFailure (RDF a)
forall a. Rdf a => Text -> Either ParseFailure (RDF a)
handleAttoparsec (Text -> Either ParseFailure (RDF a))
-> IO Text -> IO (Either ParseFailure (RDF a))
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> String -> IO Text
readFile String
path

parseURLAttoparsec :: (Rdf a) => String -> IO (Either ParseFailure (RDF a))
parseURLAttoparsec :: String -> IO (Either ParseFailure (RDF a))
parseURLAttoparsec = (Text -> Either ParseFailure (RDF a))
-> String -> IO (Either ParseFailure (RDF a))
forall rdfImpl.
(Text -> Either ParseFailure (RDF rdfImpl))
-> String -> IO (Either ParseFailure (RDF rdfImpl))
parseFromURL Text -> Either ParseFailure (RDF a)
forall a. Rdf a => Text -> Either ParseFailure (RDF a)
handleAttoparsec

parseStringAttoparsec :: (Rdf a) => T.Text -> Either ParseFailure (RDF a)
parseStringAttoparsec :: Text -> Either ParseFailure (RDF a)
parseStringAttoparsec = Text -> Either ParseFailure (RDF a)
forall a. Rdf a => Text -> Either ParseFailure (RDF a)
handleAttoparsec

handleAttoparsec :: (Rdf a) => T.Text -> Either ParseFailure (RDF a)
handleAttoparsec :: Text -> Either ParseFailure (RDF a)
handleAttoparsec Text
bs = IResult ByteString [Triple] -> Either ParseFailure (RDF a)
forall rdfImpl.
Rdf rdfImpl =>
IResult ByteString [Triple] -> Either ParseFailure (RDF rdfImpl)
handleResult (IResult ByteString [Triple] -> Either ParseFailure (RDF a))
-> IResult ByteString [Triple] -> Either ParseFailure (RDF a)
forall a b. (a -> b) -> a -> b
$ Parser [Triple] -> ByteString -> IResult ByteString [Triple]
forall a. Parser a -> ByteString -> Result a
parse Parser [Triple]
forall (m :: * -> *).
(CharParsing m, LookAheadParsing m, Monad m) =>
m [Triple]
nt_ntripleDoc (Text -> ByteString
T.encodeUtf8 Text
bs)
  where
    handleResult :: IResult ByteString [Triple] -> Either ParseFailure (RDF rdfImpl)
handleResult IResult ByteString [Triple]
res = case IResult ByteString [Triple]
res of
      Fail ByteString
_i [String]
_contexts String
err -> ParseFailure -> Either ParseFailure (RDF rdfImpl)
forall a b. a -> Either a b
Left (ParseFailure -> Either ParseFailure (RDF rdfImpl))
-> ParseFailure -> Either ParseFailure (RDF rdfImpl)
forall a b. (a -> b) -> a -> b
$ String -> ParseFailure
ParseFailure (String -> ParseFailure) -> String -> ParseFailure
forall a b. (a -> b) -> a -> b
$ String
"Parse failure: \n" String -> String -> String
forall a. Semigroup a => a -> a -> a
<> String -> String
forall a. Show a => a -> String
show String
err
      -- error $
      -- "\nnot consumed: " <> show i
      -- <> "\ncontexts: " <> show contexts
      -- <> "\nerror: " <> show err
      Partial ByteString -> IResult ByteString [Triple]
f -> IResult ByteString [Triple] -> Either ParseFailure (RDF rdfImpl)
handleResult (ByteString -> IResult ByteString [Triple]
f (Text -> ByteString
T.encodeUtf8 Text
forall a. Monoid a => a
mempty))
      Done ByteString
_ [Triple]
ts -> RDF rdfImpl -> Either ParseFailure (RDF rdfImpl)
forall a b. b -> Either a b
Right (RDF rdfImpl -> Either ParseFailure (RDF rdfImpl))
-> RDF rdfImpl -> Either ParseFailure (RDF rdfImpl)
forall a b. (a -> b) -> a -> b
$ [Triple] -> Maybe BaseUrl -> PrefixMappings -> RDF rdfImpl
forall rdfImpl.
Rdf rdfImpl =>
[Triple] -> Maybe BaseUrl -> PrefixMappings -> RDF rdfImpl
mkRdf [Triple]
ts Maybe BaseUrl
forall a. Maybe a
Nothing (Map Text Text -> PrefixMappings
PrefixMappings Map Text Text
forall a. Monoid a => a
mempty)

---------------------------------