0 | module Libraries.Text.Parser.Core
6 | import public Libraries.Control.Delayed
7 | import public Libraries.Text.Bounded
22 | data Grammar : (state : Type) -> (tok : Type) -> (consumes : Bool) -> Type -> Type where
23 | Empty : (val : ty) -> Grammar state tok False ty
24 | Terminal : String -> (tok -> Maybe a) -> Grammar state tok True a
25 | NextIs : String -> (tok -> Bool) -> Grammar state tok False tok
26 | EOF : Grammar state tok False ()
28 | Fail : (location : Maybe Bounds) -> (fatal : Bool) -> String -> Grammar state tok c ty
29 | Warning : (location : Maybe Bounds) -> String -> Grammar state tok False ()
31 | Try : Grammar state tok c ty -> Grammar state tok c ty
33 | Commit : Grammar state tok False ()
34 | MustWork : Grammar state tok c a -> Grammar state tok c a
36 | SeqEat : {c2 : Bool} ->
37 | Grammar state tok True a -> Inf (a -> Grammar state tok c2 b) ->
38 | Grammar state tok True b
39 | SeqEmpty : {c1, c2 : Bool} ->
40 | Grammar state tok c1 a -> (a -> Grammar state tok c2 b) ->
41 | Grammar state tok (c1 || c2) b
43 | ThenEat : {c2 : Bool} ->
44 | Grammar state tok True () -> Inf (Grammar state tok c2 a) ->
45 | Grammar state tok True a
46 | ThenEmpty : {c1, c2 : Bool} ->
47 | Grammar state tok c1 () -> Grammar state tok c2 a ->
48 | Grammar state tok (c1 || c2) a
50 | Alt : {c1, c2 : Bool} ->
51 | Grammar state tok c1 ty -> Lazy (Grammar state tok c2 ty) ->
52 | Grammar state tok (c1 && c2) ty
53 | Bounds : Grammar state tok c ty -> Grammar state tok c (WithBounds ty)
54 | Position : Grammar state tok False Bounds
56 | Act : state -> Grammar state tok False ()
63 | (>>=) : {c1, c2 : Bool} ->
64 | Grammar state tok c1 a ->
65 | inf c1 (a -> Grammar state tok c2 b) ->
66 | Grammar state tok (c1 || c2) b
67 | (>>=) {c1 = False} = SeqEmpty
68 | (>>=) {c1 = True} = SeqEat
74 | public export %inline %tcinline
75 | (>>) : {c1, c2 : Bool} ->
76 | Grammar state tok c1 () ->
77 | inf c1 (Grammar state tok c2 a) ->
78 | Grammar state tok (c1 || c2) a
79 | (>>) {c1 = False} = ThenEmpty
80 | (>>) {c1 = True} = ThenEat
86 | seq : {c1,c2 : Bool} ->
87 | Grammar state tok c1 a ->
88 | (a -> Grammar state tok c2 b) ->
89 | Grammar state tok (c1 || c2) b
94 | join : {c1,c2 : Bool} ->
95 | Grammar state tok c1 (Grammar state tok c2 a) ->
96 | Grammar state tok (c1 || c2) a
97 | join {c1 = False} p = SeqEmpty p id
98 | join {c1 = True} p = SeqEat p id
103 | Functor (Grammar state tok c) where
104 | map f (Empty val) = Empty (f val)
105 | map f (Fail bd fatal msg) = Fail bd fatal msg
106 | map f (Try g) = Try (map f g)
107 | map f (MustWork g) = MustWork (map f g)
108 | map f (Terminal msg g) = Terminal msg (map f . g)
109 | map f (Alt x y) = Alt (map f x) (map f y)
110 | map f (SeqEat act next)
111 | = SeqEat act (\val => map f (next val))
112 | map f (SeqEmpty act next)
113 | = SeqEmpty act (\ val => map f (next val))
114 | map f (ThenEat act next)
115 | = ThenEat act (map f next)
116 | map f (ThenEmpty act next)
117 | = ThenEmpty act (map f next)
118 | map {c} f (Bounds act)
119 | = rewrite sym $
orFalseNeutral c in
120 | SeqEmpty (Bounds act) (Empty . f)
123 | map {c = False} f p = SeqEmpty p (Empty . f)
128 | (<|>) : {c1,c2 : Bool} ->
129 | Grammar state tok c1 ty ->
130 | Lazy (Grammar state tok c2 ty) ->
131 | Grammar state tok (c1 && c2) ty
134 | export infixr 2 <||>
138 | (<||>) : {c1,c2 : Bool} ->
139 | Grammar state tok c1 a ->
140 | Lazy (Grammar state tok c2 b) ->
141 | Grammar state tok (c1 && c2) (Either a b)
142 | (<||>) p q = (Left <$> p) <|> (Right <$> q)
149 | (<*>) : {c1, c2 : Bool} ->
150 | Grammar state tok c1 (a -> b) ->
151 | Grammar state tok c2 a ->
152 | Grammar state tok (c1 || c2) b
153 | (<*>) x y = SeqEmpty x (\f => map f y)
158 | (<*) : {c1,c2 : Bool} ->
159 | Grammar state tok c1 a ->
160 | Grammar state tok c2 b ->
161 | Grammar state tok (c1 || c2) a
162 | (<*) x y = map const x <*> y
167 | (*>) : {c1,c2 : Bool} ->
168 | Grammar state tok c1 a ->
169 | Grammar state tok c2 b ->
170 | Grammar state tok (c1 || c2) b
171 | (*>) x y = map (const id) x <*> y
174 | act : state -> Grammar state tok False ()
180 | mapToken : (a -> b) -> Grammar state b c ty -> Grammar state a c ty
181 | mapToken f (Empty val) = Empty val
182 | mapToken f (Terminal msg g) = Terminal msg (g . f)
183 | mapToken f (NextIs msg g) = SeqEmpty (NextIs msg (g . f)) (Empty . f)
184 | mapToken f EOF = EOF
185 | mapToken f (Warning bd msg) = Warning bd msg
186 | mapToken f (Fail bd fatal msg) = Fail bd fatal msg
187 | mapToken f (Try g) = Try (mapToken f g)
188 | mapToken f (MustWork g) = MustWork (mapToken f g)
189 | mapToken f Commit = Commit
190 | mapToken f (SeqEat act next)
191 | = SeqEat (mapToken f act) (\x => mapToken f (next x))
192 | mapToken f (SeqEmpty act next)
193 | = SeqEmpty (mapToken f act) (\x => mapToken f (next x))
194 | mapToken f (ThenEat act next)
195 | = ThenEat (mapToken f act) (mapToken f next)
196 | mapToken f (ThenEmpty act next)
197 | = ThenEmpty (mapToken f act) (mapToken f next)
198 | mapToken f (Alt x y) = Alt (mapToken f x) (mapToken f y)
199 | mapToken f (Bounds act) = Bounds (mapToken f act)
200 | mapToken f Position = Position
201 | mapToken f (Act action) = Act action
205 | pure : (val : ty) -> Grammar state tok False ty
210 | nextIs : String -> (tok -> Bool) -> Grammar state tok False tok
215 | peek : Grammar state tok False tok
216 | peek = nextIs "Unrecognised token" (const True)
221 | terminal : String -> (tok -> Maybe a) -> Grammar state tok True a
222 | terminal = Terminal
226 | fail : String -> Grammar state tok c ty
227 | fail = Fail Nothing False
231 | failLoc : Bounds -> String -> Grammar state tok c ty
232 | failLoc b = Fail (Just b) False
237 | fatalError : String -> Grammar state tok c ty
238 | fatalError = Fail Nothing True
243 | fatalLoc : Bounds -> String -> Grammar state tok c ty
244 | fatalLoc b = Fail (Just b) True
248 | try : Grammar state tok c ty -> Grammar state tok c ty
253 | eof : Grammar state tok False ()
259 | commit : Grammar state tok False ()
264 | mustWork : {c : Bool} -> Grammar state tok c ty -> Grammar state tok c ty
265 | mustWork = MustWork
270 | {c : Bool} -> Bounds -> String ->
271 | Grammar state tok c ty -> Grammar state tok c ty
272 | mustWorkBecause {c} loc msg p
273 | = rewrite sym (andSameNeutral c) in
274 | p <|> fatalLoc loc msg
277 | bounds : Grammar state tok c ty -> Grammar state tok c (WithBounds ty)
283 | Grammar state tok True ty -> Grammar state tok False Unit
284 | mustFailBecause msg p
285 | = (bounds p >>= \res => fatalLoc {c=False} res.bounds msg) <|> pure ()
288 | position : Grammar state tok False Bounds
289 | position = Position
293 | withWarning : {c : _} -> String -> Grammar state tok c ty -> Grammar state tok c ty
295 | = rewrite sym $
orFalseNeutral c in
296 | SeqEmpty (bounds p) $
\ res =>
297 | do Warning (Just res.bounds) warn
301 | data ParsingError tok = Error String (Maybe Bounds)
304 | ParsingWarnings : Type
305 | ParsingWarnings = List (Maybe Bounds, String)
307 | data ParseResult : Type -> Type -> Type -> Type where
308 | Failure : (committed : Bool) -> (fatal : Bool) ->
309 | List1 (ParsingError tok) -> ParseResult state tok ty
311 | (ws : ParsingWarnings) ->
312 | (committed : Bool) ->
313 | (val : WithBounds ty) ->
314 | (more : List (WithBounds tok)) ->
315 | ParseResult state tok ty
317 | mergeWith : WithBounds ty -> ParseResult state tok sy -> ParseResult state tok sy
318 | mergeWith x (Res s ws committed val more) = Res s ws committed (mergeBounds x val) more
321 | doParse : Semigroup state =>
322 | state -> (ws : ParsingWarnings) ->
324 | (act : Grammar state tok c ty) ->
325 | (xs : List (WithBounds tok)) ->
326 | ParseResult state tok ty
327 | doParse s ws com (Empty val) xs = Res s ws com (irrelevantBounds val) xs
328 | doParse s ws com (Warning mb msg) xs = Res s ((mb, msg) :: ws) com (irrelevantBounds ()) xs
329 | doParse s ws com (Fail location fatal str) xs
330 | = Failure com fatal (Error str (location <|> (bounds <$> head' xs)) ::: Nil)
331 | doParse s ws com (Try g) xs = case doParse s ws com g xs of
333 | Failure com _ errs => Failure com False errs
335 | doParse s ws com Commit xs = Res s ws True (irrelevantBounds ()) xs
336 | doParse s ws com (MustWork g) xs =
337 | case doParse s ws com g xs of
338 | Failure com' _ errs => Failure com' True errs
340 | doParse s ws com (Terminal err f) [] = Failure com False (Error "End of input" Nothing ::: Nil)
341 | doParse s ws com (Terminal err f) (x :: xs) =
343 | Nothing => Failure com False (Error err (Just x.bounds) ::: Nil)
344 | Just a => Res s ws com (const a <$> x) xs
345 | doParse s ws com EOF [] = Res s ws com (irrelevantBounds ()) []
346 | doParse s ws com EOF (x :: xs) = Failure com False (Error "Expected end of input" (Just x.bounds) ::: Nil)
347 | doParse s ws com (NextIs err f) [] = Failure com False (Error "End of input" Nothing ::: Nil)
348 | doParse s ws com (NextIs err f) (x :: xs)
350 | then Res s ws com (removeIrrelevance x) (x :: xs)
351 | else Failure com False (Error err (Just x.bounds) ::: Nil)
352 | doParse s ws com (Alt {c1} {c2} x y) xs
353 | = case doParse s ws False x xs of
354 | Failure com' fatal errs
355 | => if com' || fatal
358 | then Failure com fatal errs
359 | else case doParse s ws False y xs of
360 | (Failure com'' fatal' errs') => if com'' || fatal'
363 | then Failure com'' fatal' errs'
364 | else Failure com False (errs ++ errs')
365 | (Res s ws _ val xs) => Res s ws com val xs
367 | Res s ws _ val xs => Res s ws com val xs
368 | doParse s ws com (SeqEmpty act next) xs
369 | = case doParse s ws com act xs of
370 | Failure com fatal errs => Failure com fatal errs
371 | Res s ws com v xs =>
372 | mergeWith v $
doParse s ws com (next v.val) xs
373 | doParse s ws com (SeqEat act next) xs
374 | = case doParse s ws com act xs of
375 | Failure com fatal errs => Failure com fatal errs
376 | Res s ws com v xs =>
377 | mergeWith v $
assert_total doParse s ws com (next v.val) xs
378 | doParse s ws com (ThenEmpty act next) xs
379 | = case doParse s ws com act xs of
380 | Failure com fatal errs => Failure com fatal errs
381 | Res s ws com v xs =>
382 | mergeWith v $
doParse s ws com next xs
383 | doParse s ws com (ThenEat act next) xs
384 | = case doParse s ws com act xs of
385 | Failure com fatal errs => Failure com fatal errs
386 | Res s ws com v xs =>
387 | mergeWith v $
assert_total doParse s ws com next xs
388 | doParse s ws com (Bounds act) xs
389 | = case doParse s ws com act xs of
390 | Failure com fatal errs => Failure com fatal errs
391 | Res s ws com v xs => Res s ws com (const v <$> v) xs
392 | doParse s ws com Position [] = Failure com False (Error "End of input" Nothing ::: Nil)
393 | doParse s ws com Position (x :: xs)
394 | = Res s ws com (irrelevantBounds x.bounds) (x :: xs)
395 | doParse s ws com (Act action) xs
396 | = Res (s <+> action) ws com (irrelevantBounds ()) xs
402 | parse : {c : Bool} -> (act : Grammar () tok c ty) -> (xs : List (WithBounds tok)) ->
403 | Either (List1 (ParsingError tok))
404 | (ParsingWarnings, ty, List (WithBounds tok))
406 | = case doParse neutral [] False act xs of
407 | Failure _ _ errs => Left errs
408 | Res _ ws _ v rest => Right (ws, v.val, rest)
411 | parseWith : Monoid state => {c : Bool} -> (act : Grammar state tok c ty) -> (xs : List (WithBounds tok)) ->
412 | Either (List1 (ParsingError tok))
413 | (state, ParsingWarnings, ty, List (WithBounds tok))
415 | = case doParse neutral [] False act xs of
416 | Failure _ _ errs => Left errs
417 | Res s ws _ v rest => Right (s, ws, v.val, rest)