packages feed

adp-multi-0.1.1: tests/ADP/Combinators.hs

{-
ADP combinators and functions from:

R. Giegerich, C. Meyer and P. Steffen. Towards a discipline of dynamic
programming.
-}

module ADP.Combinators where
import Data.Array

-- # Lexical parsers


type Subword  = (Int,Int)
type Parser b = Subword -> [b]

empty        :: Parser ()
empty  (i,j) =  [() | i == j]

acharSep'           ::  Array Int Char -> Char -> Parser Char
acharSep' z s (i,j) =  [z!j | i+1 == j, z!j /= s] 

achar'         :: Array Int a -> Parser a
achar' z (i,j) = [z!j | i+1 == j]

char'           ::  Eq a => Array Int a -> a -> Parser a
char' z c (i,j) =  [c | i+1 == j, z!j == c]

astring       :: Parser Subword
astring (i,j) =  [(i,j) | i <= j]

string'           :: Eq a => Array Int a -> [a] -> Parser Subword
string' z s (i,j) = [(i,j)| and [z!(i+k) == s!!(k-1) | k <-[1..(j-i)]]]

-- # Parser combinators

infixr 6 ||| 
(|||)           :: Parser b -> Parser b -> Parser b
(|||) r q (i,j) = r (i,j) ++ q (i,j)

infix  8 <<<
(<<<)           :: (b -> c) -> Parser b -> Parser c
(<<<) f q (i,j) =  map f (q (i,j))

infixl 7 ~~~
(~~~)           :: Parser (b -> c) -> Parser b -> Parser c
(~~~) r q (i,j) =  [f y | k <- [i..j], f <- r (i,k), y <- q (k,j)]

infix  5 ...
(...)           :: Parser b -> ([b] -> [b]) -> Parser b
(...) r h (i,j) = h (r (i,j))


type Filter    =  (Int, Int) -> Bool
with           :: Parser b -> Filter -> Parser b
with q c (i,j) =  if c (i,j) then q (i,j)  else []

axiom'        :: Int -> Parser b -> [b]
axiom' l ax   =  ax (0,l) 

-- # Tabulation

-- two-dimensional tabulation
table     :: Int -> Parser b -> Parser b
table n q =  (!) $ array ((0,0),(n,n))
                   [((i,j),q (i,j)) | i<- [0..n], j<- [i..n]]

-- one-dimensional tabulation; index j fixed
listi :: Int -> Parser b -> Parser b
listi n p = q $ array (0,n) [(i, p (i,n)) | i <- [0..n]] 
   where
   q t (i,j) = if j==n then t!i else []

-- one-dimensional tabulation; index i fixed
listj :: Int -> Parser b -> Parser b
listj n p = q $ array (0,n) [(j, p (0,j)) | j <- [0..n]] 
   where
   q t (i,j) = if i==0 then t!j else []

-- the most common listed type is listi (input read from left
-- to right), so we define a default list here:
list :: Int -> Parser b -> Parser b
list = listi

-- # Variants of the <<< and ~~~ Combinators

infix  8 ><<
infixl 7 ~~, ~~*, *~~, *~*
infixl 7 -~~, ~~-, +~~, ~~+, +~+

-- The operator ><< is the special case of <<< for a nullary function f

(><<)           :: c -> Parser b -> Parser c
(><<) f q (i,j) =  [f|a <- (q (i,j))]

-- Subwords on left and right of an explicit length range.

(~~) :: (Int,Int) -> (Int,Int) 
     -> Parser (b -> c) -> Parser b -> Parser c
(~~) (l,u) (l',u') r q (i,j) 
     = [x y | k <- [max (i+l) (j-u') .. min (i+u) (j-l')],
              x <- r (i,k), y <- q (k,j)]

-- Subwords of explicit length range and unbounded length on one or on either side.

(~~*) :: (Int,Int) -> Int 
      -> Parser (a -> b) -> Parser a -> Parser b 
(~~*) (l, u) l' r q (i, j) 
      = [x y | k <- [(i + l) .. min (i + u) (j - l')], 
               x <- r (i, k), y <- q (k, j)] 

(*~~) :: Int -> (Int,Int) 
      -> Parser (a -> b) -> Parser a -> Parser b 
(*~~) l (l', u') r q (i, j) 
      = [x y | k <- [max (i + l) (j - u') .. (j - l')], 
          x <- r (i, k), y <- q (k, j)] 

(*~*) :: Int -> Int 
      -> Parser (a -> b) -> Parser a -> Parser b 
(*~*) l l' r q (i, j) 
      = [x y | k <- [(i + l) .. (j - l')], 
               x <- r (i, k), y <- q (k, j)] 

-- Single character on the lefthand (respectively righthand) side

(-~~)           :: Parser (b -> c) -> Parser b -> Parser c
(-~~) q r (i,j) = [x y | i<j, x <- q (i,i+1), y <- r (i+1,j)]

(~~-)           :: Parser (b -> c) -> Parser b -> Parser c
(~~-) q r (i,j) = [x y | i<j, x <- q (i,j-1), y <- r (j-1,j)]

-- Nonempty sequence on the lefthand (respectively righthand) side

(+~~)           :: Parser (b -> c) -> Parser b -> Parser c
(+~~) r q (i,j) =  [f y | k <- [i+1..j], f <- r (i,k), y <- q (k,j)]  

(~~+)           :: Parser (b -> c) -> Parser b -> Parser c
(~~+) r q (i,j) =  [f y | k <- [i..j-1], f <- r (i,k), y <- q (k,j)]  

-- Nonempty sequence on either side

(+~+)           :: Parser (b -> c) -> Parser b -> Parser c
(+~+) r q (i,j) = [f y | k <- [(i+1)..(j-1)], f <- r (i,k), y <- q (k,j)]  


-- # Create array from List

mk :: [a] -> Array Int a
mk xs = array (1,n) (zip [1..n] xs) where n = length xs