Visualize DFAs over a finite set of tokens
This commit is contained in:
parent
868f4e203f
commit
0656a2faf4
2 changed files with 28 additions and 9 deletions
|
|
@ -6,6 +6,7 @@ module Rextra.Dfa
|
||||||
( Dfa
|
( Dfa
|
||||||
, dfa
|
, dfa
|
||||||
, State(..)
|
, State(..)
|
||||||
|
, stateTransition
|
||||||
, normalize
|
, normalize
|
||||||
, mapState
|
, mapState
|
||||||
, transitionsByState
|
, transitionsByState
|
||||||
|
|
@ -25,6 +26,12 @@ data State s t = State
|
||||||
, defaultTransition :: s
|
, defaultTransition :: s
|
||||||
} deriving (Show, Eq, Ord)
|
} deriving (Show, Eq, Ord)
|
||||||
|
|
||||||
|
stateTransition :: (Ord t) => State s t -> t -> s
|
||||||
|
stateTransition state token =
|
||||||
|
case transitions state Map.!? token of
|
||||||
|
Nothing -> defaultTransition state
|
||||||
|
Just s -> s
|
||||||
|
|
||||||
normalize :: (Eq s) => State s t -> State s t
|
normalize :: (Eq s) => State s t -> State s t
|
||||||
normalize State{transitions, defaultTransition} =
|
normalize State{transitions, defaultTransition} =
|
||||||
State { transitions = Map.filter (/= defaultTransition) transitions
|
State { transitions = Map.filter (/= defaultTransition) transitions
|
||||||
|
|
@ -50,16 +57,9 @@ type Dfa s t = Fa State s t
|
||||||
|
|
||||||
instance (Ord s) => Executable (Fa State s) s where
|
instance (Ord s) => Executable (Fa State s) s where
|
||||||
startState = entryState
|
startState = entryState
|
||||||
transition = dfaTransition
|
transition a s = stateTransition (getState a s)
|
||||||
accepts a s = s `Set.member` exitStates a
|
accepts a s = s `Set.member` exitStates a
|
||||||
|
|
||||||
dfaTransition :: (Ord s, Ord t) => Dfa s t -> s -> t -> s
|
|
||||||
dfaTransition a s t =
|
|
||||||
let state = getState a s
|
|
||||||
in case transitions state Map.!? t of
|
|
||||||
(Just nextState) -> nextState
|
|
||||||
Nothing -> defaultTransition state
|
|
||||||
|
|
||||||
dfa :: (Ord s, Ord t) => [(s, [(t, s)], s)] -> s -> [s] -> Maybe (Dfa s t)
|
dfa :: (Ord s, Ord t) => [(s, [(t, s)], s)] -> s -> [s] -> Maybe (Dfa s t)
|
||||||
dfa stateInfo entryState exitStates =
|
dfa stateInfo entryState exitStates =
|
||||||
let stateList = map (\(s, ts, dt) -> (s, State (Map.fromList ts) dt)) stateInfo
|
let stateList = map (\(s, ts, dt) -> (s, State (Map.fromList ts) dt)) stateInfo
|
||||||
|
|
|
||||||
|
|
@ -1,16 +1,26 @@
|
||||||
{-# LANGUAGE FlexibleInstances #-}
|
{-# LANGUAGE FlexibleInstances #-}
|
||||||
|
|
||||||
module Rextra.Visualize where
|
module Rextra.Visualize
|
||||||
|
( showDot
|
||||||
|
, saveDot
|
||||||
|
, saveDotAsPng
|
||||||
|
, dfaToDot
|
||||||
|
, dfaToDotNoDefault
|
||||||
|
, dfaToDotWithTokens
|
||||||
|
, nfaToDot
|
||||||
|
) where
|
||||||
|
|
||||||
import Control.Monad
|
import Control.Monad
|
||||||
import Data.GraphViz
|
import Data.GraphViz
|
||||||
import Data.List
|
import Data.List
|
||||||
import qualified Data.Map as Map
|
import qualified Data.Map as Map
|
||||||
import qualified Data.Set as Set
|
import qualified Data.Set as Set
|
||||||
|
import Data.Tuple
|
||||||
|
|
||||||
import qualified Rextra.Dfa as Dfa
|
import qualified Rextra.Dfa as Dfa
|
||||||
import Rextra.Fa
|
import Rextra.Fa
|
||||||
import qualified Rextra.Nfa as Nfa
|
import qualified Rextra.Nfa as Nfa
|
||||||
|
import Rextra.Util
|
||||||
|
|
||||||
-- First, some labelling...
|
-- First, some labelling...
|
||||||
|
|
||||||
|
|
@ -105,6 +115,15 @@ dfaToDot = faToDot dfaShowAll
|
||||||
dfaToDotNoDefault :: (Ord s, AsLabel s, Ord t, AsLabel t) => Dfa.Dfa s t -> DotGraph String
|
dfaToDotNoDefault :: (Ord s, AsLabel s, Ord t, AsLabel t) => Dfa.Dfa s t -> DotGraph String
|
||||||
dfaToDotNoDefault = faToDot dfaShowNoDefault
|
dfaToDotNoDefault = faToDot dfaShowNoDefault
|
||||||
|
|
||||||
|
dfaShowTokens :: (Ord s, Ord t, AsLabel t) => Set.Set t -> Dfa.State s t -> [(String, s)]
|
||||||
|
dfaShowTokens tokens state =
|
||||||
|
let bareEdges = Map.assocs $ Map.fromSet (Dfa.stateTransition state) tokens
|
||||||
|
groupedEdges = Map.assocs $ groupByFirst $ map swap bareEdges
|
||||||
|
in map (\(s, t) -> (asLabel t, s)) groupedEdges
|
||||||
|
|
||||||
|
dfaToDotWithTokens :: (Ord s, AsLabel s, Ord t, AsLabel t) => [t] -> Dfa.Dfa s t -> DotGraph String
|
||||||
|
dfaToDotWithTokens tokenList = faToDot $ dfaShowTokens $ Set.fromList tokenList
|
||||||
|
|
||||||
{-
|
{-
|
||||||
- 'Nfa' stuff
|
- 'Nfa' stuff
|
||||||
-}
|
-}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue