packages feed

spdx 0.0.1.0 → 0.1.0.0

raw patch · 16 files changed

+840/−655 lines, 16 filesdep +xmldep ~basenew-component:exe:spdx-dataPVP ok

version bump matches the API change (PVP)

Dependencies added: xml

Dependency ranges changed: base

API changes (from Hackage documentation)

- Distribution.SPDX: EConjunction :: !LicenseExpression -> !LicenseExpression -> LicenseExpression
- Distribution.SPDX: EDisjunction :: !LicenseExpression -> !LicenseExpression -> LicenseExpression
- Distribution.SPDX: ELicense :: !Bool -> !(Either LicenseRef LicenseId) -> !(Maybe LicenseExceptionId) -> LicenseExpression
- Distribution.SPDX: LicenseRef :: !(Maybe String) -> !String -> LicenseRef
- Distribution.SPDX: data LicenseExpression
- Distribution.SPDX: data LicenseRef
- Distribution.SPDX: instance Eq Lic
- Distribution.SPDX: instance Ord Lic
- Distribution.SPDX: instance Read Lic
- Distribution.SPDX: instance Show Lic
- Distribution.SPDX: licenseExceptions :: [LicenseExceptionId]
- Distribution.SPDX: licenseIdentifiers :: [LicenseId]
- Distribution.SPDX: licenseRanges :: [[LicenseId]]
- Distribution.SPDX: lookupLicenseRange :: LicenseId -> [LicenseId]
- Distribution.SPDX: lrDocument :: LicenseRef -> !(Maybe String)
- Distribution.SPDX: lrLicense :: LicenseRef -> !String
- Distribution.SPDX: parseExpression :: String -> [LicenseExpression]
- Distribution.SPDX: satisfies :: LicenseExpression -> LicenseExpression -> Bool
- Distribution.SPDX: type LicenseExceptionId = String
- Distribution.SPDX: type LicenseId = String
- Distribution.SPDX: unsafeParseExpr :: String -> LicenseExpression
- Distribution.SPDX.LatticeSyntax: LBound :: Bool -> LatticeSyntax a
- Distribution.SPDX.LatticeSyntax: LJoin :: (LatticeSyntax a) -> (LatticeSyntax a) -> LatticeSyntax a
- Distribution.SPDX.LatticeSyntax: LMeet :: (LatticeSyntax a) -> (LatticeSyntax a) -> LatticeSyntax a
- Distribution.SPDX.LatticeSyntax: LVar :: a -> LatticeSyntax a
- Distribution.SPDX.LatticeSyntax: data LatticeSyntax a
- Distribution.SPDX.LatticeSyntax: dual :: LatticeSyntax a -> LatticeSyntax a
- Distribution.SPDX.LatticeSyntax: equivalent :: Eq a => LatticeSyntax a -> LatticeSyntax a -> Bool
- Distribution.SPDX.LatticeSyntax: freeVars :: LatticeSyntax a -> [a]
- Distribution.SPDX.LatticeSyntax: instance Alternative (Eval v)
- Distribution.SPDX.LatticeSyntax: instance Applicative (Eval v)
- Distribution.SPDX.LatticeSyntax: instance Applicative LatticeSyntax
- Distribution.SPDX.LatticeSyntax: instance Data a => Data (LatticeSyntax a)
- Distribution.SPDX.LatticeSyntax: instance Eq a => Eq (LatticeSyntax a)
- Distribution.SPDX.LatticeSyntax: instance Foldable LatticeSyntax
- Distribution.SPDX.LatticeSyntax: instance Functor (Eval v)
- Distribution.SPDX.LatticeSyntax: instance Functor LatticeSyntax
- Distribution.SPDX.LatticeSyntax: instance Monad (Eval v)
- Distribution.SPDX.LatticeSyntax: instance Monad LatticeSyntax
- Distribution.SPDX.LatticeSyntax: instance MonadPlus (Eval v)
- Distribution.SPDX.LatticeSyntax: instance Ord a => Ord (LatticeSyntax a)
- Distribution.SPDX.LatticeSyntax: instance Read a => Read (LatticeSyntax a)
- Distribution.SPDX.LatticeSyntax: instance Show a => Show (LatticeSyntax a)
- Distribution.SPDX.LatticeSyntax: instance Traversable LatticeSyntax
- Distribution.SPDX.LatticeSyntax: instance Typeable LatticeSyntax
- Distribution.SPDX.LatticeSyntax: preorder :: Eq a => LatticeSyntax a -> LatticeSyntax a -> Bool
- Distribution.SPDX.LatticeSyntax: satisfiable :: Eq a => LatticeSyntax a -> Bool
+ Data.SPDX: EConjunction :: !LicenseExpression -> !LicenseExpression -> LicenseExpression
+ Data.SPDX: EDisjunction :: !LicenseExpression -> !LicenseExpression -> LicenseExpression
+ Data.SPDX: ELicense :: !Bool -> !(Either LicenseRef LicenseId) -> !(Maybe LicenseExceptionId) -> LicenseExpression
+ Data.SPDX: LicenseRef :: !(Maybe String) -> !String -> LicenseRef
+ Data.SPDX: data LicenseExceptionId
+ Data.SPDX: data LicenseExpression
+ Data.SPDX: data LicenseId
+ Data.SPDX: data LicenseRef
+ Data.SPDX: getLicenseExceptionId :: LicenseExceptionId -> String
+ Data.SPDX: getLicenseId :: LicenseId -> String
+ Data.SPDX: instance Eq Lic
+ Data.SPDX: instance Ord Lic
+ Data.SPDX: instance Read Lic
+ Data.SPDX: instance Show Lic
+ Data.SPDX: isOsiApproved :: LicenseId -> Bool
+ Data.SPDX: licenseExceptions :: [LicenseExceptionId]
+ Data.SPDX: licenseIdentifiers :: [LicenseId]
+ Data.SPDX: licenseRanges :: [[LicenseId]]
+ Data.SPDX: licenses :: [(LicenseId, String, Bool)]
+ Data.SPDX: lookupLicenseRange :: LicenseId -> [LicenseId]
+ Data.SPDX: lrDocument :: LicenseRef -> !(Maybe String)
+ Data.SPDX: lrLicense :: LicenseRef -> !String
+ Data.SPDX: mkLicenseId :: String -> Maybe LicenseId
+ Data.SPDX: parseExpression :: String -> [LicenseExpression]
+ Data.SPDX: satisfies :: LicenseExpression -> LicenseExpression -> Bool
+ Data.SPDX: unsafeParseExpr :: String -> LicenseExpression
+ Data.SPDX.LatticeSyntax: LBound :: Bool -> LatticeSyntax a
+ Data.SPDX.LatticeSyntax: LJoin :: (LatticeSyntax a) -> (LatticeSyntax a) -> LatticeSyntax a
+ Data.SPDX.LatticeSyntax: LMeet :: (LatticeSyntax a) -> (LatticeSyntax a) -> LatticeSyntax a
+ Data.SPDX.LatticeSyntax: LVar :: a -> LatticeSyntax a
+ Data.SPDX.LatticeSyntax: data LatticeSyntax a
+ Data.SPDX.LatticeSyntax: dual :: LatticeSyntax a -> LatticeSyntax a
+ Data.SPDX.LatticeSyntax: equivalent :: Eq a => LatticeSyntax a -> LatticeSyntax a -> Bool
+ Data.SPDX.LatticeSyntax: freeVars :: LatticeSyntax a -> [a]
+ Data.SPDX.LatticeSyntax: instance Alternative (Eval v)
+ Data.SPDX.LatticeSyntax: instance Applicative (Eval v)
+ Data.SPDX.LatticeSyntax: instance Applicative LatticeSyntax
+ Data.SPDX.LatticeSyntax: instance Data a => Data (LatticeSyntax a)
+ Data.SPDX.LatticeSyntax: instance Eq a => Eq (LatticeSyntax a)
+ Data.SPDX.LatticeSyntax: instance Foldable LatticeSyntax
+ Data.SPDX.LatticeSyntax: instance Functor (Eval v)
+ Data.SPDX.LatticeSyntax: instance Functor LatticeSyntax
+ Data.SPDX.LatticeSyntax: instance Monad (Eval v)
+ Data.SPDX.LatticeSyntax: instance Monad LatticeSyntax
+ Data.SPDX.LatticeSyntax: instance MonadPlus (Eval v)
+ Data.SPDX.LatticeSyntax: instance Ord a => Ord (LatticeSyntax a)
+ Data.SPDX.LatticeSyntax: instance Read a => Read (LatticeSyntax a)
+ Data.SPDX.LatticeSyntax: instance Show a => Show (LatticeSyntax a)
+ Data.SPDX.LatticeSyntax: instance Traversable LatticeSyntax
+ Data.SPDX.LatticeSyntax: instance Typeable LatticeSyntax
+ Data.SPDX.LatticeSyntax: preorder :: Eq a => LatticeSyntax a -> LatticeSyntax a -> Bool
+ Data.SPDX.LatticeSyntax: satisfiable :: Eq a => LatticeSyntax a -> Bool

Files

