{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE ScopedTypeVariables #-}

-- | This module provides a way to specify a grammar of @.cabal@ -like files.
module Distribution.FieldGrammar
  ( -- * Field grammar type
    FieldGrammar (..)
  , uniqueField
  , optionalField
  , optionalFieldDef
  , monoidalField

    -- * Concrete grammar implementations
  , ParsecFieldGrammar
  , ParsecFieldGrammar'
  , parseFieldGrammar
  , fieldGrammarKnownFieldList
  , PrettyFieldGrammar
  , PrettyFieldGrammar'
  , prettyFieldGrammar

    -- * Auxiliary
  , (^^^)
  , Section (..)
  , Fields
  , partitionFields
  , takeFields
  , runFieldParser
  , runFieldParser'
  , defaultFreeTextFieldDefST

    -- * Newtypes
  , module Distribution.FieldGrammar.Newtypes
  ) where

import Distribution.Compat.Prelude
import Prelude ()

import qualified Data.Map.Strict as Map

import Distribution.FieldGrammar.Class
import Distribution.FieldGrammar.Newtypes
import Distribution.FieldGrammar.Parsec
import Distribution.FieldGrammar.Pretty
import Distribution.Fields.Field
import Distribution.Utils.Generic (spanMaybe)

type ParsecFieldGrammar' a = ParsecFieldGrammar a a
type PrettyFieldGrammar' a = PrettyFieldGrammar a a

infixl 5 ^^^

-- | Reverse function application which binds tighter than '<$>' and '<*>'.
-- Useful for refining grammar specification.
--
-- @
-- \<*\> 'monoidalFieldAla' "extensions"           (alaList' FSep MQuoted)       oldExtensions
--     ^^^ 'deprecatedSince' [1,12] "Please use 'default-extensions' or 'other-extensions' fields."
-- @
(^^^) :: a -> (a -> b) -> b
a
x ^^^ :: forall a b. a -> (a -> b) -> b
^^^ a -> b
f = a -> b
f a
x

-- | Partitioning state
data PS ann = PS (Fields ann) [Section ann] [[Section ann]]

-- | Partition field list into field map and groups of sections.
partitionFields :: [Field ann] -> (Fields ann, [[Section ann]])
partitionFields :: forall ann. [Field ann] -> (Fields ann, [[Section ann]])
partitionFields = PS ann -> (Fields ann, [[Section ann]])
forall ann. PS ann -> (Fields ann, [[Section ann]])
finalize (PS ann -> (Fields ann, [[Section ann]]))
-> ([Field ann] -> PS ann)
-> [Field ann]
-> (Fields ann, [[Section ann]])
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (PS ann -> Field ann -> PS ann) -> PS ann -> [Field ann] -> PS ann
forall b a. (b -> a -> b) -> b -> [a] -> b
forall (t :: * -> *) b a.
Foldable t =>
(b -> a -> b) -> b -> t a -> b
foldl' PS ann -> Field ann -> PS ann
forall ann. PS ann -> Field ann -> PS ann
f (Fields ann -> [Section ann] -> [[Section ann]] -> PS ann
forall ann.
Fields ann -> [Section ann] -> [[Section ann]] -> PS ann
PS Fields ann
forall a. Monoid a => a
mempty [Section ann]
forall a. Monoid a => a
mempty [[Section ann]]
forall a. Monoid a => a
mempty)
  where
    finalize :: PS ann -> (Fields ann, [[Section ann]])
    finalize :: forall ann. PS ann -> (Fields ann, [[Section ann]])
finalize (PS Fields ann
fs [Section ann]
s [[Section ann]]
ss)
      | [Section ann] -> Bool
forall a. [a] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null [Section ann]
s = (Fields ann
fs, [[Section ann]] -> [[Section ann]]
forall a. [a] -> [a]
reverse [[Section ann]]
ss)
      | Bool
otherwise = (Fields ann
fs, [[Section ann]] -> [[Section ann]]
forall a. [a] -> [a]
reverse ([Section ann] -> [Section ann]
forall a. [a] -> [a]
reverse [Section ann]
s [Section ann] -> [[Section ann]] -> [[Section ann]]
forall a. a -> [a] -> [a]
: [[Section ann]]
ss))

    f :: PS ann -> Field ann -> PS ann
    f :: forall ann. PS ann -> Field ann -> PS ann
f (PS Fields ann
fs [Section ann]
s [[Section ann]]
ss) (Field (Name ann
ann ByteString
name) [FieldLine ann]
fss) =
      Fields ann -> [Section ann] -> [[Section ann]] -> PS ann
forall ann.
Fields ann -> [Section ann] -> [[Section ann]] -> PS ann
PS (([NamelessField ann] -> [NamelessField ann] -> [NamelessField ann])
-> ByteString -> [NamelessField ann] -> Fields ann -> Fields ann
forall k a. Ord k => (a -> a -> a) -> k -> a -> Map k a -> Map k a
Map.insertWith (([NamelessField ann] -> [NamelessField ann] -> [NamelessField ann])
-> [NamelessField ann]
-> [NamelessField ann]
-> [NamelessField ann]
forall a b c. (a -> b -> c) -> b -> a -> c
flip [NamelessField ann] -> [NamelessField ann] -> [NamelessField ann]
forall a. [a] -> [a] -> [a]
(++)) ByteString
name [ann -> [FieldLine ann] -> NamelessField ann
forall ann. ann -> [FieldLine ann] -> NamelessField ann
MkNamelessField ann
ann [FieldLine ann]
fss] Fields ann
fs) [] [[Section ann]]
ss'
      where
        ss' :: [[Section ann]]
ss'
          | [Section ann] -> Bool
forall a. [a] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null [Section ann]
s = [[Section ann]]
ss
          | Bool
otherwise = [Section ann] -> [Section ann]
forall a. [a] -> [a]
reverse [Section ann]
s [Section ann] -> [[Section ann]] -> [[Section ann]]
forall a. a -> [a] -> [a]
: [[Section ann]]
ss
    f (PS Fields ann
fs [Section ann]
s [[Section ann]]
ss) (Section Name ann
name [SectionArg ann]
sargs [Field ann]
sfields) =
      Fields ann -> [Section ann] -> [[Section ann]] -> PS ann
forall ann.
Fields ann -> [Section ann] -> [[Section ann]] -> PS ann
PS Fields ann
fs (Name ann -> [SectionArg ann] -> [Field ann] -> Section ann
forall ann.
Name ann -> [SectionArg ann] -> [Field ann] -> Section ann
MkSection Name ann
name [SectionArg ann]
sargs [Field ann]
sfields Section ann -> [Section ann] -> [Section ann]
forall a. a -> [a] -> [a]
: [Section ann]
s) [[Section ann]]
ss

-- | Take all fields from the front.
takeFields :: [Field ann] -> (Fields ann, [Field ann])
takeFields :: forall ann. [Field ann] -> (Fields ann, [Field ann])
takeFields = ([(ByteString, [NamelessField ann])], [Field ann])
-> (Map ByteString [NamelessField ann], [Field ann])
forall {k} {a} {b}. Ord k => ([(k, [a])], b) -> (Map k [a], b)
finalize (([(ByteString, [NamelessField ann])], [Field ann])
 -> (Map ByteString [NamelessField ann], [Field ann]))
-> ([Field ann]
    -> ([(ByteString, [NamelessField ann])], [Field ann]))
-> [Field ann]
-> (Map ByteString [NamelessField ann], [Field ann])
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Field ann -> Maybe (ByteString, [NamelessField ann]))
-> [Field ann]
-> ([(ByteString, [NamelessField ann])], [Field ann])
forall a b. (a -> Maybe b) -> [a] -> ([b], [a])
spanMaybe Field ann -> Maybe (ByteString, [NamelessField ann])
forall {ann}. Field ann -> Maybe (ByteString, [NamelessField ann])
match
  where
    finalize :: ([(k, [a])], b) -> (Map k [a], b)
finalize ([(k, [a])]
fs, b
rest) = (([a] -> [a] -> [a]) -> [(k, [a])] -> Map k [a]
forall k a. Ord k => (a -> a -> a) -> [(k, a)] -> Map k a
Map.fromListWith (([a] -> [a] -> [a]) -> [a] -> [a] -> [a]
forall a b c. (a -> b -> c) -> b -> a -> c
flip [a] -> [a] -> [a]
forall a. [a] -> [a] -> [a]
(++)) [(k, [a])]
fs, b
rest)

    match :: Field ann -> Maybe (ByteString, [NamelessField ann])
match (Field (Name ann
ann ByteString
name) [FieldLine ann]
fs) = (ByteString, [NamelessField ann])
-> Maybe (ByteString, [NamelessField ann])
forall a. a -> Maybe a
Just (ByteString
name, [ann -> [FieldLine ann] -> NamelessField ann
forall ann. ann -> [FieldLine ann] -> NamelessField ann
MkNamelessField ann
ann [FieldLine ann]
fs])
    match Field ann
_ = Maybe (ByteString, [NamelessField ann])
forall a. Maybe a
Nothing