-
Notifications
You must be signed in to change notification settings - Fork 0
/
TransportationParser.hs
118 lines (87 loc) · 3.37 KB
/
TransportationParser.hs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE TypeSynonymInstances #-}
{-# LANGUAGE DeriveGeneric #-}
{-# LANGUAGE RecordWildCards #-}
module TransportationParser (parseTop) where
import Text.ParserCombinators.Parsek
import Data.Char
import Data.Function
import Data.Maybe
import HaskToProlin
import GHC.Generics
type P = Parser Char
integer :: P Int
integer = read <$> munch1 isDigit
-- integer = read <$> ((:) <$> digit <*> manyGreedy digit)
vehicle :: P String
vehicle = string "bus" <|> string "tram"
place :: P String
place = string "science park"
<|> string "central station"
<|> string "airport"
<|> string "university"
anything :: P ()
anything = skipMany anySymbol
thanks :: P ()
thanks = do
anything
_ <- string "thank"
return ()
data Clarification = To String | From String | With Int deriving (Show,Generic)
instance Encode Clarification
clarification :: Parser Char Clarification
clarification = (To <$> (string "to " >> place))
<|> (From <$> (string "from " >> place))
<|> (With <$> (vehicle >> munch1 (not . isDigit) >> integer))
instance Encode Request
data Request = Request {reqTo :: Maybe String
,reqFrom :: Maybe String
,reqWith :: Maybe Int} deriving (Show,Generic)
emptyRequest :: Request
emptyRequest = Request Nothing Nothing Nothing
addToRequest :: Clarification -> Request -> Request
addToRequest (To x) Request{..} = Request{reqTo = Just x,..}
addToRequest (From x) Request{..} = Request{reqFrom = Just x,..}
addToRequest (With x) Request{..} = Request{reqWith = Just x,..}
makeRequest :: [Clarification] -> Request
makeRequest = foldr addToRequest emptyRequest
request :: Parser Char Request
request = do
anything
_ <- string "when" <|> string "what"
anything
cs <- sepBy1 clarification anything
return (makeRequest cs)
data Message = Thanks | Req Request | Clarify Clarification deriving (Show,Generic)
instance Encode Message
reqScore :: Request -> Int
reqScore (Request a b c) = length $ filter id $ [isJust a, isJust b, isJust c]
bestReq :: Request -> Request -> Request
bestReq x y = case (compare `on` reqScore) x y of
LT -> y
GT -> x
_ -> error ("Cannot decide best request: " ++ show x ++ show y)
best :: Message -> Message -> Message
Thanks `best` x = x
Clarify _ `best` x = x
Req x `best` Req y = Req (x `bestReq` y) -- FIXME: HACK!
Req x `best` _ = Req x
bests :: [Message] -> Message
bests = foldr1 best
message :: Parser Char Message
message = (Req <$> request) <|>
(pure Thanks <* thanks) <|>
(Clarify <$> (anything *> clarification) <* anything)
parseTop :: String -> ParseResult Char Message
parseTop msg = bests <$> parse message allResults (map toLower msg)
-- >>> parseTest "thank you!!!"
-- Right Thanks
-- >>> parseTest "hum, to central station please"
-- Right (Clarify (To "central station"))
-- >>> parseTest "Hey! When is the next fucking bus 55 from Science park, you stupid machine?"
-- Right (Req (Request {reqTo = Nothing, reqFrom = Just "science park", reqWith = Just 55}))
errToMaybe :: Either a b -> Maybe b
errToMaybe (Left _) = Nothing
errToMaybe (Right a) = Just a
-- >>> encode (errToMaybe (parseTest "Hey! When is the next fucking bus 55 from Science park, you stupid machine?"))
-- App [Con "Just",App [Con "Req",App [Con "Request",App [Con "Nothing"],App [Con "Just",Con "science park"],App [Con "Just",Con "55"]]]]