Contact
CoCalc Logo Icon
StoreFeaturesDocsShareSupport News AboutSign UpSign In
| Download

Logic of "all" + verbs + relative clauses, for a class at Indiana University

Views: 6871
1
{-# LANGUAGE LambdaCase #-}
2
module FrontEnd where
3
4
import Data.List
5
import ARC/Syntax2
6
import ARC/ExampleSentences
7
import Control.Arrow
8
import Control.Monad (guard)
9
import Data.Maybe (listToMaybe,maybeToList)
10
import Data.Char (toLower)
11
import Data.List (transpose, intercalate)
12
13
type Parser a b = [a] -> [(b,[a])]
14
type PARSER a b = Parser a (ParseTree a b)
15
16
epsilonT :: PARSER a b
17
epsilonT = succeed Ep
18
19
symbolT :: Eq a => a -> PARSER a b
20
symbolT s = (\ x -> Leaf x) <$$> symbol s
21
22
symbol :: Eq a => a -> Parser a a
23
symbol c [] = []
24
symbol c (x:xs) | c == x = [(x,xs)]
25
| otherwise = []
26
27
infixl 6 <:>
28
29
(<:>) :: Parser a b -> Parser a [b] -> Parser a [b]
30
(p <:> q) xs = [ (r:rs,zs) | (r,ys) <- p xs,
31
(rs,zs) <- q ys ]
32
33
(<|>) :: Parser a b -> Parser a b -> Parser a b
34
(p1 <|> p2) xs = p1 xs ++ p2 xs
35
36
(<**>) :: Parser a [b] -> Parser a [b] -> Parser a [b]
37
(p <**> q) xs = [ (r1 ++ r2,zs) | (r1,ys) <- p xs,
38
(r2,zs) <- q ys ]
39
infixl 7 <$$>
40
41
(<$$>) :: (a -> b) -> Parser s a -> Parser s b
42
(f <$$> p) xs = [ (f x,ys) | (x,ys) <- p xs ]
43
44
data ParseTree a b = Ep | Leaf a | Branch b [ParseTree a b]
45
deriving Eq
46
47
instance (Show a, Show b) => Show (ParseTree a b) where
48
show Ep = "[]"
49
show (Leaf t) = show t
50
show (Branch l ts) = "[." ++ show l ++ " "
51
++ show ts ++ "]"
52
53
54
succeed :: b -> Parser a b
55
succeed r xs = [(r,xs)]
56
57
collect :: [Parser a b] -> Parser a [b]
58
collect [] = succeed []
59
collect (p:ps) = p <:> collect ps
60
61
parseAs :: b -> [PARSER a b] -> PARSER a b
62
parseAs label ps = (\ xs -> Branch label xs) <$$> collect ps
63
64
sent, tv, cn, det, t, int, intOrT, neg, np :: PARSER String String
65
cn = symbolT "skunks"
66
<|> symbolT "mammals"
67
<|> symbolT "chordates"
68
<|> symbolT "boys" <|> symbolT "girls" <|> symbolT "animals"
69
70
tv = symbolT "see" <|> symbolT "love" <|> symbolT "admire" <|> symbolT "hate"
71
72
det = symbolT "every"
73
<|> symbolT "some"
74
<|> symbolT "no"
75
<|> symbolT "all"
76
<|> symbolT "most"
77
78
t = parseAs "Term" [cn]
79
<|> parseAs "Term" [symbolT "non" ,cn]
80
<|> parseAs "Term" [tv, det, intOrT]
81
<|> parseAs "Term" [tv, det, symbolT "who", intOrT]
82
83
--pcn = parseAs "PCN" [pol, cn]
84
neg = symbolT "non"
85
86
np = parseAs "NP" [det,intOrT]
87
--pv = parseAs "PV" [pol, tv]
88
89
sent = parseAs "S" [det,intOrT,intOrT]
90
91
92
int = parseAs "Int" [cn,symbolT "who",t]
93
94
intOrT = int <|> t
95
96
move :: ParseTree String String -> Term
97
move (Branch "Term" [Leaf "skunks"]) = (CNasTerm skunks)
98
move (Branch "Term" [Leaf "mammals"]) = (CNasTerm mammals)
99
move (Branch "Term" [Leaf "animals"]) = (CNasTerm animals)
100
move (Branch "Term" [Leaf "chordates"]) = (CNasTerm chordates)
101
move (Branch "Term" [Leaf "sneetches"]) = (CNasTerm sneetches)
102
move (Branch "Term" [(Leaf "non"), (Leaf "skunks")]) = (CNasTerm non_skunks)
103
move (Branch "Term" [(Leaf "non"), Leaf "mammals"]) = (CNasTerm non_mammals)
104
move (Branch "Term" [(Leaf "non"), Leaf "animals"]) = (CNasTerm non_animals)
105
move (Branch "Term" [(Leaf "non"), Leaf "chordates"]) = (CNasTerm non_chordates)
106
move (Branch "Term" [(Leaf "non"), Leaf "sneetches"]) = (CNasTerm non_sneetches)
107
108
109
move (Branch "Term" [(Leaf "see"), (Leaf "all"), (Leaf "who"), subtree])
110
= (TermMaker sees (TermNP All (move subtree)))
111
move (Branch "Term" [(Leaf "see"), (Leaf "all"), subtree])
112
= (TermMaker sees (TermNP All (move subtree)))
113
move (Branch "Term" [(Leaf "love"), (Leaf "all"), (Leaf "who"), subtree])
114
= (TermMaker loves (TermNP All (move subtree)))
115
move (Branch "Term" [(Leaf "love"), (Leaf "all"), subtree])
116
= (TermMaker loves (TermNP All (move subtree)))
117
move (Branch "Term" [(Leaf "hate"), (Leaf "all"), (Leaf "who"), subtree])
118
= (TermMaker hates (TermNP All (move subtree)))
119
move (Branch "Term" [(Leaf "hate"), (Leaf "all"), subtree])
120
= (TermMaker hates (TermNP All (move subtree)))
121
move (Leaf "skunks") = (CNasTerm skunks)
122
--move (Leaf ["mammals"]) = (CNasTerm mammals)
123
--move (Leaf ["animals"]) = (CNasTerm animals)
124
125
moveS :: ParseTree String String -> Sent
126
moveS (Branch "S" [(Leaf "all"), ttree, ttree2]) = (Sent All (move ttree) (move ttree2))
127
128
readMe = moveS . fst . head . sent . words
129
130
sentParses :: String -> [Sent]
131
sentParses =
132
map (moveS . fst)
133
. filter (null . snd)
134
. sent
135
. words
136
137
-----USAGE: moveS $ (fst.head) $ sent $ words "all see all see all skunks love all mammals"
138
---- ALSO move $ (fst . head) $ t $ words "see all see all non skunks"
139
--- note how 'non' worls
140
141
split2 :: [t] -> [[[t]]] ---- split2 takes any list $\ell$ and gives the list of all ways to split $\ell$ into two sublists
142
--- whose concatenation is $\ell$ again.
143
split2 [] = [[[],[]]]
144
split2 (x:xs) = [[ [], x:xs]] ++ map (\z -> [x:(z!!0),z!!1]) (split2 xs)
145
146
split2' :: [t] -> [([t],[t])]
147
split2' = \case
148
xs@(x : xs') -> ([],xs) : map (first (x :)) (split2' xs')
149
150
{-
151
[] = [([],[])]
152
split2' (x:xs) = [[ [], x:xs]] ++ map (\z -> [x:(z!!0),z!!1]) (split2 xs)
153
-}
154
155
tF :: [String] -> [Term]
156
tF quoted -- this parses terms
157
| quoted == [] = []
158
| (quoted!! 0 == "who") = tF $ drop 1 quoted
159
| (quoted!! 0 == "are") = tF $ drop 1 quoted
160
| (quoted!! 0 == "also") = tF $ drop 1 quoted
161
| quoted == ["skunks"] = [CNasTerm skunks]
162
| quoted == ["mammals"] = [CNasTerm mammals]
163
| quoted == ["chordates"] = [CNasTerm chordates]
164
| quoted == ["boys"] = [CNasTerm boys]
165
| quoted == ["girls"] = [CNasTerm girls]
166
| quoted == ["dogs"] = [CNasTerm dogs]
167
| quoted == ["cats"] = [CNasTerm cats]
168
| quoted == ["birds"] = [CNasTerm birds]
169
| quoted == ["animals"] = [CNasTerm animals]
170
| quoted == ["sneetches"] = [CNasTerm sneetches]
171
| quoted == ["non-skunks"] = [CNasTerm non_skunks]
172
| quoted == ["non-mammals"] = [CNasTerm non_mammals]
173
| quoted == ["non-chordates"] = [CNasTerm non_chordates]
174
| quoted == ["non-boys"] = [CNasTerm non_boys]
175
| quoted == ["non-girls"] = [CNasTerm non_girls]
176
| quoted == ["non-dogs"] = [CNasTerm non_dogs]
177
| quoted == ["non-cats"] = [CNasTerm non_cats]
178
| quoted == ["non-birds"] = [CNasTerm non_birds]
179
| quoted == ["non-animals"] = [CNasTerm non_animals]
180
| quoted == ["non-sneetches"] = [CNasTerm non_sneetches]
181
| quoted == ["x"] = [CNasTerm x]
182
| quoted == ["y"] = [CNasTerm y]
183
| quoted == ["z"] = [CNasTerm z]
184
| quoted == ["p"] = [CNasTerm p]
185
| quoted == ["q"] = [CNasTerm q]
186
| quoted == ["non-x"] = [CNasTerm non_x]
187
| quoted == ["non-y"] = [CNasTerm non_y]
188
| quoted == ["non-z"] = [CNasTerm non_z]
189
| quoted == ["non-p"] = [CNasTerm non_p]
190
| quoted == ["non-q"] = [CNasTerm non_q]
191
| (quoted!! 0 == "see") = [(TermMaker sees r) | r <- (npF (drop 1 quoted))]
192
| (quoted!! 0 == "sees") = [(TermMaker sees r) | r <- (npF (drop 1 quoted))]
193
| (quoted!! 0 == "admires") = [(TermMaker admires r) | r <- (npF (drop 1 quoted))]
194
| (quoted!! 0 == "admire") = [(TermMaker admires r) | r <- (npF (drop 1 quoted))]
195
| (quoted!! 0 == "loves") = [(TermMaker loves r) | r <- (npF (drop 1 quoted))]
196
| (quoted!! 0 == "love") = [(TermMaker loves r) | r <- (npF (drop 1 quoted))]
197
| (quoted!! 0 == "helps") = [(TermMaker helps r) | r <- (npF (drop 1 quoted))]
198
| (quoted!! 0 == "help") = [(TermMaker helps r) | r <- (npF (drop 1 quoted))]
199
| (quoted!! 0 == "hates") = [(TermMaker hates r) | r <- (npF (drop 1 quoted))]
200
| (quoted!! 0 == "hate") = [(TermMaker hates r) | r <- (npF (drop 1 quoted))]
201
| (quoted!! 0 == "doesn't-see") = [(TermMaker not_sees r) | r <- (npF (drop 1 quoted))]
202
| (quoted!! 0 == "doesn't-admire") = [(TermMaker not_admires r) | r <- (npF (drop 1 quoted))]
203
| (quoted!! 0 == "doesn't-love") = [(TermMaker not_loves r) | r <- (npF (drop 1 quoted))]
204
| (quoted!! 0 == "doesn't-help") = [(TermMaker not_helps r) | r <- (npF (drop 1 quoted))]
205
| (quoted!! 0 == "doesn't-hate") = [(TermMaker not_hates r) | r <- (npF (drop 1 quoted))]
206
| (quoted!! 0 == "don't-see") = [(TermMaker not_sees r) | r <- (npF (drop 1 quoted))]
207
| (quoted!! 0 == "don't-admire") = [(TermMaker not_admires r) | r <- (npF (drop 1 quoted))]
208
| (quoted!! 0 == "don't-love") = [(TermMaker not_loves r) | r <- (npF (drop 1 quoted))]
209
| (quoted!! 0 == "don't-help") = [(TermMaker not_helps r) | r <- (npF (drop 1 quoted))]
210
| (quoted!! 0 == "don't-hate") = [(TermMaker not_hates r) | r <- (npF (drop 1 quoted))]
211
| (quoted!! 0 == "r") = [(TermMaker r blurt) | blurt <- (npF (drop 1 quoted))]
212
| otherwise = []
213
214
{--
215
intTF quoted
216
| (quoted !! 0 == ["skunks"]) = [(IntersectionTerm (PCN Pos Skunks) x) | x <- (map tF (drop 1 quoted))]
217
| quoted !! 0 == ["mammals"] = [CNasTerm mammals]
218
| quoted !! 0== ["chordates"] = [CNasTerm chordates]
219
| quoted !! 0== ["boys"] = [CNasTerm boys]
220
| quoted !! 0 == ["girls"] = [CNasTerm girls]
221
| quoted !! 0 == ["dogs"] = [CNasTerm dogs]
222
| quoted !! 0 == ["cats"] = [CNasTerm cats]
223
| quoted !! 0 == ["birds"] = [CNasTerm birds]
224
| quoted !! 0 == ["animals"] = [CNasTerm animals]
225
| quoted !! 0 == ["sneetches"] = [CNasTerm sneetches]
226
| otherwise = []
227
--}
228
229
npF x --- this parses noun phrases
230
| x == [] = []
231
| (x!! 0 == "all") = [(TermNP All w) | w <- tF (drop 1 x)]
232
| (x!! 0 == "some") = [(TermNP Some w) | w <- tF (drop 1 x)]
233
| (x!! 0 == "no") = [(TermNP No w) | w <- tF (drop 1 x)]
234
| (x!! 0 == "most") = [(TermNP Most w) | w <- tF (drop 1 x)]
235
| otherwise = []
236
237
readS input = --- this parses sentences
238
let
239
w = words input
240
firstWord = head w
241
y = tail w
242
sp = split2 y
243
tr = [ x | x <- (map (map tF) sp), (x!!0) /= [], (x!!1) /= []]
244
a = head $ head $ head tr
245
b = head $ head $ tail $ head tr
246
output
247
| firstWord == "all" = Sent All a b
248
| firstWord == "some" = Sent Some a b
249
| firstWord == "most" = Sent Most a b
250
| firstWord == "atleast" = Sent Atleast a b
251
| firstWord == "more" = Sent More a b
252
| firstWord == "no" = Sent No a b
253
| firstWord == "All" = Sent All a b
254
| firstWord == "Some" = Sent Some a b
255
| firstWord == "Most" = Sent Most a b
256
| firstWord == "No" = Sent No a b
257
| otherwise = None
258
in output
259
260
readSs = map readS
261
262
toMaybe :: Foldable t => t a -> Maybe a
263
toMaybe = foldl (maybe Just (const . Just)) Nothing
264
{-# INLINE toMaybe #-}
265
266
readS' :: String -> Maybe Sent
267
readS' input = case words input of
268
w0:ws -> do
269
q <- lookup (toLower <$> w0)
270
[ ( "all" , All )
271
, ( "some" , Some )
272
, ( "most" , Most )
273
, ( "atleast" , Atleast )
274
, ( "more" , More )
275
, ( "no" , No )
276
]
277
(a,b) <- listToMaybe
278
$ split2' ws >>= uncurry zip . (tF *** tF)
279
return $ Sent q a b
280
_ -> Nothing
281
282
-- return either the strings which failed to be parsed,
283
-- or the full set of parsed sentences.
284
readSs' :: [String] -> Either [String] [Sent]
285
readSs' = foldr rS $ Right []
286
where
287
rS :: String -> Either [String] [Sent] -> Either [String] [Sent]
288
rS s es = case readS' s of
289
Just s' -> case es of
290
Left bad -> Left bad
291
Right good -> Right $ s' : good
292
Nothing -> case es of
293
Left bad -> Left $ s : bad
294
Right good -> Left [s]
295
296
-- A few items used in display of models and proofs
297
298
299
-- a type for fill functions
300
type Filler = Int -> String -> String
301
302
-- a type for describing table columns
303
data ColDesc t = ColDesc { colTitleFill :: Filler
304
, colTitle :: String
305
, colValueFill :: Filler
306
, colValue :: t -> String
307
}
308
309
310
311
-- functions that fill a string (s) to a given width (n) by adding pad
312
-- character (c) to align left, right, or center
313
fillLeft c n s = s ++ replicate (n - length s) c
314
fillRight c n s = replicate (n - length s) c ++ s
315
fillCenter c n s = replicate l c ++ s ++ replicate r c
316
where x = n - length s
317
l = x `div` 2
318
r = x - l
319
320
-- functions that fill with spaces
321
322
left = fillLeft ' '
323
right = fillRight ' '
324
center = fillCenter ' '
325
--showTable :: [ColDesc t] -> [t] -> String
326
327
328
showTable cs ts =
329
let header = map colTitle cs
330
rows = [[colValue c t | c <- cs] | t <- ts]
331
widths = [maximum $ map length col | col <- transpose $ header : rows]
332
separator = intercalate "-+-" [replicate width '-' | width <- widths]
333
fillCols fill cols = intercalate " | " [fill c width col | (c, width, col) <- zip3 cs widths cols]
334
in
335
unlines $ fillCols colTitleFill header : separator : map (fillCols colValueFill) rows
336
337
showTableForProofs cs ts =
338
let header = map colTitle cs
339
rows = [[colValue c t | c <- cs] | t <- ts]
340
widths = [maximum $ map length col | col <- transpose $ header : rows]
341
separator = intercalate " " [replicate width ' ' | width <- widths]
342
fillCols fill cols = intercalate " " [fill c width col | (c, width, col) <- zip3 cs widths cols]
343
in
344
-- unlines $ fillCols colTitleFill header : separator : map (fillCols colValueFill) rows
345
unlines $ fillCols colTitleFill header : map (fillCols colValueFill) rows
346
{--
347
showTableForProofs cs ts =
348
let header = map colTitle cs
349
-- rows = [[colValue c t | c <- cs] | t <- ts]
350
-- widths = [maximum $ map length col | col <- transpose $ header : rows]
351
-- separator = intercalate " " [replicate width ' ' | width <- widths]
352
-- fillCols fill cols = intercalate " " [fill c width col | (c, width, col) <- zip3 cs widths cols]
353
in
354
tableWithLegend
355
(("first", "second"), "third")
356
[((linum, prop), just)
357
| linum <- [1 .. (length header)]
358
, prop <- cs
359
, just <- ts] :: Table [(Int, String, String)]
360
--}
361
362