packages feed

domain-0.1.1.5: library/Domain/YamlUnscrambler/TypeCentricDoc.hs

module Domain.YamlUnscrambler.TypeCentricDoc where

import qualified Control.Foldl as Fold
import qualified Data.Text as Text
import qualified Domain.Attoparsec.General as GeneralAttoparsec
import qualified Domain.Attoparsec.TypeString as TypeStringAttoparsec
import Domain.Models.TypeCentricDoc
import qualified Domain.Models.TypeString as TypeStringModel
import Domain.Prelude
import YamlUnscrambler

doc :: Value [(Text, Structure)]
doc =
  value onScalar (Just onMapping) Nothing
  where
    onScalar =
      [nullScalar []]
    onMapping =
      foldMapping (,) Fold.list typeNameString structure
      where
        typeNameString =
          formattedString "type name" $ \input ->
            case Text.uncons input of
              Just (h, t) ->
                if isUpper h
                  then
                    if Text.all (\a -> isAlphaNum a || a == '\'' || a == '_') t
                      then Right input
                      else Left "Contains invalid chars"
                  else Left "First char is not upper-case"
              Nothing ->
                Left "Empty string"

structure :: Value Structure
structure =
  value [] (Just structureMapping) Nothing

byFieldName :: Value val -> Value [(Text, val)]
byFieldName onElement =
  value onScalar (Just onMapping) Nothing
  where
    onScalar =
      [nullScalar []]
    onMapping =
      foldMapping (,) Fold.list textString onElement

sumTypeExpression :: Value [NestedTypeExpression]
sumTypeExpression =
  value onScalar (Just onMapping) (Just onSequence)
  where
    onScalar =
      [ nullScalar [],
        fmap (fmap AppSeqNestedTypeExpression)
          $ stringScalar
          $ attoparsedString "Type signature"
          $ GeneralAttoparsec.only TypeStringAttoparsec.commaSeq
      ]
    onMapping =
      pure . StructureNestedTypeExpression <$> structureMapping
    onSequence =
      foldSequence Fold.list nestedTypeExpression

nestedTypeExpression :: Value NestedTypeExpression
nestedTypeExpression =
  value [onScalar] (Just onMapping) Nothing
  where
    onScalar =
      AppSeqNestedTypeExpression <$> appTypeStringScalar
    onMapping =
      StructureNestedTypeExpression <$> structureMapping

enumVariants :: Value [Text]
enumVariants =
  sequenceValue (foldSequence Fold.list variant)
  where
    variant =
      scalarsValue [stringScalar textString]

-- * Scalar

-------------------------

appTypeStringScalar :: Scalar (NonEmpty TypeStringModel.Unit)
appTypeStringScalar =
  stringScalar
    $ attoparsedString "Type signature"
    $ GeneralAttoparsec.only TypeStringAttoparsec.appSeq

-- * Mapping

-------------------------

structureMapping :: Mapping Structure
structureMapping =
  byKeyMapping (CaseSensitive True)
    $ atByKey "product" (ProductStructure <$> byFieldName nestedTypeExpression)
    <|> atByKey "sum" (SumStructure <$> byFieldName sumTypeExpression)
    <|> atByKey "enum" (EnumStructure <$> enumVariants)