--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/progs/haskell/re.hs Fri Aug 15 14:10:58 2014 +0100
@@ -0,0 +1,400 @@
+import System.Environment
+import Data.List
+import Text.Printf
+import Control.Exception
+import System.CPUTime
+import Control.Parallel.Strategies
+import Control.Monad
+
+lim :: Int
+lim = 1
+-- lim = 10^6
+
+time :: (Num t, NFData t) => t -> IO ()
+time y = do
+ start <- getCPUTime
+ replicateM_ lim $ do
+ x <- evaluate $ 1 + y
+ rdeepseq x `seq` return ()
+ end <- getCPUTime
+ let diff = (fromIntegral (end - start)) / (10^12)
+ printf "%0.9f\n" (diff :: Double)
+ return ()
+
+data Rexp =
+ NULL
+ | EMPTY
+ | CHAR Char
+ | ALT Rexp Rexp
+ | SEQ Rexp Rexp
+ | STAR Rexp
+ | RECD String Rexp deriving (Eq, Show)
+
+data Value =
+ Void
+ | Chr Char
+ | Sequ Value Value
+ | Lf Value
+ | Rg Value
+ | Stars [Value]
+ | Rec String Value deriving (Eq, Show)
+
+string_repeat :: String -> Int -> String
+string_repeat s n = concat (replicate n s)
+
+sequ :: [Char] -> Rexp
+sequ s = case s of
+ [] -> EMPTY
+ [c] -> CHAR c
+ c:cs -> SEQ (CHAR c) (sequ cs)
+
+
+str :: String -> Rexp
+str s = sequ s
+
+plus :: Rexp -> Rexp
+plus r = SEQ r (STAR r)
+
+(\/) :: Rexp -> Rexp -> Rexp
+r1 \/ r2 = ALT r1 r2
+
+(~~) :: Rexp -> Rexp -> Rexp
+r1 ~~ r2 = SEQ r1 r2
+
+($$) :: String -> Rexp -> Rexp
+x $$ r = RECD x r
+
+alts :: [Rexp] -> Rexp
+alts rs = case rs of
+ [] -> NULL
+ [r] -> r
+ r:rs -> foldl (ALT) r rs
+
+size :: Rexp -> Int
+size r = case r of
+ NULL -> 1
+ EMPTY -> 1
+ CHAR _ -> 1
+ ALT r1 r2 -> 1 + (size r1) + (size r2)
+ SEQ r1 r2 -> 1 + (size r1) + (size r2)
+ STAR r -> 1 + (size r)
+ RECD _ r -> 1 + (size r)
+
+nullable :: Rexp -> Bool
+nullable r = case r of
+ NULL -> False
+ EMPTY -> True
+ CHAR _ -> False
+ ALT r1 r2 -> nullable(r1) || nullable(r2)
+ SEQ r1 r2 -> nullable(r1) && nullable(r2)
+ STAR _ -> True
+ RECD _ r -> nullable(r)
+
+der :: Char -> Rexp -> Rexp
+der c r = case r of
+ NULL -> NULL
+ EMPTY -> NULL
+ CHAR d -> if c == d then EMPTY else NULL
+ ALT r1 r2 -> ALT (der c r1) (der c r2)
+ SEQ r1 r2 ->
+ if nullable r1 then ALT (SEQ (der c r1) r2) (der c r2)
+ else SEQ (der c r1) r2
+ STAR r -> SEQ (der c r) (STAR r)
+ RECD _ r -> der c r
+
+ders :: [Char] -> Rexp -> Rexp
+ders s r = case s of
+ [] -> r
+ c:s -> ders s (der c r)
+
+flatten :: Value -> String
+flatten v = case v of
+ Void -> ""
+ Chr c -> [c]
+ Lf v -> flatten v
+ Rg v -> flatten v
+ Sequ v1 v2 -> flatten v1 ++ flatten v2
+ Stars vs -> concat (map flatten vs)
+ Rec _ v -> flatten v
+
+env :: Value -> [(String, String)]
+env v = case v of
+ Void -> []
+ Chr c -> []
+ Lf v -> env v
+ Rg v -> env v
+ Sequ v1 v2 -> env v1 ++ env v2
+ Stars vs -> foldl (++) [] (map env vs)
+ Rec x v -> (x, flatten v) : env v
+
+string_of_pair :: (String, String) -> String
+string_of_pair (x, s) = "(" ++ x ++ "," ++ s ++ ")"
+
+string_of_env :: [(String, String)] -> String
+string_of_env xs = intercalate "," (map string_of_pair xs)
+
+mkeps :: Rexp -> Value
+mkeps r = case r of
+ EMPTY -> Void
+ ALT r1 r2 ->
+ if nullable r1 then Lf (mkeps r1) else Rg (mkeps r2)
+ SEQ r1 r2 -> Sequ (mkeps r1) (mkeps r2)
+ STAR r -> Stars []
+ RECD x r -> Rec x (mkeps r)
+
+inj :: Rexp -> Char -> Value -> Value
+inj r c v = case (r, v) of
+ (STAR r, Sequ v1 (Stars vs)) -> Stars (inj r c v1 : vs)
+ (SEQ r1 r2, Sequ v1 v2) -> Sequ (inj r1 c v1) v2
+ (SEQ r1 r2, Lf (Sequ v1 v2)) -> Sequ (inj r1 c v1) v2
+ (SEQ r1 r2, Rg v2) -> Sequ (mkeps r1) (inj r2 c v2)
+ (ALT r1 r2, Lf v1) -> Lf (inj r1 c v1)
+ (ALT r1 r2, Rg v2) -> Rg (inj r2 c v2)
+ (CHAR d, Void) -> Chr d
+ (RECD x r1, _) -> Rec x (inj r1 c v)
+
+f_id :: Value -> Value
+f_id v = v
+
+f_right :: (Value -> Value) -> Value -> Value
+f_right f = \v -> Rg (f v)
+
+f_left :: (Value -> Value) -> Value -> Value
+f_left f = \v -> Lf (f v)
+
+f_alt :: (Value -> Value) -> (Value -> Value) -> Value -> Value
+f_alt f1 f2 = \v -> case v of
+ Rg v -> Rg (f2 v)
+ Lf v -> Lf (f1 v)
+
+f_seq :: (Value -> Value) -> (Value -> Value) -> Value -> Value
+f_seq f1 f2 = \v -> case v of
+ Sequ v1 v2 -> Sequ (f1 v1) (f2 v2)
+
+f_seq_void1 :: (Value -> Value) -> (Value -> Value) -> Value -> Value
+f_seq_void1 f1 f2 = \v -> Sequ (f1 Void) (f2 v)
+
+f_seq_void2 :: (Value -> Value) -> (Value -> Value) -> Value -> Value
+f_seq_void2 f1 f2 = \v -> Sequ(f1 v) (f2 Void)
+
+f_rec :: (Value -> Value) -> Value -> Value
+f_rec f = \v -> case v of
+ Rec x v -> Rec x (f v)
+
+simp :: Rexp -> (Rexp, Value -> Value)
+simp r = case r of
+ ALT r1 r2 ->
+ let (r1s, f1s) = simp r1
+ (r2s, f2s) = simp r2
+ in
+ (case (r1s, r2s) of
+ (NULL, _) -> (r2s, f_right f2s)
+ (_, NULL) -> (r1s, f_left f1s)
+ (_, _) -> if r1s == r2s then (r1s, f_left f1s)
+ else (ALT r1s r2s, f_alt f1s f2s))
+ SEQ r1 r2 ->
+ let (r1s, f1s) = simp r1
+ (r2s, f2s) = simp r2
+ in
+ (case (r1s, r2s) of
+ (NULL, _) -> (NULL, f_right f2s)
+ (_, NULL) -> (NULL, f_left f1s)
+ (EMPTY, _) -> (r2s, f_seq_void1 f1s f2s)
+ (_, EMPTY) -> (r1s, f_seq_void2 f1s f2s)
+ (_, _) -> (SEQ r1s r2s, f_seq f1s f2s))
+ RECD x r1 ->
+ let (r1s, f1s) = simp r1
+ in
+ (RECD x r1s, f_rec f1s)
+ r -> (r, f_id)
+
+der_simp :: Char -> Rexp -> (Rexp, Value -> Value)
+der_simp c r = case r of
+ NULL -> (NULL, f_id)
+ EMPTY -> (NULL, f_id)
+ CHAR(d) -> ((if c == d then EMPTY else NULL), f_id)
+ ALT r1 r2 ->
+ let (r1d, f1d) = der_simp c r1
+ (r2d, f2d) = der_simp c r2
+ in
+ (case (r1d, r2d) of
+ (NULL, _) -> (r2d, f_right f2d)
+ (_, NULL) -> (r1d, f_left f1d)
+ (_, _) -> if r1d == r2d then (r1d, f_left f1d)
+ else (ALT r1d r2d, f_alt f1d f2d))
+ SEQ r1 r2 ->
+ if nullable r1
+ then
+ let (r1d, f1d) = der_simp c r1
+ (r2d, f2d) = der_simp c r2
+ (r2s, f2s) = simp r2
+ in
+ (case (r1d, r2s, r2d) of
+ (NULL, _, _) -> (r2d, f_right f2d)
+ (_, NULL, _) -> (r2d, f_right f2d)
+ (_, _, NULL) -> (SEQ r1d r2s, f_left (f_seq f1d f2s))
+ (EMPTY, _, _) -> (ALT r2s r2d, f_alt (f_seq_void1 f1d f2s) f2d)
+ (_, EMPTY, _) -> (ALT r1d r2d, f_alt (f_seq_void2 f1d f2s) f2d)
+ (_, _, _) -> (ALT (SEQ r1d r2s) r2d, f_alt (f_seq f1d f2s) f2d))
+ else
+ let (r1d, f1d) = der_simp c r1
+ (r2s, f2s) = simp r2
+ in
+ (case (r1d, r2s) of
+ (NULL, _) -> (NULL, f_id)
+ (_, NULL) -> (NULL, f_id)
+ (EMPTY, _) -> (r2s, f_seq_void1 f1d f2s)
+ (_, EMPTY) -> (r1d, f_seq_void2 f1d f2s)
+ (_, _) -> (SEQ r1d r2s, f_seq f1d f2s))
+ STAR r1 ->
+ let (r1d, f1d) = der_simp c r1
+ in
+ (case r1d of
+ NULL -> (NULL, f_id)
+ EMPTY -> (STAR r1, f_seq_void1 f1d f_id)
+ _ -> (SEQ r1d (STAR r1), f_seq f1d f_id))
+ RECD x r1 -> der_simp c r1
+
+
+
+matcher :: Rexp -> String -> Bool
+matcher r s = nullable (ders s r)
+
+lex0 :: Rexp -> String -> Maybe Value
+lex0 r s = case s of
+ [] -> if (nullable r)
+ then Just (mkeps r)
+ else Nothing
+ c:cs -> do res <- lex0 (der c r) cs
+ return (inj r c res)
+
+lex_simp :: Rexp -> String -> Maybe Value
+lex_simp r s = case s of
+ [] -> if (nullable r)
+ then Just (mkeps r)
+ else Nothing
+ c:cs -> let
+ (r_simp, f_simp) = simp (der c r)
+ in
+ do
+ res <- lex_simp r_simp cs
+ return (inj r c (f_simp res))
+
+lex_simp2 :: Rexp -> String -> Maybe Value
+lex_simp2 r s = case s of
+ [] -> if (nullable r)
+ then Just (mkeps r)
+ else Nothing
+ c:cs -> let
+ (r_simp, f_simp) = der_simp c r
+ in
+ do
+ res <- lex_simp2 r_simp cs
+ return (inj r c (f_simp res))
+
+lex_acc :: Rexp -> String -> (Value -> Value) -> Maybe Value
+lex_acc r s f = case s of
+ [] -> if (nullable r)
+ then Just (f (mkeps r))
+ else Nothing
+ c:cs -> let
+ (r_simp, f_simp) = simp (der c r)
+ in
+ lex_acc r_simp cs (\v -> f (inj r c (f_simp v)))
+
+lex_acc2 :: Rexp -> String -> (Value -> Value) -> Maybe Value
+lex_acc2 r s f = case s of
+ [] -> if (nullable r)
+ then Just (f (mkeps r))
+ else Nothing
+ c:cs -> let
+ (r_simp, f_simp) = der_simp c r
+ in
+ lex_acc2 r_simp cs (\v -> f (inj r c (f_simp v)))
+
+sym = alts (map CHAR "abcdefghijklmnopqrstuvwxyz")
+digit = alts (map CHAR "0123456789")
+idents = sym ~~ STAR(sym \/ digit)
+nums = plus digit
+keywords = alts (map str ["skip", "while", "do", "if", "then", "else", "read", "write", "true", "false"])
+semicolon = str ";"
+ops = alts (map str [":=", "==", "-", "+", "*", "!=", "<", ">", "<=", ">=", "%", "/"])
+whitespace = plus(str " " \/ str "\n" \/ str "\t")
+rparen = str ")"
+lparen = str "("
+begin_paren = str "{"
+end_paren = str "}"
+
+while_regs = STAR(("k" $$ keywords) \/
+ ("i" $$ idents) \/
+ ("o" $$ ops) \/
+ ("n" $$ nums) \/
+ ("s" $$ semicolon) \/
+ ("p" $$ (lparen \/ rparen)) \/
+ ("b" $$ (begin_paren \/ end_paren)) \/
+ ("w" $$ whitespace))
+
+prog2 = intercalate "\n"
+ ["i := 2;",
+ "max := 100;",
+ "while i < max do {",
+ " isprime := 1;",
+ " j := 2;",
+ " while (j * j) <= i + 1 do {",
+ " if i % j == 0 then isprime := 0 else skip;",
+ " j := j + 1",
+ " };",
+ " if isprime == 1 then write i else skip;",
+ " i := i + 1",
+ "}"]
+
+
+lexing_simp :: Int -> Int
+lexing_simp n = case (lex_simp while_regs (string_repeat prog2 n)) of
+ Just result -> 1
+ Nothing -> 0
+
+step_simp :: Int -> IO ()
+step_simp n = do
+ putStr (show n ++ ": ")
+ time (lexing_simp n)
+
+lexing_simp2 :: Int -> Int
+lexing_simp2 n = case (lex_simp2 while_regs (string_repeat prog2 n)) of
+ Just result -> 1
+ Nothing -> 0
+
+step_simp2 :: Int -> IO ()
+step_simp2 n = do
+ putStr (show n ++ ": ")
+ time (lexing_simp2 n)
+
+lexing_acc :: Int -> Int
+lexing_acc n = case (lex_acc while_regs (string_repeat prog2 n) f_id) of
+ Just result -> 1
+ Nothing -> 0
+
+step_acc :: Int -> IO ()
+step_acc n = do
+ putStr (show n ++ ": ")
+ time (lexing_acc n)
+
+lexing_acc2 :: Int -> Int
+lexing_acc2 n = case (lex_acc2 while_regs (string_repeat prog2 n) f_id) of
+ Just result -> 1
+ Nothing -> 0
+
+step_acc2 :: Int -> IO ()
+step_acc2 n = do
+ putStr (show n ++ ": ")
+ time (lexing_acc2 n)
+
+main :: IO ()
+main = do
+ forM_ [1000,2000..5000] step_simp
+ printf "\n"
+ forM_ [1000,2000..5000] step_simp2
+ printf "\n"
+ forM_ [1000,2000..5000] step_acc
+ printf "\n"
+ forM_ [1000,2000..5000] step_acc2
\ No newline at end of file