README.md view
@@ -1,4 +1,4 @@-# sdpx +# sdpx  [![Build Status](https://travis-ci.org/phadej/spdx.svg?branch=master)](https://travis-ci.org/phadej/spdx) 
+ dev/Main.hs view
@@ -0,0 +1,55 @@+module Main (main) where++import Control.Applicative+import Data.List+import Data.Maybe+import Data.Traversable+import Text.XML.Light++simplify :: Element -> [[[String]]]+simplify el = +  let worksheets = filter isWorksheetElement $ childrenElements el+      Just tables = traverse tableFromWorksheet worksheets+  in map tableElements tables++toElem :: Content -> Maybe Element+toElem (Elem e) = Just e+toElem _        = Nothing++isElement :: String -> Element -> Bool+isElement name = (name ==) . qName . elName++isWorksheetElement :: Element -> Bool+isWorksheetElement = isElement "Worksheet"++childrenElements :: Element -> [Element]+childrenElements = mapMaybe toElem . elContent++tableFromWorksheet :: Element -> Maybe Element+tableFromWorksheet = listToMaybe . filter (isElement "Table") . childrenElements++textContent :: Content -> Maybe String+textContent (Text t) = Just $ cdData t+textContent _        = Nothing++extractData :: Element -> String+extractData el = maybe "" id $ do dataEl <- listToMaybe . filter (isElement "Data") . childrenElements $ el+                                  textEl <- listToMaybe $ elContent dataEl+                                  text <- textContent textEl+                                  return text++tableElements :: Element -> [[String]] +tableElements = map cells . filter (isElement "Row") . childrenElements+  where cells = map extractData . filter (isElement "Cell") . childrenElements++extractLicense :: [String] -> (String, String, Bool)+extractLicense row = (row !! 1, row !! 0, (row !! 4) == "YES")++main :: IO ()+main = do+  contents <- readFile "data/spdx_licenselist.xml"+  let Just el = parseXMLDoc contents+  let parsed = simplify el+  let licenses = filter (not . null) $ parsed !! 0+  f `mapM_` (sort $ map extractLicense licenses)+  where f (l, n, osi) = putStrLn $ "  , (LicenseId " ++ show l ++ ", " ++ show n ++ ", " ++ show osi ++ ")"
spdx.cabal view
@@ -1,5 +1,5 @@ name:                spdx-version:             0.0.1.0+version:             0.1.0.0 synopsis:            SPDX license expression language description:         Implementation of <http://spdx.org/sites/spdx/files/SPDX-2.0.pdf SPDX> related functionality. homepage:            https://github.com/phadej/spdx@@ -8,19 +8,24 @@ author:              Oleg Grenrus maintainer:          Oleg Grenrus <oleg.grenrus@iki.fi> copyright:           (c) 2015 Oleg Grenrus-category:            Distribution+category:            Data build-type:          Simple extra-source-files:  README.md cabal-version:       >=1.10 +flag developer+  description:       Whether to build development tools+  default:           False+  manual:            True+ library   default-language:    Haskell2010-  exposed-modules:     Distribution.SPDX,-                       Distribution.SPDX.LatticeSyntax-  other-modules:       Distribution.SPDX.Licenses,-                       Distribution.SPDX.Types,-                       Distribution.SPDX.Parser,-                       Distribution.SPDX.Ranges+  exposed-modules:     Data.SPDX,+                       Data.SPDX.LatticeSyntax+  other-modules:       Data.SPDX.Licenses,+                       Data.SPDX.Types,+                       Data.SPDX.Parser,+                       Data.SPDX.Ranges   other-extensions:    CPP                        DeriveFunctor,                        GeneralizedNewtypeDeriving,@@ -39,7 +44,16 @@   default-language:    Haskell2010   hs-source-dirs:      tests   ghc-options:         -Wall-  build-depends:       base              >=4.5  && <5,+  build-depends:       base              >=4.5  && <4.9,                        tasty             >=0.10 && <0.11,                        tasty-quickcheck  >=0.8  && <0.9,                        spdx++executable spdx-data+  if !flag(developer)+    buildable:         False+  main-is:             Main.hs+  default-language:    Haskell2010+  hs-source-dirs:      dev+  build-depends:       base              >=4.5  && <4.9,+                       xml               >=1.3  && <1.4
+ src/Data/SPDX.hs view
@@ -0,0 +1,70 @@+-- |+-- Module      : Data.SPDX+-- Description : SPDX licenses and expression language+-- Copyright   : (c) 2015 Oleg Grenrus+-- License     : BSD3+-- Maintainer  : Oleg Grenrus <oleg.grenrus@iki.fi>+--+module Data.SPDX (+  -- * Types+    LicenseId+  , getLicenseId+  , LicenseExceptionId+  , getLicenseExceptionId+  , LicenseRef(..)+  , LicenseExpression(..)+  -- * Data+  , licenses+  , licenseIdentifiers+  , mkLicenseId+  , isOsiApproved+  , licenseExceptions+  -- ** Ranges+  , licenseRanges+  , lookupLicenseRange+  -- * Parsing+  , parseExpression+  , unsafeParseExpr+  -- * Logic+  , satisfies+  ) where++import Data.SPDX.Types+import Data.SPDX.Ranges+import Data.SPDX.Licenses+import Data.SPDX.Parser+import Data.SPDX.LatticeSyntax++data Lic = Lic (Either LicenseRef LicenseId) (Maybe LicenseExceptionId)+  deriving (Eq, Ord, Show, Read)++exprToLSLic :: LicenseExpression -> LatticeSyntax Lic+exprToLSLic (ELicense False l e) = LVar (Lic l e)+exprToLSLic (ELicense True (Right l) e) = foldr1 LJoin $ map (\l' -> LVar $ Lic (Right l') e) $ lookupLicenseRange l+-- We don't know anything about newer license references+exprToLSLic (ELicense True (Left l) e) = LVar (Lic (Left l) e)+exprToLSLic (EConjunction a b) = LMeet (exprToLSLic a) (exprToLSLic b)+exprToLSLic (EDisjunction a b) = LJoin (exprToLSLic a) (exprToLSLic b)++-- |+--+-- @⟦ satisfies a b ⟧ ≡ a ≥ b ≡ a ∧ b = b @+--+-- >>> unsafeParseExpr "GPL-3.0" `satisfies` unsafeParseExpr "ISC AND MIT"+-- False+--+-- >>> unsafeParseExpr "Zlib" `satisfies` unsafeParseExpr "ISC AND MIT AND Zlib"+-- True+--+-- >>> unsafeParseExpr "(MIT OR GPL-2.0)" `satisfies` unsafeParseExpr "(ISC AND MIT)"+-- True+--+-- >>> unsafeParseExpr "(MIT AND GPL-2.0)" `satisfies` unsafeParseExpr "(MIT AND GPL-2.0)"+-- True+--+-- >>> unsafeParseExpr "(MIT AND GPL-2.0)" `satisfies` unsafeParseExpr "(ISC AND GPL-2.0)"+-- False+satisfies :: LicenseExpression -- ^ package license+          -> LicenseExpression -- ^ license policy+          -> Bool+satisfies a b = exprToLSLic b `preorder` exprToLSLic a
+ src/Data/SPDX/LatticeSyntax.hs view
@@ -0,0 +1,126 @@+{-# LANGUAGE DeriveFunctor #-}+{-# LANGUAGE GeneralizedNewtypeDeriving #-}+{-# LANGUAGE DeriveFoldable #-}+{-# LANGUAGE DeriveTraversable #-}+{-# LANGUAGE DeriveDataTypeable #-}+-- |+-- Module      : Data.SPDX.LatticeSyntax+-- Description : General lattice tools+-- Copyright   : (c) 2015 Oleg Grenrus+-- License     : BSD3+-- Maintainer  : Oleg Grenrus <oleg.grenrus@iki.fi>+--+-- Inspired by <http://www.well-typed.com/blog/2014/12/simple-smt-solver/ Simple SMT Solver>.+--+-- In future this module will probably be moved into separate package.+module Data.SPDX.LatticeSyntax (LatticeSyntax(..), dual, freeVars, equivalent, preorder, satisfiable) where++import Control.Applicative+import Control.Monad+import Control.Monad.Trans.State+import Data.Data+import Data.Foldable+import Data.Traversable+import Prelude hiding (all, or)++data LatticeSyntax a = LVar a+                     | LBound Bool+                     | LJoin (LatticeSyntax a) (LatticeSyntax a)+                     | LMeet (LatticeSyntax a) (LatticeSyntax a)+  deriving (Eq, Ord, Read, Show, Functor, Foldable, Traversable, Typeable, Data)++instance Applicative LatticeSyntax where+  pure  = return+  (<*>) = ap++instance Monad LatticeSyntax where+  return = LVar+  LVar x    >>= f = f x+  LBound b  >>= _ = LBound b+  LJoin a b >>= f = LJoin (a >>= f) (b >>= f)+  LMeet a b >>= f = LMeet (a >>= f) (b >>= f)++freeVars :: LatticeSyntax a -> [a]+freeVars = toList++dual :: LatticeSyntax a -> LatticeSyntax a+dual (LVar v) = LVar v+dual (LBound t) = LBound $ not t+dual (LJoin a b) = LMeet (dual a) (dual b)+dual (LMeet a b) = LJoin (dual a) (dual b)++-- | Test for equivalence.+--+-- >>> equivalent (LMeet (LVar 'a') (LVar 'b')) (LMeet (LVar 'b') (LVar 'a'))+-- True+--+-- >>> equivalent (LVar 'a') (LMeet (LVar 'a') (LVar 'a'))+-- True+--+-- >>> equivalent (LMeet (LVar 'a') (LVar 'b')) (LMeet (LVar 'b') (LVar 'b'))+-- False+equivalent :: Eq a => LatticeSyntax a -> LatticeSyntax a -> Bool+equivalent a b = all (uncurry (==)) . runEval $ p+  where p = (,) <$> evalLattice a <*> evalLattice b++-- | Test for preorder.+--+-- @ a ≤ b ⇔ a ∨ b ≡ b ⇔ a ≡ a ∧ b @+--+-- >>> preorder (LVar 'a' `LMeet` LVar 'b') (LVar 'a')+-- True+--+-- >>> preorder (LVar 'a') (LVar 'a' `LMeet` LVar 'b')+-- False+preorder :: Eq a => LatticeSyntax a -> LatticeSyntax a -> Bool+preorder a b = (a `LJoin` b) `equivalent` b++-- | Return `True` if for some variable assigment expression evaluates to `True`.+satisfiable :: Eq a => LatticeSyntax a -> Bool +satisfiable = or . runEval . evalLattice++newtype Eval v a = Eval { unEval :: StateT [(v, Bool)] [] a }+  deriving (Functor, Applicative, Alternative, Monad, MonadPlus)++runEval :: Eval v a -> [a]+runEval act = evalStateT (unEval act) []++evalLattice :: Eq v => LatticeSyntax v -> Eval v Bool+evalLattice (LVar v)    = guess v+evalLattice (LBound b)  = return b+evalLattice (LJoin a b) = evalLattice a ||^ evalLattice b+evalLattice (LMeet a b) = evalLattice a &&^ evalLattice b++guess :: Eq v => v -> Eval v Bool+guess v = Eval $ do+  st <- get+  let remember b = put ((v, b) : st) >> return b+  case lookup v st of+    Just b  -> return b+    Nothing -> remember True <|> remember False++-- From Control.Monad.Extra of extra++-- | Like @if@, but where the test can be monadic.+ifM :: Monad m => m Bool -> m a -> m a -> m a+ifM b t f = do b' <- b; if b' then t else f++-- | The lazy '||' operator lifted to a monad. If the first+--   argument evaluates to 'True' the second argument will not+--   be evaluated.+--+-- > Just True  ||^ undefined  == Just True+-- > Just False ||^ Just True  == Just True+-- > Just False ||^ Just False == Just False+(||^) :: Monad m => m Bool -> m Bool -> m Bool+(||^) a b = ifM a (return True) b++-- | The lazy '&&' operator lifted to a monad. If the first+--   argument evaluates to 'False' the second argument will not+--   be evaluated.+--+-- > Just False &&^ undefined  == Just False+-- > Just True  &&^ Just True  == Just True+-- > Just True  &&^ Just False == Just False+(&&^) :: Monad m => m Bool -> m Bool -> m Bool+(&&^) a b = ifM a b (return False)
+ src/Data/SPDX/Licenses.hs view
@@ -0,0 +1,352 @@+module Data.SPDX.Licenses (+    licenses+  , licenseIdentifiers+  , mkLicenseId+  , isOsiApproved+  , licenseExceptions+  ) where++import Data.Foldable+import Data.Maybe++import Data.SPDX.Types++licenseExceptions :: [LicenseExceptionId]+licenseExceptions = map LicenseExceptionId [+  "Autoconf-exception-2.0",+  "Autoconf-exception-3.0",+  "Bison-exception-2.2",+  "Classpath-exception-2.0",+  "eCos-exception-2.0",+  "Font-exception-2.0",+  "GCC-exception-2.0",+  "GCC-exception-3.1",+  "WxWindows-exception-3.1"+  ]++-- | A list of SPDX licenses identifiers.+--+-- See <http://spdx.org/licenses/>.+licenseIdentifiers :: [LicenseId]+licenseIdentifiers = map fstOf3 licenses++fstOf3 :: (a, b, c) -> a+fstOf3 (x,_,_) = x++--sndOf3 :: (a, b, c) -> b+--sndOf3 (_,x,_) = x++trdOf3 :: (a, b, c) -> c+trdOf3 (_,_,x) = x++-- | Lookup `LicenseId` by string representation+mkLicenseId :: String -> Maybe LicenseId+mkLicenseId str = find ((== str) . getLicenseId) licenseIdentifiers++-- | Whether license is OSI approved+--+-- See <http://opensource.org/licenses/alphabetical>+isOsiApproved :: LicenseId -> Bool+isOsiApproved l = trdOf3 $ fromJust $ find ((==l) . fstOf3) licenses++-- | A list of `LicenseId`, license name and whether the license is OSI approved.+--+-- See <http://spdx.org/licenses/>.+licenses :: [(LicenseId, String, Bool)]+licenses =+  [ (LicenseId "AAL", "Attribution Assurance License", True)+  , (LicenseId "ADSL", "Amazon Digital Services License", False)+  , (LicenseId "AFL-1.1", "Academic Free License v1.1", True)+  , (LicenseId "AFL-1.2", "Academic Free License v1.2", True)+  , (LicenseId "AFL-2.0", "Academic Free License v2.0", True)+  , (LicenseId "AFL-2.1", "Academic Free License v2.1", True)+  , (LicenseId "AFL-3.0", "Academic Free License v3.0", True)+  , (LicenseId "AGPL-1.0", "Affero General Public License v1.0", False)+  , (LicenseId "AGPL-3.0", "GNU Affero General Public License v3.0", True)+  , (LicenseId "AMDPLPA", "AMD's plpa_map.c License", False)+  , (LicenseId "AML", "Apple MIT License", False)+  , (LicenseId "AMPAS", "Academy of Motion Picture Arts and Sciences BSD", False)+  , (LicenseId "ANTLR-PD", "ANTLR Software Rights Notice", False)+  , (LicenseId "APAFML", "Adobe Postscript AFM License", False)+  , (LicenseId "APL-1.0", "Adaptive Public License 1.0", True)+  , (LicenseId "APSL-1.0", "Apple Public Source License 1.0", True)+  , (LicenseId "APSL-1.1", "Apple Public Source License 1.1", True)+  , (LicenseId "APSL-1.2", "Apple Public Source License 1.2", True)+  , (LicenseId "APSL-2.0", "Apple Public Source License 2.0", True)+  , (LicenseId "Abstyles", "Abstyles License", False)+  , (LicenseId "Adobe-2006", "Adobe Systems Incorporated Source Code License Agreement", False)+  , (LicenseId "Adobe-Glyph", "Adobe Glyph List License", False)+  , (LicenseId "Afmparse", "Afmparse License", False)+  , (LicenseId "Aladdin", "Aladdin Free Public License", False)+  , (LicenseId "Apache-1.0", "Apache License 1.0", False)+  , (LicenseId "Apache-1.1", "Apache License 1.1", True)+  , (LicenseId "Apache-2.0", "Apache License 2.0", True)+  , (LicenseId "Artistic-1.0", "Artistic License 1.0", True)+  , (LicenseId "Artistic-1.0-Perl", "Artistic License 1.0 (Perl)", True)+  , (LicenseId "Artistic-1.0-cl8", "Artistic License 1.0 w/clause 8", True)+  , (LicenseId "Artistic-2.0", "Artistic License 2.0", True)+  , (LicenseId "BSD-2-Clause", "BSD 2-clause \"Simplified\" License", True)+  , (LicenseId "BSD-2-Clause-FreeBSD", "BSD 2-clause FreeBSD License", False)+  , (LicenseId "BSD-2-Clause-NetBSD", "BSD 2-clause NetBSD License", False)+  , (LicenseId "BSD-3-Clause", "BSD 3-clause \"New\" or \"Revised\" License", True)+  , (LicenseId "BSD-3-Clause-Attribution", "BSD with attribution", False)+  , (LicenseId "BSD-3-Clause-Clear", "BSD 3-clause Clear License", False)+  , (LicenseId "BSD-3-Clause-LBNL", "Lawrence Berkeley National Labs BSD variant license", False)+  , (LicenseId "BSD-4-Clause", "BSD 4-clause \"Original\" or \"Old\" License", False)+  , (LicenseId "BSD-4-Clause-UC", "BSD-4-Clause (University of California-Specific)", False)+  , (LicenseId "BSD-Protection", "BSD Protection License", False)+  , (LicenseId "BSL-1.0", "Boost Software License 1.0", True)+  , (LicenseId "Bahyph", "Bahyph License", False)+  , (LicenseId "Barr", "Barr License", False)+  , (LicenseId "Beerware", "Beerware License", False)+  , (LicenseId "BitTorrent-1.0", "BitTorrent Open Source License v1.0", False)+  , (LicenseId "BitTorrent-1.1", "BitTorrent Open Source License v1.1", False)+  , (LicenseId "Borceux", "Borceux license", False)+  , (LicenseId "CATOSL-1.1", "Computer Associates Trusted Open Source License 1.1", True)+  , (LicenseId "CC-BY-1.0", "Creative Commons Attribution 1.0", False)+  , (LicenseId "CC-BY-2.0", "Creative Commons Attribution 2.0", False)+  , (LicenseId "CC-BY-2.5", "Creative Commons Attribution 2.5", False)+  , (LicenseId "CC-BY-3.0", "Creative Commons Attribution 3.0", False)+  , (LicenseId "CC-BY-4.0", "Creative Commons Attribution 4.0", False)+  , (LicenseId "CC-BY-NC-1.0", "Creative Commons Attribution Non Commercial 1.0", False)+  , (LicenseId "CC-BY-NC-2.0", "Creative Commons Attribution Non Commercial 2.0", False)+  , (LicenseId "CC-BY-NC-2.5", "Creative Commons Attribution Non Commercial 2.5", False)+  , (LicenseId "CC-BY-NC-3.0", "Creative Commons Attribution Non Commercial 3.0", False)+  , (LicenseId "CC-BY-NC-4.0", "Creative Commons Attribution Non Commercial 4.0", False)+  , (LicenseId "CC-BY-NC-ND-1.0", "Creative Commons Attribution Non Commercial No Derivatives 1.0", False)+  , (LicenseId "CC-BY-NC-ND-2.0", "Creative Commons Attribution Non Commercial No Derivatives 2.0", False)+  , (LicenseId "CC-BY-NC-ND-2.5", "Creative Commons Attribution Non Commercial No Derivatives 2.5", False)+  , (LicenseId "CC-BY-NC-ND-3.0", "Creative Commons Attribution Non Commercial No Derivatives 3.0", False)+  , (LicenseId "CC-BY-NC-ND-4.0", "Creative Commons Attribution Non Commercial No Derivatives 4.0", False)+  , (LicenseId "CC-BY-NC-SA-1.0", "Creative Commons Attribution Non Commercial Share Alike 1.0", False)+  , (LicenseId "CC-BY-NC-SA-2.0", "Creative Commons Attribution Non Commercial Share Alike 2.0", False)+  , (LicenseId "CC-BY-NC-SA-2.5", "Creative Commons Attribution Non Commercial Share Alike 2.5", False)+  , (LicenseId "CC-BY-NC-SA-3.0", "Creative Commons Attribution Non Commercial Share Alike 3.0", False)+  , (LicenseId "CC-BY-NC-SA-4.0", "Creative Commons Attribution Non Commercial Share Alike 4.0", False)+  , (LicenseId "CC-BY-ND-1.0", "Creative Commons Attribution No Derivatives 1.0", False)+  , (LicenseId "CC-BY-ND-2.0", "Creative Commons Attribution No Derivatives 2.0", False)+  , (LicenseId "CC-BY-ND-2.5", "Creative Commons Attribution No Derivatives 2.5", False)+  , (LicenseId "CC-BY-ND-3.0", "Creative Commons Attribution No Derivatives 3.0", False)+  , (LicenseId "CC-BY-ND-4.0", "Creative Commons Attribution No Derivatives 4.0", False)+  , (LicenseId "CC-BY-SA-1.0", "Creative Commons Attribution Share Alike 1.0", False)+  , (LicenseId "CC-BY-SA-2.0", "Creative Commons Attribution Share Alike 2.0", False)+  , (LicenseId "CC-BY-SA-2.5", "Creative Commons Attribution Share Alike 2.5", False)+  , (LicenseId "CC-BY-SA-3.0", "Creative Commons Attribution Share Alike 3.0", False)+  , (LicenseId "CC-BY-SA-4.0", "Creative Commons Attribution Share Alike 4.0", False)+  , (LicenseId "CC0-1.0", "Creative Commons Zero v1.0 Universal", False)+  , (LicenseId "CDDL-1.0", "Common Development and Distribution License 1.0", True)+  , (LicenseId "CDDL-1.1", "Common Development and Distribution License 1.1", False)+  , (LicenseId "CECILL-1.0", "CeCILL Free Software License Agreement v1.0", False)+  , (LicenseId "CECILL-1.1", "CeCILL Free Software License Agreement v1.1", False)+  , (LicenseId "CECILL-2.0", "CeCILL Free Software License Agreement v2.0", False)+  , (LicenseId "CECILL-B", "CeCILL-B Free Software License Agreement", False)+  , (LicenseId "CECILL-C", "CeCILL-C Free Software License Agreement", False)+  , (LicenseId "CNRI-Python", "CNRI Python License", True)+  , (LicenseId "CNRI-Python-GPL-Compatible", "CNRI Python Open Source GPL Compatible License Agreement", False)+  , (LicenseId "CPAL-1.0", "Common Public Attribution License 1.0", True)+  , (LicenseId "CPL-1.0", "Common Public License 1.0", True)+  , (LicenseId "CPOL-1.02", "Code Project Open License 1.02", False)+  , (LicenseId "CUA-OPL-1.0", "CUA Office Public License v1.0", True)+  , (LicenseId "Caldera", "Caldera License", False)+  , (LicenseId "ClArtistic", "Clarified Artistic License", False)+  , (LicenseId "Condor-1.1", "Condor Public License v1.1", False)+  , (LicenseId "Crossword", "Crossword License", False)+  , (LicenseId "Cube", "Cube License", False)+  , (LicenseId "D-FSL-1.0", "Deutsche Freie Software Lizenz", False)+  , (LicenseId "DOC", "DOC License", False)+  , (LicenseId "DSDP", "DSDP License", False)+  , (LicenseId "Dotseqn", "Dotseqn License", False)+  , (LicenseId "ECL-1.0", "Educational Community License v1.0", True)+  , (LicenseId "ECL-2.0", "Educational Community License v2.0", True)+  , (LicenseId "EFL-1.0", "Eiffel Forum License v1.0", True)+  , (LicenseId "EFL-2.0", "Eiffel Forum License v2.0", True)+  , (LicenseId "EPL-1.0", "Eclipse Public License 1.0", True)+  , (LicenseId "EUDatagrid", "EU DataGrid Software License", True)+  , (LicenseId "EUPL-1.0", "European Union Public License 1.0", False)+  , (LicenseId "EUPL-1.1", "European Union Public License 1.1", True)+  , (LicenseId "Entessa", "Entessa Public License v1.0", True)+  , (LicenseId "ErlPL-1.1", "Erlang Public License v1.1", False)+  , (LicenseId "Eurosym", "Eurosym License", False)+  , (LicenseId "FSFUL", "FSF Unlimited License", False)+  , (LicenseId "FSFULLR", "FSF Unlimited License (with License Retention)", False)+  , (LicenseId "FTL", "Freetype Project License", False)+  , (LicenseId "Fair", "Fair License", True)+  , (LicenseId "Frameworx-1.0", "Frameworx Open License 1.0", True)+  , (LicenseId "FreeImage", "FreeImage Public License v1.0", False)+  , (LicenseId "GFDL-1.1", "GNU Free Documentation License v1.1", False)+  , (LicenseId "GFDL-1.2", "GNU Free Documentation License v1.2", False)+  , (LicenseId "GFDL-1.3", "GNU Free Documentation License v1.3", False)+  , (LicenseId "GL2PS", "GL2PS License", False)+  , (LicenseId "GPL-1.0", "GNU General Public License v1.0 only", False)+  , (LicenseId "GPL-2.0", "GNU General Public License v2.0 only", True)+  , (LicenseId "GPL-3.0", "GNU General Public License v3.0 only", True)+  , (LicenseId "Giftware", "Giftware License", False)+  , (LicenseId "Glide", "3dfx Glide License", False)+  , (LicenseId "Glulxe", "Glulxe License", False)+  , (LicenseId "HPND", "Historic Permission Notice and Disclaimer", True)+  , (LicenseId "HaskellReport", "Haskell Language Report License", False)+  , (LicenseId "IBM-pibs", "IBM PowerPC Initialization and Boot Software", False)+  , (LicenseId "ICU", "ICU License", False)+  , (LicenseId "IJG", "Independent JPEG Group License", False)+  , (LicenseId "IPA", "IPA Font License", True)+  , (LicenseId "IPL-1.0", "IBM Public License v1.0", True)+  , (LicenseId "ISC", "ISC License", True)+  , (LicenseId "ImageMagick", "ImageMagick License", False)+  , (LicenseId "Imlib2", "Imlib2 License", False)+  , (LicenseId "Intel", "Intel Open Source License", True)+  , (LicenseId "Intel-ACPI", "Intel ACPI Software License Agreement", False)+  , (LicenseId "JSON", "JSON License", False)+  , (LicenseId "JasPer-2.0", "JasPer License", False)+  , (LicenseId "LGPL-2.0", "GNU Library General Public License v2 only", True)+  , (LicenseId "LGPL-2.1", "GNU Lesser General Public License v2.1 only", True)+  , (LicenseId "LGPL-3.0", "GNU Lesser General Public License v3.0 only", True)+  , (LicenseId "LPL-1.0", "Lucent Public License Version 1.0", True)+  , (LicenseId "LPL-1.02", "Lucent Public License v1.02", True)+  , (LicenseId "LPPL-1.0", "LaTeX Project Public License v1.0", False)+  , (LicenseId "LPPL-1.1", "LaTeX Project Public License v1.1", False)+  , (LicenseId "LPPL-1.2", "LaTeX Project Public License v1.2", False)+  , (LicenseId "LPPL-1.3a", "LaTeX Project Public License 1.3a", False)+  , (LicenseId "LPPL-1.3c", "LaTeX Project Public License v1.3c", True)+  , (LicenseId "Latex2e", "Latex2e License", False)+  , (LicenseId "Leptonica", "Leptonica License", False)+  , (LicenseId "Libpng", "libpng License", False)+  , (LicenseId "License Identifier", "Full name of License", False)+  , (LicenseId "MIT", "MIT License", True)+  , (LicenseId "MIT-CMU", "CMU License", False)+  , (LicenseId "MIT-advertising", "Enlightenment License (e16)", False)+  , (LicenseId "MIT-enna", "enna License", False)+  , (LicenseId "MIT-feh", "feh License", False)+  , (LicenseId "MITNFA", "MIT +no-false-attribs license", False)+  , (LicenseId "MPL-1.0", "Mozilla Public License 1.0", True)+  , (LicenseId "MPL-1.1", "Mozilla Public License 1.1", True)+  , (LicenseId "MPL-2.0", "Mozilla Public License 2.0", True)+  , (LicenseId "MPL-2.0-no-copyleft-exception", "Mozilla Public License 2.0 (no copyleft exception)", True)+  , (LicenseId "MS-PL", "Microsoft Public License", True)+  , (LicenseId "MS-RL", "Microsoft Reciprocal License", True)+  , (LicenseId "MTLL", "Matrix Template Library License", False)+  , (LicenseId "MakeIndex", "MakeIndex License", False)+  , (LicenseId "MirOS", "MirOS Licence", True)+  , (LicenseId "Motosoto", "Motosoto License", True)+  , (LicenseId "Multics", "Multics License", True)+  , (LicenseId "Mup", "Mup License", False)+  , (LicenseId "NASA-1.3", "NASA Open Source Agreement 1.3", True)+  , (LicenseId "NBPL-1.0", "Net Boolean Public License v1", False)+  , (LicenseId "NCSA", "University of Illinois/NCSA Open Source License", True)+  , (LicenseId "NGPL", "Nethack General Public License", True)+  , (LicenseId "NLPL", "No Limit Public License", False)+  , (LicenseId "NOSL", "Netizen Open Source License", False)+  , (LicenseId "NPL-1.0", "Netscape Public License v1.0", False)+  , (LicenseId "NPL-1.1", "Netscape Public License v1.1", False)+  , (LicenseId "NPOSL-3.0", "Non-Profit Open Software License 3.0", True)+  , (LicenseId "NRL", "NRL License", False)+  , (LicenseId "NTP", "NTP License", True)+  , (LicenseId "Naumen", "Naumen Public License", True)+  , (LicenseId "NetCDF", "NetCDF license", False)+  , (LicenseId "Newsletr", "Newsletr License", False)+  , (LicenseId "Nokia", "Nokia Open Source License", True)+  , (LicenseId "Noweb", "Noweb License", False)+  , (LicenseId "Nunit", "Nunit License", False)+  , (LicenseId "OCLC-2.0", "OCLC Research Public License 2.0", True)+  , (LicenseId "ODbL-1.0", "ODC Open Database License v1.0", False)+  , (LicenseId "OFL-1.0", "SIL Open Font License 1.0", False)+  , (LicenseId "OFL-1.1", "SIL Open Font License 1.1", True)+  , (LicenseId "OGTSL", "Open Group Test Suite License", True)+  , (LicenseId "OLDAP-1.1", "Open LDAP Public License v1.1", False)+  , (LicenseId "OLDAP-1.2", "Open LDAP Public License v1.2", False)+  , (LicenseId "OLDAP-1.3", "Open LDAP Public License v1.3", False)+  , (LicenseId "OLDAP-1.4", "Open LDAP Public License v1.4", False)+  , (LicenseId "OLDAP-2.0", "Open LDAP Public License v2.0 (or possibly 2.0A and 2.0B)", False)+  , (LicenseId "OLDAP-2.0.1", "Open LDAP Public License v2.0.1", False)+  , (LicenseId "OLDAP-2.1", "Open LDAP Public License v2.1", False)+  , (LicenseId "OLDAP-2.2", "Open LDAP Public License v2.2", False)+  , (LicenseId "OLDAP-2.2.1", "Open LDAP Public License v2.2.1", False)+  , (LicenseId "OLDAP-2.2.2", "Open LDAP Public License  2.2.2", False)+  , (LicenseId "OLDAP-2.3", "Open LDAP Public License v2.3", False)+  , (LicenseId "OLDAP-2.4", "Open LDAP Public License v2.4", False)+  , (LicenseId "OLDAP-2.5", "Open LDAP Public License v2.5", False)+  , (LicenseId "OLDAP-2.6", "Open LDAP Public License v2.6", False)+  , (LicenseId "OLDAP-2.7", "Open LDAP Public License v2.7", False)+  , (LicenseId "OLDAP-2.8", "Open LDAP Public License v2.8", False)+  , (LicenseId "OML", "Open Market License", False)+  , (LicenseId "OPL-1.0", "Open Public License v1.0", False)+  , (LicenseId "OSL-1.0", "Open Software License 1.0", True)+  , (LicenseId "OSL-1.1", "Open Software License 1.1", False)+  , (LicenseId "OSL-2.0", "Open Software License 2.0", True)+  , (LicenseId "OSL-2.1", "Open Software License 2.1", True)+  , (LicenseId "OSL-3.0", "Open Software License 3.0", True)+  , (LicenseId "OpenSSL", "OpenSSL License", False)+  , (LicenseId "PDDL-1.0", "ODC Public Domain Dedication & License 1.0", False)+  , (LicenseId "PHP-3.0", "PHP License v3.0", True)+  , (LicenseId "PHP-3.01", "PHP License v3.01", False)+  , (LicenseId "Plexus", "Plexus Classworlds License", False)+  , (LicenseId "PostgreSQL", "PostgreSQL License", True)+  , (LicenseId "Python-2.0", "Python License 2.0", True)+  , (LicenseId "QPL-1.0", "Q Public License 1.0", True)+  , (LicenseId "Qhull", "Qhull License", False)+  , (LicenseId "RHeCos-1.1", "Red Hat eCos Public License v1.1", False)+  , (LicenseId "RPL-1.1", "Reciprocal Public License 1.1", True)+  , (LicenseId "RPL-1.5", "Reciprocal Public License 1.5", True)+  , (LicenseId "RPSL-1.0", "RealNetworks Public Source License v1.0", True)+  , (LicenseId "RSCPL", "Ricoh Source Code Public License", True)+  , (LicenseId "Rdisc", "Rdisc License", False)+  , (LicenseId "Ruby", "Ruby License", False)+  , (LicenseId "SAX-PD", "Sax Public Domain Notice", False)+  , (LicenseId "SCEA", "SCEA Shared Source License", False)+  , (LicenseId "SGI-B-1.0", "SGI Free Software License B v1.0", False)+  , (LicenseId "SGI-B-1.1", "SGI Free Software License B v1.1", False)+  , (LicenseId "SGI-B-2.0", "SGI Free Software License B v2.0", False)+  , (LicenseId "SISSL", "Sun Industry Standards Source License v1.1", True)+  , (LicenseId "SISSL-1.2", "Sun Industry Standards Source License v1.2", False)+  , (LicenseId "SMLNJ", "Standard ML of New Jersey License", False)+  , (LicenseId "SNIA", "SNIA Public License 1.1", False)+  , (LicenseId "SPL-1.0", "Sun Public License v1.0", True)+  , (LicenseId "SWL", "Scheme Widget Library (SWL) Software License Agreement", False)+  , (LicenseId "Saxpath", "Saxpath License", False)+  , (LicenseId "SimPL-2.0", "Simple Public License 2.0", True)+  , (LicenseId "Sleepycat", "Sleepycat License", True)+  , (LicenseId "SugarCRM-1.1.3", "SugarCRM Public License v1.1.3", False)+  , (LicenseId "TCL", "TCL/TK License", False)+  , (LicenseId "TMate", "TMate Open Source License", False)+  , (LicenseId "TORQUE-1.1", "TORQUE v2.5+ Software License v1.1", False)+  , (LicenseId "TOSL", "Trusster Open Source License", False)+  , (LicenseId "Unicode-TOU", "Unicode Terms of Use", False)+  , (LicenseId "Unlicense", "The Unlicense", False)+  , (LicenseId "VOSTROM", "VOSTROM Public License for Open Source", False)+  , (LicenseId "VSL-1.0", "Vovida Software License v1.0", True)+  , (LicenseId "Vim", "Vim License", False)+  , (LicenseId "W3C", "W3C Software Notice and License (2002-12-31)", True)+  , (LicenseId "W3C-19980720", "W3C Software Notice and License (1998-07-20)", False)+  , (LicenseId "WTFPL", "Do What The F*ck You Want To Public License", False)+  , (LicenseId "Watcom-1.0", "Sybase Open Watcom Public License 1.0", True)+  , (LicenseId "Wsuipa", "Wsuipa License", False)+  , (LicenseId "X11", "X11 License", False)+  , (LicenseId "XFree86-1.1", "XFree86 License 1.1", False)+  , (LicenseId "XSkat", "XSkat License", False)+  , (LicenseId "Xerox", "Xerox License", False)+  , (LicenseId "Xnet", "X.Net License", True)+  , (LicenseId "YPL-1.0", "Yahoo! Public License v1.0", False)+  , (LicenseId "YPL-1.1", "Yahoo! Public License v1.1", False)+  , (LicenseId "ZPL-1.1", "Zope Public License 1.1", False)+  , (LicenseId "ZPL-2.0", "Zope Public License 2.0", True)+  , (LicenseId "ZPL-2.1", "Zope Public License 2.1", False)+  , (LicenseId "Zed", "Zed License", False)+  , (LicenseId "Zend-2.0", "Zend License v2.0", False)+  , (LicenseId "Zimbra-1.3", "Zimbra Public License v1.3", False)+  , (LicenseId "Zimbra-1.4", "Zimbra Public License v1.4", False)+  , (LicenseId "Zlib", "zlib License", True)+  , (LicenseId "bzip2-1.0.5", "bzip2 and libbzip2 License v1.0.5", False)+  , (LicenseId "bzip2-1.0.6", "bzip2 and libbzip2 License v1.0.6", False)+  , (LicenseId "diffmark", "diffmark license", False)+  , (LicenseId "dvipdfm", "dvipdfm License", False)+  , (LicenseId "eGenix", "eGenix.com Public License 1.1.0", False)+  , (LicenseId "gSOAP-1.3b", "gSOAP Public License v1.3b", False)+  , (LicenseId "gnuplot", "gnuplot License", False)+  , (LicenseId "iMatix", "iMatix Standard Function Library Agreement", False)+  , (LicenseId "libtiff", "libtiff License", False)+  , (LicenseId "mpich2", "mpich2 License", False)+  , (LicenseId "psfrag", "psfrag License", False)+  , (LicenseId "psutils", "psutils License", False)+  , (LicenseId "xinetd", "xinetd License", False)+  , (LicenseId "xpp", "XPP License", False)+  , (LicenseId "zlib-acknowledgement", "zlib/libpng License with Acknowledgement", False)+  ]
+ src/Data/SPDX/Parser.hs view
@@ -0,0 +1,87 @@+{-# LANGUAGE CPP #-}+module Data.SPDX.Parser (parseExpression, unsafeParseExpr) where++#ifndef MIN_VERSION_base+#define MIN_VERSION_base(x,y,z) 0+#endif++#if !MIN_VERSION_base(4, 8, 0)+import Control.Applicative+#endif++import Data.Char+import Text.ParserCombinators.ReadP++import Data.SPDX.Types+import Data.SPDX.Licenses (licenseIdentifiers, licenseExceptions)++license :: ReadP LicenseId+license = choice (map f licenseIdentifiers)+  where f l = l <$ string (getLicenseId l)++licenseException :: ReadP LicenseExceptionId+licenseException = choice (map f licenseExceptions)+  where f l = l <$ string (getLicenseExceptionId l)++elicense :: ReadP LicenseExpression+elicense = (\l -> ELicense False (Right l) Nothing) <$> license++elicenseWith :: ReadP LicenseExpression+elicenseWith = (\l e -> ELicense False (Right l) (Just e)) <$> license <* skipSpaces1 <* string "WITH" <* skipSpaces1 <*> licenseException++elicenseAndNewer :: ReadP LicenseExpression+elicenseAndNewer = (\l -> ELicense True (Right l) Nothing) <$> license <* char '+'++elicenseWithAndNewer :: ReadP LicenseExpression+elicenseWithAndNewer = (\l e -> ELicense True (Right l) (Just e)) <$> license <* char '+' <* string " WITH " <*> licenseException++elicenseRef :: ReadP LicenseExpression+elicenseRef = (\licId -> ELicense False (Left $ LicenseRef Nothing licId) Nothing) <$ string "LicenseRef-" <*> idString++elicenseDocRef :: ReadP LicenseExpression+elicenseDocRef = f <$ string "DocumentRef-" <*> idString <* char ':' <* string "LicenseRef-" <*> idString+  where f docId licId = ELicense False (Left $ LicenseRef (Just docId) licId) Nothing++idString :: ReadP String+idString = munch1 p+  where p '.' = True+        p '-' = True+        p c   = isAlphaNum c++skipSpaces1 :: ReadP ()+skipSpaces1 = () <$ char ' ' <* skipSpaces++parens :: ReadP a -> ReadP a+parens = between (char '(') (skipSpaces <* char ')')++terminal :: ReadP LicenseExpression+terminal = choice [ elicense+                  , elicenseWith+                  , elicenseAndNewer+                  , elicenseWithAndNewer+                  , elicenseRef+                  , elicenseDocRef+                  , parens expression+                  ]++conjunction :: ReadP LicenseExpression+conjunction = chainr1 terminal (EConjunction <$ skipSpaces1 <* string "AND" <* skipSpaces1)++disjunction :: ReadP LicenseExpression+disjunction = chainr1 conjunction (EDisjunction <$ skipSpaces1 <* string "OR" <* skipSpaces1)++expression :: ReadP LicenseExpression+expression = skipSpaces *> disjunction++-- | Parse SPDX License Expression+--+-- >>> parseExpression "LGPL-2.1 OR MIT"+-- [EDisjunction (ELicense False (Right (LicenseId "LGPL-2.1")) Nothing) (ELicense False (Right (LicenseId "MIT")) Nothing)]+parseExpression :: String -> [LicenseExpression]+parseExpression = map fst . readP_to_S (expression <* skipSpaces <* eof)++unsafeParseExpr :: String -> LicenseExpression+unsafeParseExpr s = f . parseExpression $ s+  where f []      = error $ "Failed parse of license expression: " ++ s+        f [l]     = l+        f (_:_:_) = error $ "Ambigious parse of license expression: " ++ s
+ src/Data/SPDX/Ranges.hs view
@@ -0,0 +1,47 @@+module Data.SPDX.Ranges (licenseRanges, lookupLicenseRange) where++import Data.Char+import Data.List+import Data.Maybe++import Data.SPDX.Types+import Data.SPDX.Licenses++licenseRanges :: [[LicenseId]]+licenseRanges = filter longerThanSingleton . map f $ prefixes+  where f p = filter (\l -> p `isPrefixOf` getLicenseId l && restIsNumber (getLicenseId l) p) licenseIdentifiers++-- | Lookup newer licenses we know about+--+-- >>> lookupLicenseRange $ fromJust $ mkLicenseId "MIT"+-- [LicenseId "MIT"]+--+-- >>> lookupLicenseRange $ fromJust $ mkLicenseId "GPL-2.0"+-- [LicenseId "GPL-2.0",LicenseId "GPL-3.0"]+--+-- >>> lookupLicenseRange $ fromJust $ mkLicenseId "LGPL-2.0"+-- [LicenseId "LGPL-2.0",LicenseId "LGPL-2.1",LicenseId "LGPL-3.0"]+lookupLicenseRange :: LicenseId -> [LicenseId]+lookupLicenseRange l = fromMaybe [l] $ lookup l ranges'++ranges' :: [(LicenseId, [LicenseId])]+ranges' = map (\r -> (head r, r)) . filter (not . nullOrSingleton) . concatMap tails $ licenseRanges++nullOrSingleton :: [a] -> Bool+nullOrSingleton []      = True+nullOrSingleton [_]     = True+nullOrSingleton (_:_:_) = False++restIsNumber :: String -> String -> Bool+restIsNumber l p = all (\c -> isDigit c || c == 'a' || c == 'b' || c == 'c' || c == '.') (drop (length p) l)++pref :: String -> String+pref = reverse . dropWhile (/= '-') . reverse++prefixes :: [String]+prefixes = nub (filter (not . null) $ map (pref . getLicenseId) licenseIdentifiers)++longerThanSingleton :: [a] -> Bool+longerThanSingleton []      = False+longerThanSingleton [_]     = False+longerThanSingleton (_:_:_) = True
+ src/Data/SPDX/Types.hs view
@@ -0,0 +1,38 @@+{-# LANGUAGE DeriveDataTypeable #-}+{-# LANGUAGE DeriveGeneric #-}+module Data.SPDX.Types (+    LicenseId(..)+  , getLicenseId+  , LicenseExceptionId(..)+  , getLicenseExceptionId+  , LicenseRef(..)+  , LicenseExpression(..)+  ) where++import Data.Data+import GHC.Generics++data LicenseRef = LicenseRef+  { lrDocument :: !(Maybe String)+  , lrLicense  :: !String+  }+  deriving (Eq, Ord, Show, Read, Typeable, Data, Generic)++-- | Opaque license identifier type.+newtype LicenseId = LicenseId String+  deriving (Eq, Ord, Show, Read, Typeable, Data, Generic)++getLicenseId :: LicenseId -> String+getLicenseId (LicenseId l) = l++-- | Opaque license exception identifier type.+newtype LicenseExceptionId = LicenseExceptionId String+  deriving (Eq, Ord, Show, Read, Typeable, Data, Generic)++getLicenseExceptionId :: LicenseExceptionId -> String+getLicenseExceptionId (LicenseExceptionId l) = l++data LicenseExpression = ELicense !Bool !(Either LicenseRef LicenseId) !(Maybe LicenseExceptionId)+                       | EConjunction !LicenseExpression !LicenseExpression+                       | EDisjunction !LicenseExpression !LicenseExpression+  deriving (Eq, Ord, Show, Read, Typeable, Data, Generic)
− src/Distribution/SPDX.hs
@@ -1,65 +0,0 @@--- |--- Module      : Distribution.SPDX--- Description : SPDX licenses and expression language--- Copyright   : (c) 2015 Oleg Grenrus--- License     : BSD3--- Maintainer  : Oleg Grenrus <oleg.grenrus@iki.fi>----module Distribution.SPDX (-  -- * Types-    LicenseId-  , LicenseExceptionId-  , LicenseRef(..)-  , LicenseExpression(..)-  -- * Data-  , licenseIdentifiers-  , licenseExceptions-  -- ** Ranges-  , licenseRanges-  , lookupLicenseRange-  -- * Parsing-  , parseExpression-  , unsafeParseExpr-  -- * Logic-  , satisfies-  ) where--import Distribution.SPDX.Types-import Distribution.SPDX.Ranges-import Distribution.SPDX.Licenses-import Distribution.SPDX.Parser-import Distribution.SPDX.LatticeSyntax--data Lic = Lic (Either LicenseRef String) (Maybe String)-  deriving (Eq, Ord, Show, Read)--exprToLSLic :: LicenseExpression -> LatticeSyntax Lic-exprToLSLic (ELicense False l e) = LVar (Lic l e)-exprToLSLic (ELicense True (Right l) e) = foldr1 LJoin $ map (\l' -> LVar $ Lic (Right l') e) $ lookupLicenseRange l--- We don't know anything about newer license references-exprToLSLic (ELicense True (Left l) e) = LVar (Lic (Left l) e)-exprToLSLic (EConjunction a b) = LMeet (exprToLSLic a) (exprToLSLic b)-exprToLSLic (EDisjunction a b) = LJoin (exprToLSLic a) (exprToLSLic b)---- |------ @⟦ satisfies a b ⟧ ≡ a ≥ b ≡ a ∧ b = b @------ >>> unsafeParseExpr "GPL-3.0" `satisfies` unsafeParseExpr "ISC AND MIT"--- False------ >>> unsafeParseExpr "Zlib" `satisfies` unsafeParseExpr "ISC AND MIT AND Zlib"--- True------ >>> unsafeParseExpr "(MIT OR GPL-2.0)" `satisfies` unsafeParseExpr "(ISC AND MIT)"--- True------ >>> unsafeParseExpr "(MIT AND GPL-2.0)" `satisfies` unsafeParseExpr "(MIT AND GPL-2.0)"--- True------ >>> unsafeParseExpr "(MIT AND GPL-2.0)" `satisfies` unsafeParseExpr "(ISC AND GPL-2.0)"--- False-satisfies :: LicenseExpression -- ^ package license-          -> LicenseExpression -- ^ license policy-          -> Bool-satisfies a b = exprToLSLic b `preorder` exprToLSLic a
− src/Distribution/SPDX/LatticeSyntax.hs
@@ -1,101 +0,0 @@-{-# LANGUAGE DeriveFunctor #-}-{-# LANGUAGE GeneralizedNewtypeDeriving #-}-{-# LANGUAGE DeriveFoldable #-}-{-# LANGUAGE DeriveTraversable #-}-{-# LANGUAGE DeriveDataTypeable #-}--- |--- Module      : Distribution.SPDX.LatticeSyntax--- Description : General lattice tools--- Copyright   : (c) 2015 Oleg Grenrus--- License     : BSD3--- Maintainer  : Oleg Grenrus <oleg.grenrus@iki.fi>------ Inspired by <http://www.well-typed.com/blog/2014/12/simple-smt-solver/ Simple SMT Solver>.------ In future this module will probably be moved into separate package.-module Distribution.SPDX.LatticeSyntax (LatticeSyntax(..), dual, freeVars, equivalent, preorder, satisfiable) where--import Control.Applicative-import Control.Monad-import Control.Monad.Trans.State-import Data.Data-import Data.Foldable-import Data.Traversable-import Prelude hiding (all, or)--data LatticeSyntax a = LVar a-                     | LBound Bool-                     | LJoin (LatticeSyntax a) (LatticeSyntax a)-                     | LMeet (LatticeSyntax a) (LatticeSyntax a)-  deriving (Eq, Ord, Read, Show, Functor, Foldable, Traversable, Typeable, Data)--instance Applicative LatticeSyntax where-  pure  = return-  (<*>) = ap--instance Monad LatticeSyntax where-  return = LVar-  LVar x    >>= f = f x-  LBound b  >>= _ = LBound b-  LJoin a b >>= f = LJoin (a >>= f) (b >>= f)-  LMeet a b >>= f = LMeet (a >>= f) (b >>= f)--freeVars :: LatticeSyntax a -> [a]-freeVars = toList--dual :: LatticeSyntax a -> LatticeSyntax a-dual (LVar v) = LVar v-dual (LBound t) = LBound $ not t-dual (LJoin a b) = LMeet (dual a) (dual b)-dual (LMeet a b) = LJoin (dual a) (dual b)---- | Test for equivalence.------ >>> equivalent (LMeet (LVar 'a') (LVar 'b')) (LMeet (LVar 'b') (LVar 'a'))--- True------ >>> equivalent (LVar 'a') (LMeet (LVar 'a') (LVar 'a'))--- True------ >>> equivalent (LMeet (LVar 'a') (LVar 'b')) (LMeet (LVar 'b') (LVar 'b'))--- False-equivalent :: Eq a => LatticeSyntax a -> LatticeSyntax a -> Bool-equivalent a b = all (uncurry (==)) . runEval $ p-  where p = (,) <$> evalLattice a <*> evalLattice b---- | Test for preorder.------ @ a ≤ b ⇔ a ∨ b ≡ b ⇔ a ≡ a ∧ b@------ >>> preorder (LVar 'a' `LMeet` LVar 'b') (LVar 'a')--- True------ >>> preorder (LVar 'a') (LVar 'a' `LMeet` LVar 'b')--- False-preorder :: Eq a => LatticeSyntax a -> LatticeSyntax a -> Bool-preorder a b = (a `LJoin` b) `equivalent` b---- | Return `True` if for some variable assigment expression evaluates to `True`.-satisfiable :: Eq a => LatticeSyntax a -> Bool -satisfiable = or . runEval . evalLattice--newtype Eval v a = Eval { unEval :: StateT [(v, Bool)] [] a }-  deriving (Functor, Applicative, Alternative, Monad, MonadPlus)--runEval :: Eval v a -> [a]-runEval act = evalStateT (unEval act) []--evalLattice :: Eq v => LatticeSyntax v -> Eval v Bool-evalLattice (LVar v)    = guess v-evalLattice (LBound b)  = return b-evalLattice (LJoin a b) = (||) <$> evalLattice a <*> evalLattice b-evalLattice (LMeet a b) = (&&) <$> evalLattice a <*> evalLattice b--guess :: Eq v => v -> Eval v Bool-guess v = Eval $ do-  st <- get-  let remember b = put ((v, b) : st) >> return b-  case lookup v st of-    Just b  -> return b-    Nothing -> remember True <|> remember False-
− src/Distribution/SPDX/Licenses.hs
@@ -1,322 +0,0 @@-module Distribution.SPDX.Licenses (LicenseId, LicenseExceptionId, licenseIdentifiers, licenseExceptions) where--import Distribution.SPDX.Types--import Data.List--licenseExceptions :: [LicenseExceptionId]-licenseExceptions = [-  "Autoconf-exception-2.0",-  "Autoconf-exception-3.0",-  "Bison-exception-2.2",-  "Classpath-exception-2.0",-  "eCos-exception-2.0",-  "Font-exception-2.0",-  "GCC-exception-2.0",-  "GCC-exception-3.1",-  "WxWindows-exception-3.1"-  ]---- | A list of SPDX licenses identifiers.------ See <http://spdx.org/licenses/>.-licenseIdentifiers :: [LicenseId]-licenseIdentifiers = sort $ [-  "Glide",-  "Abstyles",-  "AFL-1.1",-  "AFL-1.2",-  "AFL-2.0",-  "AFL-2.1",-  "AFL-3.0",-  "AMPAS",-  "APL-1.0",-  "Adobe-Glyph",-  "APAFML",-  "Adobe-2006",-  "AGPL-1.0",-  "Afmparse",-  "Aladdin",-  "ADSL",-  "AMDPLPA",-  "ANTLR-PD",-  "Apache-1.0",-  "Apache-1.1",-  "Apache-2.0",-  "AML",-  "APSL-1.0",-  "APSL-1.1",-  "APSL-1.2",-  "APSL-2.0",-  "Artistic-1.0",-  "Artistic-1.0-Perl",-  "Artistic-1.0-cl8",-  "Artistic-2.0",-  "AAL",-  "Bahyph",-  "Barr",-  "Beerware",-  "BitTorrent-1.0",-  "BitTorrent-1.1",-  "BSL-1.0",-  "Borceux",-  "BSD-2-Clause",-  "BSD-2-Clause-FreeBSD",-  "BSD-2-Clause-NetBSD",-  "BSD-3-Clause",-  "BSD-3-Clause-Clear",-  "BSD-4-Clause",-  "BSD-Protection",-  "BSD-3-Clause-Attribution",-  "BSD-4-Clause-UC",-  "bzip2-1.0.5",-  "bzip2-1.0.6",-  "Caldera",-  "CECILL-1.0",-  "CECILL-1.1",-  "CECILL-2.0",-  "CECILL-B",-  "CECILL-C",-  "ClArtistic",-  "MIT-CMU",-  "CNRI-Jython",-  "CNRI-Python",-  "CNRI-Python-GPL-Compatible",-  "CPOL-1.02",-  "CDDL-1.0",-  "CDDL-1.1",-  "CPAL-1.0",-  "CPL-1.0",-  "CATOSL-1.1",-  "Condor-1.1",-  "CC-BY-1.0",-  "CC-BY-2.0",-  "CC-BY-2.5",-  "CC-BY-3.0",-  "CC-BY-4.0",-  "CC-BY-ND-1.0",-  "CC-BY-ND-2.0",-  "CC-BY-ND-2.5",-  "CC-BY-ND-3.0",-  "CC-BY-ND-4.0",-  "CC-BY-NC-1.0",-  "CC-BY-NC-2.0",-  "CC-BY-NC-2.5",-  "CC-BY-NC-3.0",-  "CC-BY-NC-4.0",-  "CC-BY-NC-ND-1.0",-  "CC-BY-NC-ND-2.0",-  "CC-BY-NC-ND-2.5",-  "CC-BY-NC-ND-3.0",-  "CC-BY-NC-ND-4.0",-  "CC-BY-NC-SA-1.0",-  "CC-BY-NC-SA-2.0",-  "CC-BY-NC-SA-2.5",-  "CC-BY-NC-SA-3.0",-  "CC-BY-NC-SA-4.0",-  "CC-BY-SA-1.0",-  "CC-BY-SA-2.0",-  "CC-BY-SA-2.5",-  "CC-BY-SA-3.0",-  "CC-BY-SA-4.0",-  "CC0-1.0",-  "Crossword",-  "CUA-OPL-1.0",-  "Cube",-  "D-FSL-1.0",-  "diffmark",-  "WTFPL",-  "DOC",-  "Dotseqn",-  "DSDP",-  "dvipdfm",-  "EPL-1.0",-  "ECL-1.0",-  "ECL-2.0",-  "eGenix",-  "EFL-1.0",-  "EFL-2.0",-  "MIT-advertising",-  "MIT-enna",-  "Entessa",-  "ErlPL-1.1",-  "EUDatagrid",-  "EUPL-1.0",-  "EUPL-1.1",-  "Eurosym",-  "Fair",-  "MIT-feh",-  "Frameworx-1.0",-  "FreeImage",-  "FTL",-  "FSFUL",-  "FSFULLR",-  "Giftware",-  "GL2PS",-  "Glulxe",-  "AGPL-3.0",-  "GFDL-1.1",-  "GFDL-1.2",-  "GFDL-1.3",-  "GPL-1.0",-  "GPL-2.0",-  "GPL-3.0",-  "LGPL-2.1",-  "LGPL-3.0",-  "LGPL-2.0",-  "gnuplot",-  "gSOAP-1.3b",-  "HaskellReport",-  "HPND",-  "IBM-pibs",-  "IPL-1.0",-  "ICU",-  "ImageMagick",-  "iMatix",-  "Imlib2",-  "IJG",-  "Intel-ACPI",-  "Intel",-  "IPA",-  "ISC",-  "JasPer-2.0",-  "JSON",-  "LPPL-1.3a",-  "LPPL-1.0",-  "LPPL-1.1",-  "LPPL-1.2",-  "LPPL-1.3c",-  "Latex2e",-  "BSD-3-Clause-LBNL",-  "Leptonica",-  "Libpng",-  "libtiff",-  "LPL-1.02",-  "LPL-1.0",-  "MakeIndex",-  "MTLL",-  "MS-PL",-  "MS-RL",-  "MirOS",-  "MITNFA",-  "MIT",-  "Motosoto",-  "MPL-1.0",-  "MPL-1.1",-  "MPL-2.0",-  "MPL-2.0-no-copyleft-exception",-  "mpich2",-  "Multics",-  "Mup",-  "NASA-1.3",-  "Naumen",-  "NBPL-1.0",-  "NetCDF",-  "NGPL",-  "NOSL",-  "NPL-1.0",-  "NPL-1.1",-  "Newsletr",-  "NLPL",-  "Nokia",-  "NPOSL-3.0",-  "Noweb",-  "NRL",-  "NTP",-  "Nunit",-  "OCLC-2.0",-  "ODbL-1.0",-  "PDDL-1.0",-  "OGTSL",-  "OLDAP-2.2.2",-  "OLDAP-1.1",-  "OLDAP-1.2",-  "OLDAP-1.3",-  "OLDAP-1.4",-  "OLDAP-2.0",-  "OLDAP-2.0.1",-  "OLDAP-2.1",-  "OLDAP-2.2",-  "OLDAP-2.2.1",-  "OLDAP-2.3",-  "OLDAP-2.4",-  "OLDAP-2.5",-  "OLDAP-2.6",-  "OLDAP-2.7",-  "OLDAP-2.8",-  "OML",-  "OPL-1.0",-  "OSL-1.0",-  "OSL-1.1",-  "OSL-2.0",-  "OSL-2.1",-  "OSL-3.0",-  "OpenSSL",-  "PHP-3.0",-  "PHP-3.01",-  "Plexus",-  "PostgreSQL",-  "psfrag",-  "psutils",-  "Python-2.0",-  "QPL-1.0",-  "Qhull",-  "Rdisc",-  "RPSL-1.0",-  "RPL-1.1",-  "RPL-1.5",-  "RHeCos-1.1",-  "RSCPL",-  "RSA-MD",-  "Ruby",-  "SAX-PD",-  "Saxpath",-  "SCEA",-  "SWL",-  "SGI-B-1.0",-  "SGI-B-1.1",-  "SGI-B-2.0",-  "OFL-1.0",-  "OFL-1.1",-  "SimPL-2.0",-  "Sleepycat",-  "SNIA",-  "SMLNJ",-  "SugarCRM-1.1.3",-  "SISSL",-  "SISSL-1.2",-  "SPL-1.0",-  "Watcom-1.0",-  "TCL",-  "Unlicense",-  "TMate",-  "TORQUE-1.1",-  "TOSL",-  "Unicode-TOU",-  "UPL-1.0",-  "NCSA",-  "Vim",-  "VOSTROM",-  "VSL-1.0",-  "W3C-19980720",-  "W3C",-  "Wsuipa",-  "Xnet",-  "X11",-  "Xerox",-  "XFree86-1.1",-  "xinetd",-  "xpp",-  "XSkat",-  "YPL-1.0",-  "YPL-1.1",-  "Zed",-  "Zend-2.0",-  "Zimbra-1.3",-  "Zimbra-1.4",-  "Zlib",-  "zlib-acknowledgement",-  "ZPL-1.1",-  "ZPL-2.0",-  "ZPL-2.1"-  ]
− src/Distribution/SPDX/Parser.hs
@@ -1,81 +0,0 @@-{-# LANGUAGE CPP #-}-module Distribution.SPDX.Parser (parseExpression, unsafeParseExpr) where--#if !MIN_VERSION_base(4, 8, 0)-import Control.Applicative-#endif--import Data.Char-import Text.ParserCombinators.ReadP--import Distribution.SPDX.Types-import Distribution.SPDX.Licenses (licenseIdentifiers, licenseExceptions)--license :: ReadP LicenseId-license = choice (map string licenseIdentifiers)--licenseException :: ReadP LicenseExceptionId-licenseException = choice (map string licenseExceptions)--elicense :: ReadP LicenseExpression-elicense = (\l -> ELicense False (Right l) Nothing) <$> license--elicenseWith :: ReadP LicenseExpression-elicenseWith = (\l e -> ELicense False (Right l) (Just e)) <$> license <* skipSpaces1 <* string "WITH" <* skipSpaces1 <*> licenseException--elicenseAndNewer :: ReadP LicenseExpression-elicenseAndNewer = (\l -> ELicense True (Right l) Nothing) <$> license <* char '+'--elicenseWithAndNewer :: ReadP LicenseExpression-elicenseWithAndNewer = (\l e -> ELicense True (Right l) (Just e)) <$> license <* char '+' <* string " WITH " <*> licenseException--elicenseRef :: ReadP LicenseExpression-elicenseRef = (\licId -> ELicense False (Left $ LicenseRef Nothing licId) Nothing) <$ string "LicenseRef-" <*> idString--elicenseDocRef :: ReadP LicenseExpression-elicenseDocRef = f <$ string "DocumentRef-" <*> idString <* char ':' <* string "LicenseRef-" <*> idString-  where f docId licId = ELicense False (Left $ LicenseRef (Just docId) licId) Nothing--idString :: ReadP String-idString = munch1 p-  where p '.' = True-        p '-' = True-        p c   = isAlphaNum c--skipSpaces1 :: ReadP ()-skipSpaces1 = () <$ char ' ' <* skipSpaces--parens :: ReadP a -> ReadP a-parens = between (char '(') (skipSpaces <* char ')')--terminal :: ReadP LicenseExpression-terminal = choice [ elicense-                  , elicenseWith-                  , elicenseAndNewer-                  , elicenseWithAndNewer-                  , elicenseRef-                  , elicenseDocRef-                  , parens expression-                  ]--conjunction :: ReadP LicenseExpression-conjunction = chainr1 terminal (EConjunction <$ skipSpaces1 <* string "AND" <* skipSpaces1)--disjunction :: ReadP LicenseExpression-disjunction = chainr1 conjunction (EDisjunction <$ skipSpaces1 <* string "OR" <* skipSpaces1)--expression :: ReadP LicenseExpression-expression = skipSpaces *> disjunction---- | Parse SPDX License Expression------ >>> parseExpression "LGPL-2.1 OR MIT"--- [EDisjunction (ELicense False "LGPL-2.1" Nothing) (ELicense False "MIT" Nothing)]-parseExpression :: String -> [LicenseExpression]-parseExpression = map fst . readP_to_S (expression <* skipSpaces <* eof)--unsafeParseExpr :: String -> LicenseExpression-unsafeParseExpr s = f . parseExpression $ s-  where f []      = error $ "Failed parse of license expression: " ++ s-        f [l]     = l-        f (_:_:_) = error $ "Ambigious parse of license expression: " ++ s
− src/Distribution/SPDX/Ranges.hs
@@ -1,47 +0,0 @@-module Distribution.SPDX.Ranges (licenseRanges, lookupLicenseRange) where--import Data.Char-import Data.List-import Data.Maybe--import Distribution.SPDX.Types-import Distribution.SPDX.Licenses--licenseRanges :: [[LicenseId]]-licenseRanges = filter longerThanSingleton . map f $ prefixes-  where f p = filter (\l -> p `isPrefixOf` l && restIsNumber l p) licenseIdentifiers---- | Lookup newer licenses we know about------ >>> lookupLicenseRange "MIT"--- ["MIT"]------ >>> lookupLicenseRange "GPL-2.0"--- ["GPL-2.0","GPL-3.0"]------ >>> lookupLicenseRange "LGPL-2.0"--- ["LGPL-2.0","LGPL-2.1","LGPL-3.0"]-lookupLicenseRange :: LicenseId -> [LicenseId]-lookupLicenseRange l = fromMaybe [l] $ lookup l ranges'--ranges' :: [(LicenseId, [LicenseId])]-ranges' = map (\r -> (head r, r)) . filter (not . nullOrSingleton) . concatMap tails $ licenseRanges--nullOrSingleton :: [a] -> Bool-nullOrSingleton []      = True-nullOrSingleton [_]     = True-nullOrSingleton (_:_:_) = False--restIsNumber :: String -> String -> Bool-restIsNumber l p = all (\c -> isDigit c || c == 'a' || c == 'b' || c == 'c' || c == '.') (drop (length p) l)--pref :: String -> String-pref = reverse . dropWhile (/= '-') . reverse--prefixes :: [String]-prefixes = nub (filter (not . null) $ map pref licenseIdentifiers)--longerThanSingleton :: [a] -> Bool-longerThanSingleton []      = False-longerThanSingleton [_]     = False-longerThanSingleton (_:_:_) = True
− src/Distribution/SPDX/Types.hs
@@ -1,20 +0,0 @@-{-# LANGUAGE DeriveDataTypeable #-}-{-# LANGUAGE DeriveGeneric #-}-module Distribution.SPDX.Types where--import Data.Data-import GHC.Generics--data LicenseRef = LicenseRef-  { lrDocument :: !(Maybe String)-  , lrLicense  :: !String-  }-  deriving (Eq, Ord, Show, Read, Typeable, Data, Generic)--type LicenseId = String-type LicenseExceptionId = String--data LicenseExpression = ELicense !Bool !(Either LicenseRef LicenseId) !(Maybe LicenseExceptionId)-                       | EConjunction !LicenseExpression !LicenseExpression-                       | EDisjunction !LicenseExpression !LicenseExpression-  deriving (Eq, Ord, Show, Read, Typeable, Data, Generic)
tests/Tests.hs view
@@ -5,8 +5,8 @@ import Test.Tasty import Test.Tasty.QuickCheck as QC -import Distribution.SPDX-import Distribution.SPDX.LatticeSyntax+import Data.SPDX+import Data.SPDX.LatticeSyntax  main :: IO () main = defaultMain tests@@ -35,19 +35,29 @@                                , rangeUnit                                ] -simpleExprGen :: Gen String+simpleExprGen :: Gen LicenseId simpleExprGen = elements licenseIdentifiers  latticeSyntaxGen :: Gen (LatticeSyntax Char) latticeSyntaxGen = sized gen-  where var = elements "abcdef"-        gen 0 = LVar <$> var-        gen n = oneof [ LVar <$> var+  where var   = LVar <$> elements "abcdef"+        gen 0 = var+        gen n = oneof [ var                       , LMeet <$> gen' <*> gen'                       , LJoin <$> gen' <*> gen'                       ]           where gen' = gen (n `div` 2) +exprGen :: Gen LicenseExpression+exprGen = sized gen+  where sim   = ELicense <$> arbitrary <*> (Right <$> simpleExprGen) <*> (pure Nothing)+        gen 0 = sim+        gen n = oneof [ sim+                      , EDisjunction <$> gen' <*> gen'+                      , EConjunction <$> gen' <*> gen'+                      ]+          where gen' = gen (n `div` 2)+ simpleUnits :: TestTree simpleUnits = testGroup "Simple License Expressions"   [ invalidExpr "Invalid-Identifier"@@ -70,7 +80,7 @@   ]  rangeUnit :: TestTree-rangeUnit = QC.testProperty "calculated license ranges" $ once $ property $ sort licenseRanges == sort ranges+rangeUnit = QC.testProperty "calculated license ranges" $ once $ property $ sort (map (map getLicenseId) licenseRanges) == sort ranges  lsProps :: TestTree lsProps = testGroup "LatticeSyntax"@@ -82,13 +92,35 @@   , QC.testProperty "preorder reflexive" $ forAll latticeSyntaxGen $ \a -> a `preorder` a   ] +osiLicenseIds :: [LicenseId]+osiLicenseIds = filter isOsiApproved licenseIdentifiers++osiLicenseExpr :: LicenseExpression+osiLicenseExpr = foldr1 EConjunction $ map (\l -> ELicense False (Right l) Nothing) osiLicenseIds++isOsiApprovedExpr :: LicenseExpression -> Bool+isOsiApprovedExpr (ELicense _ (Left _) _) = False+isOsiApprovedExpr (ELicense _ _ (Just _)) = False+isOsiApprovedExpr (ELicense False (Right e) Nothing) = isOsiApproved e+isOsiApprovedExpr (ELicense True (Right e2) Nothing) = any isOsiApproved $ lookupLicenseRange e2+isOsiApprovedExpr (EConjunction e1 e2) = isOsiApprovedExpr e1 && isOsiApprovedExpr e2+isOsiApprovedExpr (EDisjunction e1 e2) = isOsiApprovedExpr e1 || isOsiApprovedExpr e2++isOsiApprovedExpr' :: LicenseExpression -> Bool+isOsiApprovedExpr' e = e `satisfies` osiLicenseExpr++scaleGen :: (Int -> Int) -> Gen a -> Gen a+scaleGen f g = sized (\n -> resize (f n) g)+ qcProps :: TestTree qcProps = testGroup "By Quickcheck"-  [ QC.testProperty "licence identifiers are valid licenses" $ forAll simpleExprGen $ valid+  [ QC.testProperty "licence identifiers are valid licenses" $ forAll simpleExprGen $ valid . getLicenseId+  , QC.testProperty "satisfies osi checked" $ forAll (scaleGen (`div` 2) exprGen) $+      \e -> isOsiApprovedExpr e == isOsiApprovedExpr' e -- Skip   , lsProps   ] -ranges :: [[LicenseId]]+ranges :: [[String]] ranges = [   [     "AFL-1.1",