packages feed

GrammarProducts-0.0.0.2: FormalLanguage/GrammarProduct/Op/Subtract.hs

{-# LANGUAGE FlexibleInstances #-}

module FormalLanguage.GrammarProduct.Op.Subtract where

import Control.Newtype
import Data.Semigroup
import Control.Lens
import Control.Lens.Fold
import qualified Data.Set as S
import Data.List (genericReplicate)
import Text.Printf

import FormalLanguage.CFG.Grammar

import FormalLanguage.GrammarProduct.Op.Common



-- | Subtract two grammars.

subtract :: Grammar -> Grammar -> Grammar
subtract l r
    | gDim l /= gDim r = error $ printf "grammars %s and %s have different dimensions, cannot unify. (subtract)" (show l) (show r)
    | otherwise        = Grammar ts ns es rs s (l^.name ++ r^.name) where
        ts = collectTerminals rs
        ns = collectNonTerminals rs
        es = collectEpsilons rs
        rs = (l^.rules) S.\\ (r^.rules)
        s  = case (l^.start) of
               Nothing -> Nothing
               Just s' -> if anyOf (rules.folded.lhs) (==s') l
                            then l^.start
                            else Nothing