Advertisement
Guest User

Untitled

a guest
Apr 28th, 2015
225
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 4.78 KB | None | 0 0
  1. import Data.Char (isDigit, isLower, isUpper, isAlpha, isAlphaNum, isSpace)
  2. import Test.HUnit
  3. import Test.HUnit.Tools (assertRaises)
  4. import Control.Exception (ErrorCall(ErrorCall), evaluate)
  5.  
  6. newtype Parser a = Parser {getParser :: String -> [(a, String)]}
  7.  
  8. parse :: Parser a -> String -> [(a, String)]
  9. parse p inp = (getParser p) inp
  10.  
  11. instance Monad Parser where
  12. return v = Parser $ \ inp -> [(v, inp)]
  13. fail s = Parser $ \ inp -> []
  14. p >>= f = Parser $ \ inp -> case parse p inp of
  15. [] -> []
  16. [(v, out)] -> parse (f v) out
  17.  
  18. item :: Parser Char
  19. item = Parser $ \ inp -> case inp of
  20. [] -> []
  21. (x:xs) -> [(x,xs)]
  22.  
  23. (+++) :: Parser a -> Parser a -> Parser a
  24. p +++ q = Parser $ \ inp -> case parse p inp of
  25. [] -> parse q inp
  26. [(v, out)] -> [(v, out)]
  27.  
  28. tests1 :: Test
  29. tests1 = "+++" ~: TestList ["test1" ~: (parse (item +++ return 'd') "abc") ~?= [('a', "bc")],
  30. "test2" ~: (parse (fail "" +++ return 'd') "abc") ~?= [('d', "abc")],
  31. "test3" ~: (parse (fail "" +++ fail "") "abc") ~?= ([] :: [(Char, String)])]
  32.  
  33. sat :: (Char -> Bool) -> Parser Char
  34. sat p = do x <- item
  35. if p x then return x else fail ""
  36.  
  37. digit :: Parser Char
  38. digit = sat isDigit
  39.  
  40. lower :: Parser Char
  41. lower = sat isLower
  42.  
  43. upper :: Parser Char
  44. upper = sat isUpper
  45.  
  46. letter :: Parser Char
  47. letter = sat isAlpha
  48.  
  49. alphanum :: Parser Char
  50. alphanum = sat isAlphaNum
  51.  
  52. char :: Char -> Parser Char
  53. char x = sat (==x)
  54.  
  55. tests2 :: Test
  56. tests2 = "testForSat" ~:
  57. TestList ["test1" ~: (parse digit "123") ~?= [('1', "23")],
  58. "test2" ~: (parse digit "abc") ~?= [],
  59. "test3" ~: (parse (char 'a') "abc") ~?= [('a', "bc")],
  60. "test4" ~: (parse (char 'a') "123") ~?= []]
  61.  
  62.  
  63. string :: String -> Parser String
  64. string [] = return []
  65. string (x:xs) = do char x
  66. string xs
  67. return (x:xs)
  68.  
  69. tests3 :: Test
  70. tests3 = "testForString" ~:
  71. TestList ["test1" ~: (parse (string "abc") "abcdef") ~?= [("abc", "def")],
  72. "test2" ~: (parse (string "abc") "ab123") ~?= []]
  73.  
  74.  
  75. many :: Parser a -> Parser [a]
  76. many p = many1 p +++ return []
  77.  
  78. many1 :: Parser a -> Parser [a]
  79. many1 p = do v <- p
  80. vs <- many p
  81. return (v:vs)
  82.  
  83. tests4 :: Test
  84. tests4 = "testForManyAndMany1" ~:
  85. TestList ["test1" ~: (parse (many digit) "123abc") ~?= [("123", "abc")],
  86. "test2" ~: (parse (many digit) "abcdef") ~?= [("", "abcdef")],
  87. "test3" ~: (parse (many1 digit) "abcdef") ~?= []]
  88.  
  89. ident :: Parser String
  90. ident = do x <- lower
  91. xs <- many alphanum
  92. return (x:xs)
  93.  
  94. nat :: Parser Int
  95. nat = do xs <- many1 digit
  96. return (read xs)
  97.  
  98. space :: Parser ()
  99. space = do many (sat isSpace)
  100. return ()
  101.  
  102. tests5 :: Test
  103. tests5 = "for ident nat space" ~:
  104. TestList ["test1" ~: (parse ident "abc def") ~?= [("abc", " def")],
  105. "test2" ~: (parse nat "123 abc") ~?= [(123, " abc")],
  106. "test3" ~: (parse space " abc" ~?= [((), "abc")])]
  107.  
  108. token :: Parser a -> Parser a
  109. token p = do space
  110. v <- p
  111. space
  112. return v
  113.  
  114. identifier :: Parser String
  115. identifier = token ident
  116.  
  117. natural :: Parser Int
  118. natural = token nat
  119.  
  120. symbol :: String -> Parser String
  121. symbol xs = token (string xs)
  122.  
  123. p :: Parser [Int]
  124. p = do symbol "["
  125. n <- natural
  126. ns <- many (do symbol ","
  127. natural)
  128. symbol "]"
  129. return (n:ns)
  130.  
  131. tests6 :: Test
  132. tests6 = "test:p" ~:
  133. TestList ["test1" ~: (parse p " [1, 2, 3] ") ~?= [([1,2,3], "")],
  134. "test2" ~: (parse p " [1, 2, ]") ~?= []]
  135.  
  136. expr :: Parser Int
  137. expr = do t <- term
  138. do symbol "+"
  139. e <- expr
  140. return $ t + e
  141. +++ return t
  142.  
  143. term :: Parser Int
  144. term = do f <- factor
  145. do symbol "*"
  146. t <- term
  147. return (f * t)
  148. +++ return f
  149.  
  150. factor :: Parser Int
  151. factor = do symbol "("
  152. e <- expr
  153. symbol ")"
  154. return e
  155. +++ natural
  156.  
  157. eval' :: String -> [(Int, String)]
  158. eval' xs = parse expr xs
  159.  
  160. eval :: String -> Int
  161. eval xs = case parse expr xs of
  162. [(n, [])] -> n
  163. [(_, out)] -> error $ "unused input " ++ out
  164. [] -> error "invalid input"
  165.  
  166. tests7 :: Test
  167. tests7 = "test for eval" ~:
  168. TestList ["test1" ~: (eval "2*3+4") ~?= 10,
  169. "test2" ~: (eval "2*(3+4)") ~?= 14,
  170. "test3" ~: (eval "2 * (3 + 4)" ~?= 14),
  171. "test4" ~: (assertRaises "assert" (ErrorCall "unused input wie") $ evaluate (eval "1*2wie"))]
  172.  
  173. main :: IO Counts
  174. main = do
  175. runTestTT . TestList $ [tests1, tests2, tests3, tests4, tests5, tests6, tests7]
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement