/struct-parse

Error-reporting parser for unityped data structures (e.g. JSON)

Primary LanguageHaskellBSD 3-Clause "New" or "Revised" LicenseBSD-3-Clause

struct-parse

Error-reporting parser for unityped data structures (e.g. JSON). Aimed to be convenient for parsing resource files, configs and other pieces written by human.

Some examples of parsing and error-reporting:

-- We'll use example.toml from Tom's Preston-Werner https://github.com/toml-lang/toml
ghci> :t parseFromFile
parseFromFile :: FilePath -> Data.TomlObject.TomlParser a -> IO (Either String a)

-- So let's read it, run parser and print results (or errors)
ghci> let example p = either putStrLn print =<< parseFromFile "example.toml" p

-- What is the interface of parser?
ghci> :browse Data.TomlObject
...
bool :: StructParser AnnotatedTomlObject Bool
int :: StructParser AnnotatedTomlObject GHC.Int.Int64
double :: StructParser AnnotatedTomlObject Double
string :: StructParser AnnotatedTomlObject Data.Text.Internal.Text
index :: Int -> StructParser AnnotatedTomlObject AnnotatedTomlObject
elems :: StructParser AnnotatedTomlObject [AnnotatedTomlObject]
key :: String -> StructParser AnnotatedTomlObject AnnotatedTomlObject
fields :: StructParser AnnotatedTomlObject (HashMap Text AnnotatedTomlObject)
context :: String -> StructParser a a
this :: StructParser a a
traversing :: (Traversable t) => StructParser a b -> StructParser (t a) (t b)
...

-- Something simple
ghci> example $ key "title" >>> string
"TOML Example"

-- All int ports of databases
ghci> example $ key "database" >>> key "ports" >>> elems >>> traversing int
[8001,8001,8002]

-- Bool? Nah, error.
ghci> example $ key "database" >>> key "ports" >>> elems >>> traversing bool
Failure:
in .database(Object): in .ports(Array): all of
{ at [0](Integer): expected Bool, got Integer
, at [1](Integer): expected Bool, got Integer
, at [2](Integer): expected Bool, got Integer
}

-- Server names and their IPs
ghci> example $ key "servers" >>> fields >>> traversing (key "ip" >>> string)
fromList [("alpha","10.0.0.1"),("beta","10.0.0.2")]

-- More complex query?
ghci> :{
ghci| example $ (,)
ghci|   <$> (key "owner" >>> key "name" >>> string)
ghci|   <*> (key "products" >>> elems >>> traversing (key "name" >>> string))
ghci| :}
("Tom Preston-Werner",["Hammer","Nail"])