src/Math/Model/Automaton/Stack.hs
{-# OPTIONS_GHC -fno-warn-tabs #-}
{-# OPTIONS_HADDOCK show-extensions #-}
{-# LANGUAGE TypeOperators #-}
{-|
Module : StackA
Description : Stack Automaton
Copyright : (c) Jorge Santiago Alvarez Cuadros, 2016
License : GPL-3
Maintainer : sanjorgek@ciencias.unam.mx
Stability : experimental
Portability : portable
Stack Automaton
-}
module Math.Model.Automaton.Stack where
import Data.Delta
import qualified Data.Foldable as Fold
import Data.List
import qualified Data.Map.Strict as Map
import Data.Sigma
import Data.Label
import Control.Monad.State.Lazy
{-|
Delta for stack machine, takes a state, a symbol in string input or not and a
symbol in stack head and returns next state and update stack
-}
type Delta a = (:->:) a (Maybe Symbol, Symbol) Wd
{-|
A key for a delta.
-}
type Key a = (Label a, (Maybe Symbol, Symbol))
{-|
Takes a list of tuples and lift a Delta
>>>let delta = liftD [(0,"(",'Z',0,"IZ"),(0,"",'Z',0,""),(0,"(",'I',0,"II"),(0,")",'I',0,"")]
-}
liftDelta:: Ord a => [(a, Wd, Symbol, a, Wd)]-> Delta a
liftDelta xs = let
(as,bs,cs,ds,es) = unzip5 xs
f = fmap Q
g [] = Nothing
g (x:_) = Just x
ps = zip (fmap g bs) cs
ks = zip (f as) ps
rs = zip (f ds) es
in Map.fromList (zip ks rs)
nextDTuple :: Ord a => Delta a -> Key a -> (Label a, Wd)
nextDTuple dt k = if Map.member k dt then dt Map.! k else (QE,[])
-- |Stack machine only needs a delta, an init state and an initial symbol.
--
-- This works for empty stack and final state acceptor
data StackA a = Stack {
getDelta::Delta a
,getInitState::Label a
,getFinal::Final a
,getInitSymbol::Symbol} deriving(Show, Eq)
nextState::(Ord a) => Delta a -> Wd -> State (Wd, Label a) (Label a)
nextState _ [] = do
(_, q) <- get
return q