> {-# OPTIONS_HADDOCK show-extensions #-}
> {-|
> Module : LTK.Porters.ATT
> Copyright : (c) 2019-2023 Dakotah Lambert
> LICENSE : MIT
> 
> This module provides methods to convert automata to and from the
> AT&T FSM format.  Generally there will be up to three text files,
> the contents of which can be merged via 'embedSymbolsATT'.  When
> exporting, you should similarly use 'extractSymbolsATT' to unmerge
> the resulting files.
>
> @since 0.3
> -}
> module LTK.Porters.ATT
>        ( embedSymbolsATT
>        , extractSymbolsATT
>        , invertATT
>        -- *Importing
>        , readATT
>        -- *Exporting
>        , exportATT
>        ) where

> import Data.Char (isDigit)
> import Data.List (intercalate)
> import Data.Maybe (fromMaybe)
> import Data.Set (Set)
> import Data.Map (Map)
> import qualified Data.Map.Strict as Map
> import qualified Data.Set as Set

> import LTK.FSA

> separator :: String
> separator :: [Char]
separator = [Char]
"* * *"

> defaultEpsilon :: String
> defaultEpsilon :: [Char]
defaultEpsilon = [Char]
"<EPS>"

> -- |Take three strings and merge them in such a way that @(from ATT)@
> -- can understand the result.
> -- The three strings should represent the transitions,
> -- input symbols, and output symbols, respectively.
> embedSymbolsATT :: String -> Maybe String -> Maybe String -> String
> embedSymbolsATT :: [Char] -> Maybe [Char] -> Maybe [Char] -> [Char]
embedSymbolsATT [Char]
x Maybe [Char]
mi Maybe [Char]
mo
>     = [[Char]] -> [Char]
unlines forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. [a] -> [a] -> [a]
(++) ([Char] -> [[Char]]
lines [Char]
x) forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. a -> Maybe a -> a
fromMaybe [] forall b c a. (b -> c) -> (a -> b) -> a -> c
. Maybe [Char] -> Maybe [[Char]] -> Maybe [[Char]]
m Maybe [Char]
mi forall a b. (a -> b) -> a -> b
$ Maybe [Char] -> Maybe [[Char]] -> Maybe [[Char]]
m Maybe [Char]
mo forall a. Maybe a
Nothing
>     where presep :: [[Char]] -> [[Char]]
presep   = (:) [Char]
separator
>           multisep :: Maybe [[Char]] -> Maybe [[Char]] -> Maybe [[Char]]
multisep = forall b a. b -> (a -> b) -> Maybe a -> b
maybe
>                      (forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap [[Char]] -> [[Char]]
presep)
>                      (\[[Char]]
a ->
>                       forall b a. b -> (a -> b) -> Maybe a -> b
maybe (forall a. a -> Maybe a
Just forall a b. (a -> b) -> a -> b
$ [[Char]] -> [[Char]]
presep [[Char]]
a) (forall a. a -> Maybe a
Just forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. [a] -> [a] -> [a]
(++) ([[Char]] -> [[Char]]
presep [[Char]]
a))
>                      )
>           m :: Maybe [Char] -> Maybe [[Char]] -> Maybe [[Char]]
m = Maybe [[Char]] -> Maybe [[Char]] -> Maybe [[Char]]
multisep forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap [Char] -> [[Char]]
lines

> -- |Convert the output of @(to ATT)@ into strings suitable for inclusion.
> -- The result represents the transitions, input symbols, and output symbols
> -- in that order.
> extractSymbolsATT :: String -> (String, String, String)
> extractSymbolsATT :: [Char] -> ([Char], [Char], [Char])
extractSymbolsATT = forall {a}. [[a]] -> ([a], [a], [a])
f forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a b. (a -> b) -> [a] -> [b]
map [[Char]] -> [Char]
unlines forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. Eq a => a -> [a] -> [[a]]
splitOn [Char]
separator forall b c a. (b -> c) -> (a -> b) -> a -> c
. [Char] -> [[Char]]
lines
>     where f :: [[a]] -> ([a], [a], [a])
f ([a]
x:[a]
y:[a]
z:[[a]]
_)  =  ([a]
x, [a]
y, [a]
z)
>           f ([a]
x:[a]
y:[[a]]
_)    =  ([a]
x, [a]
y, [])
>           f ([a]
x:[[a]]
_)      =  ([a]
x, [], [])
>           f [[a]]
_          =  ([], [], [])

> -- |Convert an AT&T format string into one where input and output symbols
> -- have been reversed.
> invertATT :: String -> String
> invertATT :: [Char] -> [Char]
invertATT [Char]
s = [Char] -> Maybe [Char] -> Maybe [Char] -> [Char]
embedSymbolsATT [Char]
ts' (forall a. a -> Maybe a
Just [Char]
o) (forall a. a -> Maybe a
Just [Char]
i)
>     where ([Char]
ts, [Char]
i, [Char]
o)      =  [Char] -> ([Char], [Char], [Char])
extractSymbolsATT [Char]
s
>           ts' :: [Char]
ts'             =  [[Char]] -> [Char]
unlines forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a b. (a -> b) -> [a] -> [b]
map [Char] -> [Char]
invertSingle forall a b. (a -> b) -> a -> b
$ [Char] -> [[Char]]
lines [Char]
ts
>           invertSingle :: [Char] -> [Char]
invertSingle [Char]
t  =  forall a. [a] -> [[a]] -> [a]
intercalate [Char]
"\t" forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall {a}. [a] -> [a]
maybeInvert forall a b. (a -> b) -> a -> b
$ [Char] -> [[Char]]
words [Char]
t
>           maybeInvert :: [a] -> [a]
maybeInvert (a
a:a
b:a
c:a
d:[a]
xs)
>               =  a
aforall a. a -> [a] -> [a]
:a
bforall a. a -> [a] -> [a]
:a
dforall a. a -> [a] -> [a]
:a
cforall a. a -> [a] -> [a]
:[a]
xs -- swap in and out
>           maybeInvert [a]
xs  =  [a]
xs


