{- |
API for finite state automatons
-}
module FST.AutomatonInterface (
module FST.RegTypes,
module FST.AutomatonTypes,

-- * Types
Automaton,

-- * Construction of automatons
compile,
compileNFA,

-- * Transformation of automatons
determinize,
minimize,
complete,

-- * Query inforation about automatons
initial,
numberOfStates,
numberOfTransitions,
showAutomaton,
) where

import FST.Automaton
import FST.AutomatonTypes
import FST.Complete
import qualified FST.Deterministic as D
import qualified FST.LBFA as L
import FST.RegTypes hiding (reversal)
import FST.Reversal (reversal)

-- | Compile a non-deterministic finite-state automaton
compileNFA :: Ord a => Reg a -> Sigma a -> StateTy -> Automaton a
compileNFA = L.compileToAutomaton

-- | Minimize an automaton using the Brzozowski algorithm. Note that
-- the determinize function must construct an automaton with the
-- usefulS property.
minimize :: Ord a => Automaton a -> Automaton a
minimize = determinize . reversal . determinize . reversal
{-# SPECIALIZE minimize :: Automaton String -> Automaton String #-}

-- | Make a non-deterministic finite-state automaton deterministic
determinize :: Ord a => Automaton a -> Automaton a
determinize = D.determinize

-- | Compile a minimized non-deterministic finite-state automaton
compile :: Ord a => Reg a -> Sigma a -> StateTy -> Automaton a
compile reg sigma s = minimize \$ L.compileToAutomaton reg sigma s

-- | Get the initial state of a finite-state automaton
initial :: Automaton a -> StateTy
initial automaton = head \$ initials automaton

-- | Count the number of states in a finite-state automaton
numberOfStates :: Ord a => Automaton a -> Int
numberOfStates auto = length \$ states auto

-- | Count the number of transitions in a finite-state automaton
numberOfTransitions :: Ord a => Automaton a -> Int
numberOfTransitions auto = sum [length (transitionList auto s)
| s <- states auto]