-- | 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