{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE MultiParamTypeClasses #-}
-- | The free 'Cfg'
module Data.Cfg.FreeCfg (
    FreeCfg(..),
    toFreeCfg
    ) where

import Data.Cfg.Cfg(Cfg(..), Vs)
import qualified Data.Set as S

-- | Represents a context-free grammar with its nonterminal and
-- terminal types.  The canonical instance of 'Cfg': a record that
-- collects up implementations of each class method.
data FreeCfg t nt = FreeCfg {
    nonterminals' :: S.Set nt,
	-- ^ the nonterminals of the grammar
    terminals' :: S.Set t,
	-- ^ the terminals of the grammar
    productionRules' :: nt -> S.Set (Vs t nt),
	-- ^ the productions of the grammar
    startSymbol' :: nt
	-- ^ the start symbol of the grammar; must be an element of
	-- 'nonterminals' 'cfg'
    }

instance Cfg FreeCfg t nt where
    nonterminals = nonterminals'
    terminals = terminals'
    productionRules = productionRules'
    startSymbol = startSymbol'

-- | Converts any 'Cfg' into a 'FreeCfg'.
toFreeCfg :: Cfg cfg t nt => cfg t nt -> FreeCfg t nt
toFreeCfg cfg = FreeCfg {
    nonterminals' = nonterminals cfg,
    terminals' = terminals cfg,
    productionRules' = productionRules cfg,
    startSymbol' = startSymbol cfg
    }