tomland-1.3.3.3: src/Toml/Parser/Item.hs
{- |
Module : Toml.Parser.Item
Copyright : (c) 2018-2022 Kowainik
SPDX-License-Identifier : MPL-2.0
Maintainer : Kowainik <xrom.xkov@gmail.com>
Stability : Stable
Portability : Portable
This module contains the definition of the 'TomlItem' data type which
represents either key-value pair or table name. This data type serves the
purpose to be the intermediate representation of parsing a TOML file which will
be assembled to TOML AST later.
@since 1.2.0.0
-}
module Toml.Parser.Item
( TomlItem (..)
, Table (..)
, setTableName
, tomlP
, keyValP
) where
import Control.Applicative (liftA2, many)
import Control.Applicative.Combinators.NonEmpty (sepEndBy1)
import Control.Monad.Combinators (between, sepEndBy)
import Data.Foldable (asum)
import Data.List.NonEmpty (NonEmpty)
import Toml.Parser.Core (Parser, eof, sc, text, try, (<?>))
import Toml.Parser.Key (keyP, tableArrayNameP, tableNameP)
import Toml.Parser.Value (anyValueP)
import Toml.Type.AnyValue (AnyValue)
import Toml.Type.Key (Key)
{- | One item of a TOML file. It could be either:
* A name of a table
* A name of a table array
* Key-value pair
* Inline table
* Inline array of tables
Knowing a list of 'TomlItem's, it's possible to construct 'Toml.Type.TOML.TOML'
from this information.
-}
data TomlItem
= TableName !Key
| TableArrayName !Key
| KeyVal !Key !AnyValue
| InlineTable !Key !Table
| InlineTableArray !Key !(NonEmpty Table)
deriving stock (Show, Eq)
{- | Changes name of table to a new one. Works only for 'TableName' and
'TableArrayName' constructors.
-}
setTableName :: Key -> TomlItem -> TomlItem
setTableName new = \case
TableName _ -> TableName new
TableArrayName _ -> TableArrayName new
item -> item
{- | Table that contains only @key = val@ pairs.
-}
newtype Table = Table
{ unTable :: [(Key, AnyValue)]
} deriving stock (Show)
deriving newtype (Eq)
----------------------------------------------------------------------------
-- Parser
----------------------------------------------------------------------------
-- | Parser for inline tables.
inlineTableP :: Parser Table
inlineTableP =
fmap Table
$ between (text "{") (text "}")
$ liftA2 (,) (keyP <* text "=") anyValueP `sepEndBy` text ","
-- | Parser for inline arrays of tables.
inlineTableArrayP :: Parser (NonEmpty Table)
inlineTableArrayP = between (text "[") (text "]")
$ inlineTableP `sepEndBy1` text ","
-- | Parser for a single item in the TOML file.
tomlItemP :: Parser TomlItem
tomlItemP = asum
[ TableName <$> try tableNameP <?> "table name"
, TableArrayName <$> tableArrayNameP <?> "array of tables name"
, keyValP
]
{- | parser for @"key = val"@ pairs; can be one of three forms:
1. key = { ... }
2. key = [ {...}, {...}, ... ]
3. key = ...
-}
keyValP :: Parser TomlItem
keyValP = do
key <- keyP <* text "="
asum
[ InlineTable key <$> inlineTableP <?> "inline table"
, InlineTableArray key <$> try inlineTableArrayP <?> "inline array of tables"
, KeyVal key <$> anyValueP <?> "key-value pair"
]
-- | Parser for the full content of the .toml file.
tomlP :: Parser [TomlItem]
tomlP = sc *> many tomlItemP <* eof