packages feed

ideas-0.6: src/Domain/RegularExpr/Definitions.hs

-----------------------------------------------------------------------------
-- Copyright 2010, Open Universiteit Nederland. This file is distributed 
-- under the terms of the GNU General Public License. For more information, 
-- see the file "LICENSE.txt", which is included in the distribution.
-----------------------------------------------------------------------------
-- |
-- Maintainer  :  bastiaan.heeren@ou.nl
-- Stability   :  provisional
-- Portability :  portable (depends on ghc)
--
-----------------------------------------------------------------------------
module Domain.RegularExpr.Definitions where

import Domain.RegularExpr.Expr
import Common.Uniplate
import Common.Utils (distinct)

deterministic :: (Show a, Eq a) => RE a -> Bool
deterministic r = deterministicSimple r {-
   case (deterministicSimple r, det r) of
      (b1, b2) | b1==b2 -> b1
      _ -> error $ show r -}
       
deterministicSimple :: Eq a => RE a -> Bool
deterministicSimple regexp =
   distinct (lookahead regexp) && all deterministicSimple (children regexp)

det :: Eq a => RE a -> Bool
det regexp =
   case regexp of
      EmptySet -> True
      Epsilon  -> True
      Atom _   -> True
      Option r -> det (r :|: Epsilon)
      Star r   -> det r
      Plus r   -> det (r :*: Star r)
      r :|: s  -> lookahead r `disj` lookahead s && det r && det s
      EmptySet  :*: r -> det r
      Epsilon   :*: r -> det r
      Atom _    :*: r -> det r
      Option s  :*: r -> det ((s :|: Epsilon) :*: r)
      Star s    :*: r -> lookahead s `disj` lookahead r && det s && det r
      Plus s    :*: r -> det ((s :*: Star s) :*: r)
      (q :|: s) :*: r -> det ((q :*: r) :|: (s :*: r))
      (q :*: s) :*: r -> det (q :*: (s :*: r))


disj xs ys = all (`notElem` xs) ys

empty :: RE a -> Bool
empty = foldRE (False, True, const (False), const True, const True, id, (&&), (||))

lookahead :: RE a -> [a]
lookahead = map fst . firsts

firsts :: RE a -> [(a, RE a)]
firsts regexp =
   case regexp of
      EmptySet -> []
      Epsilon  -> []
      Atom a   -> [(a, Epsilon)]
      Option r -> firsts r
      Star r   -> firsts (nonempty r :*: Star r)
      Plus r   -> firsts (r :*: Star r)
      r :*: s  -> [ (a, q :*: s) | (a, q) <- firsts r ] ++
                  (if empty r then firsts s else [])
      r :|: s  -> firsts r ++ firsts s

nonempty :: RE a -> RE a
nonempty regexp = foldr (:|:) EmptySet [ Atom a :*: r | (a, r) <- firsts regexp ]