Reading an AT&T format automaton
================================

> -- |Import an FSA from its representation in AT&T format.
> -- Note that this import is not perfect;
> -- it discards weights and returns only the input projection.
> readATT :: String -> FSA Integer String
> readATT :: [Char] -> FSA Integer [Char]
readATT [Char]
x = forall e n n1.
(Ord e, Ord n, Ord n1, Enum n1) =>
FSA n e -> FSA n1 e
renameStates forall a b. (a -> b) -> a -> b
$
>             FSA { sigma :: Set [Char]
sigma            =  Set [Char]
al' forall c a. Container c a => c -> c -> c
`union` Set [Char]
as
>                 , transitions :: Set (Transition [Char] [Char])
transitions      =  Set (Transition [Char] [Char])
ts
>                 , initials :: Set (State [Char])
initials         =  forall c a. Container c a => a -> c
singleton State [Char]
qi
>                 , finals :: Set (State [Char])
finals           =  Set (State [Char])
fs
>                 , isDeterministic :: Bool
isDeterministic  =  Bool
False
>                 }
>     where ([Char]
es, [Char]
i, [Char]
_)     =  [Char] -> ([Char], [Char], [Char])
extractSymbolsATT [Char]
x
>           (Map [Char] [Char]
al, Maybe [Char]
eps)      =  [[Char]] -> (Map [Char] [Char], Maybe [Char])
makeAlphabet ([Char] -> [[Char]]
lines [Char]
i)
>           al' :: Set [Char]
al'            =  forall a. Ord a => [a] -> Set a
Set.fromList forall a b. (a -> b) -> a -> b
$ forall k a. Map k a -> [a]
Map.elems Map [Char] [Char]
al
>           (Set (Transition [Char] [Char])
ts,Set [Char]
as,State [Char]
qi,Set (State [Char])
fs)  =  [[Char]]
-> Map [Char] [Char]
-> Maybe [Char]
-> (Set (Transition [Char] [Char]), Set [Char], State [Char],
    Set (State [Char]))
