Я пытаюсь реализовать библиотеку двоичного синтаксического анализатора с использованием Span. Я не уверен, что это действительно хорошая идея, я просто хочу узнать больше об обоих.
Я уже писал небольшой двоичный парсер с использованием комбинаторов парсеров , который отлично работает.
Код выглядит так:
type ByteRange =
{ Bytes : byte array
BeginIndex : int
EndIndex : int }
type ParserError<'err> =
| EndOfStream
| FormatError of 'err
type Parser<'T, 'err> = Parser of (ByteRange -> Result<'T * ByteRange, ParserError<'err>>)
let succeed value = Parser <| fun bytes -> Ok(value, bytes)
let fail error = Parser <| fun _ -> Error error
let internal fromResult result =
Parser <| fun bytes ->
match result with
| Ok value -> Ok(value, bytes)
| Error error -> Error(FormatError error)
let internal map f (Parser parse) =
Parser <| fun byteRange ->
match parse byteRange with
| Ok(value', state') -> Ok(f value', state')
| Error error -> Error error
...
Я попытался реализовать его, используя Span вместо ByteRange, и я просто не могу это сделать.
Вот что я попробовал:
module BinaryParser
open System
open System.Runtime.CompilerServices
type ParserError<'err> =
| EndOfStream
| FormatError of 'err
[<Struct; IsByRefLike>]
type Success<'a> = {
Value: 'a
Bytes: Span<byte>
}
[<Struct; IsByRefLike>]
type ParsingResult<'a, 'err> =
| Success of success:Success<'a>
| Failure of failure:ParserError<'err>
type Parser<'T, 'err> =
Span<byte> -> ParsingResult<'T, ParserError<'err>>
let succeed (value: 'a) =
fun (bytes: Span<byte>) ->
Success { Value = value; Bytes = bytes }
let fail error =
fun _ ->
Failure error
let internal fromResult result =
fun bytes ->
match result with
| Ok value -> Success { Value = value; Bytes = bytes }
| Error error -> Failure (FormatError error)
let internal map f (parse: Parser<_, _>) =
fun bytes ->
match parse bytes with
| Success { Value = value'; Bytes = bytes' } -> Success { Value = f value'; Bytes = bytes' }
| Failure error -> Failure error
Я получаю следующую ошибку в функции map
в строке match parser bytes with
:
ошибка FS0418: набранное значение byref 'bytes' не может быть использовано в данный момент
Что это значит? Почему я не могу использовать Span здесь? Кто-нибудь пытался реализовать парсер комбинатор с Span? Как бы вы попытались решить эту проблему?
Заранее спасибо.