-- | Sets of lookahead symbols. module Data.Cfg.LookaheadSet ( LookaheadSet , mkLookaheadSet , fromList , toSet -- * Set operations , empty , singleton , unions ) where import Data.Cfg.Augment (AugT(..)) import Data.Monoid (Monoid(..)) import Data.Semigroup (Semigroup(..)) 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 => Semigroup (LookaheadSet t) where l@(LookaheadSet s) <> LookaheadSet s' = if EOF `S.member` s then LookaheadSet $ S.delete EOF s `S.union` s' else l instance Ord t => Monoid (LookaheadSet t) where mempty = LookaheadSet $ S.singleton EOF mappend = (<>) -- | 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