0 | module Text.Parser.Core
6 | import public Control.Delayed
7 | import public Text.Bounded
20 | data Grammar : (state : Type) -> (tok : Type) -> (consumes : Bool) -> Type -> Type where
21 | Empty : (val : ty) -> Grammar state tok False ty
22 | Terminal : String -> (tok -> Maybe a) -> Grammar state tok True a
23 | NextIs : String -> (tok -> Bool) -> Grammar state tok False tok
24 | EOF : Grammar state tok False ()
26 | Fail : (location : Maybe Bounds) -> (fatal : Bool) -> String -> Grammar state tok c ty
27 | Try : Grammar state tok c ty -> Grammar state tok c ty
29 | Commit : Grammar state tok False ()
30 | MustWork : Grammar state tok c a -> Grammar state tok c a
32 | SeqEat : {c2 : Bool} ->
33 | Grammar state tok True a -> Inf (a -> Grammar state tok c2 b) ->
34 | Grammar state tok True b
35 | SeqEmpty : {c1, c2 : Bool} ->
36 | Grammar state tok c1 a -> (a -> Grammar state tok c2 b) ->
37 | Grammar state tok (c1 || c2) b
39 | ThenEat : {c2 : Bool} ->
40 | Grammar state tok True () -> Inf (Grammar state tok c2 a) ->
41 | Grammar state tok True a
42 | ThenEmpty : {c1, c2 : Bool} ->
43 | Grammar state tok c1 () -> Grammar state tok c2 a ->
44 | Grammar state tok (c1 || c2) a
46 | Alt : {c1, c2 : Bool} ->
47 | Grammar state tok c1 ty -> Lazy (Grammar state tok c2 ty) ->
48 | Grammar state tok (c1 && c2) ty
49 | Bounds : Grammar state tok c ty -> Grammar state tok c (WithBounds ty)
50 | Position : Grammar state tok False Bounds
52 | Act : state -> Grammar state tok False ()
59 | (>>=) : {c1, c2 : Bool} ->
60 | Grammar state tok c1 a ->
61 | inf c1 (a -> Grammar state tok c2 b) ->
62 | Grammar state tok (c1 || c2) b
63 | (>>=) {c1 = False} = SeqEmpty
64 | (>>=) {c1 = True} = SeqEat
70 | public export %inline %tcinline
71 | (>>) : {c1, c2 : Bool} ->
72 | Grammar state tok c1 () ->
73 | inf c1 (Grammar state tok c2 a) ->
74 | Grammar state tok (c1 || c2) a
75 | (>>) {c1 = False} = ThenEmpty
76 | (>>) {c1 = True} = ThenEat
82 | seq : {c1,c2 : Bool} ->
83 | Grammar state tok c1 a ->
84 | (a -> Grammar state tok c2 b) ->
85 | Grammar state tok (c1 || c2) b
90 | join : {c1,c2 : Bool} ->
91 | Grammar state tok c1 (Grammar state tok c2 a) ->
92 | Grammar state tok (c1 || c2) a
93 | join {c1 = False} p = SeqEmpty p id
94 | join {c1 = True} p = SeqEat p id
99 | Functor (Grammar state tok c) where
100 | map f (Empty val) = Empty (f val)
101 | map f (Fail bd fatal msg) = Fail bd fatal msg
102 | map f (Try g) = Try (map f g)
103 | map f (MustWork g) = MustWork (map f g)
104 | map f (Terminal msg g) = Terminal msg (map f . g)
105 | map f (Alt x y) = Alt (map f x) (map f y)
106 | map f (SeqEat act next)
107 | = SeqEat act (\val => map f (next val))
108 | map f (SeqEmpty act next)
109 | = SeqEmpty act (\ val => map f (next val))
110 | map f (ThenEat act next)
111 | = ThenEat act (map f next)
112 | map f (ThenEmpty act next)
113 | = ThenEmpty act (map f next)
114 | map {c} f (Bounds act)
115 | = rewrite sym $
orFalseNeutral c in
116 | SeqEmpty (Bounds act) (Empty . f)
119 | map {c = False} f p = SeqEmpty p (Empty . f)
124 | (<|>) : {c1,c2 : Bool} ->
125 | Grammar state tok c1 ty ->
126 | Lazy (Grammar state tok c2 ty) ->
127 | Grammar state tok (c1 && c2) ty
130 | export infixr 2 <||>
134 | (<||>) : {c1,c2 : Bool} ->
135 | Grammar state tok c1 a ->
136 | Lazy (Grammar state tok c2 b) ->
137 | Grammar state tok (c1 && c2) (Either a b)
138 | (<||>) p q = (Left <$> p) <|> (Right <$> q)
145 | (<*>) : {c1, c2 : Bool} ->
146 | Grammar state tok c1 (a -> b) ->
147 | Grammar state tok c2 a ->
148 | Grammar state tok (c1 || c2) b
149 | (<*>) x y = SeqEmpty x (\f => map f y)
154 | (<*) : {c1,c2 : Bool} ->
155 | Grammar state tok c1 a ->
156 | Grammar state tok c2 b ->
157 | Grammar state tok (c1 || c2) a
158 | (<*) x y = map const x <*> y
163 | (*>) : {c1,c2 : Bool} ->
164 | Grammar state tok c1 a ->
165 | Grammar state tok c2 b ->
166 | Grammar state tok (c1 || c2) b
167 | (*>) x y = map (const id) x <*> y
170 | act : state -> Grammar state tok False ()
176 | mapToken : (a -> b) -> Grammar state b c ty -> Grammar state a c ty
177 | mapToken f (Empty val) = Empty val
178 | mapToken f (Terminal msg g) = Terminal msg (g . f)
179 | mapToken f (NextIs msg g) = SeqEmpty (NextIs msg (g . f)) (Empty . f)
180 | mapToken f EOF = EOF
181 | mapToken f (Fail bd fatal msg) = Fail bd fatal msg
182 | mapToken f (Try g) = Try (mapToken f g)
183 | mapToken f (MustWork g) = MustWork (mapToken f g)
184 | mapToken f Commit = Commit
185 | mapToken f (SeqEat act next)
186 | = SeqEat (mapToken f act) (\x => mapToken f (next x))
187 | mapToken f (SeqEmpty act next)
188 | = SeqEmpty (mapToken f act) (\x => mapToken f (next x))
189 | mapToken f (ThenEat act next)
190 | = ThenEat (mapToken f act) (mapToken f next)
191 | mapToken f (ThenEmpty act next)
192 | = ThenEmpty (mapToken f act) (mapToken f next)
193 | mapToken f (Alt x y) = Alt (mapToken f x) (mapToken f y)
194 | mapToken f (Bounds act) = Bounds (mapToken f act)
195 | mapToken f Position = Position
196 | mapToken f (Act action) = Act action
200 | pure : (val : ty) -> Grammar state tok False ty
205 | nextIs : String -> (tok -> Bool) -> Grammar state tok False tok
210 | peek : Grammar state tok False tok
211 | peek = nextIs "Unrecognised token" (const True)
216 | terminal : String -> (tok -> Maybe a) -> Grammar state tok True a
217 | terminal = Terminal
221 | fail : String -> Grammar state tok c ty
222 | fail = Fail Nothing False
226 | failLoc : Bounds -> String -> Grammar state tok c ty
227 | failLoc b = Fail (Just b) False
232 | fatalError : String -> Grammar state tok c ty
233 | fatalError = Fail Nothing True
238 | fatalLoc : Bounds -> String -> Grammar state tok c ty
239 | fatalLoc b = Fail (Just b) True
243 | try : Grammar state tok c ty -> Grammar state tok c ty
248 | eof : Grammar state tok False ()
254 | commit : Grammar state tok False ()
259 | mustWork : {c : Bool} -> Grammar state tok c ty -> Grammar state tok c ty
260 | mustWork = MustWork
263 | bounds : Grammar state tok c ty -> Grammar state tok c (WithBounds ty)
267 | position : Grammar state tok False Bounds
268 | position = Position
271 | data ParsingError tok = Error String (Maybe Bounds)
274 | Show tok => Show (ParsingError tok) where
275 | show (Error s Nothing) = "PARSING ERROR: " ++ s
276 | show (Error s (Just (MkBounds startLine startCol endLine endCol))) =
279 | ++ " @ L\{show startLine}:\{show startCol}-L\{show endLine}:\{show endCol}"
281 | data ParseResult : Type -> Type -> Type -> Type where
282 | Failure : (committed : Bool) -> (fatal : Bool) ->
283 | List1 (ParsingError tok) -> ParseResult state tok ty
284 | Res : state -> (committed : Bool) ->
285 | (val : WithBounds ty) -> (more : List (WithBounds tok)) -> ParseResult state tok ty
287 | mergeWith : WithBounds ty -> ParseResult state tok sy -> ParseResult state tok sy
288 | mergeWith x (Res s committed val more) = Res s committed (mergeBounds x val) more
291 | doParse : Semigroup state => state -> (commit : Bool) ->
292 | (act : Grammar state tok c ty) ->
293 | (xs : List (WithBounds tok)) ->
294 | ParseResult state tok ty
295 | doParse s com (Empty val) xs = Res s com (irrelevantBounds val) xs
296 | doParse s com (Fail location fatal str) xs
297 | = Failure com fatal (Error str (location <|> (bounds <$> head' xs)) ::: Nil)
298 | doParse s com (Try g) xs = case doParse s com g xs of
300 | Failure com _ errs => Failure com False errs
302 | doParse s com Commit xs = Res s True (irrelevantBounds ()) xs
303 | doParse s com (MustWork g) xs =
304 | case doParse s com g xs of
305 | Failure com' _ errs => Failure com' True errs
307 | doParse s com (Terminal err f) [] = Failure com False (Error "End of input" Nothing ::: Nil)
308 | doParse s com (Terminal err f) (x :: xs) =
310 | Nothing => Failure com False (Error err (Just x.bounds) ::: Nil)
311 | Just a => Res s com (const a <$> x) xs
312 | doParse s com EOF [] = Res s com (irrelevantBounds ()) []
313 | doParse s com EOF (x :: xs) = Failure com False (Error "Expected end of input" (Just x.bounds) ::: Nil)
314 | doParse s com (NextIs err f) [] = Failure com False (Error "End of input" Nothing ::: Nil)
315 | doParse s com (NextIs err f) (x :: xs)
317 | then Res s com (removeIrrelevance x) (x :: xs)
318 | else Failure com False (Error err (Just x.bounds) ::: Nil)
319 | doParse s com (Alt {c1} {c2} x y) xs
320 | = case doParse s False x xs of
321 | Failure com' fatal errs
322 | => if com' || fatal
325 | then Failure com fatal errs
326 | else case doParse s False y xs of
327 | (Failure com'' fatal' errs') => if com'' || fatal'
330 | then Failure com'' fatal' errs'
331 | else Failure com False (errs ++ errs')
332 | (Res s _ val xs) => Res s com val xs
334 | Res s _ val xs => Res s com val xs
335 | doParse s com (SeqEmpty act next) xs
336 | = case doParse s com act xs of
337 | Failure com fatal errs => Failure com fatal errs
339 | mergeWith v $
doParse s com (next v.val) xs
340 | doParse s com (SeqEat act next) xs
341 | = case doParse s com act xs of
342 | Failure com fatal errs => Failure com fatal errs
344 | mergeWith v $
assert_total doParse s com (next v.val) xs
345 | doParse s com (ThenEmpty act next) xs
346 | = case doParse s com act xs of
347 | Failure com fatal errs => Failure com fatal errs
349 | mergeWith v $
doParse s com next xs
350 | doParse s com (ThenEat act next) xs
351 | = case doParse s com act xs of
352 | Failure com fatal errs => Failure com fatal errs
354 | mergeWith v $
assert_total doParse s com next xs
355 | doParse s com (Bounds act) xs
356 | = case doParse s com act xs of
357 | Failure com fatal errs => Failure com fatal errs
358 | Res s com v xs => Res s com (const v <$> v) xs
359 | doParse s com Position [] = Failure com False (Error "End of input" Nothing ::: Nil)
360 | doParse s com Position (x :: xs)
361 | = Res s com (irrelevantBounds x.bounds) (x :: xs)
362 | doParse s com (Act action) xs = Res (s <+> action) com (irrelevantBounds ()) xs
368 | parse : {c : Bool} -> (act : Grammar () tok c ty) -> (xs : List (WithBounds tok)) ->
369 | Either (List1 (ParsingError tok)) (ty, List (WithBounds tok))
371 | = case doParse neutral False act xs of
372 | Failure _ _ errs => Left errs
373 | Res _ _ v rest => Right (v.val, rest)
376 | parseWith : Monoid state => {c : Bool} -> (act : Grammar state tok c ty) -> (xs : List (WithBounds tok)) ->
377 | Either (List1 (ParsingError tok)) (state, ty, List (WithBounds tok))
379 | = case doParse neutral False act xs of
380 | Failure _ _ errs => Left errs
381 | Res s _ v rest => Right (s, v.val, rest)