Add DFA and NFA representations
This commit is contained in:
parent
a6fdf546c3
commit
4cae9af848
3 changed files with 84 additions and 0 deletions
|
|
@ -21,6 +21,9 @@ description: Please see the README on GitHub at <https://github.com/gith
|
||||||
|
|
||||||
dependencies:
|
dependencies:
|
||||||
- base >= 4.7 && < 5
|
- base >= 4.7 && < 5
|
||||||
|
- transformers >= 0.5.6 && < 0.6
|
||||||
|
- containers >= 0.6 && < 0.7
|
||||||
|
# algebraic-graphs >= 0.4 && < 0.5
|
||||||
|
|
||||||
library:
|
library:
|
||||||
source-dirs: src
|
source-dirs: src
|
||||||
|
|
|
||||||
36
src/Rextra/Dfa.hs
Normal file
36
src/Rextra/Dfa.hs
Normal file
|
|
@ -0,0 +1,36 @@
|
||||||
|
module Rextra.Dfa where
|
||||||
|
-- TODO don't export internals
|
||||||
|
|
||||||
|
import qualified Data.Map.Strict as Map
|
||||||
|
import qualified Data.Set as Set
|
||||||
|
|
||||||
|
data State s t = State
|
||||||
|
{ transitions :: Map.Map t s
|
||||||
|
, defaultTransition :: s
|
||||||
|
, accepting :: Bool
|
||||||
|
}
|
||||||
|
|
||||||
|
data Dfa s t = Dfa
|
||||||
|
{ dfaStates :: Map.Map s (State s t)
|
||||||
|
, dfaEntryState :: s
|
||||||
|
}
|
||||||
|
|
||||||
|
{-
|
||||||
|
- Constructing and modifying a DFA
|
||||||
|
-}
|
||||||
|
|
||||||
|
-- TODO
|
||||||
|
|
||||||
|
{-
|
||||||
|
- "Executing" a DFA
|
||||||
|
-}
|
||||||
|
|
||||||
|
getState :: (Ord s) => Dfa s t -> s -> State s t
|
||||||
|
getState dfa s = dfaStates dfa Map.! s
|
||||||
|
|
||||||
|
transition :: (Ord s, Ord t) => Dfa s t -> s -> t -> s
|
||||||
|
transition dfa s t =
|
||||||
|
let state = getState dfa s
|
||||||
|
in case transitions state Map.!? t of
|
||||||
|
(Just nextState) -> nextState
|
||||||
|
Nothing -> defaultTransition state
|
||||||
45
src/Rextra/Nfa.hs
Normal file
45
src/Rextra/Nfa.hs
Normal file
|
|
@ -0,0 +1,45 @@
|
||||||
|
module Rextra.Nfa where
|
||||||
|
-- TODO don't export internals
|
||||||
|
|
||||||
|
import qualified Data.Map.Strict as Map
|
||||||
|
import qualified Data.Set as Set
|
||||||
|
|
||||||
|
data TransitionCondition t
|
||||||
|
= Only (Set.Set t)
|
||||||
|
| AllExcept (Set.Set t)
|
||||||
|
|
||||||
|
specialStates :: TransitionCondition t -> Set.Set t
|
||||||
|
specialStates (Only s) = s
|
||||||
|
specialStates (AllExcept s) = s
|
||||||
|
|
||||||
|
accepts :: (Ord t) => TransitionCondition t -> t -> Bool
|
||||||
|
accepts (Only s) t = Set.member t s
|
||||||
|
accepts (AllExcept s) t = Set.notMember t s
|
||||||
|
|
||||||
|
type State s t = [(TransitionCondition t, s)]
|
||||||
|
|
||||||
|
data Nfa s t = Nfa
|
||||||
|
{ nfaStates :: Map.Map s (State s t)
|
||||||
|
, nfaEntryState :: s
|
||||||
|
, nfaExitStates :: Set.Set s
|
||||||
|
}
|
||||||
|
|
||||||
|
{-
|
||||||
|
- Constructing and modifying a NFA
|
||||||
|
-}
|
||||||
|
|
||||||
|
-- TODO
|
||||||
|
|
||||||
|
{-
|
||||||
|
- "Executing" a NFA
|
||||||
|
-}
|
||||||
|
|
||||||
|
getState :: (Ord s) => Nfa s t -> s -> State s t
|
||||||
|
getState nfa s = nfaStates nfa Map.! s
|
||||||
|
|
||||||
|
-- * Starting from a state, find all the states that it can transition to with token 't'.
|
||||||
|
nextStates :: (Ord s, Ord t) => State s t -> t -> Set.Set s
|
||||||
|
nextStates state t = Set.fromList . map snd . filter (\(cond, _) -> cond `accepts` t) $ state
|
||||||
|
|
||||||
|
nfaTransition :: (Ord s, Ord t) => Nfa s t -> Set.Set s -> t -> Set.Set s
|
||||||
|
nfaTransition nfa ss t = foldMap (\s -> nextStates (getState nfa s) t) ss
|
||||||
Loading…
Add table
Add a link
Reference in a new issue