@@ -195,6 +195,16 @@ module ParserMonad =
195195 let parseError ( genMessage : Pos -> string ) : ParserMonad < 'a > =
196196 ParserMonad <| fun _ st -> Error ( mkOtherParseError st genMessage)
197197
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+
198208 /// Run the parser, if it fails swap the error message.
199209 let inline ( <??> ) ( parser : ParserMonad < 'a >) ( genMessage : Pos -> string ) : ParserMonad < 'a > =
200210 ParserMonad <| fun input st ->
@@ -301,66 +311,32 @@ module ParserMonad =
301311 work length state ( fun msg -> Error msg) ( fun st ac -> Ok ( ac, st))
302312 |> Result.map ( fun ( ans , st ) -> ( List.toArray ans, st))
303313
304-
305314 /// 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))
355332
356333 /// Apply the parser for /count/ times, derive the final answer
357334 /// from the intermediate list with the supplied function.
358335 let inline gencount ( plen : ParserMonad < 'T >) ( p : ParserMonad < 'a >) ( constr : ^T -> 'a array -> 'answer ) : ParserMonad < 'answer > =
359336 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)
364340 }
365341
366342 /// Drop a byte (word8).
0 commit comments