@@ -4,7 +4,8 @@ namespace ZMidi.Internal
4
4
module ParserMonad =
5
5
6
6
open System.IO
7
-
7
+ open FSharpPlus
8
+ open FSharpPlus.Data
8
9
open ZMidi.Internal .Utils
9
10
10
11
/// Status is either OFF or the previous VoiceEvent * Channel.
@@ -87,8 +88,7 @@ module ParserMonad =
87
88
#endif
88
89
)
89
90
90
- type ParserMonad < 'a > =
91
- ParserMonad of ( State -> Result < 'a * State , ParseError > )
91
+ type ParserMonad < 'a > = StateT< State, Result< 'a * State, ParseError>>
92
92
93
93
let nullOut = new StreamWriter( Stream.Null) :> TextWriter
94
94
let mutable debug = false
@@ -101,7 +101,7 @@ module ParserMonad =
101
101
102
102
let inline private apply1 ( parser : ParserMonad < 'a >)
103
103
( state : State ) : Result < 'a * State , ParseError > =
104
- let ( ParserMonad fn) = parser
104
+ let ( StateT fn) = parser
105
105
try
106
106
let result = fn state
107
107
let oldState = state
@@ -131,20 +131,20 @@ module ParserMonad =
131
131
)
132
132
133
133
let inline mreturn ( x : 'a ) : ParserMonad < 'a > =
134
- ParserMonad <| fun st -> Ok ( x, st)
134
+ StateT <| fun st -> Ok ( x, st)
135
135
136
136
let inline private bindM ( parser : ParserMonad < 'a >)
137
137
( next : 'a -> ParserMonad < 'b >) : ParserMonad < 'b > =
138
- ParserMonad <| fun state ->
138
+ StateT <| fun state ->
139
139
match apply1 parser state with
140
140
| Error msg -> Error msg
141
141
| Ok ( ans, st1) -> apply1 ( next ans) st1
142
142
143
143
let mzero () : ParserMonad < 'a > =
144
- ParserMonad <| fun state -> Error ( mkParseError state ( EOF " mzero" ))
144
+ StateT <| fun state -> Error ( mkParseError state ( EOF " mzero" ))
145
145
146
146
let inline mplus ( parser1 : ParserMonad < 'a >) ( parser2 : ParserMonad < 'a >) : ParserMonad < 'a > =
147
- ParserMonad <| fun state ->
147
+ StateT <| fun state ->
148
148
match apply1 parser1 state with
149
149
| Error _ -> apply1 parser2 state
150
150
| Ok res -> Ok res
@@ -158,31 +158,6 @@ module ParserMonad =
158
158
let (>>= ) ( m: ParserMonad< 'a>) ( k: 'a -> ParserMonad< 'b>) : ParserMonad< 'b> =
159
159
bindM m k
160
160
161
- type ParserBuilder () =
162
- member inline self.ReturnFrom ( ma : ParserMonad < 'a >) : ParserMonad < 'a > = ma
163
- member inline self.Return x = mreturn x
164
- member inline self.Bind ( p , f ) = bindM p f
165
- member inline self.Zero a = ParserMonad ( fun state -> Ok( a, state))
166
- //member self.Combine (ma, mb) = ma >>= mb
167
-
168
- // inspired from http://www.fssnip.net/7UJ/title/ResultBuilder-Computational-Expression
169
- // probably broken
170
- member inline self.TryFinally ( m , compensation ) =
171
- try self.ReturnFrom( m)
172
- finally compensation()
173
-
174
- //member self.Delay(f: unit -> ParserMonad<'a>) : ParserMonad<'a> = f ()
175
- //member self.Using(res:#System.IDisposable, body) =
176
- // self.TryFinally(body res, fun () -> if not (isNull res) then res.Dispose())
177
- //member self.While(guard, f) =
178
- // if not (guard()) then self.Zero () else
179
- // do f() |> ignore
180
- // self.While(guard, f)
181
- //member self.For(sequence:seq<_>, body) =
182
- // self.Using(sequence.GetEnumerator(), fun enum -> self.While(enum.MoveNext, fun () -> self.Delay(fun () -> body enum.Current)))
183
-
184
- let ( parseMidi : ParserBuilder ) = new ParserBuilder()
185
-
186
161
let runParser ( ma : ParserMonad < 'a >) input initialState =
187
162
apply1 ma { initialState with Input = input}
188
163
|> Result.map fst
@@ -194,11 +169,11 @@ module ParserMonad =
194
169
195
170
/// Throw a parse error
196
171
let parseError ( genMessage : Pos -> string ) : ParserMonad < 'a > =
197
- ParserMonad <| fun st -> Error ( mkOtherParseError st genMessage)
172
+ StateT <| fun st -> Error ( mkOtherParseError st genMessage)
198
173
199
174
/// Run the parser, if it fails swap the error message.
200
175
let inline ( <??> ) ( parser : ParserMonad < 'a >) ( genMessage : Pos -> string ) : ParserMonad < 'a > =
201
- ParserMonad <| fun st ->
176
+ StateT <| fun st ->
202
177
match apply1 parser st with
203
178
| Ok result -> Ok result
204
179
| Error e ->
@@ -207,13 +182,13 @@ module ParserMonad =
207
182
208
183
///
209
184
let fmap ( f : 'a -> 'b ) ( p : ParserMonad < 'a >) : ParserMonad < 'b > =
210
- parseMidi {
185
+ monad {
211
186
let! a = p
212
187
return ( f a)
213
188
}
214
189
let inline ( < ~> (* <$> *) ) ( a ) b = fmap a b
215
190
let ( *> ) ( a : ParserMonad < 'a >) ( b : 'a -> ParserMonad < 'b >) : ParserMonad < 'b > =
216
- parseMidi {
191
+ monad {
217
192
let! a = a
218
193
return ! ( b a)
219
194
}
@@ -240,16 +215,16 @@ module ParserMonad =
240
215
241
216
242
217
let fatalError err =
243
- ParserMonad <| fun st -> Error ( mkParseError st err)
218
+ StateT <| fun st -> Error ( mkParseError st err)
244
219
245
220
let getRunningEvent : ParserMonad < VoiceEvent > =
246
- ParserMonad <| fun st -> Ok ( st.RunningStatus , st)
221
+ StateT <| fun st -> Ok ( st.RunningStatus , st)
247
222
248
223
let inline setRunningEvent ( runningStatus : VoiceEvent ) : ParserMonad < unit > =
249
- ParserMonad <| fun st -> Ok ((), { st with RunningStatus = runningStatus })
224
+ StateT <| fun st -> Ok ((), { st with RunningStatus = runningStatus })
250
225
251
226
let getPos : ParserMonad < int > =
252
- ParserMonad <| fun st -> Ok ( st.Position, st)
227
+ StateT <| fun st -> Ok ( st.Position, st)
253
228
254
229
let inline private (| PositionValid | PositionInvalid |) ( input : MidiData , state : State ) =
255
230
if state.Position >= 0 && state.Position < input.Length then
@@ -258,7 +233,7 @@ module ParserMonad =
258
233
PositionInvalid
259
234
260
235
let inline private checkedParseM ( name : string ) ( f : State -> Result <( 'a * State ), ParseError >) =
261
- ParserMonad
236
+ StateT
262
237
( fun state ->
263
238
try
264
239
match state.Input, state with
@@ -286,7 +261,7 @@ module ParserMonad =
286
261
/// Repeats a given <see paramref="parser"/> <see paramref="length"/> times.
287
262
/// Fails with accumulated errors when any encountered.
288
263
let inline count ( length : ^T ) ( parser : ParserMonad < 'a >) : ParserMonad < 'a []> =
289
- ParserMonad <| fun state ->
264
+ StateT <| fun state ->
290
265
let rec work ( i : 'T )
291
266
( st : State )
292
267
( fk : ParseError -> Result < 'a list * State , ParseError >)
@@ -305,7 +280,7 @@ module ParserMonad =
305
280
306
281
/// Run a parser within a bounded section of the input stream.
307
282
let repeatTillPosition ( maxPosition : Pos ) ( p : ParserMonad < 'a >) : ParserMonad < 'a array > =
308
- ParserMonad ( fun state ->
283
+ StateT ( fun state ->
309
284
let results = ResizeArray()
310
285
let mutable firstError = Ok ( Array.empty, state)
311
286
let mutable lastState = state
@@ -328,7 +303,7 @@ module ParserMonad =
328
303
)
329
304
330
305
let inline boundRepeat ( n : ^T ) ( p : ParserMonad < 'a >) : ParserMonad < 'a array > =
331
- ParserMonad ( fun state ->
306
+ StateT ( fun state ->
332
307
let result = Array.zeroCreate ( int n)
333
308
let mutable lastState = state
334
309
// revisit with a fold?
@@ -357,7 +332,7 @@ module ParserMonad =
357
332
/// Apply the parser for /count/ times, derive the final answer
358
333
/// from the intermediate list with the supplied function.
359
334
let inline gencount ( plen : ParserMonad < 'T >) ( p : ParserMonad < 'a >) ( constr : ^T -> 'a array -> 'answer ) : ParserMonad < 'answer > =
360
- parseMidi {
335
+ monad {
361
336
let! l = plen
362
337
logf " gen count: l: %i " l
363
338
let! items = boundRepeat l p
@@ -378,22 +353,22 @@ module ParserMonad =
378
353
379
354
/// Parse a single byte char.
380
355
let readChar : ParserMonad < char > =
381
- parseMidi {
356
+ monad {
382
357
let! a = readByte
383
358
return ( char a)
384
359
}
385
360
386
361
/// Parse a string of the given length.
387
362
let readString ( length : int ) : ParserMonad < string > =
388
- parseMidi {
363
+ monad {
389
364
let! arr = count length readChar
390
365
return ( System.String arr)
391
366
}
392
367
<??> sprintf " readString failed at %i "
393
368
open ZMidi.Internal .DataTypes .FromBytes
394
369
/// Parse a uint16 (big endian).
395
370
let readUInt16be : ParserMonad < uint16 >=
396
- parseMidi {
371
+ monad {
397
372
let! a = readByte
398
373
let! b = readByte
399
374
return word16be a b
@@ -402,7 +377,7 @@ module ParserMonad =
402
377
403
378
/// Parse a word14 (big endian) from 2 consecutive bytes.
404
379
let readWord14be =
405
- parseMidi {
380
+ monad {
406
381
let! a = readByte
407
382
let! b = readByte
408
383
return ( word14be a b)
@@ -411,7 +386,7 @@ module ParserMonad =
411
386
412
387
/// Parse a word32 (big endian).
413
388
let readUInt32be =
414
- parseMidi {
389
+ monad {
415
390
let! a = readByte
416
391
let! b = readByte
417
392
let! c = readByte
@@ -421,9 +396,9 @@ module ParserMonad =
421
396
422
397
/// Parse a word24 (big endian).
423
398
let readWord24be =
424
- parseMidi {
399
+ monad {
425
400
let! a = readByte
426
401
let! b = readByte
427
402
let! c = readByte
428
403
return ( word24be a b c)
429
- }
404
+ }
0 commit comments