-- | Sets of lookahead symbols.
module Data.Cfg.LookaheadSet (
LookaheadSet,
mkLookaheadSet,
fromList,
toSet,
(<>), -- reexport
-- * Set operations
empty,
singleton,
unions
) where
import Data.Cfg.Augment(AugT(..))
import Data.Monoid(Monoid(..), (<>))
import qualified Data.Set as S
-- | Set of lookahead symbols providing different 'Monoid' semantics
-- than 'Data.Set.Set'. ('mappend' implements concatenation, not set
-- union.)
newtype LookaheadSet t = LookaheadSet {
toSet :: S.Set (AugT t)
-- ^ Converts the 'LookaheadSet' to a regular 'Data.Set.Set'
}
deriving (Eq, Ord, Show)
instance Ord t => Monoid (LookaheadSet t) where
mempty = LookaheadSet $ S.singleton EOF
l@(LookaheadSet s) `mappend` LookaheadSet s'
= if EOF `S.member` s
then LookaheadSet $ S.delete EOF s `S.union` s'
else l
-- | Creates a 'LookaheadSet'
mkLookaheadSet :: (Ord t)
=> Bool -- ^ true iff it has 'EOF'
-> [t] -- ^ terminal symbols
-> LookaheadSet t
mkLookaheadSet hasEOF = LookaheadSet . S.fromList . f . map AugT
where
f = if hasEOF then (EOF:) else id
-- | Creates a 'LookaheadSet' from a list of augmented terminals.
fromList :: Ord t => [AugT t] -> LookaheadSet t
fromList = LookaheadSet . S.fromList
-- | The empty lookahead set.
empty :: LookaheadSet t
empty = LookaheadSet S.empty
-- | Creates a singleton lookahead set.
singleton :: AugT t -> LookaheadSet t
singleton = LookaheadSet . S.singleton
-- | Returns the union of all the lookahead sets.
unions :: Ord t => [LookaheadSet t] -> LookaheadSet t
unions = LookaheadSet . S.unions . map toSet