@hackage toml-parser1.0.0.0

TOML 1.0.0 parser

TOML Parser

This package implements a validating parser for TOML 1.0.0.

This package uses an alex-generated lexer and happy-generated parser.

It also provides a pair of classes for serializing into and out of TOML.

Package Structure

---
title: Package Structure
---
stateDiagram-v2
    classDef important font-weight:bold;

    TOML:::important --> ApplicationTypes:::important : decode
    ApplicationTypes --> TOML : encode
    TOML --> [Token]: Toml.Lexer
    [Token] --> [Expr]: Toml.Parser
    [Expr] --> Table : Toml.Semantics
    Table --> ApplicationTypes : Toml.FromTable
    ApplicationTypes --> Table : Toml.ToTable
    Table --> TOML : Toml.Pretty

The highest-level interface to this package is to define FromTable and ToTable instances for your application-specific datatypes. These can be used with encode and decode to convert to and from TOML.

For low-level access to the TOML format, the lexer, parser, and validator are available for direct use. The diagram above shows how the different modules enable you to advance through the increasingly high-level TOML representations.

Example

Consider this sample TOML text from the specification.

[[fruits]]
name = "apple"

[fruits.physical]  # subtable
color = "red"
shape = "round"

[[fruits.varieties]]  # nested array of tables
name = "red delicious"

[[fruits.varieties]]
name = "granny smith"


[[fruits]]
name = "banana"

[[fruits.varieties]]
name = "plantain"

Parsing using this package generates the following value

>>> Right fruitToml = parse fruitStr
>>> fruitToml
Right (fromList [
    ("fruits",Array [
        Table (fromList [
            ("name",String "apple"),
            ("physical",Table (fromList [
                ("color",String "red"),
                ("shape",String "round")])),
            ("varieties",Array [
                Table (fromList [("name",String "red delicious")]),
                Table (fromList [("name",String "granny smith")])])]),
        Table (fromList [
            ("name",String "banana"),
            ("varieties",Array [
                Table (fromList [("name",String "plantain")])])])])])

We can render this parsed value back to TOML text using prettyToml fruitToml. In this case the input was already sorted, so the generated text will happen to match almost exactly.

Here's an example of defining datatypes and deserializers for the TOML above.

newtype Fruits = Fruits [Fruit]
    deriving (Eq, Show)

data Fruit = Fruit String (Maybe Physical) [Variety]
    deriving (Eq, Show)

data Physical = Physical String String
    deriving (Eq, Show)

newtype Variety = Variety String
    deriving (Eq, Show)

instance FromTable Fruits where
    fromTable = runParseTable (Fruits <$> reqKey "fruits")

instance FromTable Fruit where
    fromTable = runParseTable (Fruit <$> reqKey "name" <*> optKey "physical" <*> reqKey "varieties")

instance FromTable Physical where
    fromTable = runParseTable (Physical <$> reqKey "color" <*> reqKey "shape")

instance FromTable Variety where
    fromTable = runParseTable (Variety <$> reqKey "name")

instance FromValue Fruits   where fromValue = defaultTableFromValue
instance FromValue Fruit    where fromValue = defaultTableFromValue
instance FromValue Physical where fromValue = defaultTableFromValue
instance FromValue Variety  where fromValue = defaultTableFromValue

We can run this example on the original value to deserialize it into domain-specific datatypes.

>>> decode fruitToml :: Either String Fruits
Right (Fruits [
    Fruit "apple" (Just (Physical "red" "round")) [Variety "red delicious", Variety "granny smith"],
    Fruit "banana" Nothing [Variety "plantain"]])