packages feed

context-free-grammar-0.1.1: src/Data/Cfg/Bnf/Syntax.hs

-- | Syntax structures of Bnf.
{-# LANGUAGE DeriveDataTypeable #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE MultiParamTypeClasses #-}

module Data.Cfg.Bnf.Syntax
  ( Grammar(..)
  ) where

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

-- | A simple, concrete instance of 'Cfg'.  The terminal and
-- nonterminal symbols of a 'Grammar' are defined to be exactly those
-- appearing the productions.  The start symbol is defined to be the
-- head of the first of the productions.
newtype Grammar t nt = Grammar
  { grammarProductions :: [Production t nt]
    -- ^ the productions of the 'Grammar'
  } deriving (Data, Typeable)

instance (Ord nt, Ord t) => Cfg Grammar t nt where
  terminals = S.fromList . concatMap terminalsProd . grammarProductions
  nonterminals = S.fromList . concatMap nonterminalsProd . grammarProductions
  productionRules g nt =
    S.fromList [rhs | (nt', rhs) <- grammarProductions g, nt == nt']
  startSymbol = fst . head . grammarProductions

nonterminalsVs :: Vs t nt -> [nt]
nonterminalsVs vs = [nt | NT nt <- vs]

terminalsVs :: Vs t nt -> [t]
terminalsVs vs = [t | T t <- vs]

nonterminalsProd :: Production t nt -> [nt]
nonterminalsProd (nt, rhs) = nt : nonterminalsVs rhs

terminalsProd :: Production t nt -> [t]
terminalsProd = terminalsVs . snd