makeTransitions ([Char] -> [[Char]]
lines [Char]
es) Map [Char] [Char]
al Maybe [Char]
eps

> makeAlphabet :: [String] -> (Map String String, Maybe String)
> makeAlphabet :: [[Char]] -> (Map [Char] [Char], Maybe [Char])
makeAlphabet [[Char]]
ss = forall {a}.
(Map [Char] a, Maybe a) -> [(a, [Char])] -> (Map [Char] a, Maybe a)
findEps (forall k a. Map k a
Map.empty, forall a. Maybe a
Nothing) [([Char], [Char])]
ps
>     where ps :: [([Char], [Char])]
ps = forall (t :: * -> *) a b.
Foldable t =>
(a -> b -> b) -> b -> t a -> b
foldr (forall {b}. [b] -> [(b, b)] -> [(b, b)]
maybeInsert forall b c a. (b -> c) -> (a -> b) -> a -> c
. [Char] -> [[Char]]
words) [] [[Char]]
ss
>           maybeInsert :: [b] -> [(b, b)] -> [(b, b)]
maybeInsert (b
a:b
b:[b]
_)  =  (:) (b
a, b
b)
>           maybeInsert [b]
_        =  forall a. a -> a
id
>           findEps :: (Map [Char] a, Maybe a) -> [(a, [Char])] -> (Map [Char] a, Maybe a)
findEps (Map [Char] a
l, Maybe a
x) []    =  (Map [Char] a
l, Maybe a
x)
>           findEps (Map [Char] a
l, Maybe a
x) ((a
s, [Char]
t):[(a, [Char])]
as)
>               = forall a b c. (a -> b -> c) -> b -> a -> c
flip (Map [Char] a, Maybe a) -> [(a, [Char])] -> (Map [Char] a, Maybe a)
findEps [(a, [Char])]
as forall a b. (a -> b) -> a -> b
$
>                 if [Char]
t forall a. Eq a => a -> a -> Bool
== [Char]
"0" then (Map [Char] a
l, forall a. a -> Maybe a
Just a
s) else (forall k a. Ord k => k -> a -> Map k a -> Map k a
Map.insert [Char]
t a
s Map [Char] a
l, Maybe a
x)

> makeTransitions :: [String] -> Map String String -> Maybe String ->
>                    ( Set (Transition String String)  -- transitions
>                    , Set String                      -- alphabet
>                    , State String                    -- initial state
>                    , Set (State String)              -- final states
>                    )
> makeTransitions :: [[Char]]
-> Map [Char] [Char]
-> Maybe [Char]
-> (Set (Transition [Char] [Char]), Set [Char], State [Char],
    Set (State [Char]))
makeTransitions [[Char]]
ss Map [Char] [Char]
tags Maybe [Char]
meps
>     = forall (t :: * -> *) a b.
Foldable t =>
(a -> b -> b) -> b -> t a -> b
foldr ([[Char]]
-> (Set (Transition [Char] [Char]), Set [Char], State [Char],
    Set (State [Char]))
-> (Set (Transition [Char] [Char]), Set [Char], State [Char],
    Set (State [Char]))
update forall b c a. (b -> c) -> (a -> b) -> a -> c
. [Char] -> [[Char]]
words)
>       (forall a. Set a
Set.empty, forall a. Set a
Set.empty, forall n. n -> State n
State [Char]
"", forall a. Set a
Set.empty)
>       [[Char]]
ss
>     where symbolify :: [Char] -> Maybe [Char]
symbolify [Char]
x
>               | [Char]
x forall a. Eq a => a -> a -> Bool
== [Char]
"0" = forall a. Maybe a
Nothing -- 0 is reserved for epsilon
>               | forall a. a -> Maybe a
Just [Char]
x forall a. Eq a => a -> a -> Bool
== Maybe [Char]
meps = forall a. Maybe a
Nothing
>               | Bool
otherwise = forall a. a -> Maybe a
Just forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. a -> Maybe a -> a
fromMaybe [Char]
x forall a b. (a -> b) -> a -> b
$ forall k a. Ord k => k -> Map k a -> Maybe a
Map.lookup [Char]
x Map [Char] [Char]
tags
>           update :: [[Char]]
-> (Set (Transition [Char] [Char]), Set [Char], State [Char],
    Set (State [Char]))
