Commits

Doug Burke committed c0947d5

Update to 0.3.2.0 as now remove pre-defined namespace prefixes for N3 parsing

  • Participants
  • Parent commits 88d753c

Comments (0)

Files changed (13)

+0.3.2.0:
+
+  - Swish.RDF.N3Parser:
+
+    - the parser no longer has a set of pre-defined namespaces with
+      the aim of reducing un-needed statements on output.
+
+  There is no API change worthy of a bump of the minor version but
+  the behavioural change is large enough to make it worth while.
+
 0.3.1.2:
 
   - Swish.RDF.RDFGraph:

File Swish/RDF/ClassRestrictionRule.hs

     , makeDatatypeRestriction, makeDatatypeRestrictionFn
     , makeRDFClassRestrictionRules
     , makeRDFDatatypeRestrictionRules
-    , falseGraph, falseGraphStr
+    , falseGraph, falseGraphStr       
     )
 where
 

File Swish/RDF/Datatype.hs

     , deleteIndex
     )
 
+-- used to add Show instances for structures during debugging
+-- but backed out again.
+--
+-- import Swish.Utils.ShowM (ShowM(..))
+
 import Data.Maybe( isJust, catMaybes )
 
 import Control.Monad( join, liftM )
 typeMkModifiers :: Datatype ex lb vn -> [OpenVarBindingModify lb vn]
 typeMkModifiers (Datatype dtv) = tvalMkMods dtv
 
--- |Get named axiom from Datatype value
+-- |Get the named axiom from a Datatype value.
 getTypeAxiom :: ScopedName -> Datatype ex lb vn -> Maybe (Formula ex)
 getTypeAxiom nam dt = getRulesetAxiom nam (typeRules dt)
 
--- |Get named rule from Datatype value
+-- |Get the named rule from a Datatype value.
 getTypeRule :: ScopedName -> Datatype ex lb vn -> Maybe (Rule ex)
-getTypeRule  nam dt = getRulesetRule  nam (typeRules dt)
+getTypeRule nam dt = getRulesetRule nam (typeRules dt)
 
--- |Get canonical form of datatype value
+-- |Get the canonical form of a datatype value.
 typeMkCanonicalForm :: Datatype ex lb vn -> String -> Maybe String
 typeMkCanonicalForm (Datatype dtv) = tvalMkCanonicalForm dtv
 
 --
 --  A datatype is specified with respect to (polymophic in) a given
 --  type of (syntactic) expression with which it may be used, and
