-- RegEx.hs -- -- Prints 'accept' if regular expression 'abba' is recognized from -- standard in and 'reject' otherwise. -- -- compilation: -- ghc --make -O2 RegEx.hs -o regex -- -- command-line usage: -- ./regex < infile -- ./regex < infile > outfile -- -- interactive usage in ghc REPL: -- ghci -- Prelude> :l RegEx.hs -- *Main> regex "hello there ; . , * {} (bye)" -- *Main> regex "abba" -- module Main where -- needed for isChar, isAlpha, isSpace, isDigit --import Data.Char main = do file_as_str <- getContents let output = regex_abba_tbl (stripEOF file_as_str, 0) print output ----------------------------------------------------------------- -- Set of functions that match 'abba'. -- One function for each state in the finite state machine. -- The following line declares the type of the function. -- The input parameter is a String type and the function returns -- the Strings "accept" or "reject" regex_abba_q0 :: String -> String -- Below has examples of pattern matching. The first pattern -- matches some character at the beginning of a list. -- See http://www.haskell.org/haskellwiki/How_to_work_on_lists. regex_abba_q0 ('a':cs) = regex_abba_q1 cs regex_abba_q0 (_:cs) = regex_abba_q5 cs -- This approach uses a function for each state in the finite -- state machine for 'abba' (see slides from Friday Jan 30). regex_abba_q1 ('b':cs) = regex_abba_q2 cs regex_abba_q1 (_:cs) = regex_abba_q5 cs regex_abba_q2 ('b':cs) = regex_abba_q3 cs regex_abba_q2 (_:cs) = regex_abba_q5 cs regex_abba_q3 ('a':cs) = regex_abba_q4 cs regex_abba_q3 (_:cs) = regex_abba_q5 cs regex_abba_q4 [] = "accept" regex_abba_q4 (c:cs) = regex_abba_q5 cs regex_abba_q5 _ = "reject" ----------------------------------------------------------------- -- Single function that matches 'abba' by encoding transition table -- with patterns. Tuple for parameter. First item is current -- string and second item is current state in finite state machine. regex_abba_tbl ('a':cs, 0) = regex_abba_tbl (cs, 1) regex_abba_tbl (_:cs, 0) = regex_abba_tbl (cs, 5) regex_abba_tbl ('b':cs, 1) = regex_abba_tbl (cs, 2) regex_abba_tbl (_:cs, 1) = regex_abba_tbl (cs, 5) regex_abba_tbl ('b':cs, 2) = regex_abba_tbl (cs, 3) regex_abba_tbl (_:cs, 2) = regex_abba_tbl (cs, 5) regex_abba_tbl ('a':cs, 3) = regex_abba_tbl (cs, 4) regex_abba_tbl ('b':cs, 3) = regex_abba_tbl (cs, 6) regex_abba_tbl (_:cs, 3 ) = regex_abba_tbl (cs, 5) regex_abba_tbl ([], 4) = "accept" regex_abba_tbl (_:cs, 4) = regex_abba_tbl (cs, 5) regex_abba_tbl (_, 5) = "reject" regex_abba_tbl ('a':cs, 6) = regex_abba_tbl (cs, 4) regex_abba_tbl (_:cs, 6) = regex_abba_tbl (cs, 5) -- Assume EOF is last character in string and leave it off. stripEOF :: String -> String stripEOF str = take (length(str)-1) str