-> (Set (Transition [Char] [Char]), Set [Char], State [Char],
    Set (State [Char]))
update [[Char]
a] (Set (Transition [Char] [Char])
ts, Set [Char]
as, State [Char]
qi, Set (State [Char])
fs)
>               = (Set (Transition [Char] [Char])
ts, Set [Char]
as, State [Char]
qi, forall a. Ord a => a -> Set a -> Set a
Set.insert (forall n. n -> State n
State [Char]
a) Set (State [Char])
fs)
>           update [[Char]
a,[Char]
_] (Set (Transition [Char] [Char]), Set [Char], State [Char],
 Set (State [Char]))
partial  -- if final state with cost
>               = [[Char]]
-> (Set (Transition [Char] [Char]), Set [Char], State [Char],
    Set (State [Char]))
-> (Set (Transition [Char] [Char]), Set [Char], State [Char],
    Set (State [Char]))
update [[Char]
a] (Set (Transition [Char] [Char]), Set [Char], State [Char],
 Set (State [Char]))
partial -- just ignore the cost
>           update ([Char]
s:[Char]
d:[Char]
l:[[Char]]
_) (Set (Transition [Char] [Char])
ts, Set [Char]
as, State [Char]
_, Set (State [Char])
fs)
>               = ( forall a b c. (a -> b -> c) -> b -> a -> c
flip forall a. Ord a => a -> Set a -> Set a
Set.insert Set (Transition [Char] [Char])
ts forall a b. (a -> b) -> a -> b
$
>                   Transition
>                   { source :: State [Char]
source      = forall n. n -> State n
State [Char]
s
>                   , destination :: State [Char]
destination = forall n. n -> State n
State [Char]
d
>                   , edgeLabel :: Symbol [Char]
edgeLabel   = forall b a. b -> (a -> b) -> Maybe a -> b
maybe forall e. Symbol e
Epsilon forall e. e -> Symbol e
Symbol forall a b. (a -> b) -> a -> b
$ [Char] -> Maybe [Char]
symbolify [Char]
l
>                   }
>                 , forall b a. b -> (a -> b) -> Maybe a -> b
maybe Set [Char]
as (forall a. Ord a => a -> Set a -> Set a
`Set.insert` Set [Char]
as) forall a b. (a -> b) -> a -> b
$ [Char] -> Maybe [Char]
symbolify [Char]
l
>                 , forall n. n -> State n
State [Char]
s -- the first line updates this last in foldr
>                 , Set (State [Char])
fs
>                 )
>           update [[Char]]
_ (Set (Transition [Char] [Char]), Set [Char], State [Char],
 Set (State [Char]))
partial = (Set (Transition [Char] [Char]), Set [Char], State [Char],
 Set (State [Char]))
partial


Creating an AT&T format automaton
=================================

