diff --git a/package.yaml b/package.yaml index 753a614..923dbe3 100644 --- a/package.yaml +++ b/package.yaml @@ -21,6 +21,9 @@ description: Please see the README on GitHub at = 4.7 && < 5 +- transformers >= 0.5.6 && < 0.6 +- containers >= 0.6 && < 0.7 +# algebraic-graphs >= 0.4 && < 0.5 library: source-dirs: src diff --git a/src/Rextra/Dfa.hs b/src/Rextra/Dfa.hs new file mode 100644 index 0000000..e1312ee --- /dev/null +++ b/src/Rextra/Dfa.hs @@ -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 diff --git a/src/Rextra/Nfa.hs b/src/Rextra/Nfa.hs new file mode 100644 index 0000000..f26da9f --- /dev/null +++ b/src/Rextra/Nfa.hs @@ -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