1 | module TyRE.Text.Parser.Core
3 | import public Control.Delayed
4 | import public Data.List
11 | data Grammar : (tok : Type) -> (consumes : Bool) -> Type -> Type where
12 | Empty : (val : ty) -> Grammar tok False ty
13 | Terminal : String -> (tok -> Maybe a) -> Grammar tok True a
14 | NextIs : String -> (tok -> Bool) -> Grammar tok False tok
15 | EOF : Grammar tok False ()
17 | Fail : Bool -> String -> Grammar tok c ty
18 | Commit : Grammar tok False ()
19 | MustWork : Grammar tok c a -> Grammar tok c a
21 | SeqEat : {c2 : _} -> Grammar tok True a -> Inf (a -> Grammar tok c2 b) ->
23 | SeqEmpty : {c1, c2 : _} -> Grammar tok c1 a -> (a -> Grammar tok c2 b) ->
24 | Grammar tok (c1 || c2) b
26 | ThenEat : {c2 : _} -> Grammar tok True () -> Inf (Grammar tok c2 b) ->
28 | ThenEmpty : {c1, c2 : _} -> Grammar tok c1 () -> Grammar tok c2 b ->
29 | Grammar tok (c1 || c2) b
31 | Alt : {c1, c2 : _} -> Grammar tok c1 ty -> Grammar tok c2 ty ->
32 | Grammar tok (c1 && c2) ty
40 | (>>=) : {c1, c2 : Bool} ->
42 | inf c1 (a -> Grammar tok c2 b) ->
43 | Grammar tok (c1 || c2) b
44 | (>>=) {c1 = False} = SeqEmpty
45 | (>>=) {c1 = True} = SeqEat
53 | (>>) : {c1, c2 : Bool} ->
54 | Grammar tok c1 () ->
55 | inf c1 (Grammar tok c2 a) ->
56 | Grammar tok (c1 || c2) a
57 | (>>) {c1 = False} = ThenEmpty
58 | (>>) {c1 = True} = ThenEat
64 | seq : {c1, c2 : _} -> Grammar tok c1 a ->
65 | (a -> Grammar tok c2 b) ->
66 | Grammar tok (c1 || c2) b
71 | join : {c1, c2 : Bool} ->
72 | Grammar tok c1 (Grammar tok c2 a) ->
73 | Grammar tok (c1 || c2) a
74 | join {c1 = False} p = SeqEmpty p id
75 | join {c1 = True} p = SeqEat p id
80 | (<|>) : {c1, c2 : _} ->
81 | Grammar tok c1 ty ->
82 | Grammar tok c2 ty ->
83 | Grammar tok (c1 && c2) ty
88 | {c : _} -> Functor (Grammar tok c) where
89 | map f (Empty val) = Empty (f val)
90 | map f (Fail fatal msg) = Fail fatal msg
91 | map f (MustWork g) = MustWork (map f g)
92 | map f (Terminal msg g) = Terminal msg (\t => map f (g t))
93 | map f (Alt x y) = Alt (map f x) (map f y)
94 | map f (SeqEat act next)
95 | = SeqEat act (\val => map f (next val))
96 | map f (SeqEmpty act next)
97 | = SeqEmpty act (\val => map f (next val))
98 | map f (ThenEat act next)
99 | = ThenEat act (map f next)
100 | map f (ThenEmpty act next)
101 | = ThenEmpty act (map f next)
104 | map {c = False} f p = SeqEmpty p (Empty . f)
111 | (<*>) : {c1, c2 : _} ->
112 | Grammar tok c1 (a -> b) ->
113 | Inf (Grammar tok c2 a) ->
114 | Grammar tok (c1 || c2) b
115 | (<*>) {c1 = False} x y = SeqEmpty x (\f => map f y)
116 | (<*>) {c1 = True } x y = SeqEmpty x (\f => map f (Force y))
121 | (<*) : {c1, c2 : _} ->
122 | Grammar tok c1 a ->
123 | Inf (Grammar tok c2 b) ->
124 | Grammar tok (c1 || c2) a
125 | (<*) x y = map const x <*> y
130 | (*>) : {c1, c2 : _} ->
131 | Grammar tok c1 a ->
132 | Inf (Grammar tok c2 b) ->
133 | Grammar tok (c1 || c2) b
134 | (*>) x y = map (const id) x <*> y
139 | mapToken : (a -> b) -> Grammar b c ty -> Grammar a c ty
140 | mapToken f (Empty val) = Empty val
141 | mapToken f (Terminal msg g) = Terminal msg (g . f)
142 | mapToken f (NextIs msg g) = SeqEmpty (NextIs msg (g . f)) (Empty . f)
143 | mapToken f EOF = EOF
144 | mapToken f (Fail fatal msg) = Fail fatal msg
145 | mapToken f (MustWork g) = MustWork (mapToken f g)
146 | mapToken f Commit = Commit
147 | mapToken f (SeqEat act next)
148 | = SeqEat (mapToken f act) (\x => mapToken f (next x))
149 | mapToken f (SeqEmpty act next)
150 | = SeqEmpty (mapToken f act) (\x => mapToken f (next x))
151 | mapToken f (ThenEat act next)
152 | = ThenEat (mapToken f act) (mapToken f next)
153 | mapToken f (ThenEmpty act next)
154 | = ThenEmpty (mapToken f act) (mapToken f next)
155 | mapToken f (Alt x y) = Alt (mapToken f x) (mapToken f y)
159 | pure : (val : ty) -> Grammar tok False ty
164 | nextIs : String -> (tok -> Bool) -> Grammar tok False tok
169 | peek : Grammar tok False tok
170 | peek = nextIs "Unrecognised token" (const True)
175 | terminal : String -> (tok -> Maybe a) -> Grammar tok True a
176 | terminal = Terminal
180 | fail : String -> Grammar tok c ty
184 | fatalError : String -> Grammar tok c ty
185 | fatalError = Fail True
189 | eof : Grammar tok False ()
195 | commit : Grammar tok False ()
200 | mustWork : Grammar tok c ty -> Grammar tok c ty
201 | mustWork = MustWork
204 | data ParseResult : List tok -> (consumes : Bool) -> Type -> Type where
205 | Failure : {xs : List tok} ->
206 | (committed : Bool) -> (fatal : Bool) ->
207 | (err : String) -> (rest : List tok) -> ParseResult xs c ty
208 | EmptyRes : (committed : Bool) ->
209 | (val : ty) -> (more : List tok) -> ParseResult more False ty
210 | NonEmptyRes : {xs : List tok} ->
211 | (committed : Bool) ->
212 | (val : ty) -> (more : List tok) ->
213 | ParseResult (x :: xs ++ more) c ty
219 | weakenRes : {whatever, c : Bool} -> {xs : List tok} ->
221 | ParseResult xs c ty -> ParseResult xs (whatever && c) ty
222 | weakenRes com' (Failure com fatal msg ts) = Failure com' fatal msg ts
223 | weakenRes {whatever=True} com' (EmptyRes com val xs) = EmptyRes com' val xs
224 | weakenRes {whatever=False} com' (EmptyRes com val xs) = EmptyRes com' val xs
225 | weakenRes com' (NonEmptyRes {xs} com val more) = NonEmptyRes {xs} com' val more
228 | doParse : (commit : Bool) ->
229 | (act : Grammar tok c ty) ->
231 | ParseResult xs c ty
233 | doParse com (Empty val) xs = EmptyRes com val xs
234 | doParse com (Fail fatal str) [] = Failure com fatal str []
235 | doParse com (Fail fatal str) (x :: xs) = Failure com fatal str (x :: xs)
236 | doParse com Commit xs = EmptyRes True () xs
237 | doParse com (MustWork g) xs =
238 | let p' = doParse com g xs in
240 | Failure com' _ msg ts => Failure com' True msg ts
242 | doParse com (Terminal err f) [] = Failure com False "End of input" []
243 | doParse com (Terminal err f) (x :: xs)
245 | (Failure com False err (x :: xs))
246 | (\a => NonEmptyRes com {xs=[]} a xs)
248 | doParse com EOF [] = EmptyRes com () []
249 | doParse com EOF (x :: xs)
250 | = Failure com False "Expected end of input" (x :: xs)
251 | doParse com (NextIs err f) [] = Failure com False "End of input" []
252 | doParse com (NextIs err f) (x :: xs)
254 | then EmptyRes com x (x :: xs)
255 | else Failure com False err (x :: xs)
256 | doParse com (Alt {c1} {c2} x y) xs
257 | = let p' = doParse False x xs in
259 | Failure com' fatal msg ts
260 | => if com' || fatal
263 | then Failure com fatal msg ts
264 | else weakenRes {whatever = c1} com (doParse False y xs)
266 | EmptyRes _ val xs => EmptyRes com val xs
267 | NonEmptyRes {xs=xs'} _ val more => NonEmptyRes {xs=xs'} com val more
268 | doParse com (SeqEmpty {c1} {c2} act next) xs
269 | = let p' = assert_total (doParse {c = c1} com act xs) in
271 | Failure com fatal msg ts => Failure com fatal msg ts
272 | EmptyRes com val xs => assert_total (doParse com (next val) xs)
273 | NonEmptyRes {x} {xs=ys} com val more =>
274 | case (assert_total (doParse com (next val) more)) of
275 | Failure com' fatal msg ts => Failure com' fatal msg ts
276 | EmptyRes com' val _ => NonEmptyRes {xs=ys} com' val more
277 | NonEmptyRes {x=x1} {xs=xs1} com' val more' =>
278 | rewrite appendAssociative (x :: ys) (x1 :: xs1) more' in
279 | NonEmptyRes {xs = ys ++ (x1 :: xs1)} com' val more'
280 | doParse com (SeqEat act next) xs with (doParse com act xs)
281 | doParse com (SeqEat act next) xs | Failure com' fatal msg ts
282 | = Failure com' fatal msg ts
283 | doParse com (SeqEat act next) (x :: (ys ++ more)) | (NonEmptyRes {xs=ys} com' val more)
284 | = let p' = assert_total (doParse com' (next val) more) in
286 | Failure com' fatal msg ts => Failure com' fatal msg ts
287 | EmptyRes com' val _ => NonEmptyRes {xs=ys} com' val more
288 | NonEmptyRes {x=x1} {xs=xs1} com' val more' =>
289 | rewrite appendAssociative (x :: ys) (x1 :: xs1) more' in
290 | NonEmptyRes {xs = ys ++ (x1 :: xs1)} com' val more'
291 | doParse com (ThenEmpty {c1} {c2} act next) xs
292 | = let p' = assert_total (doParse {c = c1} com act xs) in
294 | Failure com fatal msg ts => Failure com fatal msg ts
295 | EmptyRes com val xs => assert_total (doParse com next xs)
296 | NonEmptyRes {x} {xs=ys} com val more =>
297 | case (assert_total (doParse com next more)) of
298 | Failure com' fatal msg ts => Failure com' fatal msg ts
299 | EmptyRes com' val _ => NonEmptyRes {xs=ys} com' val more
300 | NonEmptyRes {x=x1} {xs=xs1} com' val more' =>
301 | rewrite appendAssociative (x :: ys) (x1 :: xs1) more' in
302 | NonEmptyRes {xs = ys ++ (x1 :: xs1)} com' val more'
303 | doParse com (ThenEat act next) xs with (doParse com act xs)
304 | doParse com (ThenEat act next) xs | Failure com' fatal msg ts
305 | = Failure com' fatal msg ts
306 | doParse com (ThenEat act next) (x :: (ys ++ more)) | (NonEmptyRes {xs=ys} com' val more)
307 | = let p' = assert_total (doParse com' next more) in
309 | Failure com' fatal msg ts => Failure com' fatal msg ts
310 | EmptyRes com' val _ => NonEmptyRes {xs=ys} com' val more
311 | NonEmptyRes {x=x1} {xs=xs1} com' val more' =>
312 | rewrite appendAssociative (x :: ys) (x1 :: xs1) more' in
313 | NonEmptyRes {xs = ys ++ (x1 :: xs1)} com' val more'
320 | data ParseError tok = Error String (List tok)
326 | parse : {c : _} -> (act : Grammar tok c ty) -> (xs : List tok) ->
327 | Either (ParseError tok) (ty, List tok)
329 | = case doParse False act xs of
330 | Failure _ _ msg ts => Left (Error msg ts)
331 | EmptyRes _ val rest => pure (val, rest)
332 | NonEmptyRes _ val rest => pure (val, rest)