summaryrefslogtreecommitdiff
path: root/utils/heap-view/Parse.lhs
blob: 9d7652fdcccbfd41f58ea62fe603885f172b9de4 (plain)
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
> module Parse where

The Parser monad in "Comprehending Monads"

> infixr 9 `thenP`
> infixr 9 `thenP_`
> infixr 9 `plusP`

> type P t a = [t] -> [(a,[t])]

> unitP :: a -> P t a
> unitP a = \i -> [(a,i)]

> thenP :: P t a -> (a -> P t b) -> P t b
> m `thenP` k = \i0 -> [(b,i2) | (a,i1) <- m i0, (b,i2) <- k a i1]

> thenP_ :: P t a -> P t b -> P t b
> m `thenP_` k = \i0 -> [(b,i2) | (a,i1) <- m i0, (b,i2) <- k i1]

zeroP is the parser that always fails to parse its input

> zeroP :: P t a
> zeroP = \i -> []

plusP combines two parsers in parallel
(called "alt" in "Comprehending Monads")

> plusP :: P t a -> P t a -> P t a
> a1 `plusP` a2 = \i -> (a1 i) ++ (a2 i)

itemP is the parser that parses a single token
(called "next" in "Comprehending Monads")

> itemP :: P t t
> itemP = \i -> [(head i, tail i) | not (null i)]

force successful parse

> cutP :: P t a -> P t a
> cutP p = \u -> let l = p u in if null l then [] else [head l]

find all complete parses of a given string

> useP :: P t a -> [t] -> [a]
> useP m =  \x -> [ a | (a,[]) <- m x ]

find first complete parse

> theP :: P t a -> [t] -> a
> theP m = head . (useP m)


Some standard parser definitions

mapP applies f to all current parse trees

> mapP :: (a -> b) -> P t a -> P t b
> f `mapP` m =  m `thenP` (\a -> unitP (f a))

filter is the parser that parses a single token if it satisfies a
predicate and fails otherwise.

> filterP :: (a -> Bool) -> P t a -> P t a
> p `filterP` m = m `thenP` (\a -> (if p a then unitP a else zeroP))

lit recognises literals

> litP :: Eq t => t -> P t ()
> litP t = ((==t) `filterP` itemP) `thenP` (\c -> unitP () )

> showP :: (Text a) => P t a -> [t] -> String
> showP m xs = show (theP m xs)


Simon Peyton Jones adds some useful operations:

> zeroOrMoreP :: P t a -> P t [a]
> zeroOrMoreP p = oneOrMoreP p `plusP` unitP []

> oneOrMoreP :: P t a -> P t [a]
> oneOrMoreP p = seq p
>  where seq p = p		`thenP` (\a ->
>		(seq p		`thenP` (\as -> unitP (a:as)))
>		`plusP`
>		unitP [a] )

> oneOrMoreWithSepP :: P t a -> P t b -> P t [a]
> oneOrMoreWithSepP p1 p2 = seq1 p1 p2
>   where seq1 p1 p2 =	p1 `thenP` (\a -> seq2 p1 p2 a `plusP`  unitP [a])
>         seq2 p1 p2 a =	p2		`thenP` (\_ ->
>				seq1 p1 p2	`thenP` (\as -> unitP (a:as) ))