@@ -195,6 +195,16 @@ module ParserMonad =
195
195
let parseError ( genMessage : Pos -> string ) : ParserMonad < 'a > =
196
196
ParserMonad <| fun _ st -> Error ( mkOtherParseError st genMessage)
197
197
198
+ let fmapM ( modify : 'a -> 'b ) ( parser : ParserMonad < 'a >) : ParserMonad < 'b > =
199
+ ParserMonad <| fun input state ->
200
+ match apply1 parser input state with
201
+ | Error err -> Error err
202
+ | Ok ( a, st2) -> Ok ( modify a, st2)
203
+
204
+ /// Operator for fmapM
205
+ let ( <<| ) ( modify : 'a -> 'b ) ( parser : ParserMonad < 'a >) : ParserMonad < 'b > =
206
+ fmapM modify parser
207
+
198
208
/// Run the parser, if it fails swap the error message.
199
209
let inline ( <??> ) ( parser : ParserMonad < 'a >) ( genMessage : Pos -> string ) : ParserMonad < 'a > =
200
210
ParserMonad <| fun input st ->
@@ -301,66 +311,32 @@ module ParserMonad =
301
311
work length state ( fun msg -> Error msg) ( fun st ac -> Ok ( ac, st))
302
312
|> Result.map ( fun ( ans , st ) -> ( List.toArray ans, st))
303
313
304
-
305
314
/// Run a parser within a bounded section of the input stream.
306
- let repeatTillPosition ( maxPosition : Pos ) ( p : ParserMonad < 'a >) : ParserMonad < 'a array > =
307
- ParserMonad( fun data state ->
308
- let results = ResizeArray()
309
- let mutable firstError = Ok ( Array.empty, state)
310
- let mutable lastState = state
311
- let rec loop () =
312
- if lastState.Position < int maxPosition then
313
- match apply1 p data lastState with
314
- | Ok ( result, state) ->
315
- lastState <- state
316
- results.Add result
317
- loop ()
318
- | Error e ->
319
- firstError <- Error e
320
-
321
- loop ()
322
- match firstError with
323
- | Ok _ ->
324
- Ok( results.ToArray(), lastState)
325
- | Error _ ->
326
- firstError
327
- )
328
-
329
- let inline boundRepeat ( n : ^T ) ( p : ParserMonad < 'a >) : ParserMonad < 'a array > =
330
- ParserMonad( fun data state ->
331
- let result = Array.zeroCreate ( int n)
332
- let mutable lastState = state
333
- // revisit with a fold?
334
- let mutable error = Ok ( Unchecked.defaultof<_>, lastState)
335
- let mutable i = LanguagePrimitives.GenericZero
336
- let mutable errorOccured = false
337
- logf " bound repeat %i " n
338
-
339
- while i < n && not errorOccured do
340
- logf " bound repeat %i /%i " i n
341
-
342
- match apply1 p data lastState with
343
- | Ok ( item, state) ->
344
- lastState <- state
345
- result.[ int i] <- item
346
- | ( Error e) ->
347
- error <- Error e
348
- errorOccured <- true
349
- i <- i + LanguagePrimitives.GenericOne
350
- if errorOccured then
351
- error
352
- else
353
- Ok ( result, lastState)
354
- )
315
+ let repeatTillPosition ( maxPosition : Pos ) ( parser : ParserMonad < 'a >) : ParserMonad < 'a array > =
316
+ ParserMonad <| fun input state ->
317
+ let limit = maxPosition
318
+ let rec work ( st : State )
319
+ ( fk : ParseError -> Result < 'a list * State , ParseError >)
320
+ ( sk : State -> 'a list -> Result < 'a list * State , ParseError >) =
321
+ match apply1 parser input st with
322
+ | Error a -> fk a
323
+ | Ok( a1, st1) ->
324
+ match compare st1.Position limit with
325
+ | 0 -> sk st1 [ a1]
326
+ | t when t > 0 -> fk ( ParseError( st1.Position, Other " repeatTillPosition - too far" ))
327
+ | _ ->
328
+ work st1 fk ( fun st2 ac ->
329
+ sk st2 ( a1 :: ac))
330
+ work state ( fun msg -> Error msg) ( fun st ac -> Ok ( ac, st))
331
+ |> Result.map ( fun ( ans , st ) -> ( List.toArray ans, st))
355
332
356
333
/// Apply the parser for /count/ times, derive the final answer
357
334
/// from the intermediate list with the supplied function.
358
335
let inline gencount ( plen : ParserMonad < 'T >) ( p : ParserMonad < 'a >) ( constr : ^T -> 'a array -> 'answer ) : ParserMonad < 'answer > =
359
336
parseMidi {
360
- let! l = plen
361
- logf " gen count: l: %i " l
362
- let! items = boundRepeat l p
363
- return constr l items
337
+ let! times = plen
338
+ let! arr = count ( int times) p
339
+ return ( constr times arr)
364
340
}
365
341
366
342
/// Drop a byte (word8).
0 commit comments