yaml-light-0.1.4/0000755000000000000000000000000011462102722011746 5ustar0000000000000000yaml-light-0.1.4/yaml-light.cabal0000644000000000000000000000353711462102722015011 0ustar0000000000000000-- yaml-light.cabal auto-generated by cabal init. For additional -- options, see -- http://www.haskell.org/cabal/release/cabal-latest/doc/users-guide/authors.html#pkg-descr. -- The name of the package. Name: yaml-light -- The package version. See the Haskell package versioning policy -- (http://www.haskell.org/haskellwiki/Package_versioning_policy) for -- standards guiding when and how versions should be incremented. Version: 0.1.4 -- A short (one-line) description of the package. Synopsis: A light-weight wrapper with utility functions around HsSyck -- A longer description of the package. Description: This package provides a light-weight algebraic data type representing parsed Yaml files. It is implemented as a more conveinent wrapper around the HsSyck package, and provides utility functions as well. -- The license under which the package is released. License: BSD3 -- The file containing the license text. License-file: LICENSE -- The package author(s). Author: Michael Ilseman -- An email address to which users can send suggestions, bug reports, -- and patches. Maintainer: michael ilseman gmail com -- A copyright notice. -- Copyright: Category: Data Build-type: Simple -- Extra files to be distributed with the package, such as examples or -- a README. -- Extra-source-files: -- Constraint on the version of Cabal needed to build this package. Cabal-version: >=1.2 Library -- Modules exported by the library. Exposed-modules: Data.Yaml.YamlLight -- Packages needed in order to build this package. Build-depends: HsSyck, base >=4 && <=5, bytestring, containers -- Modules not exported by this package. -- Other-modules: -- Extra tools (e.g. alex, hsc2hs, ...) needed to build the source. -- Build-tools: yaml-light-0.1.4/Setup.hs0000644000000000000000000000005611462102722013403 0ustar0000000000000000import Distribution.Simple main = defaultMain yaml-light-0.1.4/LICENSE0000644000000000000000000000276711462102722012767 0ustar0000000000000000Copyright (c)2010, Michael Ilseman All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name of Michael Ilseman nor the names of other contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. yaml-light-0.1.4/Data/0000755000000000000000000000000011462102722012617 5ustar0000000000000000yaml-light-0.1.4/Data/Yaml/0000755000000000000000000000000011462102722013521 5ustar0000000000000000yaml-light-0.1.4/Data/Yaml/YamlLight.hs0000644000000000000000000001732011462102722015752 0ustar0000000000000000----------------------------------------------------------------------------- -- | -- Module : Data.Yaml.YamlLight -- Copyright : Michael Ilseman (c) 2010 -- License : BSD-style (see the file LICENSE) -- -- Maintainer : michael ilseman gmail com -- Stability : provisional -- Portability : portable -- -- A light-weight wrapper with utility functions around HsSyck {-# LANGUAGE OverloadedStrings #-} module Data.Yaml.YamlLight ( -- * YamlLight data type YamlLight(..) -- * YamlLight versions of Syck functions , parseYaml, parseYamlFile, parseYamlBytes -- * YamlLight utility functions , fromYamlNode, lookupYL, lookupYLWith , combineSequencedMaps, combineMappedSequences, getTerminalsKeys -- ** Extractors , unSeq, unMap, unStr ) where import Control.Applicative -- import Data.Data import Data.List import Data.Maybe import Control.Arrow import qualified Data.Yaml.Syck as Syck import qualified Data.Map as Map import qualified Data.ByteString as ByteString {- | A light-weight, single ADT representation of a yaml document in contrast with what is provided by HsSyck. Note that the YMap is an actual Map from Data.Map, so behavior with respect to identical keys and ordering of entries will behave as Data.Map dictates. This behavior is also in compliance with the Yaml spec. If you currently rely on HsSyck's preservation of ordering, you can also consider representing such maps as sequences of single entry maps. See the examples of \"Ordered Mappings\" in the Yaml spec: . -} data YamlLight = YMap (Map.Map YamlLight YamlLight) | YSeq [YamlLight] | YStr ByteString.ByteString | YNil deriving (Show, Ord, Eq) convert :: (a -> Syck.YamlNode) -> (a -> YamlLight) convert f = fromYamlNode . f convertIO :: (a -> IO Syck.YamlNode) -> (a -> IO YamlLight) convertIO f yn = fromYamlNode <$> f yn -- | Parse a regular Haskell string parseYaml :: String -> IO YamlLight parseYaml = convertIO Syck.parseYaml -- | Given a file name, parse contents of file parseYamlFile :: String -> IO YamlLight parseYamlFile = convertIO Syck.parseYamlFile -- | Parse a ByteString buffer (this is faster) parseYamlBytes :: ByteString.ByteString -> IO YamlLight parseYamlBytes = convertIO Syck.parseYamlBytes -- | Convert a Syck YamlNode to a YamlLight fromYamlNode :: Syck.YamlNode -> YamlLight fromYamlNode = yamlElemToLight . Syck.n_elem yamlElemToLight :: Syck.YamlElem -> YamlLight yamlElemToLight (Syck.EMap ms) = YMap . Map.fromList . map (\(a,b) -> (fromYamlNode a, fromYamlNode b)) $ ms yamlElemToLight (Syck.ESeq s) = YSeq $ map fromYamlNode s yamlElemToLight (Syck.EStr buf) = YStr buf yamlElemToLight (Syck.ENil) = YNil -- | Lookup the key's corresponding value in a Map. Returns Nothing if the YamlLight is not a map, or if -- the key is not found lookupYL :: YamlLight -> YamlLight -> Maybe YamlLight lookupYL key (YMap m) = Map.lookup key m lookupYL _ _ = Nothing -- | General form of lookup. Will return the first element that satisfies predicate p, otherwise Nothing lookupYLWith :: (YamlLight -> Bool) -> YamlLight -> Maybe YamlLight lookupYLWith p (YMap m) = snd <$> (find (p . fst) $ Map.toList m) lookupYLWith _ _ = Nothing {- | Combine a sequence of YMaps into a list of (key,value) pairs. The ordering of the result preserves the ordering of the sequence, but the ordering of the individual maps is as Data.Map handles it. Example: @ - key1: val1 key2: val2 - key3: val3 @ Would become: @ [(key1,val1),(key2,val2),(key3,val3)] @ where key1 and key2 might be arranged differently as Data.Map would arrange them. This does not enforce uniqueness of keys across different maps. Any items of the sequence that are not maps will not be present in the output list. Returns Nothing if not called on a Sequence -} combineSequencedMaps :: YamlLight -> Maybe [(YamlLight, YamlLight)] combineSequencedMaps (YSeq ys) = Just . concatMap Map.assocs . catMaybes $ map unMap ys combineSequencedMaps _ = Nothing {- | Take a YamlLight that is a YMap of keys to YSeqs, and return a list of (key,elem) pairs, where elem is an element of the YSeq under key. Example: @ key1: [val1, val2, val3] key2: [val4, val5] @ Would become: @ [(key1,val1),(key1,val2),(key1,val3),(key2,val4),(key2,val5)] @ where the precise ordering of the key1 and key2 pairs depends on the ordering of Data.Map. Any values of keys that are not sequences will not appear in the output list. Returns Nothing if not called on a YMap. -} combineMappedSequences :: YamlLight -> Maybe [(YamlLight, YamlLight)] combineMappedSequences (YMap m) = Just . concatMap flattenTags . removeSndMaybes $ mapThenList unSeq m combineMappedSequences _ = Nothing mapThenList :: (b -> Maybe [c]) -> Map.Map a b -> [(a, Maybe [c])] mapThenList f m = Map.toList $ Map.map f m removeSndMaybes :: [(a,Maybe [b])] -> [(a,[b])] removeSndMaybes = map (second fromJust) . filter (isJust . snd) flattenTags :: (a,[b]) -> [(a,b)] flattenTags (a,bs) = map ((,) a) bs {- | Create a list of all the terminal YStrs in a YamlLight tree, and couple them with a list of all the keys above them. Example: @ - key1: key1_1: - \"str1\" - \"str2\" key1_2: - \"str2\" - \"str3\" - key2: \"str4\" - \"str5\" @ Would become: @ [(\"str1\",[key1_1, key1]), (\"str2\", [key1_1, key1]), (\"str2\", [key1_2, key1]), (\"str3\",[key1_2, key1]), (\"str4\",[key2]), (\"str5\",[]) @ -} getTerminalsKeys :: YamlLight -> [(ByteString.ByteString,[YamlLight])] getTerminalsKeys = getTerminalsKeys' [] getTerminalsKeys' :: [YamlLight] -> YamlLight -> [(ByteString.ByteString,[YamlLight])] getTerminalsKeys' hist (YStr s) = [(s,hist)] getTerminalsKeys' hist (YSeq s) = concatMap (getTerminalsKeys' hist) s getTerminalsKeys' hist (YMap m) = concat . Map.elems $ Map.mapWithKey (\k -> getTerminalsKeys' (k : hist)) m getTerminalsKeys' _ _ = [] -- | Get the contents of a sequence unSeq :: YamlLight -> Maybe [YamlLight] unSeq (YSeq s) = Just s unSeq _ = Nothing -- | Get the contents of a map unMap :: YamlLight -> Maybe (Map.Map YamlLight YamlLight) unMap (YMap m) = Just m unMap _ = Nothing -- | Get the contents of a string unStr :: YamlLight -> Maybe ByteString.ByteString unStr (YStr s) = Just s unStr _ = Nothing -- tests performTest :: Show a => (YamlLight -> a) -> String -> IO () performTest f s = parseYaml s >>= print . f cSeqMap1 = "[{key1: val1, key2: val2}, {key3: val3}]" cMapSeq1 = "{key1: [val1, val2, val3], key2: [val4, val5]}" gtKeys1 = " [{key1: \ \ { key1_1: [str1, str2] \ \ , key1_2: [str2, str3] }} \ \ , {key2: [str4]} \ \ , str5 \ \ ] " gtKeys2 = "[a, b, c]" gtKeys3 = "a: {b: [c, {d: [e, f]}]}" gtKeys4 = "[{a: {b: [c1, c2], d: [e1, e2]}, f: [g]}, h]" testCombineSequencedMaps1 = performTest combineSequencedMaps cSeqMap1 testCombineMappedSequences1 = performTest combineMappedSequences cMapSeq1 testGetTerminalsKeys1 = performTest getTerminalsKeys gtKeys1 testGetTerminalsKeys2 = performTest getTerminalsKeys gtKeys2 testGetTerminalsKeys3 = performTest getTerminalsKeys gtKeys3 testGetTerminalsKeys4 = performTest getTerminalsKeys gtKeys4