{-# LANGUAGE DeriveFunctor #-}
module Data.Named.IOB
( IOB (..)
, Label
, Atom (..)
, encodeForest
, decodeForest
) where
import Control.Applicative ((<$>))
import Data.Maybe (fromJust)
import Data.Binary (Binary, get, put)
import Data.Named.Tree hiding (span)
data IOB w a = IOB
{ word :: w
, label :: Label a
} deriving (Show)
type Label a = [Atom a]
data Atom a = B a
| I a
deriving (Show, Eq, Ord, Functor)
instance Binary a => Binary (Atom a) where
put (B x) = put '1' >> put x
put (I x) = put '2' >> put x
get = get >>= \i -> case i of
'1' -> B <$> get
'2' -> I <$> get
_ -> error "Atom Binary instance: invalid code"
push :: Atom a -> IOB w a -> IOB w a
push x (IOB w xs) = IOB w (x:xs)
popMaybe :: IOB w a -> Maybe (Atom a, IOB w a)
popMaybe (IOB w (x:xs)) = Just (x, IOB w xs)
popMaybe (IOB _ []) = Nothing
topMaybe :: IOB w a -> Maybe (Atom a)
topMaybe iob = fst <$> popMaybe iob
pop :: IOB w a -> (Atom a, IOB w a)
pop = fromJust . popMaybe
raw :: Atom a -> a
raw (B x) = x
raw (I x) = x
isI :: Atom a -> Bool
isI (I _) = True
isI _ = False
encodeForest :: NeForest a w -> [IOB w a]
encodeForest [] = []
encodeForest (x:xs) = encodeTree x ++ encodeForest xs
encodeTree :: NeTree a w -> [IOB w a]
encodeTree (Node (Left _) []) =
error "encodeTree: label node with no children"
encodeTree (Node (Left e) forest) =
let addLayer (x:xs) = push (B e) x : map (push $ I e) xs
addLayer [] = []
in addLayer (encodeForest forest)
encodeTree (Node (Right _) (_:_)) =
error "encodeTree: word node with children"
encodeTree (Node (Right w) _) = [IOB w []]
decodeForest :: Eq a => [IOB w a] -> NeForest a w
decodeForest [] = []
decodeForest xs =
tree : decodeForest xs'
where
(chunk, xs') = followTop xs
tree = case topMaybe $ head chunk of
Nothing -> Node (Right . word $ head chunk) []
Just e -> Node (Left $ raw e) (decodeForest $ map rmTop chunk)
rmTop = snd . pop
followTop :: Eq a => [IOB w a] -> ([IOB w a], [IOB w a])
followTop [] = error "followTop: empty iob"
followTop (x:xs) =
(x:chunk, rest)
where
(chunk, rest) = span (cond (topMaybe x) . topMaybe) xs
cond (Just a) (Just b) = raw a == raw b && isI b
cond _ _ = False