> -- |Convert an 'FSA' into its AT&T format, with one caveat:
> -- The LTK internal format allows for symbols that the AT&T format
> -- does not understand, and no attempt is made to work around this.
> -- Nonnumeric symbols are exported as-is,
> -- while numeric symbols are necessarily mapped
> -- to their tags in the symbols file(s).
> exportATT :: (Ord n, Ord e, Show e) => FSA n e -> String
> exportATT :: forall n e. (Ord n, Ord e, Show e) => FSA n e -> [Char]
exportATT FSA n e
f = [[Char]] -> [Char]
unlines
>               forall a b. (a -> b) -> a -> b
$ forall n e.
(Ord n, Ord e, Show n, Show e, Num n) =>
[(e, Int)] -> Set (State n) -> [[Char]]
dumpInitials [(e, Int)]
tags (forall n e. FSA n e -> Set (State n)
initials FSA Integer e
f')
>               forall a. [a] -> [a] -> [a]
++ forall n e.
(Ord n, Ord e, Show n, Show e) =>
[(e, Int)]
-> Set (State n, State n, Symbol e) -> Set (State n) -> [[Char]]
dumpTransitions [(e, Int)]
tags Set (State Integer, State Integer, Symbol e)
ts (forall n e. FSA n e -> Set (State n)
initials FSA Integer e
f')
>               forall a. [a] -> [a] -> [a]
++ forall n e.
(Ord n, Ord e, Show n, Show e) =>
[(e, Int)]
-> Set (State n, State n, Symbol e) -> Set (State n) -> [[Char]]
dumpTransitions [(e, Int)]
tags Set (State Integer, State Integer, Symbol e)
ts (forall a. Ord a => Set a -> Set a -> Set a
Set.difference (forall e n. (Ord e, Ord n) => FSA n e -> Set (State n)
states FSA Integer e
f')
>                                           (forall n e. FSA n e -> Set (State n)
initials FSA Integer e
f'))
>               forall a. [a] -> [a] -> [a]
++ forall n. (Ord n, Show n) => Set (State n) -> [[Char]]
dumpFinals (forall n e. FSA n e -> Set (State n)
finals FSA Integer e
f')
>               forall a. [a] -> [a] -> [a]
++ [[Char]]
syms forall a. [a] -> [a] -> [a]
++ [[Char]]
syms -- once for input, once for output
>     where tags :: [(e, Int)]
tags = forall a b c. (a -> b -> c) -> b -> a -> c
flip forall a b. [a] -> [b] -> [(a, b)]
zip [Int
1..] forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. Set a -> [a]
Set.toAscList forall a b. (a -> b) -> a -> b
$ forall (g :: * -> *) e. HasAlphabet g => g e -> Set e
alphabet FSA Integer e
f'
>           syms :: [[Char]]
syms = [Char]
separator forall a. a -> [a] -> [a]
: forall e. (Ord e, Show e) => [(e, Int)] -> [[Char]]
dumpAlphabet [(e, Int)]
tags
>           f' :: FSA Integer e
f'   = if forall a. Set a -> Int
Set.size (forall n e. FSA n e -> Set (State n)
initials FSA n e
f) forall a. Eq a => a -> a -> Bool
== Int
1
>                  then forall e n n1.
(Ord e, Ord n, Ord n1) =>
(n -> n1) -> FSA n e -> FSA n1 e
renameStatesBy (forall a. Num a => a -> a -> a
subtract (Integer
1::Integer)) forall a b. (a -> b) -> a -> b
$
>                       forall e n n1.
(Ord e, Ord n, Ord n1, Enum n1) =>
FSA n e -> FSA n1 e
renameStates FSA n e
f
>                  else forall e n n1.
(Ord e, Ord n, Ord n1, Enum n1) =>
FSA n e -> FSA n1 e
renameStates FSA n e
f
>           ts :: Set (State Integer, State Integer, Symbol e)
ts   = forall b a. Ord b => (a -> b) -> Set a -> Set b
Set.map (\Transition Integer e
t -> (forall n e. Transition n e -> State n
source Transition Integer e
t, forall n e. Transition n e -> State n
destination Transition Integer e
t, forall n e. Transition n e -> Symbol e
edgeLabel Transition Integer e
t)) forall a b. (a -> b) -> a -> b
$
>                  forall n e. FSA n e -> Set (Transition n e)
transitions FSA Integer e
f'

> dumpAlphabet :: (Ord e, Show e) => [(e, Int)] -> [String]
> dumpAlphabet :: forall e. (Ord e, Show e) => [(e, Int)] -> [[Char]]
dumpAlphabet [(e, Int)]
tags = forall {a}. Show a => a -> Int -> [Char]
p [Char]
defaultEpsilon Int
0 forall a. a -> [a] -> [a]
: forall a b. (a -> b) -> [a] -> [b]
map (forall a b c. (a -> b -> c) -> (a, b) -> c
uncurry forall {a}. Show a => a -> Int -> [Char]
p) [(e, Int)]
tags
>     where p :: a -> Int -> [Char]
p a
a Int
t = [Char] -> [Char]
deescape (forall a. Show a => a -> [Char]
showish a
a) forall a. [a] -> [a] -> [a]
++ [Char]
"\t" forall a. [a] -> [a] -> [a]
++ forall a. Show a => a -> [Char]
show (Int
t forall a. Num a => a -> a -> a
+ (Int
0 :: Int))

> dumpInitials :: (Ord n, Ord e, Show n, Show e, Num n) =>
>                 [(e, Int)] -> Set (State n) -> [String]
> dumpInitials :: forall n e.
(Ord n, Ord e, Show n, Show e, Num n) =>
[(e, Int)] -> Set (State n) -> [[Char]]
dumpInitials [(e, Int)]
tags Set (State n)
qis
>     | forall a. Set a -> Int
Set.size Set (State n)
qis forall a. Ord a => a -> a -> Bool
< Int
2 = []
>     | Bool
otherwise = forall a b. (a -> b) -> [a] -> [b]
map (\State n
q -> forall n e.
(Ord n, Ord e, Show n, Show e) =>
[(e, Int)] -> (State n, State n, Symbol e) -> [Char]
dumpTr [(e, Int)]
tags (forall n. n -> State n
State n
0, State n
q, forall e. Symbol e
eps))
>                   forall a b. (a -> b) -> a -> b
$ forall a. Set a -> [a]
Set.toAscList Set (State n)
qis
>     where eps :: Symbol e
eps = forall e. Symbol e
Epsilon

> dumpTransitions :: (Ord n, Ord e, Show n, Show e) =>
>                    [(e, Int)] -> Set (State n, State n, Symbol e) ->
>                    Set (State n) ->
>                    [String]
> dumpTransitions :: forall n e.
(Ord n, Ord e, Show n, Show e) =>
[(e, Int)]
-> Set (State n, State n, Symbol e) -> Set (State n) -> [[Char]]
dumpTransitions [(e, Int)]
tags Set (State n, State n, Symbol e)
ts Set (State n)
qs = forall a b. (a -> b) -> [a] -> [b]
map (forall n e.
(Ord n, Ord e, Show n, Show e) =>
[(e, Int)] -> (State n, State n, Symbol e) -> [Char]
dumpTr [(e, Int)]
tags) forall a b. (a -> b) -> a -> b
$ forall a. Set a -> [a]
Set.toAscList Set (State n, State n, Symbol e)
ts'
>     where ts' :: Set (State n, State n, Symbol e)
ts' = forall a. (a -> Bool) -> Set a -> Set a
Set.filter (\(State n
a,State n
_,Symbol e
_) -> forall c a. (Container c a, Eq a) => c -> a -> Bool
isIn Set (State n)
qs State n
a) Set (State n, State n, Symbol e)
ts

> dumpTr :: (Ord n, Ord e, Show n, Show e) =>
>           [(e, Int)] -> (State n, State n, Symbol e) -> String
> dumpTr :: forall n e.
(Ord n, Ord e, Show n, Show e) =>
[(e, Int)] -> (State n, State n, Symbol e) -> [Char]
dumpTr [(e, Int)]
tags (State n
s, State n
d, Symbol e
l)
>     = forall a. [a] -> [[a]] -> [a]
intercalate [Char]
"\t"
>       [forall a. Show a => a -> [Char]
show forall a b. (a -> b) -> a -> b
$ forall n. State n -> n
nodeLabel State n
s, forall a. Show a => a -> [Char]
show forall a b. (a -> b) -> a -> b
$ forall n. State n -> n
nodeLabel State n
d, [Char]
l', [Char]
l']
>     where l' :: [Char]
l' = case Symbol e
l
>                of Symbol e
e -> e -> [Char]
f e
e
>                   Symbol e
_        -> [Char]
defaultEpsilon
>           f :: e -> [Char]
f e
e
>               | forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
all Char -> Bool
isDigit (forall a. Show a => a -> [Char]
showish e
e)
>                   = forall a. [a] -> a
head
>                     forall b c a. (b -> c) -> (a -> b) -> a -> c
. (forall a. [a] -> [a] -> [a]
++ [forall a. Show a => a -> [Char]
showish e
e]) forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a b. (a -> b) -> [a] -> [b]
map (forall a. Show a => a -> [Char]
showish forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a b. (a, b) -> b
snd)
>                     forall a b. (a -> b) -> a -> b
$ forall a. (a -> Bool) -> [a] -> [a]
filter ((forall a. Eq a => a -> a -> Bool
== e
e) forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a b. (a, b) -> a
fst) [(e, Int)]
tags
>               | Bool
otherwise = [Char] -> [Char]
deescape (forall a. Show a => a -> [Char]
showish e
e)

> dumpFinals :: (Ord n, Show n) => Set (State n) -> [String]
> dumpFinals :: forall n. (Ord n, Show n) => Set (State n) -> [[Char]]
dumpFinals = forall a b. (a -> b) -> [a] -> [b]
map (forall a. Show a => a -> [Char]
show forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall n. State n -> n
nodeLabel) forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. Set a -> [a]
Set.toAscList


Helpers
=======

> splitOn :: Eq a => a -> [a] -> [[a]]
> splitOn :: forall a. Eq a => a -> [a] -> [[a]]
splitOn a
_ [] = [[]]
> splitOn a
b (a
a:[a]
as)
>     | a
a forall a. Eq a => a -> a -> Bool
== a
b = []forall a. a -> [a] -> [a]
:[[a]]
x
>     | Bool
otherwise = (a
aforall a. a -> [a] -> [a]
:forall a. [a] -> a
head [[a]]
x)forall a. a -> [a] -> [a]
:forall {a}. [a] -> [a]
tail [[a]]
x
>     where x :: [[a]]
x = forall a. Eq a => a -> [a] -> [[a]]
splitOn a
b [a]
as

> showish :: Show a => a -> String
> showish :: forall a. Show a => a -> [Char]
showish = [Char] -> [Char]
f forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. Show a => a -> [Char]
show
>     where f :: [Char] -> [Char]
f  [Char]
xs     = if forall a. Int -> [a] -> [a]
take Int
1 [Char]
xs forall a. Eq a => a -> a -> Bool
== [Char]
"\"" then [Char] -> [Char]
f' (forall a. Int -> [a] -> [a]
drop Int
1 [Char]
xs) else [Char]
xs
>           f' :: [Char] -> [Char]
f' [Char]
""     = [Char]
""
>           f' [Char]
"\""   = [Char]
""
>           f' (Char
x:[Char]
xs) = Char
x forall a. a -> [a] -> [a]
: [Char] -> [Char]
f' [Char]
xs

> deescape :: String -> String
> deescape :: [Char] -> [Char]
deescape (Char
'\\' : Char
'&' : [Char]
xs) = [Char] -> [Char]
deescape [Char]
xs
> deescape (Char
'\\' : Char
x : [Char]
xs)
>     | forall c a. Container c a => c -> Bool
isEmpty [Char]
digits = Char
x forall a. a -> [a] -> [a]
: [Char] -> [Char]
deescape [Char]
xs
>     | Bool
otherwise      = forall a. Enum a => Int -> a
toEnum (forall a. Read a => [Char] -> a
read [Char]
digits) forall a. a -> [a] -> [a]
: [Char] -> [Char]
deescape [Char]
others
>     where ([Char]
digits, [Char]
others) = forall a. (a -> Bool) -> [a] -> ([a], [a])
span (forall c a. (Container c a, Eq a) => c -> a -> Bool
isIn [Char]
"0123456789") (Char
xforall a. a -> [a] -> [a]
:[Char]
xs)
> deescape (Char
x:[Char]
xs) = Char
x forall a. a -> [a] -> [a]
: [Char] -> [Char]
deescape [Char]
xs
> deescape [Char]
_      = []