{-# LANGUAGE CPP #-}
{-# LANGUAGE OverloadedStrings #-}

--------------------------------------------------------------------------------
--  See end of this file for licence information.
--------------------------------------------------------------------------------
-- |
--  Module      :  N3
--  Copyright   :  (c) 2003, Graham Klyne, 2009 Vasili I Galchin, 2011, 2012, 2013, 2014, 2018, 2020 Douglas Burke
--  License     :  GPL V2
--
--  Maintainer  :  Douglas Burke
--  Stability   :  experimental
--  Portability :  CPP, OverloadedStrings
--
--  This Module implements a Notation 3 parser, returning a
--  new 'RDFGraph' consisting of triples and namespace information parsed from
--  the supplied N3 input string, or an error indication.
--
-- REFERENCES:
--
-- - \"Notation3 (N3): A readable RDF syntax\",
--      W3C Team Submission 14 January 2008,
--      <http://www.w3.org/TeamSubmission/2008/SUBM-n3-20080114/>
--
-- - Tim Berners-Lee's design issues series notes and description,
--      <http://www.w3.org/DesignIssues/Notation3.html>
--
-- - Notation 3 Primer by Sean Palmer,
--      <http://www.w3.org/2000/10/swap/Primer.html>
--    
-- NOTES:
--
--  - The parser needs to be updated to the latest version
--    (\"W3C Team Submission 28 March 2011\",
--    <http://www.w3.org/TeamSubmission/2011/SUBM-n3-20110328/>)
--
--  - UTF-8 handling is not really tested.
--
--  - No performance testing has been applied.
--
--  - Not all N3 grammar elements are supported, including:
--
--    - @\@forSome@ (we read it in but ignore the arguments)
--
--    - @\@forAll@  (this causes a parse error)
--
--    - formulae are lightly tested
--
--    - string support is incomplete (e.g. unrecognized escape characters
--      such as @\\q@ are probably handled incorrectly)
--
--------------------------------------------------------------------------------

module Swish.RDF.Parser.N3
    ( ParseResult
    , parseN3      
    , parseN3fromText      
    , parseAnyfromText
    , parseTextFromText, parseAltFromText
    , parseNameFromText -- , parsePrefixFromText
    , parseAbsURIrefFromText, parseLexURIrefFromText, parseURIref2FromText
    
    -- * Exports for parsers that embed Notation3 in a bigger syntax
    , N3Parser, N3State(..), SpecialMap
    
    , getPrefix -- a combination of the old defaultPrefix and namedPrefix productions
    , n3symbol -- replacement for uriRef2 -- TODO: check this is semantically correct      
    , quickVariable -- was varid      
    , lexUriRef       
    , document, subgraph                                                   
    , newBlankNode
    )
where

import Swish.GraphClass (arc)
import Swish.Namespace
    ( Namespace
    , ScopedName
    , makeNamespace
    , getNamespaceTuple
    , getScopeNamespace
    , getScopedNameURI
    , getScopeNamespace
    , makeURIScopedName
    , makeQNameScopedName
    , makeNSScopedName
    , nullScopedName
    )
import Swish.QName (QName, newLName)

import Swish.RDF.Graph
    ( RDFGraph, RDFLabel(..)
    , ToRDFLabel(..)
    , NamespaceMap
    , LookupFormula(..) 
    , addArc 
    , setFormula
    , setNamespaces
    , emptyRDFGraph
    )

import Swish.RDF.Datatype (makeDatatypedLiteral)

import Swish.RDF.Vocabulary
    ( LanguageTag
    , toLangTag
    , rdfType
    , rdfFirst, rdfRest, rdfNil
    , owlSameAs, logImplies
    , xsdBoolean, xsdInteger, xsdDecimal, xsdDouble
    )

import Swish.RDF.Parser.Utils
    ( SpecialMap
    , ParseResult
    , runParserWithError
    -- , mapPrefix
    , prefixTable
    , specialTable
    , ignore
    , notFollowedBy
    , endBy
    , sepEndBy
    -- , manyTill
    , noneOf
    , char
    , ichar
    , string
    , stringT
    , symbol
    , lexeme
    , whiteSpace
    , hex4  
    , hex8  
    , appendURIs
    )

import Control.Applicative
import Control.Monad (forM_, foldM)

import Data.Char (isSpace, isDigit, ord, isAsciiLower)

#if MIN_VERSION_base(4, 7, 0)
import Data.Functor (($>))
#endif

import Data.Maybe (fromMaybe, fromJust)
import Data.Word (Word32)

import Network.URI (URI(..), 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

#if !MIN_VERSION_base(4, 7, 0)
($>) :: Functor f => f a -> b -> f b
($>) = flip (<$)
#endif

----------------------------------------------------------------------
-- Define parser state and helper functions
----------------------------------------------------------------------

-- | N3 parser state
data N3State = N3State
        { N3State -> RDFGraph
graphState :: RDFGraph            -- Graph under construction
        , N3State -> RDFLabel
thisNode   :: RDFLabel            -- current context node (aka 'this')
        , N3State -> NamespaceMap
prefixUris :: NamespaceMap        -- namespace prefix mapping table
        , N3State -> SpecialMap
syntaxUris :: SpecialMap          -- special name mapping table
        , N3State -> Word32
nodeGen    :: Word32              -- blank node id generator
        , N3State -> [Text]
keywordsList :: [T.Text]          -- contents of the @keywords statement
        , N3State -> Bool
allowLocalNames :: Bool           -- True if @keywords used so that bare names are QNames in default namespace
        }

-- | Functions to update N3State vector (use with stUpdate)

setPrefix :: Maybe T.Text -> URI -> N3State -> N3State
setPrefix :: Maybe Text -> URI -> N3State -> N3State
setPrefix Maybe Text
pre URI
uri N3State
st =  N3State
st { prefixUris :: NamespaceMap
prefixUris=NamespaceMap
p' }
    where
        p' :: NamespaceMap
p' = Maybe Text -> URI -> NamespaceMap -> NamespaceMap
forall k a. Ord k => k -> a -> Map k a -> Map k a
M.insert Maybe Text
pre URI
uri (N3State -> NamespaceMap
prefixUris N3State
st)

-- | Set name for special syntax element
setSName :: String -> ScopedName -> N3State -> N3State
setSName :: String -> ScopedName -> N3State -> N3State
setSName String
nam ScopedName
snam N3State
st =  N3State
st { syntaxUris :: SpecialMap
syntaxUris=SpecialMap
s' }
    where
        s' :: SpecialMap
s' = String -> ScopedName -> SpecialMap -> SpecialMap
forall k a. Ord k => k -> a -> Map k a -> Map k a
M.insert String
nam ScopedName
snam (N3State -> SpecialMap
syntaxUris N3State
st)

setSUri :: String -> URI -> N3State -> N3State
setSUri :: String -> URI -> N3State -> N3State
setSUri String
nam = String -> ScopedName -> N3State -> N3State
setSName String
nam (ScopedName -> N3State -> N3State)
-> (URI -> ScopedName) -> URI -> N3State -> N3State
forall b c a. (b -> c) -> (a -> b) -> a -> c
. URI -> ScopedName
makeURIScopedName

-- | Set the list of tokens that can be used without needing the leading 
-- \@ symbol.
setKeywordsList :: [T.Text] -> N3State -> N3State
setKeywordsList :: [Text] -> N3State -> N3State
setKeywordsList [Text]
ks N3State
st = N3State
st { keywordsList :: [Text]
keywordsList = [Text]
ks, allowLocalNames :: Bool
allowLocalNames = Bool
True }

--  Functions to access state:

-- | Get name for special syntax element, default null
getSName :: N3State -> String -> ScopedName
getSName :: N3State -> String -> ScopedName
getSName N3State
st String
nam = ScopedName -> String -> SpecialMap -> ScopedName
forall k a. Ord k => a -> k -> Map k a -> a
M.findWithDefault ScopedName
nullScopedName String
nam (SpecialMap -> ScopedName) -> SpecialMap -> ScopedName
forall a b. (a -> b) -> a -> b
$ N3State -> SpecialMap
syntaxUris N3State
st

getSUri :: N3State -> String -> URI
getSUri :: N3State -> String -> URI
getSUri N3State
st String
nam = ScopedName -> URI
getScopedNameURI (ScopedName -> URI) -> ScopedName -> URI
forall a b. (a -> b) -> a -> b
$ N3State -> String -> ScopedName
getSName N3State
st String
nam

--  Map prefix to URI
getPrefixURI :: N3State -> Maybe T.Text -> Maybe URI
getPrefixURI :: N3State -> Maybe Text -> Maybe URI
getPrefixURI N3State
st Maybe Text
pre = Maybe Text -> NamespaceMap -> Maybe URI
forall k a. Ord k => k -> Map k a -> Maybe a
M.lookup Maybe Text
pre (N3State -> NamespaceMap
prefixUris N3State
st)

getKeywordsList :: N3State -> [T.Text]
getKeywordsList :: N3State -> [Text]
getKeywordsList = N3State -> [Text]
keywordsList

getAllowLocalNames :: N3State -> Bool
getAllowLocalNames :: N3State -> Bool
getAllowLocalNames = N3State -> Bool
allowLocalNames

--  Return function to update graph in N3 parser state,
--  using the supplied function of a graph
--
updateGraph :: (RDFGraph -> RDFGraph) -> N3State -> N3State
updateGraph :: (RDFGraph -> RDFGraph) -> N3State -> N3State
updateGraph RDFGraph -> RDFGraph
f N3State
s = N3State
s { graphState :: RDFGraph
graphState = RDFGraph -> RDFGraph
f (N3State -> RDFGraph
graphState N3State
s) }

----------------------------------------------------------------------
--  Define top-level parser function:
--  accepts a string and returns a graph or error
----------------------------------------------------------------------

-- | The N3 parser.
type N3Parser a = Parser N3State a

-- | Parse a string as N3 (with no real base URI).
-- 
-- See 'parseN3' if you need to provide a base URI.
--
parseN3fromText ::
  L.Text -- ^ input in N3 format.
  -> ParseResult
parseN3fromText :: Text -> ParseResult
parseN3fromText = (Text -> Maybe QName -> ParseResult)
-> Maybe QName -> Text -> ParseResult
forall a b c. (a -> b -> c) -> b -> a -> c
flip Text -> Maybe QName -> ParseResult
parseN3 Maybe QName
forall a. Maybe a
Nothing

-- | Parse a string with an optional base URI.
--            
-- See also 'parseN3fromString'.            
--
parseN3 ::
  L.Text -- ^ input in N3 format.
  -> Maybe QName -- ^ optional base URI
  -> ParseResult
parseN3 :: Text -> Maybe QName -> ParseResult
parseN3 Text
txt Maybe QName
mbase = N3Parser RDFGraph -> Maybe QName -> Text -> ParseResult
forall a. N3Parser a -> Maybe QName -> Text -> Either String a
parseAnyfromText N3Parser RDFGraph
document Maybe QName
mbase Text
txt

{-
-- useful for testing
test :: String -> RDFGraph
test = either error id . parseAnyfromString document Nothing
-}

hashURI :: URI
hashURI :: URI
hashURI = Maybe URI -> URI
forall a. HasCallStack => Maybe a -> a
fromJust (Maybe URI -> URI) -> Maybe URI -> URI
forall a b. (a -> b) -> a -> b
$ String -> Maybe URI
parseURIReference String
"#"

emptyState :: 
  Maybe QName  -- ^ starting base for the graph
  -> N3State
emptyState :: Maybe QName -> N3State
emptyState Maybe QName
mbase = 
  let pmap :: Map (Maybe a) URI
pmap   = Maybe a -> URI -> Map (Maybe a) URI
forall k a. k -> a -> Map k a
M.singleton Maybe a
forall a. Maybe a
Nothing URI
hashURI
      muri :: Maybe ScopedName
muri   = (QName -> ScopedName) -> Maybe QName -> Maybe ScopedName
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (Maybe Text -> QName -> ScopedName
makeQNameScopedName Maybe Text
forall a. Maybe a
Nothing) Maybe QName
mbase
      smap :: SpecialMap
smap   = [(String, ScopedName)] -> SpecialMap
forall k a. Ord k => [(k, a)] -> Map k a
M.fromList ([(String, ScopedName)] -> SpecialMap)
-> [(String, ScopedName)] -> SpecialMap
forall a b. (a -> b) -> a -> b
$ Maybe ScopedName -> [(String, ScopedName)]
specialTable Maybe ScopedName
muri
  in N3State :: RDFGraph
-> RDFLabel
-> NamespaceMap
-> SpecialMap
-> Word32
-> [Text]
-> Bool
-> N3State
N3State
     { graphState :: RDFGraph
graphState = RDFGraph
emptyRDFGraph
     , thisNode :: RDFLabel
thisNode   = RDFLabel
NoNode
     , prefixUris :: NamespaceMap
prefixUris = NamespaceMap
forall a. Map (Maybe a) URI
pmap
     , syntaxUris :: SpecialMap
syntaxUris = SpecialMap
smap
     , nodeGen :: Word32
nodeGen    = Word32
0
     , keywordsList :: [Text]
keywordsList = [Text
"a", Text
"is", Text
"of", Text
"true", Text
"false"] -- not 100% sure about true/false here
     , allowLocalNames :: Bool
allowLocalNames = Bool
False
     }


-- TODO: change from QName to URI for the base?

-- | Function to supply initial context and parse supplied term.
--
parseAnyfromText :: N3Parser a      -- ^ parser to apply
                    -> Maybe QName  -- ^ base URI of the input, or @Nothing@ to use default base value
                    -> L.Text       -- ^ input to be parsed
                    -> Either String a
parseAnyfromText :: N3Parser a -> Maybe QName -> Text -> Either String a
parseAnyfromText N3Parser a
parser Maybe QName
mbase = N3Parser a -> N3State -> Text -> Either String a
forall a b. Parser a b -> a -> Text -> Either String b
runParserWithError N3Parser a
parser (Maybe QName -> N3State
emptyState Maybe QName
mbase)

-- | Create a new blank node.
newBlankNode :: N3Parser RDFLabel
newBlankNode :: N3Parser RDFLabel
newBlankNode = do
  Word32
n <- (N3State -> Word32) -> Parser N3State Word32
forall s a. (s -> a) -> Parser s a
stQuery (Word32 -> Word32
forall a. Enum a => a -> a
succ (Word32 -> Word32) -> (N3State -> Word32) -> N3State -> Word32
forall b c a. (b -> c) -> (a -> b) -> a -> c
. N3State -> Word32
nodeGen)
  (N3State -> N3State) -> Parser N3State ()
forall s. (s -> s) -> Parser s ()
stUpdate ((N3State -> N3State) -> Parser N3State ())
-> (N3State -> N3State) -> Parser N3State ()
forall a b. (a -> b) -> a -> b
$ \N3State
s -> N3State
s { nodeGen :: Word32
nodeGen = Word32
n }
  RDFLabel -> N3Parser RDFLabel
forall (m :: * -> *) a. Monad m => a -> m a
return (RDFLabel -> N3Parser RDFLabel) -> RDFLabel -> N3Parser RDFLabel
forall a b. (a -> b) -> a -> b
$ String -> RDFLabel
Blank (Word32 -> String
forall a. Show a => a -> String
show Word32
n)
  
--  Test functions for selected element parsing

-- TODO: remove these
  
-- | Used in testing.
parseTextFromText :: String -> L.Text -> Either String String
parseTextFromText :: String -> Text -> Either String String
parseTextFromText String
s =
    N3Parser String -> Maybe QName -> Text -> Either String String
forall a. N3Parser a -> Maybe QName -> Text -> Either String a
parseAnyfromText (String -> N3Parser String
forall s. String -> Parser s String
string String
s) Maybe QName
forall a. Maybe a
Nothing

-- | Used in testing.
parseAltFromText :: String -> String -> L.Text -> Either String String
parseAltFromText :: String -> String -> Text -> Either String String
parseAltFromText String
s1 String
s2 =
    N3Parser String -> Maybe QName -> Text -> Either String String
forall a. N3Parser a -> Maybe QName -> Text -> Either String a
parseAnyfromText (String -> N3Parser String
forall s. String -> Parser s String
string String
s1 N3Parser String -> N3Parser String -> N3Parser String
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> String -> N3Parser String
forall s. String -> Parser s String
string String
s2) Maybe QName
forall a. Maybe a
Nothing

-- | Used in testing.
parseNameFromText :: L.Text -> Either String String
parseNameFromText :: Text -> Either String String
parseNameFromText =
    N3Parser String -> Maybe QName -> Text -> Either String String
forall a. N3Parser a -> Maybe QName -> Text -> Either String a
parseAnyfromText N3Parser String
n3NameStr Maybe QName
forall a. Maybe a
Nothing

{-
This has been made tricky by the attempt to remove the default list
of prefixes from the starting point of a N3 parse and the subsequent
attempt to add every new namespace we come across to the parser state.

So we add in the original default namespaces for testing, since
this routine is really for testing.
-}

addTestPrefixes :: N3Parser ()
addTestPrefixes :: Parser N3State ()
addTestPrefixes = (N3State -> N3State) -> Parser N3State ()
forall s. (s -> s) -> Parser s ()
stUpdate ((N3State -> N3State) -> Parser N3State ())
-> (N3State -> N3State) -> Parser N3State ()
forall a b. (a -> b) -> a -> b
$ \N3State
st -> N3State
st { prefixUris :: NamespaceMap
prefixUris = 
                                         [(Maybe Text, URI)] -> NamespaceMap
forall k a. Ord k => [(k, a)] -> Map k a
M.fromList 
                                          ([(Maybe Text, URI)] -> NamespaceMap)
-> [(Maybe Text, URI)] -> NamespaceMap
forall a b. (a -> b) -> a -> b
$ (Namespace -> (Maybe Text, URI))
-> [Namespace] -> [(Maybe Text, URI)]
forall a b. (a -> b) -> [a] -> [b]
map Namespace -> (Maybe Text, URI)
getNamespaceTuple [Namespace]
prefixTable 
                                       } -- should append to existing map

{-
parsePrefixFromText :: L.Text -> Either String URI
parsePrefixFromText =
    parseAnyfromText p Nothing
      where
        p = do
          addTestPrefixes
          pref <- n3Name
          st   <- stGet
          case getPrefixURI st (Just pref) of
            Just uri -> return uri
            _ -> fail $ "Undefined prefix: '" ++ pref ++ "'"
-}

-- | Used in testing.
parseAbsURIrefFromText :: L.Text -> Either String URI
parseAbsURIrefFromText :: Text -> Either String URI
parseAbsURIrefFromText =
    N3Parser URI -> Maybe QName -> Text -> Either String URI
forall a. N3Parser a -> Maybe QName -> Text -> Either String a
parseAnyfromText N3Parser URI
explicitURI Maybe QName
forall a. Maybe a
Nothing

-- | Used in testing.
parseLexURIrefFromText :: L.Text -> Either String URI
parseLexURIrefFromText :: Text -> Either String URI
parseLexURIrefFromText =
    N3Parser URI -> Maybe QName -> Text -> Either String URI
forall a. N3Parser a -> Maybe QName -> Text -> Either String a
parseAnyfromText N3Parser URI
lexUriRef Maybe QName
forall a. Maybe a
Nothing

-- | Used in testing.
parseURIref2FromText :: L.Text -> Either String ScopedName
parseURIref2FromText :: Text -> Either String ScopedName
parseURIref2FromText = 
    N3Parser ScopedName
-> Maybe QName -> Text -> Either String ScopedName
forall a. N3Parser a -> Maybe QName -> Text -> Either String a
parseAnyfromText (Parser N3State ()
addTestPrefixes Parser N3State () -> N3Parser ScopedName -> N3Parser ScopedName
forall (f :: * -> *) a b. Applicative f => f a -> f b -> f b
*> N3Parser ScopedName
n3symbol) Maybe QName
forall a. Maybe a
Nothing

----------------------------------------------------------------------
--  Syntax productions
----------------------------------------------------------------------

-- helper routines

comma, semiColon , fullStop :: N3Parser ()
comma :: Parser N3State ()
comma = N3Parser String -> Parser N3State ()
forall (f :: * -> *) a. Applicative f => f a -> f ()
ignore (N3Parser String -> Parser N3State ())
-> N3Parser String -> Parser N3State ()
forall a b. (a -> b) -> a -> b
$ String -> N3Parser String
forall s. String -> Parser s String
symbol String
","
semiColon :: Parser N3State ()
semiColon = N3Parser String -> Parser N3State ()
forall (f :: * -> *) a. Applicative f => f a -> f ()
ignore (N3Parser String -> Parser N3State ())
-> N3Parser String -> Parser N3State ()
forall a b. (a -> b) -> a -> b
$ String -> N3Parser String
forall s. String -> Parser s String
symbol String
";"
fullStop :: Parser N3State ()
fullStop = N3Parser String -> Parser N3State ()
forall (f :: * -> *) a. Applicative f => f a -> f ()
ignore (N3Parser String -> Parser N3State ())
-> N3Parser String -> Parser N3State ()
forall a b. (a -> b) -> a -> b
$ String -> N3Parser String
forall s. String -> Parser s String
symbol String
"."

-- a specialization of bracket/between 
br :: String -> String -> N3Parser a -> N3Parser a
br :: String -> String -> N3Parser a -> N3Parser a
br String
lsym String
rsym = N3Parser String -> N3Parser String -> N3Parser a -> N3Parser a
forall (p :: * -> *) bra ket a.
PolyParse p =>
p bra -> p ket -> p a -> p a
bracket (String -> N3Parser String
forall s. String -> Parser s String
symbol String
lsym) (String -> N3Parser String
forall s. String -> Parser s String
symbol String
rsym)

-- to make porting from parsec to polyparse easier
between :: Parser s lbr -> Parser s rbr -> Parser s a -> Parser s a
between :: Parser s lbr -> Parser s rbr -> Parser s a -> Parser s a
between = Parser s lbr -> Parser s rbr -> Parser s a -> Parser s a
forall (p :: * -> *) bra ket a.
PolyParse p =>
p bra -> p ket -> p a -> p a
bracket

-- The @ character is optional if the keyword is in the
-- keyword list
--
atSign :: T.Text -> N3Parser ()
atSign :: Text -> Parser N3State ()
atSign Text
s = do
  N3State
st <- Parser N3State N3State
forall s. Parser s s
stGet
  
  let p :: Parser s ()
p = Char -> Parser s ()
forall s. Char -> Parser s ()
ichar Char
'@'
  
  if Text
s Text -> [Text] -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`elem` N3State -> [Text]
getKeywordsList N3State
st
    then Parser N3State (Maybe ()) -> Parser N3State ()
forall (f :: * -> *) a. Applicative f => f a -> f ()
ignore (Parser N3State (Maybe ()) -> Parser N3State ())
-> Parser N3State (Maybe ()) -> Parser N3State ()
forall a b. (a -> b) -> a -> b
$ Parser N3State () -> Parser N3State (Maybe ())
forall (f :: * -> *) a. Alternative f => f a -> f (Maybe a)
optional Parser N3State ()
forall s. Parser s ()
p
    else Parser N3State ()
forall s. Parser s ()
p
         
atWord :: T.Text -> N3Parser T.Text
atWord :: Text -> N3Parser Text
atWord Text
s = do
  Text -> Parser N3State ()
atSign Text
s
  
  -- TODO: does it really make sense to add the not-followed-by-a-colon rule here?
  -- apply to both cases even though should only really be necessary
  -- when the at sign is not given
  --
  Parser N3State () -> Parser N3State ()
forall s a. Parser s a -> Parser s a
lexeme (Parser N3State () -> Parser N3State ())
-> Parser N3State () -> Parser N3State ()
forall a b. (a -> b) -> a -> b
$ Text -> N3Parser Text
forall s. Text -> Parser s Text
stringT Text
s N3Parser Text -> Parser N3State () -> Parser N3State ()
forall (f :: * -> *) a b. Applicative f => f a -> f b -> f b
*> (Char -> Bool) -> Parser N3State ()
forall s. (Char -> Bool) -> Parser s ()
notFollowedBy (Char -> Char -> Bool
forall a. Eq a => a -> a -> Bool
== Char
':')
  Text -> N3Parser Text
forall (m :: * -> *) a. Monad m => a -> m a
return Text
s

{-
Since operatorLabel can be used to add a label with an 
unknown namespace, we need to ensure that the namespace
is added if not known. If the namespace prefix is already
in use then it is over-written (rather than add a new
prefix for the label).

TODO:
  - could we use the reverse lookupmap functionality to
    find if the given namespace URI is in the namespace
    list? If it is, use it's key otherwise do a
    mapReplace for the input namespace.
    
-}
operatorLabel :: ScopedName -> N3Parser RDFLabel
operatorLabel :: ScopedName -> N3Parser RDFLabel
operatorLabel ScopedName
snam = do
  N3State
st <- Parser N3State N3State
forall s. Parser s s
stGet
  let (Maybe Text
pkey, URI
pval) = Namespace -> (Maybe Text, URI)
getNamespaceTuple (Namespace -> (Maybe Text, URI)) -> Namespace -> (Maybe Text, URI)
forall a b. (a -> b) -> a -> b
$ ScopedName -> Namespace
getScopeNamespace ScopedName
snam
      opmap :: NamespaceMap
opmap = N3State -> NamespaceMap
prefixUris N3State
st
      
      rval :: RDFLabel
rval = ScopedName -> RDFLabel
Res ScopedName
snam
      
  -- TODO: the lookup and the replacement could be fused
  case Maybe Text -> NamespaceMap -> Maybe URI
forall k a. Ord k => k -> Map k a -> Maybe a
M.lookup Maybe Text
pkey NamespaceMap
opmap of
    Just URI
val | URI
val URI -> URI -> Bool
forall a. Eq a => a -> a -> Bool
== URI
pval -> RDFLabel -> N3Parser RDFLabel
forall (m :: * -> *) a. Monad m => a -> m a
return RDFLabel
rval
             | Bool
otherwise   -> do
               (N3State -> N3State) -> Parser N3State ()
forall s. (s -> s) -> Parser s ()
stUpdate ((N3State -> N3State) -> Parser N3State ())
-> (N3State -> N3State) -> Parser N3State ()
forall a b. (a -> b) -> a -> b
$ \N3State
s -> N3State
s { prefixUris :: NamespaceMap
prefixUris = Maybe Text -> URI -> NamespaceMap -> NamespaceMap
forall k a. Ord k => k -> a -> Map k a -> Map k a
M.insert Maybe Text
pkey URI
pval NamespaceMap
opmap }
               RDFLabel -> N3Parser RDFLabel
forall (m :: * -> *) a. Monad m => a -> m a
return RDFLabel
rval
    
    Maybe URI
_ -> do
      (N3State -> N3State) -> Parser N3State ()
forall s. (s -> s) -> Parser s ()
stUpdate ((N3State -> N3State) -> Parser N3State ())
-> (N3State -> N3State) -> Parser N3State ()
forall a b. (a -> b) -> a -> b
$ \N3State
s -> N3State
s { prefixUris :: NamespaceMap
prefixUris = Maybe Text -> URI -> NamespaceMap -> NamespaceMap
forall k a. Ord k => k -> a -> Map k a -> Map k a
M.insert Maybe Text
pkey URI
pval NamespaceMap
opmap }
      RDFLabel -> N3Parser RDFLabel
forall (m :: * -> *) a. Monad m => a -> m a
return RDFLabel
rval
        
{-
Add statement to graph in N3 parser state.

To support literals that are written directly/implicitly - i.e.  as
true/false/1/1.0/1.0e23 - rather than a string with an explicit
datatype we need to special case handling of the object label for
literals. Is this actually needed? The N3 Formatter now doesn't
display the xsd: datatypes on output, but there may be issues with
other formats (e.g RDF/XML once it is supported).

-}

type AddStatement = RDFLabel -> N3Parser ()

addStatement :: RDFLabel -> RDFLabel -> AddStatement
addStatement :: RDFLabel -> RDFLabel -> AddStatement
addStatement RDFLabel
s RDFLabel
p o :: RDFLabel
o@(TypedLit Text
_ ScopedName
dtype) | ScopedName
dtype ScopedName -> [ScopedName] -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`elem` [ScopedName
xsdBoolean, ScopedName
xsdInteger, ScopedName
xsdDecimal, ScopedName
xsdDouble] = do 
  N3State
ost <- Parser N3State N3State
forall s. Parser s s
stGet
  let stmt :: Arc RDFLabel
stmt = RDFLabel -> RDFLabel -> RDFLabel -> Arc RDFLabel
forall lb. lb -> lb -> lb -> Arc lb
arc RDFLabel
s RDFLabel
p RDFLabel
o
      oldp :: NamespaceMap
oldp = N3State -> NamespaceMap
prefixUris N3State
ost
      ogs :: RDFGraph
ogs = N3State -> RDFGraph
graphState N3State
ost
      (Maybe Text
ns, URI
uri) = Namespace -> (Maybe Text, URI)
getNamespaceTuple (Namespace -> (Maybe Text, URI)) -> Namespace -> (Maybe Text, URI)
forall a b. (a -> b) -> a -> b
$ ScopedName -> Namespace
getScopeNamespace ScopedName
dtype
      newp :: NamespaceMap
newp = Maybe Text -> URI -> NamespaceMap -> NamespaceMap
forall k a. Ord k => k -> a -> Map k a -> Map k a
M.insert Maybe Text
ns URI
uri NamespaceMap
oldp
  (N3State -> N3State) -> Parser N3State ()
forall s. (s -> s) -> Parser s ()
stUpdate ((N3State -> N3State) -> Parser N3State ())
-> (N3State -> N3State) -> Parser N3State ()
forall a b. (a -> b) -> a -> b
$ \N3State
st -> N3State
st { prefixUris :: NamespaceMap
prefixUris = NamespaceMap
newp, graphState :: RDFGraph
graphState = Arc RDFLabel -> RDFGraph -> RDFGraph
forall lb. Label lb => Arc lb -> NSGraph lb -> NSGraph lb
addArc Arc RDFLabel
stmt RDFGraph
ogs }
addStatement RDFLabel
s RDFLabel
p RDFLabel
o = (N3State -> N3State) -> Parser N3State ()
forall s. (s -> s) -> Parser s ()
stUpdate ((RDFGraph -> RDFGraph) -> N3State -> N3State
updateGraph (Arc RDFLabel -> RDFGraph -> RDFGraph
forall lb. Label lb => Arc lb -> NSGraph lb -> NSGraph lb
addArc (RDFLabel -> RDFLabel -> RDFLabel -> Arc RDFLabel
forall lb. lb -> lb -> lb -> Arc lb
arc RDFLabel
s RDFLabel
p RDFLabel
o) ))

addStatementRev :: RDFLabel -> RDFLabel -> AddStatement
addStatementRev :: RDFLabel -> RDFLabel -> AddStatement
addStatementRev RDFLabel
o RDFLabel
p RDFLabel
s = RDFLabel -> RDFLabel -> AddStatement
addStatement RDFLabel
s RDFLabel
p RDFLabel
o

{-
A number of productions require a name, which starts with

[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#x00010000-#x000effff]

and then has

[\-0-9A-Z_a-z#x00b7#x00c0-#x00d6#x00d8-#x00f6#x00f8-#x037d#x037f-#x1fff#x200c-#x200d#x203f-#x2040#x2070-#x218f#x2c00-#x2fef#x3001-#xd7ff#xf900-#xfdcf#xfdf0-#xfffd#x00010000-#x000effff]*

we encode this as the n3Name production
-}

isaz, is09, isaz09 :: Char -> Bool
isaz :: Char -> Bool
isaz = Char -> Bool
isAsciiLower
is09 :: Char -> Bool
is09 = Char -> Bool
isDigit
isaz09 :: Char -> Bool
isaz09 Char
c = Char -> Bool
isaz Char
c Bool -> Bool -> Bool
|| Char -> Bool
is09 Char
c

match :: (Ord a) => a -> [(a,a)] -> Bool
match :: a -> [(a, a)] -> Bool
match a
v = ((a, a) -> Bool) -> [(a, a)] -> Bool
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
any (\(a
l,a
h) -> a
v a -> a -> Bool
forall a. Ord a => a -> a -> Bool
>= a
l Bool -> Bool -> Bool
&& a
v a -> a -> Bool
forall a. Ord a => a -> a -> Bool
<= a
h)

startChar :: Char -> Bool
startChar :: Char -> Bool
startChar Char
c = let i :: Int
i = Char -> Int
ord Char
c
              in Char
c Char -> Char -> Bool
forall a. Eq a => a -> a -> Bool
== Char
'_' Bool -> Bool -> Bool
|| 
                 Char -> [(Char, Char)] -> Bool
forall a. Ord a => a -> [(a, a)] -> Bool
match Char
c [(Char
'A', Char
'Z'), (Char
'a', Char
'z')] Bool -> Bool -> Bool
||
                 Int -> [(Int, Int)] -> Bool
forall a. Ord a => a -> [(a, a)] -> Bool
match Int
i [(Int
0x00c0, Int
0x00d6), (Int
0x00d8, Int
0x00f6), (Int
0x00f8, Int
0x02ff), 
                          (Int
0x0370, Int
0x037d), 
                          (Int
0x037f, Int
0x1fff), (Int
0x200c, Int
0x200d), 
                          (Int
0x2070, Int
0x218f), (Int
0x2c00, Int
0x2fef), (Int
0x3001, Int
0xd7ff), 
                          (Int
0xf900, Int
0xfdcf), (Int
0xfdf0, Int
0xfffd), 
                          (Int
0x00010000, Int
0x000effff)]           
  
inBody :: Char -> Bool
inBody :: Char -> Bool
inBody Char
c = let i :: Int
i = Char -> Int
ord Char
c
           in Char
c Char -> String -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`elem` (String
"-_"::String) Bool -> Bool -> Bool
|| Int
i Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
0x007 Bool -> Bool -> Bool
||
              Char -> [(Char, Char)] -> Bool
forall a. Ord a => a -> [(a, a)] -> Bool
match Char
c [(Char
'0', Char
'9'), (Char
'A', Char
'Z'), (Char
'a', Char
'z')] Bool -> Bool -> Bool
||
              Int -> [(Int, Int)] -> Bool
forall a. Ord a => a -> [(a, a)] -> Bool
match Int
i [(Int
0x00c0, Int
0x00d6), (Int
0x00d8, Int
0x00f6), (Int
0x00f8, Int
0x037d), 
                       (Int
0x037f, Int
0x1fff), (Int
0x200c, Int
0x200d), (Int
0x203f, Int
0x2040), 
                       (Int
0x2070, Int
0x218f), (Int
0x2c00, Int
0x2fef), (Int
0x3001, Int
0xd7ff), 
                       (Int
0xf900, Int
0xfdcf), (Int
0xfdf0, Int
0xfffd), 
                       (Int
0x00010000, Int
0x000effff)]           

-- should this be strict or lazy text?
n3Name :: N3Parser T.Text
n3Name :: N3Parser Text
n3Name = Char -> Text -> Text
T.cons (Char -> Text -> Text)
-> Parser N3State Char -> Parser N3State (Text -> Text)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Parser N3State Char
forall s. Parser s Char
n3Init Parser N3State (Text -> Text) -> N3Parser Text -> N3Parser Text
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> N3Parser Text
forall s. Parser s Text
n3Body
  where
    n3Init :: Parser s Char
n3Init = (Char -> Bool) -> Parser s Char
forall s. (Char -> Bool) -> Parser s Char
satisfy Char -> Bool
startChar
    n3Body :: Parser s Text
n3Body = Text -> Text
L.toStrict (Text -> Text) -> Parser s Text -> Parser s Text
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> (Char -> Bool) -> Parser s Text
forall s. (Char -> Bool) -> Parser s Text
manySatisfy Char -> Bool
inBody


n3NameStr :: N3Parser String
n3NameStr :: N3Parser String
n3NameStr = Text -> String
T.unpack (Text -> String) -> N3Parser Text -> N3Parser String
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> N3Parser Text
n3Name

{-
quickvariable ::=	\?[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#x00010000-#x000effff][\-0-9A-Z_a-z#x00b7#x00c0-#x00d6#x00d8-#x00f6#x00f8-#x037d#x037f-#x1fff#x200c-#x200d#x203f-#x2040#x2070-#x218f#x2c00-#x2fef#x3001-#xd7ff#xf900-#xfdcf#xfdf0-#xfffd#x00010000-#x000effff]*
-}

-- TODO: is mapping to Var correct?
-- | Match @?<variable name>@.
quickVariable :: N3Parser RDFLabel
quickVariable :: N3Parser RDFLabel
quickVariable = Char -> Parser N3State Char
forall s. Char -> Parser s Char
char Char
'?' Parser N3State Char -> N3Parser RDFLabel -> N3Parser RDFLabel
forall (f :: * -> *) a b. Applicative f => f a -> f b -> f b
*> (String -> RDFLabel
Var (String -> RDFLabel) -> N3Parser String -> N3Parser RDFLabel
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> N3Parser String
n3NameStr) 

{-
string ::=	("""[^"\\]*(?:(?:\\.|"(?!""))[^"\\]*)*""")|("[^"\\]*(?:\\.[^"\\]*)*")

or

string ::= tripleQuoted | singleQUoted

-}

n3string :: N3Parser T.Text
n3string :: N3Parser Text
n3string = N3Parser Text
tripleQuoted N3Parser Text -> N3Parser Text -> N3Parser Text
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> N3Parser Text
singleQuoted 

{-
singleQuoted ::=  "[^"\\]*(?:\\.[^"\\]*)*"

asciiChars :: String
asciiChars = map chr [0x20..0x7e]

asciiCharsN3 :: String
asciiCharsN3 = filter (`notElem` "\\\"") asciiChars

-}

digit :: N3Parser Char
digit :: Parser N3State Char
digit = (Char -> Bool) -> Parser N3State Char
forall s. (Char -> Bool) -> Parser s Char
satisfy Char -> Bool
isDigit

{-
This is very similar to NTriples accept that also allow the escaping of '
even though it is not required.

The Python rules allow \N{name}, where name is the Unicode name. It's
not clear whether we need to support this too, so for now we do not.

-}
protectedChar :: N3Parser Char
protectedChar :: Parser N3State Char
protectedChar =
  (Char -> Parser N3State Char
forall s. Char -> Parser s Char
char Char
't' Parser N3State Char -> Char -> Parser N3State Char
forall (f :: * -> *) a b. Functor f => f a -> b -> f b
$> Char
'\t')
  Parser N3State Char -> Parser N3State Char -> Parser N3State Char
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> (Char -> Parser N3State Char
forall s. Char -> Parser s Char
char Char
'n' Parser N3State Char -> Char -> Parser N3State Char
forall (f :: * -> *) a b. Functor f => f a -> b -> f b
$> Char
'\n')
  Parser N3State Char -> Parser N3State Char -> Parser N3State Char
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> (Char -> Parser N3State Char
forall s. Char -> Parser s Char
char Char
'r' Parser N3State Char -> Char -> Parser N3State Char
forall (f :: * -> *) a b. Functor f => f a -> b -> f b
$> Char
'\r')
  Parser N3State Char -> Parser N3State Char -> Parser N3State Char
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> (Char -> Parser N3State Char
forall s. Char -> Parser s Char
char Char
'"' Parser N3State Char -> Char -> Parser N3State Char
forall (f :: * -> *) a b. Functor f => f a -> b -> f b
$> Char
'"')
  Parser N3State Char -> Parser N3State Char -> Parser N3State Char
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> (Char -> Parser N3State Char
forall s. Char -> Parser s Char
char Char
'\'' Parser N3State Char -> Char -> Parser N3State Char
forall (f :: * -> *) a b. Functor f => f a -> b -> f b
$> Char
'\'')
  Parser N3State Char -> Parser N3State Char -> Parser N3State Char
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> (Char -> Parser N3State Char
forall s. Char -> Parser s Char
char Char
'\\' Parser N3State Char -> Char -> Parser N3State Char
forall (f :: * -> *) a b. Functor f => f a -> b -> f b
$> Char
'\\')
  Parser N3State Char -> Parser N3State Char -> Parser N3State Char
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> (Char -> Parser N3State Char
forall s. Char -> Parser s Char
char Char
'u' Parser N3State Char -> Parser N3State Char -> Parser N3State Char
forall (f :: * -> *) a b. Applicative f => f a -> f b -> f b
*> Parser N3State Char
forall s. Parser s Char
hex4)
  Parser N3State Char -> Parser N3State Char -> Parser N3State Char
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> (Char -> Parser N3State Char
forall s. Char -> Parser s Char
char Char
'U' Parser N3State Char -> Parser N3State Char -> Parser N3State Char
forall (f :: * -> *) a b. Applicative f => f a -> f b -> f b
*> Parser N3State Char
forall s. Parser s Char
hex8)

-- Accept an escape character or any character as long as it isn't
-- a new-line or quote. Unrecognized escape sequences should therefore
-- be left alone by this. 
--
n3Character :: N3Parser Char
n3Character :: Parser N3State Char
n3Character = 
  (Char -> Parser N3State Char
forall s. Char -> Parser s Char
char Char
'\\' Parser N3State Char -> Parser N3State Char -> Parser N3State Char
forall (f :: * -> *) a b. Applicative f => f a -> f b -> f b
*> (Parser N3State Char
protectedChar Parser N3State Char -> Parser N3State Char -> Parser N3State Char
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> Char -> Parser N3State Char
forall (m :: * -> *) a. Monad m => a -> m a
return Char
'\\'))
  Parser N3State Char -> Parser N3State Char -> Parser N3State Char
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> String -> Parser N3State Char
forall s. String -> Parser s Char
noneOf String
"\"\n"
      
{-
      <|> (oneOf asciiCharsN3 <?> "ASCII character")
              -- TODO: bodyChar and asciiCharsN3 overlap
      <|> (oneOf bodyChar <?> "Unicode character")
-}              

sQuot :: N3Parser Char
sQuot :: Parser N3State Char
sQuot = Char -> Parser N3State Char
forall s. Char -> Parser s Char
char Char
'"'

{-
TODO: there must be a better way of building up the Text
-}

singleQuoted :: N3Parser T.Text
singleQuoted :: N3Parser Text
singleQuoted = String -> Text
T.pack (String -> Text) -> N3Parser String -> N3Parser Text
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Parser N3State Char
-> Parser N3State Char -> N3Parser String -> N3Parser String
forall (p :: * -> *) bra ket a.
PolyParse p =>
p bra -> p ket -> p a -> p a
bracket Parser N3State Char
sQuot Parser N3State Char
sQuot (Parser N3State Char -> N3Parser String
forall (f :: * -> *) a. Alternative f => f a -> f [a]
many Parser N3State Char
n3Character)
    
{-
tripleQUoted ::=	"""[^"\\]*(?:(?:\\.|"(?!""))[^"\\]*)*"""

The following may not match the output format we now create (with the
move to the Turtle Candidate Recommendation), so re-writing as a test,
but this means pulling in a lot of Turtle productions, which should
be shared.

tripleQuoted = tQuot *> fmap T.pack (manyTill (n3Character <|> sQuot <|> char '\n') tQuot)
  where
    -- tQuot = try (count 3 sQuot)
    tQuot = exactly 3 sQuot
-}
tripleQuoted :: N3Parser T.Text
tripleQuoted :: N3Parser Text
tripleQuoted =
  let sep :: N3Parser String
sep = Int -> Parser N3State Char -> N3Parser String
forall (p :: * -> *) a. PolyParse p => Int -> p a -> p [a]
exactly Int
3 Parser N3State Char
sQuot
  in [Text] -> Text
T.concat ([Text] -> Text) -> Parser N3State [Text] -> N3Parser Text
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> N3Parser String
-> N3Parser String
-> Parser N3State [Text]
-> Parser N3State [Text]
forall (p :: * -> *) bra ket a.
PolyParse p =>
p bra -> p ket -> p a -> p a
bracket N3Parser String
sep N3Parser String
sep (N3Parser Text -> Parser N3State [Text]
forall (f :: * -> *) a. Alternative f => f a -> f [a]
many N3Parser Text
_tCharsLong)

{-- Turtle productions: start --}
oneOrTwo :: N3Parser T.Text
oneOrTwo :: N3Parser Text
oneOrTwo = do
  Parser N3State Char -> Parser N3State ()
forall (f :: * -> *) a. Applicative f => f a -> f ()
ignore (Parser N3State Char -> Parser N3State ())
-> Parser N3State Char -> Parser N3State ()
forall a b. (a -> b) -> a -> b
$ Char -> Parser N3State Char
forall s. Char -> Parser s Char
char Char
'"'
  Maybe Char
mb <- Parser N3State Char -> Parser N3State (Maybe Char)
forall (f :: * -> *) a. Alternative f => f a -> f (Maybe a)
optional (Char -> Parser N3State Char
forall s. Char -> Parser s Char
char Char
'"')
  case Maybe Char
mb of
    Just Char
_ -> Text -> N3Parser Text
forall (m :: * -> *) a. Monad m => a -> m a
return Text
"\"\""
    Maybe Char
_      -> Text -> N3Parser Text
forall (m :: * -> *) a. Monad m => a -> m a
return Text
"\""

_multiQuote :: N3Parser T.Text
_multiQuote :: N3Parser Text
_multiQuote = do
  Maybe Text
mq <- N3Parser Text -> Parser N3State (Maybe Text)
forall (f :: * -> *) a. Alternative f => f a -> f (Maybe a)
optional N3Parser Text
oneOrTwo
  Char
r <- String -> Parser N3State Char
forall s. String -> Parser s Char
noneOf String
"\"\\"
  Text -> N3Parser Text
forall (m :: * -> *) a. Monad m => a -> m a
return (Text -> N3Parser Text) -> Text -> N3Parser Text
forall a b. (a -> b) -> a -> b
$ Text -> Maybe Text -> Text
forall a. a -> Maybe a -> a
fromMaybe Text
T.empty Maybe Text
mq Text -> Char -> Text
`T.snoc` Char
r
                
_tCharsLong :: N3Parser T.Text
_tCharsLong :: N3Parser Text
_tCharsLong =
  Char -> Text
T.singleton (Char -> Text) -> Parser N3State Char -> N3Parser Text
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Parser N3State Char
_protChar
  N3Parser Text -> N3Parser Text -> N3Parser Text
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> N3Parser Text
_multiQuote

_protChar :: N3Parser Char
_protChar :: Parser N3State Char
_protChar = Char -> Parser N3State Char
forall s. Char -> Parser s Char
char Char
'\\' Parser N3State Char -> Parser N3State Char -> Parser N3State Char
forall (f :: * -> *) a b. Applicative f => f a -> f b -> f b
*> (Parser N3State Char
_echar' Parser N3State Char -> Parser N3State Char -> Parser N3State Char
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> Parser N3State Char
_uchar')

_echar' :: N3Parser Char
_echar' :: Parser N3State Char
_echar' = 
  (Char -> Parser N3State Char
forall s. Char -> Parser s Char
char Char
't' Parser N3State Char -> Char -> Parser N3State Char
forall (f :: * -> *) a b. Functor f => f a -> b -> f b
$> Char
'\t') Parser N3State Char -> Parser N3State Char -> Parser N3State Char
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|>
  (Char -> Parser N3State Char
forall s. Char -> Parser s Char
char Char
'b' Parser N3State Char -> Char -> Parser N3State Char
forall (f :: * -> *) a b. Functor f => f a -> b -> f b
$> Char
'\b') Parser N3State Char -> Parser N3State Char -> Parser N3State Char
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|>
  (Char -> Parser N3State Char
forall s. Char -> Parser s Char
char Char
'n' Parser N3State Char -> Char -> Parser N3State Char
forall (f :: * -> *) a b. Functor f => f a -> b -> f b
$> Char
'\n') Parser N3State Char -> Parser N3State Char -> Parser N3State Char
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|>
  (Char -> Parser N3State Char
forall s. Char -> Parser s Char
char Char
'r' Parser N3State Char -> Char -> Parser N3State Char
forall (f :: * -> *) a b. Functor f => f a -> b -> f b
$> Char
'\r') Parser N3State Char -> Parser N3State Char -> Parser N3State Char
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|>
  (Char -> Parser N3State Char
forall s. Char -> Parser s Char
char Char
'f' Parser N3State Char -> Char -> Parser N3State Char
forall (f :: * -> *) a b. Functor f => f a -> b -> f b
$> Char
'\f') Parser N3State Char -> Parser N3State Char -> Parser N3State Char
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|>
  (Char -> Parser N3State Char
forall s. Char -> Parser s Char
char Char
'\\' Parser N3State Char -> Char -> Parser N3State Char
forall (f :: * -> *) a b. Functor f => f a -> b -> f b
$> Char
'\\') Parser N3State Char -> Parser N3State Char -> Parser N3State Char
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|>
  (Char -> Parser N3State Char
forall s. Char -> Parser s Char
char Char
'"' Parser N3State Char -> Char -> Parser N3State Char
forall (f :: * -> *) a b. Functor f => f a -> b -> f b
$> Char
'"') Parser N3State Char -> Parser N3State Char -> Parser N3State Char
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|>
  (Char -> Parser N3State Char
forall s. Char -> Parser s Char
char Char
'\'' Parser N3State Char -> Char -> Parser N3State Char
forall (f :: * -> *) a b. Functor f => f a -> b -> f b
$> Char
'\'')

_uchar' :: N3Parser Char
_uchar' :: Parser N3State Char
_uchar' =
  (Char -> Parser N3State Char
forall s. Char -> Parser s Char
char Char
'u' Parser N3State Char -> Parser N3State Char -> Parser N3State Char
forall (f :: * -> *) a b. Applicative f => f a -> f b -> f b
*> Parser N3State Char -> Parser N3State Char
forall (p :: * -> *) a. Commitment p => p a -> p a
commit Parser N3State Char
forall s. Parser s Char
hex4)
  Parser N3State Char -> Parser N3State Char -> Parser N3State Char
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|>
  (Char -> Parser N3State Char
forall s. Char -> Parser s Char
char Char
'U' Parser N3State Char -> Parser N3State Char -> Parser N3State Char
forall (f :: * -> *) a b. Applicative f => f a -> f b -> f b
*> Parser N3State Char -> Parser N3State Char
forall (p :: * -> *) a. Commitment p => p a -> p a
commit Parser N3State Char
forall s. Parser s Char
hex8)

{-- Turtle productions: end --}

getDefaultPrefix :: N3Parser Namespace
getDefaultPrefix :: N3Parser Namespace
getDefaultPrefix = do
  N3State
s <- Parser N3State N3State
forall s. Parser s s
stGet
  case N3State -> Maybe Text -> Maybe URI
getPrefixURI N3State
s Maybe Text
forall a. Maybe a
Nothing of
    Just URI
uri -> Namespace -> N3Parser Namespace
forall (m :: * -> *) a. Monad m => a -> m a
return (Namespace -> N3Parser Namespace)
-> Namespace -> N3Parser Namespace
forall a b. (a -> b) -> a -> b
$ Maybe Text -> URI -> Namespace
makeNamespace Maybe Text
forall a. Maybe a
Nothing URI
uri
    Maybe URI
_ -> String -> N3Parser Namespace
forall (m :: * -> *) a. MonadFail m => String -> m a
fail String
"No default prefix defined; how unexpected!"

addBase :: URI -> N3Parser ()
addBase :: URI -> Parser N3State ()
addBase = (N3State -> N3State) -> Parser N3State ()
forall s. (s -> s) -> Parser s ()
stUpdate ((N3State -> N3State) -> Parser N3State ())
-> (URI -> N3State -> N3State) -> URI -> Parser N3State ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> URI -> N3State -> N3State
setSUri String
"base" 

addPrefix :: Maybe T.Text -> URI -> N3Parser ()
addPrefix :: Maybe Text -> URI -> Parser N3State ()
addPrefix Maybe Text
p = (N3State -> N3State) -> Parser N3State ()
forall s. (s -> s) -> Parser s ()
stUpdate ((N3State -> N3State) -> Parser N3State ())
-> (URI -> N3State -> N3State) -> URI -> Parser N3State ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Maybe Text -> URI -> N3State -> N3State
setPrefix Maybe Text
p 

{-|
Update the set of keywords that can be given without
an \@ sign.
-}
updateKeywordsList :: [T.Text] -> N3Parser ()
updateKeywordsList :: [Text] -> Parser N3State ()
updateKeywordsList = (N3State -> N3State) -> Parser N3State ()
forall s. (s -> s) -> Parser s ()
stUpdate ((N3State -> N3State) -> Parser N3State ())
-> ([Text] -> N3State -> N3State) -> [Text] -> Parser N3State ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [Text] -> N3State -> N3State
setKeywordsList

{-
document ::=		|	statements_optional EOF
-}

-- | Process a N3 document, returning a graph.
document :: N3Parser RDFGraph
document :: N3Parser RDFGraph
document = N3State -> RDFGraph
mkGr (N3State -> RDFGraph)
-> Parser N3State N3State -> N3Parser RDFGraph
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> (Parser N3State ()
forall s. Parser s ()
whiteSpace Parser N3State () -> Parser N3State () -> Parser N3State ()
forall (f :: * -> *) a b. Applicative f => f a -> f b -> f b
*> Parser N3State ()
statementsOptional Parser N3State () -> Parser N3State () -> Parser N3State ()
forall (f :: * -> *) a b. Applicative f => f a -> f b -> f b
*> Parser N3State ()
forall s. Parser s ()
eof Parser N3State ()
-> Parser N3State N3State -> Parser N3State N3State
forall (f :: * -> *) a b. Applicative f => f a -> f b -> f b
*> Parser N3State N3State
forall s. Parser s s
stGet)
  where
    mkGr :: N3State -> RDFGraph
mkGr N3State
s = NamespaceMap -> RDFGraph -> RDFGraph
forall lb. NamespaceMap -> NSGraph lb -> NSGraph lb
setNamespaces (N3State -> NamespaceMap
prefixUris N3State
s) (N3State -> RDFGraph
graphState N3State
s)

{-
statements_optional ::=		|	statement  "."  statements_optional
		|	void

-}

statementsOptional :: N3Parser ()
statementsOptional :: Parser N3State ()
statementsOptional = Parser N3State [()] -> Parser N3State ()
forall (f :: * -> *) a. Applicative f => f a -> f ()
ignore (Parser N3State [()] -> Parser N3State ())
-> Parser N3State [()] -> Parser N3State ()
forall a b. (a -> b) -> a -> b
$ Parser N3State () -> Parser N3State () -> Parser N3State [()]
forall s a b. Parser s a -> Parser s b -> Parser s [a]
endBy (Parser N3State () -> Parser N3State ()
forall s a. Parser s a -> Parser s a
lexeme Parser N3State ()
statement) Parser N3State ()
fullStop
    
{-
statement ::=		|	declaration
		|	existential
		|	simpleStatement
		|	universal

-}

statement :: N3Parser ()
statement :: Parser N3State ()
statement =
  Parser N3State ()
declaration
  Parser N3State () -> Parser N3State () -> Parser N3State ()
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> Parser N3State ()
existential
  Parser N3State () -> Parser N3State () -> Parser N3State ()
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> Parser N3State ()
universal
  Parser N3State () -> Parser N3State () -> Parser N3State ()
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> Parser N3State ()
simpleStatement
  -- having an error here leads to less informative errors in general, it seems
  -- <?> "statement (existential or universal quantification or a simple statement)"
  
{-
declaration ::=		|	 "@base"  explicituri
		|	 "@keywords"  barename_csl
		|	 "@prefix"  prefix explicituri
-}

-- TODO: do we need the try statements here? atWord would need to have a try on '@'
-- (if applicable) which should mean being able to get rid of try
--
declaration :: N3Parser ()
declaration :: Parser N3State ()
declaration = [Parser N3State ()] -> Parser N3State ()
forall (p :: * -> *) a. PolyParse p => [p a] -> p a
oneOf [
  Text -> N3Parser Text
atWord Text
"base" N3Parser Text -> N3Parser URI -> N3Parser URI
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> N3Parser URI
explicitURI N3Parser URI -> (URI -> Parser N3State ()) -> Parser N3State ()
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= URI -> Parser N3State ()
addBase,
  Text -> N3Parser Text
atWord Text
"keywords" N3Parser Text -> Parser N3State [Text] -> Parser N3State [Text]
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> Parser N3State [Text]
bareNameCsl Parser N3State [Text]
-> ([Text] -> Parser N3State ()) -> Parser N3State ()
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= [Text] -> Parser N3State ()
updateKeywordsList,
  Text -> N3Parser Text
atWord Text
"prefix" N3Parser Text -> Parser N3State () -> Parser N3State ()
forall (f :: * -> *) a b. Applicative f => f a -> f b -> f b
*> Parser N3State ()
getPrefix
  ]

  {-
  (try (atWord "base") >> explicitURI >>= addBase)
  <|>
  (try (atWord "keywords") >> bareNameCsl >>= updateKeywordsList)
  <|>
  (try (atWord "prefix") *> getPrefix)
  -}

-- | Process the remainder of an @\@prefix@ line (after this
-- has been processed). The prefix value and URI are added to the parser
-- state.
getPrefix :: N3Parser ()  
getPrefix :: Parser N3State ()
getPrefix = do
  Maybe Text
p <- Parser N3State (Maybe Text) -> Parser N3State (Maybe Text)
forall s a. Parser s a -> Parser s a
lexeme Parser N3State (Maybe Text)
prefix
  URI
u <- N3Parser URI
explicitURI
  Maybe Text -> URI -> Parser N3State ()
addPrefix Maybe Text
p URI
u

{-
explicituri ::=	<[^>]*>

Note: white space is to be ignored within <>
-}

explicitURI :: N3Parser URI
explicitURI :: N3Parser URI
explicitURI = do
  Parser N3State Char -> Parser N3State ()
forall (f :: * -> *) a. Applicative f => f a -> f ()
ignore (Parser N3State Char -> Parser N3State ())
-> Parser N3State Char -> Parser N3State ()
forall a b. (a -> b) -> a -> b
$ Char -> Parser N3State Char
forall s. Char -> Parser s Char
char Char
'<'
  String
ustr <- Parser N3State Char -> Parser N3State Char -> N3Parser String
forall (p :: * -> *) a z.
(PolyParse p, Show a) =>
p a -> p z -> p [a]
manyFinally' (((Char -> Bool) -> Parser N3State Char
forall s. (Char -> Bool) -> Parser s Char
satisfy Char -> Bool
isSpace Parser N3State Char -> Parser N3State Char -> Parser N3State Char
forall (f :: * -> *) a b. Applicative f => f a -> f b -> f b
*> Parser N3State Char
forall s. Parser s Char
next) Parser N3State Char -> Parser N3State Char -> Parser N3State Char
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> Parser N3State Char
forall s. Parser s Char
next) (Char -> Parser N3State Char
forall s. Char -> Parser s Char
char Char
'>')
  case String -> Maybe URI
parseURIReference String
ustr of
    Maybe URI
Nothing -> String -> N3Parser URI
forall (p :: * -> *) a. PolyParse p => String -> p a
failBad (String -> N3Parser URI) -> String -> N3Parser URI
forall a b. (a -> b) -> a -> b
$ String
"Invalid URI: <" String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
ustr String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
">"
    Just URI
uref -> do
      N3State
s <- Parser N3State N3State
forall s. Parser s s
stGet
      let base :: URI
base = N3State -> String -> URI
getSUri N3State
s String
"base"
      (String -> N3Parser URI)
-> (URI -> N3Parser URI) -> Either String URI -> N3Parser URI
forall a c b. (a -> c) -> (b -> c) -> Either a b -> c
either String -> N3Parser URI
forall (m :: * -> *) a. MonadFail m => String -> m a
fail URI -> N3Parser URI
forall (m :: * -> *) a. Monad m => a -> m a
return (Either String URI -> N3Parser URI)
-> Either String URI -> N3Parser URI
forall a b. (a -> b) -> a -> b
$ URI -> URI -> Either String URI
appendURIs URI
base URI
uref
      
-- production from the old parser; used in SwishScript
-- | An explicitly given URI followed by white space.
lexUriRef :: N3Parser URI
lexUriRef :: N3Parser URI
lexUriRef = N3Parser URI -> N3Parser URI
forall s a. Parser s a -> Parser s a
lexeme N3Parser URI
explicitURI

{-
barename ::=	[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#x00010000-#x000effff][\-0-9A-Z_a-z#x00b7#x00c0-#x00d6#x00d8-#x00f6#x00f8-#x037d#x037f-#x1fff#x200c-#x200d#x203f-#x2040#x2070-#x218f#x2c00-#x2fef#x3001-#xd7ff#xf900-#xfdcf#xfdf0-#xfffd#x00010000-#x000effff]*
barename_csl ::=		|	barename barename_csl_tail
		|	void
barename_csl_tail ::=		|	 ","  barename barename_csl_tail
		|	void
-}

bareNameCsl :: N3Parser [T.Text]
bareNameCsl :: Parser N3State [Text]
bareNameCsl = N3Parser Text -> Parser N3State () -> Parser N3State [Text]
forall (p :: * -> *) a sep. PolyParse p => p a -> p sep -> p [a]
sepBy (N3Parser Text -> N3Parser Text
forall s a. Parser s a -> Parser s a
lexeme N3Parser Text
bareName) Parser N3State ()
comma

bareName :: N3Parser T.Text
bareName :: N3Parser Text
bareName = N3Parser Text
n3Name 

{-
prefix ::=	([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#x00010000-#x000effff][\-0-9A-Z_a-z#x00b7#x00c0-#x00d6#x00d8-#x00f6#x00f8-#x037d#x037f-#x1fff#x200c-#x200d#x203f-#x2040#x2070-#x218f#x2c00-#x2fef#x3001-#xd7ff#xf900-#xfdcf#xfdf0-#xfffd#x00010000-#x000effff]*)?:
-}

prefix :: N3Parser (Maybe T.Text)
prefix :: Parser N3State (Maybe Text)
prefix = N3Parser Text -> Parser N3State (Maybe Text)
forall (f :: * -> *) a. Alternative f => f a -> f (Maybe a)
optional (N3Parser Text -> N3Parser Text
forall s a. Parser s a -> Parser s a
lexeme N3Parser Text
n3Name) Parser N3State (Maybe Text)
-> Parser N3State Char -> Parser N3State (Maybe Text)
forall (f :: * -> *) a b. Applicative f => f a -> f b -> f a
<* Char -> Parser N3State Char
forall s. Char -> Parser s Char
char Char
':'
         

{-
symbol ::=		|	explicituri
		|	qname
symbol_csl ::=		|	symbol symbol_csl_tail
		|	void
symbol_csl_tail ::=		|	 ","  symbol symbol_csl_tail
		|	void

-}

-- | Match a N3 symbol (an explicit URI or a QName)
-- and convert it to a 'ScopedName'.
n3symbol :: N3Parser ScopedName
n3symbol :: N3Parser ScopedName
n3symbol = 
  (URI -> ScopedName
makeURIScopedName (URI -> ScopedName) -> N3Parser URI -> N3Parser ScopedName
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> N3Parser URI
explicitURI)
  N3Parser ScopedName -> N3Parser ScopedName -> N3Parser ScopedName
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> N3Parser ScopedName
qname

symbolCsl :: N3Parser [ScopedName]
symbolCsl :: N3Parser [ScopedName]
symbolCsl = N3Parser ScopedName -> Parser N3State () -> N3Parser [ScopedName]
forall (p :: * -> *) a sep. PolyParse p => p a -> p sep -> p [a]
sepBy (N3Parser ScopedName -> N3Parser ScopedName
forall s a. Parser s a -> Parser s a
lexeme N3Parser ScopedName
n3symbol) Parser N3State ()
comma

{-
qname ::=	(([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#x00010000-#x000effff][\-0-9A-Z_a-z#x00b7#x00c0-#x00d6#x00d8-#x00f6#x00f8-#x037d#x037f-#x1fff#x200c-#x200d#x203f-#x2040#x2070-#x218f#x2c00-#x2fef#x3001-#xd7ff#xf900-#xfdcf#xfdf0-#xfffd#x00010000-#x000effff]*)?:)?[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#x00010000-#x000effff][\-0-9A-Z_a-z#x00b7#x00c0-#x00d6#x00d8-#x00f6#x00f8-#x037d#x037f-#x1fff#x200c-#x200d#x203f-#x2040#x2070-#x218f#x2c00-#x2fef#x3001-#xd7ff#xf900-#xfdcf#xfdf0-#xfffd#x00010000-#x000effff]*

TODO:
  Note that, for now, we explicitly handle blank nodes
  (of the form _:name) direcly in pathItem'.
  This is not a good idea since qname' is used elsewhere
  and so shouldn't we do the same thing there too?
-}

-- for now assume that the parsing rule for the local part
-- will not create an invalid LName.
toName :: Namespace -> T.Text -> ScopedName
toName :: Namespace -> Text -> ScopedName
toName Namespace
ns Text
l = 
    case Text -> Maybe LName
newLName Text
l of
      Just LName
local -> Namespace -> LName -> ScopedName
makeNSScopedName Namespace
ns LName
local
      Maybe LName
_ -> String -> ScopedName
forall a. HasCallStack => String -> a
error (String -> ScopedName) -> String -> ScopedName
forall a b. (a -> b) -> a -> b
$ String
"Invalid local name: " String -> String -> String
forall a. [a] -> [a] -> [a]
++ Text -> String
T.unpack Text
l

qname :: N3Parser ScopedName
qname :: N3Parser ScopedName
qname = N3Parser ScopedName
qname1 N3Parser ScopedName -> N3Parser ScopedName -> N3Parser ScopedName
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> N3Parser ScopedName
qname2

qname1 :: N3Parser ScopedName
qname1 :: N3Parser ScopedName
qname1 = ((Namespace, Text) -> ScopedName)
-> Parser N3State (Namespace, Text) -> N3Parser ScopedName
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap ((Namespace -> Text -> ScopedName)
-> (Namespace, Text) -> ScopedName
forall a b c. (a -> b -> c) -> (a, b) -> c
uncurry Namespace -> Text -> ScopedName
toName) (Char -> Parser N3State Char
forall s. Char -> Parser s Char
char Char
':' Parser N3State Char
-> Parser N3State (Namespace, Text)
-> Parser N3State (Namespace, Text)
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> Parser N3State (Namespace, Text)
g)
    where
      g :: Parser N3State (Namespace, Text)
g = (,) (Namespace -> Text -> (Namespace, Text))
-> N3Parser Namespace -> Parser N3State (Text -> (Namespace, Text))
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> N3Parser Namespace
getDefaultPrefix Parser N3State (Text -> (Namespace, Text))
-> N3Parser Text -> Parser N3State (Namespace, Text)
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> (N3Parser Text
n3Name N3Parser Text -> N3Parser Text -> N3Parser Text
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> Text -> N3Parser Text
forall (m :: * -> *) a. Monad m => a -> m a
return Text
"")
               
qname2 :: N3Parser ScopedName
qname2 :: N3Parser ScopedName
qname2 = N3Parser Text
n3Name N3Parser Text
-> (Text -> N3Parser ScopedName) -> N3Parser ScopedName
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= Text -> N3Parser ScopedName
fullOrLocalQName

fullOrLocalQName :: T.Text -> N3Parser ScopedName
fullOrLocalQName :: Text -> N3Parser ScopedName
fullOrLocalQName Text
name = 
  (Char -> Parser N3State Char
forall s. Char -> Parser s Char
char Char
':' Parser N3State Char -> N3Parser ScopedName -> N3Parser ScopedName
forall (f :: * -> *) a b. Applicative f => f a -> f b -> f b
*> Text -> N3Parser ScopedName
fullQName Text
name)
  N3Parser ScopedName -> N3Parser ScopedName -> N3Parser ScopedName
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> Text -> N3Parser ScopedName
localQName Text
name
  
fullQName :: T.Text -> N3Parser ScopedName
fullQName :: Text -> N3Parser ScopedName
fullQName Text
name = Namespace -> Text -> ScopedName
toName (Namespace -> Text -> ScopedName)
-> N3Parser Namespace -> Parser N3State (Text -> ScopedName)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Text -> N3Parser Namespace
findPrefix Text
name Parser N3State (Text -> ScopedName)
-> N3Parser Text -> N3Parser ScopedName
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> (N3Parser Text
n3Name N3Parser Text -> N3Parser Text -> N3Parser Text
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> Text -> N3Parser Text
forall (f :: * -> *) a. Applicative f => a -> f a
pure Text
"")
  
findPrefix :: T.Text -> N3Parser Namespace
findPrefix :: Text -> N3Parser Namespace
findPrefix Text
pre = do
  N3State
st <- Parser N3State N3State
forall s. Parser s s
stGet
  case Maybe Text -> NamespaceMap -> Maybe URI
forall k a. Ord k => k -> Map k a -> Maybe a
M.lookup (Text -> Maybe Text
forall a. a -> Maybe a
Just Text
pre) (N3State -> NamespaceMap
prefixUris N3State
st) of
    Just URI
uri -> Namespace -> N3Parser Namespace
forall (m :: * -> *) a. Monad m => a -> m a
return (Namespace -> N3Parser Namespace)
-> Namespace -> N3Parser Namespace
forall a b. (a -> b) -> a -> b
$ Maybe Text -> URI -> Namespace
makeNamespace (Text -> Maybe Text
forall a. a -> Maybe a
Just Text
pre) URI
uri
    Maybe URI
Nothing  -> String -> N3Parser Namespace
forall (p :: * -> *) a. PolyParse p => String -> p a
failBad (String -> N3Parser Namespace) -> String -> N3Parser Namespace
forall a b. (a -> b) -> a -> b
$ String
"Prefix '" String -> String -> String
forall a. [a] -> [a] -> [a]
++ Text -> String
T.unpack Text
pre String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
":' not bound."
  
localQName :: T.Text -> N3Parser ScopedName
localQName :: Text -> N3Parser ScopedName
localQName Text
name = do
  N3State
st <- Parser N3State N3State
forall s. Parser s s
stGet
  if N3State -> Bool
getAllowLocalNames N3State
st
    then let g :: Parser N3State (Namespace, Text)
g = (,) (Namespace -> Text -> (Namespace, Text))
-> N3Parser Namespace -> Parser N3State (Text -> (Namespace, Text))
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> N3Parser Namespace
getDefaultPrefix Parser N3State (Text -> (Namespace, Text))
-> N3Parser Text -> Parser N3State (Namespace, Text)
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Text -> N3Parser Text
forall (f :: * -> *) a. Applicative f => a -> f a
pure Text
name
         in (Namespace -> Text -> ScopedName)
-> (Namespace, Text) -> ScopedName
forall a b c. (a -> b -> c) -> (a, b) -> c
uncurry Namespace -> Text -> ScopedName
toName ((Namespace, Text) -> ScopedName)
-> Parser N3State (Namespace, Text) -> N3Parser ScopedName
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Parser N3State (Namespace, Text)
g
            
    else String -> N3Parser ScopedName
forall (m :: * -> *) a. MonadFail m => String -> m a
fail (String
"Invalid 'bare' word: " String -> String -> String
forall a. [a] -> [a] -> [a]
++ Text -> String
T.unpack Text
name)-- TODO: not ideal error message; can we handle this case differently?

{-
existential ::=		|	 "@forSome"  symbol_csl

For now we just read in the symbols and ignore them,
since we do not mark blank nodes as existentially quantified
(we assume this is the case).

TODO: fix this?
-}

existential :: N3Parser ()
-- existential = try (atWord "forSome") *> symbolCsl >> return ()
existential :: Parser N3State ()
existential = (Text -> N3Parser Text
atWord Text
"forSome" N3Parser Text -> N3Parser [ScopedName] -> N3Parser [ScopedName]
forall (f :: * -> *) a b. Applicative f => f a -> f b -> f b
*> N3Parser [ScopedName]
symbolCsl) N3Parser [ScopedName] -> () -> Parser N3State ()
forall (f :: * -> *) a b. Functor f => f a -> b -> f b
$> ()

{-
simpleStatement ::=		|	subject propertylist
-}

simpleStatement :: N3Parser ()
simpleStatement :: Parser N3State ()
simpleStatement = N3Parser RDFLabel
subject N3Parser RDFLabel -> AddStatement -> Parser N3State ()
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= AddStatement
propertyListWith
  
{-
subject ::=		|	expression
-}

subject :: N3Parser RDFLabel
subject :: N3Parser RDFLabel
subject = N3Parser RDFLabel -> N3Parser RDFLabel
forall s a. Parser s a -> Parser s a
lexeme N3Parser RDFLabel
expression

{-
expression ::=		|	pathitem pathtail
pathtail ::=		|	 "!"  expression
		|	 "^"  expression
		|	void

-}

expression :: N3Parser RDFLabel
expression :: N3Parser RDFLabel
expression = do
  RDFLabel
i <- N3Parser RDFLabel
pathItem
  
  let backwardExpr :: Parser s (RDFLabel -> RDFLabel -> AddStatement)
backwardExpr = Char -> Parser s Char
forall s. Char -> Parser s Char
char Char
'!' Parser s Char
-> (RDFLabel -> RDFLabel -> AddStatement)
-> Parser s (RDFLabel -> RDFLabel -> AddStatement)
forall (f :: * -> *) a b. Functor f => f a -> b -> f b
$> RDFLabel -> RDFLabel -> AddStatement
addStatementRev
      forwardExpr :: Parser s (RDFLabel -> RDFLabel -> AddStatement)
forwardExpr  = Char -> Parser s Char
forall s. Char -> Parser s Char
char Char
'^' Parser s Char
-> (RDFLabel -> RDFLabel -> AddStatement)
-> Parser s (RDFLabel -> RDFLabel -> AddStatement)
forall (f :: * -> *) a b. Functor f => f a -> b -> f b
$> RDFLabel -> RDFLabel -> AddStatement
addStatement
  
  Maybe (RDFLabel -> RDFLabel -> AddStatement, RDFLabel)
mpt <- Parser N3State (RDFLabel -> RDFLabel -> AddStatement, RDFLabel)
-> Parser
     N3State (Maybe (RDFLabel -> RDFLabel -> AddStatement, RDFLabel))
forall (f :: * -> *) a. Alternative f => f a -> f (Maybe a)
optional
        ( (,) ((RDFLabel -> RDFLabel -> AddStatement)
 -> RDFLabel -> (RDFLabel -> RDFLabel -> AddStatement, RDFLabel))
-> Parser N3State (RDFLabel -> RDFLabel -> AddStatement)
-> Parser
     N3State
     (RDFLabel -> (RDFLabel -> RDFLabel -> AddStatement, RDFLabel))
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Parser N3State (RDFLabel -> RDFLabel -> AddStatement)
-> Parser N3State (RDFLabel -> RDFLabel -> AddStatement)
forall s a. Parser s a -> Parser s a
lexeme (Parser N3State (RDFLabel -> RDFLabel -> AddStatement)
forall s. Parser s (RDFLabel -> RDFLabel -> AddStatement)
forwardExpr Parser N3State (RDFLabel -> RDFLabel -> AddStatement)
-> Parser N3State (RDFLabel -> RDFLabel -> AddStatement)
-> Parser N3State (RDFLabel -> RDFLabel -> AddStatement)
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> Parser N3State (RDFLabel -> RDFLabel -> AddStatement)
forall s. Parser s (RDFLabel -> RDFLabel -> AddStatement)
backwardExpr) Parser
  N3State
  (RDFLabel -> (RDFLabel -> RDFLabel -> AddStatement, RDFLabel))
-> N3Parser RDFLabel
-> Parser N3State (RDFLabel -> RDFLabel -> AddStatement, RDFLabel)
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> N3Parser RDFLabel -> N3Parser RDFLabel
forall s a. Parser s a -> Parser s a
lexeme N3Parser RDFLabel
expression )
  case Maybe (RDFLabel -> RDFLabel -> AddStatement, RDFLabel)
mpt of
    Maybe (RDFLabel -> RDFLabel -> AddStatement, RDFLabel)
Nothing -> RDFLabel -> N3Parser RDFLabel
forall (m :: * -> *) a. Monad m => a -> m a
return RDFLabel
i 
    Just (RDFLabel -> RDFLabel -> AddStatement
addFunc, RDFLabel
pt) -> do
      RDFLabel
bNode <- N3Parser RDFLabel
newBlankNode
      RDFLabel -> RDFLabel -> AddStatement
addFunc RDFLabel
bNode RDFLabel
pt RDFLabel
i
      RDFLabel -> N3Parser RDFLabel
forall (m :: * -> *) a. Monad m => a -> m a
return RDFLabel
bNode
  
{-
pathitem ::=		|	 "("  pathlist  ")" 
		|	 "["  propertylist  "]" 
		|	 "{"  formulacontent  "}" 
		|	boolean
		|	literal
		|	numericliteral
		|	quickvariable
		|	symbol

pathlist ::=		|	expression pathlist
		|	void

Need to think about how to handle formulae, since need to know the context
of the call to know where to add them.

TOOD: may include direct support for blank nodes here,
namely convert _:stringval -> Blank stringval since although
this should be done by symbol the types don't seem to easily match
up (at first blush anyway)
-}

pathItem :: N3Parser RDFLabel
pathItem :: N3Parser RDFLabel
pathItem = 
  String -> String -> N3Parser RDFLabel -> N3Parser RDFLabel
forall a. String -> String -> N3Parser a -> N3Parser a
br String
"(" String
")" N3Parser RDFLabel
pathList
  N3Parser RDFLabel -> N3Parser RDFLabel -> N3Parser RDFLabel
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> String -> String -> N3Parser RDFLabel -> N3Parser RDFLabel
forall a. String -> String -> N3Parser a -> N3Parser a
br String
"[" String
"]" N3Parser RDFLabel
propertyListBNode
  N3Parser RDFLabel -> N3Parser RDFLabel -> N3Parser RDFLabel
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> String -> String -> N3Parser RDFLabel -> N3Parser RDFLabel
forall a. String -> String -> N3Parser a -> N3Parser a
br String
"{" String
"}" N3Parser RDFLabel
formulaContent
  -- <|> try boolean
  N3Parser RDFLabel -> N3Parser RDFLabel -> N3Parser RDFLabel
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> N3Parser RDFLabel
boolean
  N3Parser RDFLabel -> N3Parser RDFLabel -> N3Parser RDFLabel
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> N3Parser RDFLabel
literal
  N3Parser RDFLabel -> N3Parser RDFLabel -> N3Parser RDFLabel
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> N3Parser RDFLabel
numericLiteral
  N3Parser RDFLabel -> N3Parser RDFLabel -> N3Parser RDFLabel
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> N3Parser RDFLabel
quickVariable
  N3Parser RDFLabel -> N3Parser RDFLabel -> N3Parser RDFLabel
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> String -> RDFLabel
Blank (String -> RDFLabel) -> N3Parser String -> N3Parser RDFLabel
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> (String -> N3Parser String
forall s. String -> Parser s String
string String
"_:" N3Parser String -> N3Parser String -> N3Parser String
forall (f :: * -> *) a b. Applicative f => f a -> f b -> f b
*> N3Parser String
n3NameStr) -- TODO a hack that needs fixing
  N3Parser RDFLabel -> N3Parser RDFLabel -> N3Parser RDFLabel
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> ScopedName -> RDFLabel
Res (ScopedName -> RDFLabel)
-> N3Parser ScopedName -> N3Parser RDFLabel
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> N3Parser ScopedName
n3symbol
  
{-  
we create a blank node for the list and return it, whilst
adding the list contents to the graph
-}
pathList :: N3Parser RDFLabel
pathList :: N3Parser RDFLabel
pathList = do
  [RDFLabel]
cts <- N3Parser RDFLabel -> Parser N3State [RDFLabel]
forall (f :: * -> *) a. Alternative f => f a -> f [a]
many (N3Parser RDFLabel -> N3Parser RDFLabel
forall s a. Parser s a -> Parser s a
lexeme N3Parser RDFLabel
expression)
  RDFLabel
eNode <- ScopedName -> N3Parser RDFLabel
operatorLabel ScopedName
rdfNil
  case [RDFLabel]
cts of
    [] -> RDFLabel -> N3Parser RDFLabel
forall (m :: * -> *) a. Monad m => a -> m a
return RDFLabel
eNode
      
    (RDFLabel
c:[RDFLabel]
cs) -> do
      RDFLabel
sNode <- N3Parser RDFLabel
newBlankNode
      RDFLabel
first <- ScopedName -> N3Parser RDFLabel
operatorLabel ScopedName
rdfFirst
      RDFLabel -> RDFLabel -> AddStatement
addStatement RDFLabel
sNode RDFLabel
first RDFLabel
c
      RDFLabel
lNode <- (RDFLabel -> RDFLabel -> N3Parser RDFLabel)
-> RDFLabel -> [RDFLabel] -> N3Parser RDFLabel
forall (t :: * -> *) (m :: * -> *) b a.
(Foldable t, Monad m) =>
(b -> a -> m b) -> b -> t a -> m b
foldM RDFLabel -> RDFLabel -> N3Parser RDFLabel
addElem RDFLabel
sNode [RDFLabel]
cs
      RDFLabel
rest <- ScopedName -> N3Parser RDFLabel
operatorLabel ScopedName
rdfRest
      RDFLabel -> RDFLabel -> AddStatement
addStatement RDFLabel
lNode RDFLabel
rest RDFLabel
eNode
      RDFLabel -> N3Parser RDFLabel
forall (m :: * -> *) a. Monad m => a -> m a
return RDFLabel
sNode

    where      
      addElem :: RDFLabel -> RDFLabel -> N3Parser RDFLabel
addElem RDFLabel
prevNode RDFLabel
curElem = do
        RDFLabel
bNode <- N3Parser RDFLabel
newBlankNode
        RDFLabel
first <- ScopedName -> N3Parser RDFLabel
operatorLabel ScopedName
rdfFirst
        RDFLabel
rest <- ScopedName -> N3Parser RDFLabel
operatorLabel ScopedName
rdfRest
        RDFLabel -> RDFLabel -> AddStatement
addStatement RDFLabel
prevNode RDFLabel
rest RDFLabel
bNode
        RDFLabel -> RDFLabel -> AddStatement
addStatement RDFLabel
bNode RDFLabel
first RDFLabel
curElem
        RDFLabel -> N3Parser RDFLabel
forall (m :: * -> *) a. Monad m => a -> m a
return RDFLabel
bNode
        
{-
formulacontent ::=		|	statementlist

statementlist ::=		|	statement statementtail
		|	void
statementtail ::=		|	 "."  statementlist
		|	void
-}

restoreState :: N3State -> N3Parser N3State
restoreState :: N3State -> Parser N3State N3State
restoreState N3State
origState = do
  N3State
oldState <- Parser N3State N3State
forall s. Parser s s
stGet
  (N3State -> N3State) -> Parser N3State ()
forall s. (s -> s) -> Parser s ()
stUpdate ((N3State -> N3State) -> Parser N3State ())
-> (N3State -> N3State) -> Parser N3State ()
forall a b. (a -> b) -> a -> b
$ N3State -> N3State -> N3State
forall a b. a -> b -> a
const N3State
origState { nodeGen :: Word32
nodeGen = N3State -> Word32
nodeGen N3State
oldState }
  N3State -> Parser N3State N3State
forall (m :: * -> *) a. Monad m => a -> m a
return N3State
oldState

{-
We create a subgraph and assign it to a blank node, returning the
blank node. At present it is a combination of the subgraph and formula
productions from the origial parser.

TODO: is it correct?
-}
formulaContent :: N3Parser RDFLabel
formulaContent :: N3Parser RDFLabel
formulaContent = do
  RDFLabel
bNode <- N3Parser RDFLabel
newBlankNode
  N3State
pstate <- Parser N3State N3State
forall s. Parser s s
stGet
  (N3State -> N3State) -> Parser N3State ()
forall s. (s -> s) -> Parser s ()
stUpdate ((N3State -> N3State) -> Parser N3State ())
-> (N3State -> N3State) -> Parser N3State ()
forall a b. (a -> b) -> a -> b
$ \N3State
st -> N3State
st { graphState :: RDFGraph
graphState = RDFGraph
emptyRDFGraph, thisNode :: RDFLabel
thisNode = RDFLabel
bNode }
  Parser N3State ()
statementList
  N3State
oldState <- N3State -> Parser N3State N3State
restoreState N3State
pstate
  (N3State -> N3State) -> Parser N3State ()
forall s. (s -> s) -> Parser s ()
stUpdate ((N3State -> N3State) -> Parser N3State ())
-> (N3State -> N3State) -> Parser N3State ()
forall a b. (a -> b) -> a -> b
$ (RDFGraph -> RDFGraph) -> N3State -> N3State
updateGraph ((RDFGraph -> RDFGraph) -> N3State -> N3State)
-> (RDFGraph -> RDFGraph) -> N3State -> N3State
forall a b. (a -> b) -> a -> b
$ Formula RDFLabel -> RDFGraph -> RDFGraph
forall lb. Label lb => Formula lb -> NSGraph lb -> NSGraph lb
setFormula (RDFLabel -> RDFGraph -> Formula RDFLabel
forall lb gr. lb -> gr -> LookupFormula lb gr
Formula RDFLabel
bNode (N3State -> RDFGraph
graphState N3State
oldState))
  RDFLabel -> N3Parser RDFLabel
forall (m :: * -> *) a. Monad m => a -> m a
return RDFLabel
bNode

-- | Process a sub graph and assign it to the given label.  
subgraph :: RDFLabel -> N3Parser RDFGraph
subgraph :: RDFLabel -> N3Parser RDFGraph
subgraph RDFLabel
this = do
  N3State
pstate <- Parser N3State N3State
forall s. Parser s s
stGet
  (N3State -> N3State) -> Parser N3State ()
forall s. (s -> s) -> Parser s ()
stUpdate ((N3State -> N3State) -> Parser N3State ())
-> (N3State -> N3State) -> Parser N3State ()
forall a b. (a -> b) -> a -> b
$ \N3State
st -> N3State
st { graphState :: RDFGraph
graphState = RDFGraph
emptyRDFGraph, thisNode :: RDFLabel
thisNode = RDFLabel
this }
  Parser N3State ()
statementsOptional    -- parse statements of formula
  N3State
oldState <- N3State -> Parser N3State N3State
restoreState N3State
pstate  
  RDFGraph -> N3Parser RDFGraph
forall (m :: * -> *) a. Monad m => a -> m a
return (RDFGraph -> N3Parser RDFGraph) -> RDFGraph -> N3Parser RDFGraph
forall a b. (a -> b) -> a -> b
$ N3State -> RDFGraph
graphState N3State
oldState
  
statementList :: N3Parser ()
statementList :: Parser N3State ()
statementList = Parser N3State [()] -> Parser N3State ()
forall (f :: * -> *) a. Applicative f => f a -> f ()
ignore (Parser N3State [()] -> Parser N3State ())
-> Parser N3State [()] -> Parser N3State ()
forall a b. (a -> b) -> a -> b
$ Parser N3State () -> Parser N3State () -> Parser N3State [()]
forall s a b. Parser s a -> Parser s b -> Parser s [a]
sepEndBy (Parser N3State () -> Parser N3State ()
forall s a. Parser s a -> Parser s a
lexeme Parser N3State ()
statement) Parser N3State ()
fullStop

{-
boolean ::=		|	 "@false" 
		|	 "@true" 
-}

boolean :: N3Parser RDFLabel
boolean :: N3Parser RDFLabel
boolean = ScopedName -> Text -> RDFLabel
makeDatatypedLiteral ScopedName
xsdBoolean (Text -> RDFLabel) -> N3Parser Text -> N3Parser RDFLabel
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> 
          (Text -> N3Parser Text
atWord Text
"false" N3Parser Text -> N3Parser Text -> N3Parser Text
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> Text -> N3Parser Text
atWord Text
"true")
          -- (try (atWord "false") <|> atWord "true")
           
{-
dtlang ::=		|	 "@"  langcode
		|	 "^^"  symbol
		|	void
literal ::=		|	string dtlang

langcode ::=	[a-z]+(-[a-z0-9]+)*

-}

literal :: N3Parser RDFLabel
literal :: N3Parser RDFLabel
literal = do
    Text
lit <- N3Parser Text
n3string
    Maybe (Either LanguageTag ScopedName)
opt <- Parser N3State (Either LanguageTag ScopedName)
-> Parser N3State (Maybe (Either LanguageTag ScopedName))
forall (f :: * -> *) a. Alternative f => f a -> f (Maybe a)
optional Parser N3State (Either LanguageTag ScopedName)
dtlang
    RDFLabel -> N3Parser RDFLabel
forall (m :: * -> *) a. Monad m => a -> m a
return (RDFLabel -> N3Parser RDFLabel) -> RDFLabel -> N3Parser RDFLabel
forall a b. (a -> b) -> a -> b
$ case Maybe (Either LanguageTag ScopedName)
opt of
               Just (Left LanguageTag
lcode)  -> Text -> LanguageTag -> RDFLabel
LangLit Text
lit LanguageTag
lcode
               Just (Right ScopedName
dtype) -> Text -> ScopedName -> RDFLabel
TypedLit Text
lit ScopedName
dtype
               Maybe (Either LanguageTag ScopedName)
_                  -> Text -> RDFLabel
Lit Text
lit
  
dtlang :: N3Parser (Either LanguageTag ScopedName)
dtlang :: Parser N3State (Either LanguageTag ScopedName)
dtlang = 
  (Char -> Parser N3State Char
forall s. Char -> Parser s Char
char Char
'@' Parser N3State Char
-> Parser N3State (Either LanguageTag ScopedName)
-> Parser N3State (Either LanguageTag ScopedName)
forall (f :: * -> *) a b. Applicative f => f a -> f b -> f b
*> (LanguageTag -> Either LanguageTag ScopedName
forall a b. a -> Either a b
Left (LanguageTag -> Either LanguageTag ScopedName)
-> Parser N3State LanguageTag
-> Parser N3State (Either LanguageTag ScopedName)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Parser N3State LanguageTag
langcode))
  Parser N3State (Either LanguageTag ScopedName)
-> Parser N3State (Either LanguageTag ScopedName)
-> Parser N3State (Either LanguageTag ScopedName)
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> String -> N3Parser String
forall s. String -> Parser s String
string String
"^^" N3Parser String
-> Parser N3State (Either LanguageTag ScopedName)
-> Parser N3State (Either LanguageTag ScopedName)
forall (f :: * -> *) a b. Applicative f => f a -> f b -> f b
*> (ScopedName -> Either LanguageTag ScopedName
forall a b. b -> Either a b
Right (ScopedName -> Either LanguageTag ScopedName)
-> N3Parser ScopedName
-> Parser N3State (Either LanguageTag ScopedName)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> N3Parser ScopedName
n3symbol)

-- Note that toLangTag may fail since it does some extra
-- validation not done by the parser (mainly on the length of the
-- primary and secondary tags).
--
-- NOTE: This parser does not accept multiple secondary tags which RFC3066
-- does.
--
langcode :: N3Parser LanguageTag
langcode :: Parser N3State LanguageTag
langcode = do
    Text
h <- (Char -> Bool) -> Parser N3State Text
forall s. (Char -> Bool) -> Parser s Text
many1Satisfy Char -> Bool
isaz
    Maybe Text
mt <- Parser N3State Text -> Parser N3State (Maybe Text)
forall (f :: * -> *) a. Alternative f => f a -> f (Maybe a)
optional (Char -> Text -> Text
L.cons (Char -> Text -> Text)
-> Parser N3State Char -> Parser N3State (Text -> Text)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Char -> Parser N3State Char
forall s. Char -> Parser s Char
char Char
'-' Parser N3State (Text -> Text)
-> Parser N3State Text -> Parser N3State Text
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> (Char -> Bool) -> Parser N3State Text
forall s. (Char -> Bool) -> Parser s Text
many1Satisfy Char -> Bool
isaz09)
    let lbl :: Text
lbl = Text -> Text
L.toStrict (Text -> Text) -> Text -> Text
forall a b. (a -> b) -> a -> b
$ Text -> Text -> Text
L.append Text
h (Text -> Text) -> Text -> Text
forall a b. (a -> b) -> a -> b
$ Text -> Maybe Text -> Text
forall a. a -> Maybe a -> a
fromMaybe Text
L.empty Maybe Text
mt
    case Text -> Maybe LanguageTag
toLangTag Text
lbl of
        Just LanguageTag
lt -> LanguageTag -> Parser N3State LanguageTag
forall (m :: * -> *) a. Monad m => a -> m a
return LanguageTag
lt
        Maybe LanguageTag
_ -> String -> Parser N3State LanguageTag
forall (m :: * -> *) a. MonadFail m => String -> m a
fail (String
"Invalid language tag: " String -> String -> String
forall a. [a] -> [a] -> [a]
++ Text -> String
T.unpack Text
lbl) -- should this be failBad?
    
{-
decimal ::=	[-+]?[0-9]+(\.[0-9]+)?
double ::=	[-+]?[0-9]+(\.[0-9]+)?([eE][-+]?[0-9]+)
integer ::=	[-+]?[0-9]+
numericliteral ::=		|	decimal
		|	double
		|	integer

We actually support 1. for decimal values which isn't supported 
by the above production.

TODO: we could convert via something like

  maybeRead value :: Double >>= Just . toRDFLabel

which would mean we store the canonical XSD value in the
label, but it is not useful for the xsd:decimal case
since we currently don't have a Haskell type that
goes with it.
-}

numericLiteral :: N3Parser RDFLabel
numericLiteral :: N3Parser RDFLabel
numericLiteral =
  -- -- try (makeDatatypedLiteral xsdDouble <$> n3double)
  -- try (d2s <$> n3double)
  -- <|> try (makeDatatypedLiteral xsdDecimal <$> n3decimal)
  String -> RDFLabel
d2s (String -> RDFLabel) -> N3Parser String -> N3Parser RDFLabel
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> N3Parser String
n3double
  N3Parser RDFLabel -> N3Parser RDFLabel -> N3Parser RDFLabel
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> ScopedName -> Text -> RDFLabel
makeDatatypedLiteral ScopedName
xsdDecimal (Text -> RDFLabel) -> (String -> Text) -> String -> RDFLabel
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> Text
T.pack (String -> RDFLabel) -> N3Parser String -> N3Parser RDFLabel
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> N3Parser String
n3decimal
  N3Parser RDFLabel -> N3Parser RDFLabel -> N3Parser RDFLabel
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> ScopedName -> Text -> RDFLabel
makeDatatypedLiteral ScopedName
xsdInteger (Text -> RDFLabel) -> (String -> Text) -> String -> RDFLabel
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> Text
T.pack (String -> RDFLabel) -> N3Parser String -> N3Parser RDFLabel
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> N3Parser String
n3integer

n3sign :: N3Parser Char
n3sign :: Parser N3State Char
n3sign = Char -> Parser N3State Char
forall s. Char -> Parser s Char
char Char
'+' Parser N3State Char -> Parser N3State Char -> Parser N3State Char
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> Char -> Parser N3State Char
forall s. Char -> Parser s Char
char Char
'-'

n3integer :: N3Parser String
n3integer :: N3Parser String
n3integer = do
  Maybe Char
ms <- Parser N3State Char -> Parser N3State (Maybe Char)
forall (f :: * -> *) a. Alternative f => f a -> f (Maybe a)
optional Parser N3State Char
n3sign
  String
ds <- Parser N3State Char -> N3Parser String
forall (p :: * -> *) a. PolyParse p => p a -> p [a]
many1 Parser N3State Char
digit
  case Maybe Char
ms of
    Just Char
s -> String -> N3Parser String
forall (m :: * -> *) a. Monad m => a -> m a
return (String -> N3Parser String) -> String -> N3Parser String
forall a b. (a -> b) -> a -> b
$ Char
s Char -> String -> String
forall a. a -> [a] -> [a]
: String
ds
    Maybe Char
_ -> String -> N3Parser String
forall (m :: * -> *) a. Monad m => a -> m a
return String
ds

n3decimal :: N3Parser String
-- n3decimal = (++) <$> n3integer <*> ( (:) <$> char '.' <*> many1 digit )
n3decimal :: N3Parser String
n3decimal = String -> String -> String
forall a. [a] -> [a] -> [a]
(++) (String -> String -> String)
-> N3Parser String -> Parser N3State (String -> String)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> N3Parser String
n3integer Parser N3State (String -> String)
-> N3Parser String -> N3Parser String
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> ( (:) (Char -> String -> String)
-> Parser N3State Char -> Parser N3State (String -> String)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Char -> Parser N3State Char
forall s. Char -> Parser s Char
char Char
'.' Parser N3State (String -> String)
-> N3Parser String -> N3Parser String
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Parser N3State Char -> N3Parser String
forall (f :: * -> *) a. Alternative f => f a -> f [a]
many Parser N3State Char
digit )
           
n3double :: N3Parser String
n3double :: N3Parser String
n3double = String -> String -> String
forall a. [a] -> [a] -> [a]
(++) 
           (String -> String -> String)
-> N3Parser String -> Parser N3State (String -> String)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> N3Parser String
n3decimal 
           Parser N3State (String -> String)
-> N3Parser String -> N3Parser String
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> ( (:) (Char -> String -> String)
-> Parser N3State Char -> Parser N3State (String -> String)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> (Char -> Bool) -> Parser N3State Char
forall s. (Char -> Bool) -> Parser s Char
satisfy (Char -> String -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`elem` (String
"eE"::String)) Parser N3State (String -> String)
-> N3Parser String -> N3Parser String
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> N3Parser String
n3integer )

-- Convert a double, as returned by n3double, into it's
-- canonical XSD form. We assume that n3double returns
-- a syntactivally valid Double, so do not bother with reads here
--
d2s :: String -> RDFLabel
d2s :: String -> RDFLabel
d2s String
s = Double -> RDFLabel
forall a. ToRDFLabel a => a -> RDFLabel
toRDFLabel (String -> Double
forall a. Read a => String -> a
read String
s :: Double)

{-
propertylist ::=		|	verb object objecttail propertylisttail
		|	void
propertylisttail ::=		|	 ";"  propertylist
		|	void

-}

-- it's probably important that bNode is created *after*
-- processing the plist (mainly for the assumptions made by
-- formatting the output as N3; e.g. list/sequence ordering)
--
propertyListBNode :: N3Parser RDFLabel
propertyListBNode :: N3Parser RDFLabel
propertyListBNode = do
  [((RDFLabel -> RDFLabel -> AddStatement, RDFLabel), [RDFLabel])]
plist <- Parser
  N3State
  ((RDFLabel -> RDFLabel -> AddStatement, RDFLabel), [RDFLabel])
-> Parser N3State ()
-> Parser
     N3State
     [((RDFLabel -> RDFLabel -> AddStatement, RDFLabel), [RDFLabel])]
forall s a b. Parser s a -> Parser s b -> Parser s [a]
sepEndBy ((,) ((RDFLabel -> RDFLabel -> AddStatement, RDFLabel)
 -> [RDFLabel]
 -> ((RDFLabel -> RDFLabel -> AddStatement, RDFLabel), [RDFLabel]))
-> Parser N3State (RDFLabel -> RDFLabel -> AddStatement, RDFLabel)
-> Parser
     N3State
     ([RDFLabel]
      -> ((RDFLabel -> RDFLabel -> AddStatement, RDFLabel), [RDFLabel]))
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Parser N3State (RDFLabel -> RDFLabel -> AddStatement, RDFLabel)
-> Parser N3State (RDFLabel -> RDFLabel -> AddStatement, RDFLabel)
forall s a. Parser s a -> Parser s a
lexeme Parser N3State (RDFLabel -> RDFLabel -> AddStatement, RDFLabel)
verb Parser
  N3State
  ([RDFLabel]
   -> ((RDFLabel -> RDFLabel -> AddStatement, RDFLabel), [RDFLabel]))
-> Parser N3State [RDFLabel]
-> Parser
     N3State
     ((RDFLabel -> RDFLabel -> AddStatement, RDFLabel), [RDFLabel])
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Parser N3State [RDFLabel]
objectList) Parser N3State ()
semiColon
  RDFLabel
bNode <- N3Parser RDFLabel
newBlankNode
  let addList :: ((RDFLabel -> t -> a -> m b, t), t a) -> m ()
addList ((RDFLabel -> t -> a -> m b
addFunc,t
vrb),t a
items) = (a -> m b) -> t a -> m ()
forall (t :: * -> *) (m :: * -> *) a b.
(Foldable t, Monad m) =>
(a -> m b) -> t a -> m ()
mapM_ (RDFLabel -> t -> a -> m b
addFunc RDFLabel
bNode t
vrb) t a
items
  [((RDFLabel -> RDFLabel -> AddStatement, RDFLabel), [RDFLabel])]
-> (((RDFLabel -> RDFLabel -> AddStatement, RDFLabel), [RDFLabel])
    -> Parser N3State ())
-> Parser N3State ()
forall (t :: * -> *) (m :: * -> *) a b.
(Foldable t, Monad m) =>
t a -> (a -> m b) -> m ()
forM_ [((RDFLabel -> RDFLabel -> AddStatement, RDFLabel), [RDFLabel])]
plist ((RDFLabel -> RDFLabel -> AddStatement, RDFLabel), [RDFLabel])
-> Parser N3State ()
forall (t :: * -> *) (m :: * -> *) t a b.
(Foldable t, Monad m) =>
((RDFLabel -> t -> a -> m b, t), t a) -> m ()
addList
  RDFLabel -> N3Parser RDFLabel
forall (m :: * -> *) a. Monad m => a -> m a
return RDFLabel
bNode

propertyListWith :: RDFLabel -> N3Parser ()
propertyListWith :: AddStatement
propertyListWith RDFLabel
subj = 
  let -- term = lexeme verb >>= objectListWith subj
      term :: Parser N3State ()
term = Parser N3State (RDFLabel -> RDFLabel -> AddStatement, RDFLabel)
-> Parser N3State (RDFLabel -> RDFLabel -> AddStatement, RDFLabel)
forall s a. Parser s a -> Parser s a
lexeme Parser N3State (RDFLabel -> RDFLabel -> AddStatement, RDFLabel)
verb Parser N3State (RDFLabel -> RDFLabel -> AddStatement, RDFLabel)
-> ((RDFLabel -> RDFLabel -> AddStatement, RDFLabel)
    -> Parser N3State ())
-> Parser N3State ()
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= \(RDFLabel -> RDFLabel -> AddStatement
addFunc, RDFLabel
vrb) -> AddStatement -> Parser N3State ()
objectListWith (RDFLabel -> RDFLabel -> AddStatement
addFunc RDFLabel
subj RDFLabel
vrb)
  in Parser N3State [()] -> Parser N3State ()
forall (f :: * -> *) a. Applicative f => f a -> f ()
ignore (Parser N3State [()] -> Parser N3State ())
-> Parser N3State [()] -> Parser N3State ()
forall a b. (a -> b) -> a -> b
$ Parser N3State () -> Parser N3State () -> Parser N3State [()]
forall s a b. Parser s a -> Parser s b -> Parser s [a]
sepEndBy Parser N3State ()
term Parser N3State ()
semiColon
  
{-
object ::=		|	expression
objecttail ::=		|	 ","  object objecttail
		|	void

We change the production rule from objecttail to objectlist for lists of
objects (may change back).

-}

object :: N3Parser RDFLabel
object :: N3Parser RDFLabel
object = N3Parser RDFLabel -> N3Parser RDFLabel
forall s a. Parser s a -> Parser s a
lexeme N3Parser RDFLabel
expression

objectList :: N3Parser [RDFLabel]
objectList :: Parser N3State [RDFLabel]
objectList = N3Parser RDFLabel -> Parser N3State () -> Parser N3State [RDFLabel]
forall (p :: * -> *) a sep. PolyParse p => p a -> p sep -> p [a]
sepBy1 N3Parser RDFLabel
object Parser N3State ()
comma

objectWith :: AddStatement -> N3Parser ()
objectWith :: AddStatement -> Parser N3State ()
objectWith AddStatement
addFunc = N3Parser RDFLabel
object N3Parser RDFLabel -> AddStatement -> Parser N3State ()
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= AddStatement
addFunc 

objectListWith :: AddStatement -> N3Parser ()
objectListWith :: AddStatement -> Parser N3State ()
objectListWith AddStatement
addFunc =
  Parser N3State [()] -> Parser N3State ()
forall (f :: * -> *) a. Applicative f => f a -> f ()
ignore (Parser N3State [()] -> Parser N3State ())
-> Parser N3State [()] -> Parser N3State ()
forall a b. (a -> b) -> a -> b
$ Parser N3State () -> Parser N3State () -> Parser N3State [()]
forall (p :: * -> *) a sep. PolyParse p => p a -> p sep -> p [a]
sepBy1 (AddStatement -> Parser N3State ()
objectWith AddStatement
addFunc) Parser N3State ()
comma

{-
objectList1 :: N3Parser [RDFLabel]
objectList1 = sepBy1 object comma
-}

{-
verb ::=		|	 "<=" 
		|	 "=" 
		|	 "=>" 
		|	 "@a" 
		|	 "@has"  expression
		|	 "@is"  expression  "@of" 
		|	expression

-}

verb :: N3Parser (RDFLabel -> RDFLabel -> AddStatement, RDFLabel)
verb :: Parser N3State (RDFLabel -> RDFLabel -> AddStatement, RDFLabel)
verb = 
  -- we check reverse first so that <= is tried before looking for a URI via expression rule
  (,) RDFLabel -> RDFLabel -> AddStatement
addStatementRev (RDFLabel -> (RDFLabel -> RDFLabel -> AddStatement, RDFLabel))
-> N3Parser RDFLabel
-> Parser N3State (RDFLabel -> RDFLabel -> AddStatement, RDFLabel)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> N3Parser RDFLabel
verbReverse
  Parser N3State (RDFLabel -> RDFLabel -> AddStatement, RDFLabel)
-> Parser N3State (RDFLabel -> RDFLabel -> AddStatement, RDFLabel)
-> Parser N3State (RDFLabel -> RDFLabel -> AddStatement, RDFLabel)
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> (,) RDFLabel -> RDFLabel -> AddStatement
addStatement (RDFLabel -> (RDFLabel -> RDFLabel -> AddStatement, RDFLabel))
-> N3Parser RDFLabel
-> Parser N3State (RDFLabel -> RDFLabel -> AddStatement, RDFLabel)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> N3Parser RDFLabel
verbForward

-- those verbs for which subject is on the right and object on the left
verbReverse :: N3Parser RDFLabel
verbReverse :: N3Parser RDFLabel
verbReverse =
  String -> N3Parser String
forall s. String -> Parser s String
string String
"<=" N3Parser String -> N3Parser RDFLabel -> N3Parser RDFLabel
forall (f :: * -> *) a b. Applicative f => f a -> f b -> f b
*> ScopedName -> N3Parser RDFLabel
operatorLabel ScopedName
logImplies
  N3Parser RDFLabel -> N3Parser RDFLabel -> N3Parser RDFLabel
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> N3Parser Text
-> N3Parser Text -> N3Parser RDFLabel -> N3Parser RDFLabel
forall s lbr rbr a.
Parser s lbr -> Parser s rbr -> Parser s a -> Parser s a
between (Text -> N3Parser Text
atWord Text
"is") (Text -> N3Parser Text
atWord Text
"of") (N3Parser RDFLabel -> N3Parser RDFLabel
forall s a. Parser s a -> Parser s a
lexeme N3Parser RDFLabel
expression)

{-
  try (string "<=") *> operatorLabel logImplies
  <|> between (try (atWord "is")) (atWord "of") (lexeme expression)
-}

-- those verbs with subject on the left and object on the right
verbForward :: N3Parser RDFLabel
verbForward :: N3Parser RDFLabel
verbForward =  
  -- (try (string "=>") *> operatorLabel logImplies)
  (String -> N3Parser String
forall s. String -> Parser s String
string String
"=>" N3Parser String -> N3Parser RDFLabel -> N3Parser RDFLabel
forall (f :: * -> *) a b. Applicative f => f a -> f b -> f b
*> ScopedName -> N3Parser RDFLabel
operatorLabel ScopedName
logImplies)
  N3Parser RDFLabel -> N3Parser RDFLabel -> N3Parser RDFLabel
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> (String -> N3Parser String
forall s. String -> Parser s String
string String
"=" N3Parser String -> N3Parser RDFLabel -> N3Parser RDFLabel
forall (f :: * -> *) a b. Applicative f => f a -> f b -> f b
*> ScopedName -> N3Parser RDFLabel
operatorLabel ScopedName
owlSameAs)
  -- <|> (try (atWord "a") *> operatorLabel rdfType)
  N3Parser RDFLabel -> N3Parser RDFLabel -> N3Parser RDFLabel
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> (Text -> N3Parser Text
atWord Text
"a" N3Parser Text -> N3Parser RDFLabel -> N3Parser RDFLabel
forall (f :: * -> *) a b. Applicative f => f a -> f b -> f b
*> ScopedName -> N3Parser RDFLabel
operatorLabel ScopedName
rdfType)
  N3Parser RDFLabel -> N3Parser RDFLabel -> N3Parser RDFLabel
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> (Text -> N3Parser Text
atWord Text
"has" N3Parser Text -> N3Parser RDFLabel -> N3Parser RDFLabel
forall (f :: * -> *) a b. Applicative f => f a -> f b -> f b
*> N3Parser RDFLabel -> N3Parser RDFLabel
forall s a. Parser s a -> Parser s a
lexeme N3Parser RDFLabel
expression)
  N3Parser RDFLabel -> N3Parser RDFLabel -> N3Parser RDFLabel
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> N3Parser RDFLabel -> N3Parser RDFLabel
forall s a. Parser s a -> Parser s a
lexeme N3Parser RDFLabel
expression

{-
universal ::=		|	 "@forAll"  symbol_csl

TODO: what needs to be done to support universal quantification
-}
universal :: N3Parser ()
universal :: Parser N3State ()
universal = 
  -- try (atWord "forAll") *> 
  Text -> N3Parser Text
atWord Text
"forAll" N3Parser Text -> Parser N3State () -> Parser N3State ()
forall (f :: * -> *) a b. Applicative f => f a -> f b -> f b
*> 
  String -> Parser N3State ()
forall (p :: * -> *) a. PolyParse p => String -> p a
failBad String
"universal (@forAll) currently unsupported." 
  -- will be something like: *> symbolCsl

--------------------------------------------------------------------------------
--
--  Copyright (c) 2003, Graham Klyne, 2009 Vasili I Galchin,
--    2011, 2012, 2013, 2014, 2018, 2020 Douglas Burke
--  All rights reserved.
--
--  This file is part of Swish.
--
--  Swish is free software; you can redistribute it and/or modify
--  it under the terms of the GNU General Public License as published by
--  the Free Software Foundation; either version 2 of the License, or
--  (at your option) any later version.
--
--  Swish is distributed in the hope that it will be useful,
--  but WITHOUT ANY WARRANTY; without even the implied warranty of
--  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
--  GNU General Public License for more details.
--
--  You should have received a copy of the GNU General Public License
--  along with Swish; if not, write to:
--    The Free Software Foundation, Inc.,
--    59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
--
--------------------------------------------------------------------------------