---  a value type (whos existence is hidden as an existential type
---  within `DatatypeMap`.
+--  a value type (whose existence is hidden as an existential type
+--  within `DatatypeMap`).
 --
 --  (I tried hiding the value type with an internal existential
 --  declaration, but that wouldn't wash.  Hence this two-part
                                 --  value for @tvalRel@.
     }
 
+{-
+instance ShowM ex => Show (DatatypeVal ex vt lb vn) where
+  show dv = "DatatypeVal: " ++ show (tvalName dv) ++ "\n -> rules:\n" ++ show (tvalRules dv)
+-}
+
 --  Other accessor functions
 
 getDTRel ::
 getDTMod nam dtv =
     mapFindMaybe nam (LookupMap (tvalMod dtv))
 
--- |Get canonical form of datatype value, or @Nothing@.
+-- |Get the canonical form of a datatype value, or @Nothing@.
 --
 tvalMkCanonicalForm :: DatatypeVal ex vt lb vn -> String -> Maybe String
 tvalMkCanonicalForm dtv str = can
 --
 data DatatypeMap vt = DatatypeMap
     { mapL2V  :: String -> Maybe vt
-                            -- ^ Function to map lexical string to
-                            --   datatype value.  This effectively
+                            -- ^ Function to map a lexical string to
+                            --   the datatype value.  This effectively
                             --   defines the lexical space of the
                             --   datatype to be all strings for which
                             --   yield a value other than @Nothing@.

File Swish/RDF/N3Parser.hs

                       -> String       -- ^ input to be parsed
                       -> Either String a
 parseAnyfromString parser mbase input =
-  let pmap   = LookupMap prefixTable
+  let pmap   = LookupMap [] -- [Namespace "" "#"] -- [] -- emptyLookupMap -- LookupMap prefixTable
       muri   = fmap makeQNameScopedName mbase
       smap   = LookupMap $ specialTable muri
       pstate = N3State
 parseNameFromString =
     parseAnyfromString n3Name 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 = updateState $ \st -> st { prefixUris = LookupMap prefixTable } -- should append to existing map
+
 parsePrefixFromString :: String -> Either String Namespace
 parsePrefixFromString =
     parseAnyfromString p Nothing
       where
         p = do
+          addTestPrefixes
           pref <- n3Name
           st   <- getState
           return (getPrefixNs st pref)   -- map prefix to namespace
     parseAnyfromString lexUriRef Nothing
 
 parseURIref2FromString :: String -> Either String ScopedName
-parseURIref2FromString =
-    parseAnyfromString n3symbol Nothing
+parseURIref2FromString = 
+    parseAnyfromString (addTestPrefixes >> n3symbol) Nothing
     -- parseAnyfromString uriRef2 Nothing
 
 ----------------------------------------------------------------------
 getScopedNameURI' = showURI
 -- getScopedNameURI' = getScopedNameURI . makeUriScopedName . showURI
 
+-- ensure that the namespace for the scoped name is defined;
+-- based on setPrefix/addPrefix
+--
+setNamespace :: Namespace -> N3State -> N3State
+setNamespace ns st = 
+  let p' = mapReplaceOrAdd ns (prefixUris st)
+  in st { prefixUris = p' }
+  
+addNamespace :: ScopedName -> N3Parser ()
+addNamespace (ScopedName ns _) = updateState $ setNamespace ns
+
+-- updated to now make sure that the namespace for the label
+-- exists. is this overkill here?
+--
+-- TODO: this is to be cleaned up to avoid so much
+-- state access and avoid some unnescessary code
+--
 operatorLabel :: ScopedName -> N3Parser RDFLabel
 {-
 operatorLabel snam = do
   s <- getState
   return $ Res $ getPrefixScopedName s snam
+
+operatorLabel snam = (Res . flip getPrefixScopedName snam) <$> getState
+
 -}
-operatorLabel snam = (Res . flip getPrefixScopedName snam) <$> getState
+operatorLabel snam = do
+  addNamespace snam 
+  (Res . flip getPrefixScopedName snam) <$> getState
 
 {-
 Add statement to graph in N3 parser state.
 		|	 "@has"  expression
 		|	 "@is"  expression  "@of" 
 		|	expression
+
+Note that we need to ensure that the necesary namespaces
+are added to the store when we process a short-form, but
+we delegate that responsibility to operatorLabel.
+
 -}
 
 verb :: N3Parser (RDFLabel -> RDFLabel -> AddStatement, RDFLabel)

File Swish/RDF/RDFDatatypeXsdInteger.hs

 --  Implmentation of RDFDatatypeVal for xsd:integer
 ------------------------------------------------------------
 
--- |Define Datatype value for xsd:integer
+-- |Define Datatype value for @xsd:integer@.
+--
 --  Members of this datatype are positive or negative integer values.
 --
---  The lexical form consists of an option @+@ or @-@
+--  The lexical form consists of an optional @+@ or @-@
 --  followed by a sequence of decimal digits.
 --
 --  The canonical lexical form has leading zeros and @+@ sign removed.

File Swish/RDF/RDFProofContext.hs

     )
 
 import Swish.RDF.Vocabulary
-    ( namespaceRDF
-    , namespaceRDFS
-    , namespaceRDFD
+    ( namespaceRDFD
     , scopeRDF
     , scopeRDFS
     , scopeRDFD
 
 makeFormula :: Namespace -> String -> String -> RDFFormula
 makeFormula scope local gr =
-    makeRDFFormula scope local (prefixRDF++gr)
+    makeRDFFormula scope local gr
 
 requireAny :: [RDFVarBindingFilter] -> RDFVarBindingFilter
 requireAny = varFilterDisjunction
 --  Common definitions
 ------------------------------------------------------------
 
-prefixRDF :: String
-prefixRDF =
-    "@prefix rdf:  <" ++ nsURI namespaceRDF  ++ "> . \n" ++
-    "@prefix rdfs: <" ++ nsURI namespaceRDFS ++ "> . \n" ++
-    "@prefix rdfd: <" ++ nsURI namespaceRDFD ++ "> . \n" ++
-    " \n"
-
 ------------------------------------------------------------
 --  Define RDF axioms
 ------------------------------------------------------------

File Swish/RDF/RDFRuleset.hs

 --  This module defines some datatypes and functions that are
 --  used to define rules and rulesets over RDF graphs.
 --
+--  For the routines that accept a graph in N3 format, the following
+--  namespaces are pre-defined for use by the graph:
+--     `rdf:` and `rdfs:`.
+--
 --------------------------------------------------------------------------------
 
 module Swish.RDF.RDFRuleset
     ( Namespace(..)
     , ScopedName(..) )
 
-import Swish.RDF.Vocabulary
-    ( swishName )
+import Swish.RDF.Vocabulary (swishName, namespaceRDF, namespaceRDFS)
 
 {-
 import Swish.RDF.Proof
 --  Method for creating an RDF formula value from N3 text
 ------------------------------------------------------------
 
+prefixRDF :: String
+prefixRDF =
+    "@prefix rdf:  <" ++ nsURI namespaceRDF  ++ "> . \n" ++
+    "@prefix rdfs: <" ++ nsURI namespaceRDFS ++ "> . \n" ++
+    -- "@prefix rdfd: <" ++ nsURI namespaceRDFD ++ "> . \n" ++
+    " \n"
+
 -- |Helper function to parse a string containing Notation3
 --  and return the corresponding RDFGraph value.
+--
 makeRDFGraphFromN3String :: String -> RDFGraph
-makeRDFGraphFromN3String str = case parseN3fromString str of
+makeRDFGraphFromN3String str = case parseN3fromString (prefixRDF ++ str) of
     Left  msg -> error msg
     Right gr  -> gr
 

File Swish/RDF/Rule.hs

     ( LookupEntryClass(..), LookupMap(..)
     )
 
-import Swish.Utils.ShowM
-    ( ShowM(..) )
+import Swish.Utils.ShowM (ShowM(..))
 
 ------------------------------------------------------------
 --  Expressions

File Swish/RDF/Ruleset.hs

     , ScopedName(..)
     )
 
-import Swish.RDF.Rule
-    ( Formula(..), Rule(..) )
+import Swish.RDF.Rule (Formula(..), Rule(..))
 
 import Swish.Utils.LookupMap
     ( LookupEntryClass(..), LookupMap(..)
     , mapFindMaybe
     )
 
-import Data.Maybe
-    ( fromMaybe, listToMaybe, mapMaybe )
+{-
+Used for the Show instance of Ruleset, which was
+used for debugging but has been removed as not
+really needed by the general user.
+
+import Swish.Utils.ShowM (ShowM(..))
+import Data.List (intercalate)
+-}
+
+import Data.Maybe (fromMaybe, listToMaybe, mapMaybe)
 
 -- | Ruleset, having namespace, axioms and rules
 
     , rsRules     :: [Rule ex]
     }
 
+{-
+
+Used for debugging.
+
+instance (ShowM ex) => Show (Ruleset ex) where
+  show (Ruleset ns axs rls) = 
+    intercalate "\n" 
+    [ "Ruleset: " ++ show ns
+    , "Axioms:" ]
+    ++ (showsFormulae "\n" axs 
+       (intercalate "\n" ("Rules:" : map show rls))) ""
+-}
+
 instance Eq (Ruleset ex) where
     r1 == r2 = rsNamespace r1 == rsNamespace r2
 
 getRulesetRules :: Ruleset ex -> [Rule ex]
 getRulesetRules = rsRules
 
--- | Find a named axiom or rule in a ruleset or proof context
-
+-- | Find a named axiom in a ruleset.
 getRulesetAxiom :: ScopedName -> Ruleset ex -> Maybe (Formula ex)
 getRulesetAxiom nam rset =
     mapFindMaybe nam (LookupMap (getRulesetAxioms rset))
     -- listToMaybe $ filter ( (matchName nam) . formName ) $ getRulesetAxioms rset
 
+-- | Find a named rule in a ruleset. 
 getRulesetRule :: ScopedName -> Ruleset ex -> Maybe (Rule ex)
 getRulesetRule nam rset =
     mapFindMaybe nam (LookupMap (getRulesetRules rset))
     -- listToMaybe $ filter ( (matchName nam) . ruleName ) $ getRulesetRules rset
 
+-- | Find a named axiom or rule in a proof context.
 getContextAxiom :: ScopedName -> Formula ex -> [Ruleset ex] -> Formula ex
 getContextAxiom nam def rsets = fromMaybe def (getMaybeContextAxiom nam rsets)
     {-

File Swish/Utils/LookupMap.hs

 data LookupMap a = LookupMap [a]
   deriving (Functor, F.Foldable, T.Traversable)
 
+{- 
+TODO: could add
+
+instance Monoid (LookupMap a) where
+    mempty = LookupMap []
+    mappend = mapMerge
+
+but may need constraints on a, do not
+want to add instances at this time, and is
+it really useful? 
+
+-}
+
 gLM :: LookupMap a -> [a]
 gLM (LookupMap es) = es
 
 Name:               swish
-Version:            0.3.1.2
+Version:            0.3.2.0
 Stability:          experimental
 License:            LGPL
 License-file:       LICENSE 
   .
   * Complete, ready-to-run, command-line and script-driven programs.
   .
-  Major Changes:
+  Changes:
+  .
+  [Version 0.3.2.0] The N3 parser no longer assumes a set of pre-defined namespaces.
+  There is no API change worthy of a bump to the minor version number, but it
+  is a large-enough change in behaviour that I felt the need for the update.
   .
   [Version 0.3.1.2] 'Swish.RDF.RDFGraph.toRDFGraph' now sets up the
   namespace map of the graph based on the input labels (previously it

File tests/N3ParserTest.hs

     "@prefix base2 : <" ++ nsURI base2 ++ "> . \n" ++
     "@prefix base3 : <" ++ nsURI base3 ++ "> . \n"
 
+rdfPrefix :: String
+rdfPrefix = "@prefix rdf: <" ++ nsURI namespaceRDF ++ ">.\n"
+
 --  Single statement using <uri> form
 simpleN3Graph_g1_01 :: String
 simpleN3Graph_g1_01 =
 --  Literals with dataype and language
 simpleN3Graph_g17 :: String
 simpleN3Graph_g17 =
-    commonPrefixes ++
+    commonPrefixes ++ rdfPrefix ++ 
     " base1:s1 base1:p1 \"chat\"@fr . \n "                          ++
     " base2:s2 base2:p2 \"<br/>\"^^rdf:XMLLiteral . \n "            ++
     " base3:s3 base3:p3 \"<em>chat</em>\"^^rdf:XMLLiteral . \n "

File tests/RDFDatatypeXsdIntegerTest.hs

 
 import Control.Monad (unless)
 
-import Data.Maybe (isJust, fromMaybe)
+import Data.Maybe (isJust, isNothing, fromMaybe)
 
 
 ------------------------------------------------------------
 
 testNothing :: String -> Maybe a -> Test
 testNothing lab av =
-    TestCase ( assertBool ("testJust:"++lab) (not $ isJust av) )
+    TestCase ( assertBool ("testJust:"++lab) (isNothing av) )
 
 -- Compare lists and lists of lists and Maybe lists for set equivalence:
 
 testMaybeEqv lab a1 a2 =
     TestCase ( assertEqual ("testMaybeEqv:"++lab) ma1 ma2 )
     where
-        ma1 = (MaybeListTest a1)
-        ma2 = (MaybeListTest a2)
+        ma1 = MaybeListTest a1
+        ma2 = MaybeListTest a2
 
 ------------------------------------------------------------
 --  Misc values
 ------------------------------------------------------------
 
 xsd_int_name :: String -> ScopedName
-xsd_int_name nam  = ScopedName namespaceXsdInteger nam
+xsd_int_name = ScopedName namespaceXsdInteger 
 
 axiomXsdIntegerDT :: ScopedName
 axiomXsdIntegerDT       = xsd_int_name "dt"
   [ testEq  "testDatatype01" typeNameXsdInteger $
     typeName rdfDatatypeXsdInteger
   , testEq  "testDatatype02" namespaceXsdInteger $
-    rsNamespace (typeRules rdfDatatypeXsdInteger)
+    rsNamespace xsdIntRules
   , testEqv "testDatatype03" axiomsXsdInteger $
-    rsAxioms (typeRules rdfDatatypeXsdInteger)
+    rsAxioms xsdIntRules
   , testEqv "testDatatype04" rulesXsdInteger $
-    rsRules (typeRules rdfDatatypeXsdInteger)
+    rsRules xsdIntRules
   , testEq "testDatatype05" axiomXsdIntegerDT $
     formName (getXsdIntegerAxiom axiomXsdIntegerDT)
   , testEq "testDatatype06" ruleXsdIntegerAbs $
   String -> Maybe (RDFDatatypeMod Integer)
   -> [RDFVarBinding] -> [RDFVarBinding]
   -> Test
-testVmod2 = testVmodN [(Var "a"),(Var "b")]
-testVmod3 = testVmodN [(Var "a"),(Var "b"),(Var "c")]
-testVmod4 = testVmodN [(Var "a"),(Var "b"),(Var "c"),(Var "d")]
+testVmod2 = testVmodN [Var "a", Var "b"]
+testVmod3 = testVmodN [Var "a", Var "b", Var "c"]
+testVmod4 = testVmodN [Var "a", Var "b", Var "c", Var "d"]
 
 --  make various kinds of RDF variable bindings
 
 -- pvRules = makeRDFDatatypeRestrictionRules rdfDatatypeValXsdInteger gr
 pvRules = typeMkRules rdfDatatypeXsdInteger gr
     where
-        gr = (mkGraph pvRulesStr)
+        gr = mkGraph pvRulesStr
 
 pvRulesStr :: String
 pvRulesStr =