Slightly change DFA visualization
Transitions to the same state are now clumped together as one arrow.
This commit is contained in:
parent
e8168e5f35
commit
ae84e1a148
3 changed files with 26 additions and 19 deletions
|
|
@ -17,17 +17,6 @@ import qualified Rextra.Nfa as Nfa
|
||||||
- Converting a DFA to a NFA
|
- Converting a DFA to a NFA
|
||||||
-}
|
-}
|
||||||
|
|
||||||
fromMonoidalList :: (Monoid m, Ord k) => [(k, m)] -> Map.Map k m
|
|
||||||
fromMonoidalList = foldl' insertMonoidal Map.empty
|
|
||||||
where
|
|
||||||
insertMonoidal :: (Monoid m, Ord k) => Map.Map k m -> (k, m) -> Map.Map k m
|
|
||||||
insertMonoidal map (k, m) = Map.insertWith mappend k m map
|
|
||||||
|
|
||||||
groupByFirst :: (Ord a, Ord b) => [(a, b)] -> [(a, Set.Set b)]
|
|
||||||
groupByFirst pairs =
|
|
||||||
let prepared = map (\(a, b) -> (a, Set.singleton b)) pairs
|
|
||||||
in Map.assocs $ fromMonoidalList prepared
|
|
||||||
|
|
||||||
dfaStateToNfaState :: (Ord s, Ord t) => Dfa.State s t -> Nfa.State s t
|
dfaStateToNfaState :: (Ord s, Ord t) => Dfa.State s t -> Nfa.State s t
|
||||||
dfaStateToNfaState s =
|
dfaStateToNfaState s =
|
||||||
let transitionMap = Dfa.transitions s
|
let transitionMap = Dfa.transitions s
|
||||||
|
|
@ -35,9 +24,8 @@ dfaStateToNfaState s =
|
||||||
defaultTransition = (Nfa.AllExcept specialTokens, Dfa.defaultTransition s)
|
defaultTransition = (Nfa.AllExcept specialTokens, Dfa.defaultTransition s)
|
||||||
otherTransitions = map (\(tSet, s) -> (Nfa.Only tSet, s))
|
otherTransitions = map (\(tSet, s) -> (Nfa.Only tSet, s))
|
||||||
. map swap
|
. map swap
|
||||||
. groupByFirst
|
. Map.assocs
|
||||||
. map swap
|
$ Dfa.transitionsByState transitionMap
|
||||||
$ Map.assocs transitionMap
|
|
||||||
in Nfa.State { Nfa.transitions = defaultTransition : otherTransitions
|
in Nfa.State { Nfa.transitions = defaultTransition : otherTransitions
|
||||||
, Nfa.epsilonTransitions = Set.empty
|
, Nfa.epsilonTransitions = Set.empty
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,7 @@ module Rextra.Dfa (
|
||||||
, stateMap
|
, stateMap
|
||||||
, entryState
|
, entryState
|
||||||
, exitStates
|
, exitStates
|
||||||
|
, transitionsByState
|
||||||
-- ** Executing
|
-- ** Executing
|
||||||
, transition
|
, transition
|
||||||
, execute
|
, execute
|
||||||
|
|
@ -20,6 +21,7 @@ module Rextra.Dfa (
|
||||||
import Data.List
|
import Data.List
|
||||||
import qualified Data.Map.Strict as Map
|
import qualified Data.Map.Strict as Map
|
||||||
import qualified Data.Set as Set
|
import qualified Data.Set as Set
|
||||||
|
import Data.Tuple
|
||||||
|
|
||||||
import Rextra.Util
|
import Rextra.Util
|
||||||
|
|
||||||
|
|
@ -50,6 +52,20 @@ data State s t = State
|
||||||
|
|
||||||
type StateMap s t = Map.Map s (State s t)
|
type StateMap s t = Map.Map s (State s t)
|
||||||
|
|
||||||
|
fromMonoidalList :: (Monoid m, Ord k) => [(k, m)] -> Map.Map k m
|
||||||
|
fromMonoidalList = foldl' insertMonoidal Map.empty
|
||||||
|
where
|
||||||
|
insertMonoidal :: (Monoid m, Ord k) => Map.Map k m -> (k, m) -> Map.Map k m
|
||||||
|
insertMonoidal map (k, m) = Map.insertWith mappend k m map
|
||||||
|
|
||||||
|
groupByFirst :: (Ord a, Ord b) => [(a, b)] -> Map.Map a (Set.Set b)
|
||||||
|
groupByFirst pairs =
|
||||||
|
let prepared = map (\(a, b) -> (a, Set.singleton b)) pairs
|
||||||
|
in fromMonoidalList prepared
|
||||||
|
|
||||||
|
transitionsByState :: (Ord s, Ord t) => Map.Map t s -> Map.Map s (Set.Set t)
|
||||||
|
transitionsByState = groupByFirst . map swap . Map.assocs
|
||||||
|
|
||||||
{-
|
{-
|
||||||
- Constructing
|
- Constructing
|
||||||
-}
|
-}
|
||||||
|
|
|
||||||
|
|
@ -28,14 +28,20 @@ saveDot format path dg = void $ runGraphviz dg format path
|
||||||
saveDotAsPng :: String -> DotGraph Node -> IO ()
|
saveDotAsPng :: String -> DotGraph Node -> IO ()
|
||||||
saveDotAsPng = saveDot Png
|
saveDotAsPng = saveDot Png
|
||||||
|
|
||||||
|
labelFromSet :: Set.Set Char -> String
|
||||||
|
labelFromSet charSet = "{" ++ intersperse ',' (Set.toList charSet) ++ "}"
|
||||||
|
|
||||||
{-
|
{-
|
||||||
- Visualizing DFAs
|
- Visualizing DFAs
|
||||||
-}
|
-}
|
||||||
|
|
||||||
convertDfaState :: (Int, Dfa.State Int Char) -> [LEdge String]
|
convertDfaState :: (Int, Dfa.State Int Char) -> [LEdge String]
|
||||||
convertDfaState (from, state) =
|
convertDfaState (from, state) =
|
||||||
let normalEdges = map (\(t, to) -> (from, to, [t])) . Map.assocs $ Dfa.transitions state
|
let normalEdges = map (\(to, tSet) -> (from, to, labelFromSet tSet))
|
||||||
defaultEdge = (from, Dfa.defaultTransition state, "**")
|
. Map.assocs
|
||||||
|
. Dfa.transitionsByState
|
||||||
|
$ Dfa.transitions state
|
||||||
|
defaultEdge = (from, Dfa.defaultTransition state, "*")
|
||||||
in defaultEdge : normalEdges
|
in defaultEdge : normalEdges
|
||||||
|
|
||||||
-- | Convert a 'Dfa.Dfa' to a 'Gr' graph.
|
-- | Convert a 'Dfa.Dfa' to a 'Gr' graph.
|
||||||
|
|
@ -71,9 +77,6 @@ dfaToDot dfa = graphToDot (dfaAttributes dfa) (dfaToGraph dfa)
|
||||||
- Visualizing NFAs
|
- Visualizing NFAs
|
||||||
-}
|
-}
|
||||||
|
|
||||||
labelFromSet :: Set.Set Char -> String
|
|
||||||
labelFromSet charSet = "{" ++ intersperse ',' (Set.toList charSet) ++ "}"
|
|
||||||
|
|
||||||
labelFromCondition :: Nfa.TransitionCondition Char -> String
|
labelFromCondition :: Nfa.TransitionCondition Char -> String
|
||||||
labelFromCondition (Nfa.Only charSet) = labelFromSet charSet
|
labelFromCondition (Nfa.Only charSet) = labelFromSet charSet
|
||||||
labelFromCondition (Nfa.AllExcept charSet)
|
labelFromCondition (Nfa.AllExcept charSet)
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue