summaryrefslogtreecommitdiff
path: root/edit-lens/src/Control/FST.lhs
diff options
context:
space:
mode:
Diffstat (limited to 'edit-lens/src/Control/FST.lhs')
-rw-r--r--edit-lens/src/Control/FST.lhs53
1 files changed, 51 insertions, 2 deletions
diff --git a/edit-lens/src/Control/FST.lhs b/edit-lens/src/Control/FST.lhs
index 4f1f364..9298e11 100644
--- a/edit-lens/src/Control/FST.lhs
+++ b/edit-lens/src/Control/FST.lhs
@@ -24,11 +24,11 @@ import qualified Data.Set as Set
24import Data.Sequence (Seq) 24import Data.Sequence (Seq)
25import qualified Data.Sequence as Seq 25import qualified Data.Sequence as Seq
26 26
27import Data.Maybe (mapMaybe, fromMaybe) 27import Data.Maybe (mapMaybe, fromMaybe, isJust, fromJust)
28 28
29import Numeric.Natural 29import Numeric.Natural
30 30
31import Control.Lens.TH 31import Control.Lens
32 32
33import Control.Monad.State.Strict 33import Control.Monad.State.Strict
34 34
@@ -59,6 +59,55 @@ instance (Show state, Show input, Show output) => Pretty (FST state input output
59 list :: [PP.Doc] -> PP.Doc 59 list :: [PP.Doc] -> PP.Doc
60 list = PP.encloseSep (PP.lbracket PP.<> PP.space) (PP.space PP.<> PP.rbracket) (PP.comma PP.<> PP.space) 60 list = PP.encloseSep (PP.lbracket PP.<> PP.space) (PP.space PP.<> PP.rbracket) (PP.comma PP.<> PP.space)
61 61
62runFST :: forall input output state. (Ord input, Ord output, Ord state) => FST state input output -> Seq input -> [Seq output]
63runFST = fmap (map $ catMaybes . fmap (view _2) . view _2) . runFST'
64 where
65 catMaybes = fmap fromJust . Seq.filter isJust
66
67runFST' :: forall input output state. (Ord input, Ord output, Ord state)
68 => FST state input output
69 -> Seq input
70 -> [(state, Seq (state, Maybe output))] -- ^ Tuples of initial state and chosen transitions; not neccessarily finite
71-- ^ Compute all possible runs on the given input
72runFST' fst Seq.Empty = guardAccept $ (\(_, st, _) -> (st, Seq.Empty)) <$> step fst Nothing Nothing
73runFST' fst cs = guardAccept $ do
74 initial <- view _2 <$> step fst Nothing Nothing
75 go (initial, Seq.Empty) cs
76 where
77 guardAccept res = do
78 (initial, path) <- res
79 let
80 finalState
81 | (_ :> (st, _)) <- path = st
82 | otherwise = initial
83 guard $ finalState `Set.member` stAccept
84 return res
85
86 go :: (state, Seq (state, Maybe output)) -> Seq input-> [(state, Seq (state, Maybe output))]
87 go (initial, path) cs = do
88 let
89 current
90 | (_ :> (st, _)) <- path = st
91 | otherwise = initial
92 (head, next, out) <- step fst (Just current) (Seq.lookup 0 cs)
93 let
94 nPath = path :> (next, out)
95 ncs = maybe id (:<) head cs
96 go (initial, nPath) ncs
97
98
99step :: forall input output state. (Ord input, Ord output, Ord state)
100 => FST state input output
101 -> Maybe state -- ^ Current state
102 -> Maybe input -- ^ Head of remaining input
103 -> [(Maybe input, state, Maybe output)] -- ^ Tuples of unconsumed input, next state, and produced output
104step FST{..} Nothing inS = (\s -> (inS, s, Nothing)) <$> Set.toList stInitial
105step FST{..} (Just c) inS = let
106 consuming = fromMaybe Set.empty $ Map.lookup (c, inS) stTransition
107 unconsuming = fromMaybe Set.empty $ Map.lookup (c, Nothing) stTransition
108 in Set.toList $ Set.map (\(n, mOut) -> (Nothing, n, mOut)) consuming `Set.union` Set.map (\(n, mOut) -> (inS, n, mOut)) unconsuming
109
110
62wordFST :: forall input output. Seq output -> FST Natural input output 111wordFST :: forall input output. Seq output -> FST Natural input output
63-- ^ @wordFST str@ is the linear FST generating @str@ as output when given no input 112-- ^ @wordFST str@ is the linear FST generating @str@ as output when given no input
64wordFST outs = FST 113wordFST outs = FST