PageRenderTime 8ms CodeModel.GetById 4ms app.highlight 121ms RepoModel.GetById 1ms app.codeStats 0ms

/FParsec/CharParsers.fs

https://bitbucket.org/banshee/fparsec-samples
F# | 1309 lines | 1078 code | 187 blank | 44 comment | 351 complexity | 4b6e4ccea3f15f27074ae7f96d70c16a MD5 | raw file

Large files files are truncated, but you can click here to view the full file

   1// Copyright (c) Stephan Tolksdorf 2007-2009
   2// License: Simplified BSD License. See accompanying documentation.
   3
   4namespace FParsec
   5
   6module CharParsers
   7
   8open System.Diagnostics
   9open System.Text
  10open System.Text.RegularExpressions
  11
  12open Microsoft.FSharp.NativeInterop
  13
  14open FParsec.Internals
  15open FParsec.Error
  16open FParsec.Primitives
  17
  18#nowarn "9" // "Uses of this construct may result in the generation of unverifiable .NET IL code."
  19#nowarn "51" // "The address-of operator may result in non-verifiable code."
  20
  21// ================
  22// Helper functions
  23// ================
  24
  25[<Literal>]
  26let EOS = CharStream.Iterator.EndOfStreamChar
  27
  28let foldCase = CharStream.FoldCase
  29let normalizeNewlines = CharStream.NormalizeNewlines
  30
  31let floatToHexString d = Helper.DoubleToHexString(d)
  32let floatOfHexString s = Helper.DoubleFromHexString(s)
  33
  34let float32ToHexString d = Helper.SingleToHexString(d)
  35let float32OfHexString s = Helper.SingleFromHexString(s)
  36
  37// ========================
  38// Running parsers on input
  39// ========================
  40
  41[<StructuredFormatDisplay("{StructuredFormatDisplay}")>]
  42type ParserResult<'Result,'UserState> =
  43     | Success of 'Result * 'UserState * Pos
  44     | Failure of string * ParserError * 'UserState
  45     with
  46        member private t.StructuredFormatDisplay =
  47            match t with
  48            | Success(r,_,_) ->
  49                if typeof<'Result> = typeof<unit> then "Success: ()"
  50                else sprintf "Success: %A" r
  51            | Failure(msg,_,_) ->
  52                sprintf "Failure:\n%s" msg
  53
  54let internal applyParser (parser: Parser<'Result,'UserState>) (state: State<'UserState>) =
  55    let reply = parser state
  56    if reply.Status = Ok then
  57        Success(reply.Result, reply.State.UserState, reply.State.Pos)
  58    else
  59        let error = ParserError(reply.State.Pos, reply.Error)
  60        Failure(error.ToString(reply.State.Stream), error, reply.State.UserState)
  61
  62let runParser (parser: Parser<'Result,'UserState>) (ustate: 'UserState) (name: string) (stream: CharStream) =
  63    let state0 = new State<'UserState>(stream, ustate, name)
  64    applyParser parser state0
  65
  66let runParserOnString (parser: Parser<'Result,'UserState>) (ustate: 'UserState) (streamName: string) (chars: string) =
  67    use stream = new CharStream(chars, 0, chars.Length)
  68    let state0 = new State<'UserState>(stream, ustate, streamName)
  69    applyParser parser state0
  70
  71let runParserOnSubstring (parser: Parser<'Result,'UserState>) (ustate: 'UserState) (streamName: string) (chars: string) (index: int) length =
  72    use stream = new CharStream(chars, index, length)
  73    let state0 = new State<'UserState>(stream, ustate, streamName)
  74    applyParser parser state0
  75
  76let runParserOnStream (parser: Parser<'Result,'UserState>) (ustate: 'UserState) (streamName: string) (byteStream: System.IO.Stream) (encoding: System.Text.Encoding) =
  77    use stream = new CharStream(byteStream, encoding)
  78    let state0 = new State<'UserState>(stream, ustate, streamName)
  79    applyParser parser state0
  80
  81let runParserOnFile (parser: Parser<'Result,'UserState>) (ustate: 'UserState) (path: string) (encoding: System.Text.Encoding) =
  82    use stream = new CharStream(path, encoding)
  83    let state0 = new State<'UserState>(stream, ustate, path)
  84    applyParser parser state0
  85
  86let runParserOnSubstream (parser: Parser<'Result,'SubstreamUserState>) ustate (stateBeforeSubstream: State<'UserState>) stateAfterSubStream =
  87    Helper.RunParserOnSubstream(applyParser parser, ustate, stateBeforeSubstream, stateAfterSubStream)
  88
  89let run parser (string: string) =
  90    runParserOnString parser () "" string
  91
  92// some predefined error messages
  93
  94let internal expectedEndOfFile            = expectedError "end of file"
  95let internal expectedAnyChar              = expectedError "any char"
  96let internal expectedWhitespace           = expectedError "whitespace"
  97let internal expectedAsciiUppercaseLetter = expectedError "Ascii uppercase letter"
  98let internal expectedAsciiLowercaseLetter = expectedError "Ascii lowercase letter"
  99let internal expectedAsciiLetter          = expectedError "Ascii letter"
 100let internal expectedUppercaseLetter      = expectedError "uppercase letter"
 101let internal expectedLowercaseLetter      = expectedError "lowercase letter"
 102let internal expectedLetter               = expectedError "letter"
 103let internal expectedBinaryDigit          = expectedError "binary digit"
 104let internal expectedOctalDigit           = expectedError "octal digit"
 105let internal expectedDecimalDigit         = expectedError "digit"
 106let internal expectedHexadecimalDigit     = expectedError "hexadecimal digit"
 107let internal expectedNewline              = expectedError "newline"
 108let internal expectedTab                  = expectedError "tab"
 109let internal expectedFloatingPointNumber  = expectedError "floating-point number"
 110let internal expectedInt64                = expectedError "integer number (64-bit, signed)"
 111let internal expectedInt32                = expectedError "integer number (32-bit, signed)"
 112let internal expectedInt16                = expectedError "integer number (16-bit, signed)"
 113let internal expectedInt8                 = expectedError "integer number (8-bit, signed)"
 114let internal expectedUInt64               = expectedError "integer number (64-bit, unsigned)"
 115let internal expectedUInt32               = expectedError "integer number (32-bit, unsigned)"
 116let internal expectedUInt16               = expectedError "integer number (16-bit, unsigned)"
 117let internal expectedUInt8                = expectedError "integer number (8-bit, unsigned)"
 118
 119let internal unexpectedNewline            = unexpectedError "newline"
 120let internal unexpectedEndOfFile          = unexpectedError "end of file"
 121
 122// =======
 123// Parsers
 124// =======
 125
 126// ------------------------------------------------
 127// Reading the position and handling the user state
 128// ------------------------------------------------
 129
 130let getPos : Parser<Pos,'u> =
 131    fun state -> Reply<_,_>(state.Pos, state)
 132
 133let getUserState : Parser<'u,'u> =
 134    fun state -> Reply<_,_>(state.UserState, state)
 135
 136let setUserState (newUserState: 'u) : Parser<unit,'u> =
 137    fun state -> Reply<_,_>((), state.WithUserState(newUserState))
 138
 139let updateUserState (f: 'u -> 'u) : Parser<unit,'u> =
 140    fun state -> Reply<_,_>((), state.WithUserState(f state.UserState))
 141
 142let userStateSatisfies f : Parser<unit,'u> =
 143    fun state ->
 144        Reply<unit,_>((if f state.UserState then Ok else Error), NoErrorMessages, state)
 145
 146// --------------------
 147// Parsing single chars
 148// --------------------
 149
 150// needs to be inline because of the value restriction
 151let inline internal inlineNewlineReturn result : Parser<_,'u> =
 152    fun state ->
 153        let newState = state.SkipNewline()
 154        if not (referenceEquals state newState) then
 155            Reply<_,_>(result, newState)
 156        else
 157            Reply<_,_>(Error, expectedNewline, newState)
 158
 159let newlineReturn result = fun state -> inlineNewlineReturn result state
 160let newline              = fun state -> inlineNewlineReturn '\n' state
 161let skipNewline          = fun state -> inlineNewlineReturn () state
 162
 163let charReturn c result : Parser<'a,'u> =
 164    if c <> '\r' && c <> '\n' then
 165        let error = expectedError (quoteChar c)
 166        fun state ->
 167            if state.Iter.Match(c) then Reply<_,_>(result, state.Next)
 168            else Reply<_,_>(Error, error, state)
 169    else newlineReturn result
 170
 171let pchar    c = charReturn c c
 172let skipChar c = charReturn c ()
 173
 174
 175/// returns true for chars '\u000E' - '\ufffe'
 176let inline internal isCertainlyNoNLOrEOS (c: char) =
 177    // '\n' = '\u000A', '\r' = '\u000D'
 178    unativeint c - 0xEun < unativeint EOS - 0xEun
 179
 180let anyChar : Parser<char,'u> =
 181    fun state ->
 182        let c  = state.Iter.Read()
 183        if isCertainlyNoNLOrEOS c then
 184            Reply<_,_>(c, state.Next)
 185        elif c = '\r' || c = '\n' then
 186            Reply<_,_>('\n', state.SkipNewline())
 187        elif c <> EOS then
 188            Reply<_,_>(c, state.Next)
 189        else
 190            Reply<_,_>(Error, expectedAnyChar, state)
 191
 192let skipAnyChar : Parser<unit,'u> =
 193    fun state ->
 194        let newState = state.SkipCharOrNewline()
 195        if not (referenceEquals state newState) then
 196            Reply<_,_>((), newState)
 197        else
 198            Reply<_,_>(Error, expectedAnyChar, newState)
 199
 200
 201// doesn't check for newlines or EOS
 202let inline internal fastInlineSatisfyE f error : Parser<char,'u> =
 203    fun state ->
 204        let c = state.Iter.Read()
 205        if f c then Reply<_,_>(c, state.Next)
 206        else Reply<_,_>(Error, error, state)
 207
 208let inline internal fastInlineSkipSatisfyE f error : Parser<unit,'u> =
 209    fun state ->
 210        let c = state.Iter.Read()
 211        if f c then Reply<_,_>((), state.Next)
 212        else Reply<_,_>(Error, error, state)
 213
 214let inline internal inlineSatisfyE f error : Parser<char,'u> =
 215    fun state ->
 216        let c = state.Iter.Read()
 217        if isCertainlyNoNLOrEOS c then
 218            if f c then Reply<_,_>(c, state.Next)
 219            else Reply<_,_>(Error, error, state)
 220        elif c = '\r' || c = '\n' then
 221            if f '\n' then Reply<_,_>('\n', state.SkipNewline())
 222            else Reply<_,_>(Error, error, state)
 223        elif c <> EOS && f c then Reply<_,_>(c, state.Next)
 224        else Reply<_,_>(Error, error, state)
 225
 226let inline internal inlineSkipSatisfyE f error : Parser<unit,'u> =
 227    fun state ->
 228        let c = state.Iter.Read()
 229        if isCertainlyNoNLOrEOS c then
 230            if f c then Reply<_,_>((), state.Next)
 231            else Reply<_,_>(Error, error, state)
 232        elif c = '\r' || c = '\n' then
 233            if f '\n' then Reply<_,_>((), state.SkipNewline())
 234            else Reply<_,_>(Error, error, state)
 235        elif c <> EOS && f c then Reply<_,_>((), state.Next)
 236        else Reply<_,_>(Error, error, state)
 237
 238let internal satisfyE f error     = inlineSatisfyE f error
 239let internal skipSatisfyE f error = inlineSkipSatisfyE f error
 240
 241let satisfy f        = satisfyE f NoErrorMessages
 242let satisfyL f label = satisfyE f (expectedError label)
 243
 244let skipSatisfy f        = skipSatisfyE f NoErrorMessages
 245let skipSatisfyL f label = skipSatisfyE f (expectedError label)
 246
 247
 248let isAnyOf (chars: string) =
 249    let cs = new FParsec.Helper.CharSet(chars)
 250    fun c -> cs.Contains(c)
 251
 252let isNoneOf (chars: string) =
 253    let cs = new FParsec.Helper.CharSet(chars)
 254    fun c -> not (cs.Contains(c))
 255
 256let anyOf (chars: string) =
 257    let error = expectedError ("any char in " + quoteString chars)
 258    let cs = new FParsec.Helper.CharSet(chars)
 259    inlineSatisfyE (fun c -> cs.Contains(c)) error
 260
 261let skipAnyOf (chars: string) =
 262    let error = expectedError ("any char in " + quoteString chars)
 263    let cs = new FParsec.Helper.CharSet(chars)
 264    inlineSkipSatisfyE (fun c -> cs.Contains(c)) error
 265
 266let noneOf (chars: string) =
 267    let error = expectedError ("any char not in " + quoteString chars)
 268    let cs = new FParsec.Helper.CharSet(chars)
 269    inlineSatisfyE (fun c -> not (cs.Contains(c))) error
 270
 271let skipNoneOf (chars: string) =
 272    let error = expectedError ("any char not in " + quoteString chars)
 273    let cs = new FParsec.Helper.CharSet(chars)
 274    inlineSkipSatisfyE (fun c -> not (cs.Contains(c))) error
 275
 276
 277let inline isAsciiUpper c  = c >= 'A' && c <= 'Z'
 278let inline isAsciiLower c  = c >= 'a' && c <= 'z'
 279let inline isAsciiLetter (c: char) = let c2 = int c ||| int ' '
 280                                     c2 >= int 'a' && c2 <= int 'z'
 281
 282let inline isUpper c  =
 283    if c >= 'A' then
 284       c <= 'Z' || (c > '\u007F' && System.Char.IsUpper(c))
 285    else false
 286
 287let inline isLower c  =
 288    if c >= 'a' then
 289       c <= 'z' || (c > '\u007F' && System.Char.IsLower(c))
 290    else false
 291
 292let inline isLetter c =
 293    if c <= '\u007F' then
 294         let c2 = int c ||| int ' '
 295         c2 >= int 'a' && c2 <= int 'z'
 296    else System.Char.IsLetter(c)
 297
 298let inline isDigit c  = c <= '9' && c >= '0'
 299
 300let inline isHex c    =
 301    if   c <= '9' then c >= '0'
 302    else c <= 'f' && (c >= 'a' || (c >= 'A' && c <= 'F'))
 303
 304let inline isOctal c  = c <= '7' && c >= '0'
 305
 306let asciiUpper  state = fastInlineSatisfyE isAsciiUpper  expectedAsciiUppercaseLetter  state
 307let asciiLower  state = fastInlineSatisfyE isAsciiLower  expectedAsciiLowercaseLetter  state
 308let asciiLetter state = fastInlineSatisfyE isAsciiLetter expectedAsciiLetter           state
 309
 310// unicode is the default for letters and ascii the default for numbers
 311let upper  state = fastInlineSatisfyE isUpper  expectedUppercaseLetter  state
 312let lower  state = fastInlineSatisfyE isLower  expectedLowercaseLetter  state
 313let letter state = fastInlineSatisfyE isLetter expectedLetter           state
 314
 315let digit  state = fastInlineSatisfyE isDigit  expectedDecimalDigit     state
 316let hex    state = fastInlineSatisfyE isHex    expectedHexadecimalDigit state
 317let octal  state = fastInlineSatisfyE isOctal  expectedOctalDigit       state
 318
 319let tab state = fastInlineSatisfyE ((=) '\t') expectedTab state
 320
 321let unicodeNewline : Parser<_,'u> =
 322    fun state ->
 323        let c  = state.Iter.Read()
 324        if c < '\u0085' then
 325            if c = '\r' || c = '\n' then
 326                Reply<_,_>('\n', state.SkipNewline())
 327            elif c <> '\u000C' then
 328                Reply<_,_>(Error, expectedNewline, state)
 329            else // c = '\u000C'
 330                Reply<_,_>('\n', state.Advance(1, 1, 0))
 331        elif c <= '\u2029' && (c >= '\u2028' || c = '\u0085') then
 332            Reply<_,_>('\n', state.Advance(1, 1, 0))
 333        else
 334            Reply<_,_>(Error, expectedNewline, state)
 335
 336let whitespace : Parser<char,'u> =
 337    fun state ->
 338        let c = state.Iter.Read()
 339        if c <= ' ' then
 340            match c with
 341            | ' '  | '\t' -> Reply<_,_>(c, state.Next)
 342            | '\r' | '\n' -> Reply<_,_>('\n', state.SkipNewline())
 343            | _           -> Reply<_,_>(Error, expectedWhitespace, state)
 344        else Reply<_,_>(Error, expectedWhitespace, state)
 345
 346let unicodeWhitespace : Parser<char,'u> =
 347    fun state ->
 348        let c  = state.Iter.Read()
 349        if c = ' ' then Reply<_,_>(c, state.Next)
 350        elif System.Char.IsWhiteSpace(c) then
 351            match c with
 352            | '\r' | '\n' ->
 353               Reply<_,_>('\n', state.SkipNewline())
 354            | '\u000C' | '\u0085' | '\u2028' | '\u2029' ->
 355               Reply<_,_>('\n', state.Advance(1, 1, 0))
 356            | _ ->
 357               Reply<_,_>(c, state.Next)
 358        else Reply<_,_>(Error, expectedWhitespace, state)
 359
 360
 361let spaces : Parser<unit,'u> =
 362    fun state ->
 363        Reply<_,_>((), state.SkipWhitespace())
 364
 365let spaces1 : Parser<unit,'u> =
 366    fun state ->
 367        let newState = state.SkipWhitespace()
 368        if not (referenceEquals newState state) then Reply<_,_>((), newState)
 369        else Reply<_,_>(Error, expectedWhitespace, newState)
 370
 371let eof : Parser<unit,'u>=
 372    fun state ->
 373        if state.Iter.IsEndOfStream then Reply<_,_>((), state)
 374        else Reply<_,_>(Error, expectedEndOfFile, state)
 375
 376
 377// ------------------------
 378// Parsing strings directly
 379// ------------------------
 380
 381let internal checkStringContainsNoNewlineChar s name =
 382    if containsNewlineChar s then
 383        raise (System.ArgumentException(concat3 "The string argument to " name " may not contain newline chars ('\r' or '\n')."))
 384
 385let stringReturn s result : Parser<'a,'u> =
 386    checkStringContainsNoNewlineChar s "pstring/skipString/stringReturn"
 387    let error = expectedError (quoteString s)
 388    fun state ->
 389        if state.Iter.Match(s) then Reply<_,_>(result, state.Advance(s.Length))
 390        else Reply<_,_>(Error, error, state)
 391let pstring s    = stringReturn s s
 392let skipString s = stringReturn s ()
 393
 394
 395let pstringCI s : Parser<string,'u> =
 396    checkStringContainsNoNewlineChar s "pstringCI"
 397    let error = expectedError (quoteString s + " (case-insensitive)")
 398    let cfs = foldCase s
 399    fun state ->
 400        if state.Iter.MatchCaseFolded(cfs) then
 401             Reply<_,_>(state.Iter.Read(s.Length), state.Advance(s.Length))
 402        else Reply<_,_>(Error, error, state)
 403
 404let stringCIReturn s result : Parser<'a,'u> =
 405    checkStringContainsNoNewlineChar s "skipStringCI/stringCIReturn"
 406    let error = expectedError (quoteString s + " (case-insensitive)")
 407    let cfs = foldCase s
 408    fun state ->
 409        if state.Iter.MatchCaseFolded(cfs) then
 410             Reply<_,_>(result, state.Advance(s.Length))
 411        else Reply<_,_>(Error, error, state)
 412
 413let skipStringCI s = stringCIReturn s ()
 414
 415
 416let anyString n : Parser<string,'u> =
 417    let error = expectedError (concat3 "any sequence of " (string n) " chars")
 418    fun state ->
 419        let mutable str = null
 420        let newState = state.SkipCharsOrNewlines(n, &str)
 421        if str.Length = n then Reply<_,_>(str, newState)
 422        else Reply<_,_>(Error, error, state)
 423
 424let skipAnyString n : Parser<unit,'u> =
 425    let error = expectedError (concat3 "any sequence of " (string n) " chars")
 426    fun state ->
 427        let mutable nSkipped = 0
 428        let newState = state.SkipCharsOrNewlines(n, &nSkipped)
 429        if n = nSkipped then Reply<_,_>((), newState)
 430        else Reply<_,_>(Error, error, state)
 431
 432let restOfLine : Parser<_,_> =
 433    fun state ->
 434        let mutable str = null
 435        let newState = state.SkipRestOfLine(true, &str)
 436        Reply<_,_>(str, newState)
 437
 438let skipRestOfLine : Parser<_,_> =
 439    fun state ->
 440         Reply<_,_>((), state.SkipRestOfLine(true))
 441
 442let skipToEndOfLine : Parser<_,_> =
 443    fun state ->
 444        Reply<_,_>((), state.SkipRestOfLine(false))
 445
 446
 447let skipToString (s: string) maxChars : Parser<unit,'u> =
 448    checkStringContainsNoNewlineChar s "skipToString"
 449    if maxChars < 0 then raise (System.ArgumentOutOfRangeException("maxChars", "maxChars is negative."))
 450    let error = messageError (concat3 "Could not find the string " (quoteString s) ".")
 451    fun state ->
 452        let mutable foundString = false
 453        let state2 = state.SkipToString(s, maxChars, &foundString)
 454        if foundString then Reply<_,_>((), state2)
 455        else Reply<_,_>(Error, error, state2)
 456
 457let skipToStringCI (s: string) maxChars : Parser<unit,'u> =
 458    checkStringContainsNoNewlineChar s "skipToStringCI"
 459    if maxChars < 0 then raise (System.ArgumentOutOfRangeException("maxChars", "maxChars is negative."))
 460    let cfs = foldCase s
 461    let error = messageError (concat3 "Could not find the case-insensitive string " (quoteString s) ".")
 462    fun state ->
 463        let mutable foundString = false
 464        let state2 = state.SkipToStringCI(cfs, maxChars, &foundString)
 465        if foundString then Reply<_,_>((), state2)
 466        else Reply<_,_>(Error, error, state2)
 467
 468let charsTillString (s: string) maxChars : Parser<string,'u> =
 469    checkStringContainsNoNewlineChar s "charsTillString"
 470    if maxChars < 0 then raise (System.ArgumentOutOfRangeException("maxChars", "maxChars is negative."))
 471    let error = messageError (concat3 "Could not find the string " (quoteString s) ".")
 472    fun state ->
 473        let mutable charsBeforeString = null
 474        let state2 = state.SkipToString(s, maxChars, &charsBeforeString)
 475        if isNotNull charsBeforeString then Reply<_,_>(charsBeforeString, state2.Advance(s.Length))
 476        else Reply<_,_>(Error, error, state2)
 477
 478let charsTillStringCI (s: string) maxChars : Parser<string,'u> =
 479    checkStringContainsNoNewlineChar s "charsTillStringCI"
 480    if maxChars < 0 then raise (System.ArgumentOutOfRangeException("maxChars", "maxChars is negative."))
 481    let cfs = foldCase s
 482    let error = messageError (concat3 "Could not find the case-insensitive string " (quoteString s) ".")
 483    fun state ->
 484        let mutable charsBeforeString = null
 485        let state2 = state.SkipToStringCI(cfs, maxChars, &charsBeforeString)
 486        if isNotNull charsBeforeString then Reply<_,_>(charsBeforeString, state2.Advance(s.Length))
 487        else Reply<_,_>(Error, error, state2)
 488
 489let skipCharsTillString (s: string) maxChars : Parser<unit,'u> =
 490    checkStringContainsNoNewlineChar s "skipCharsTillString"
 491    if maxChars < 0 then raise (System.ArgumentOutOfRangeException("maxChars", "maxChars is negative."))
 492    let error = messageError (concat3 "Could not find the string " (quoteString s) ".")
 493    fun state ->
 494        let mutable foundString = false
 495        let state2 = state.SkipToString(s, maxChars, &foundString)
 496        if foundString then Reply<_,_>((), state2.Advance(s.Length))
 497        else Reply<_,_>(Error, error, state2)
 498
 499let skipCharsTillStringCI (s: string) maxChars : Parser<unit,'u> =
 500    checkStringContainsNoNewlineChar s "skipCharsTillStringCI"
 501    if maxChars < 0 then raise (System.ArgumentOutOfRangeException("maxChars", "maxChars is negative."))
 502    let cfs = foldCase s
 503    let error = messageError (concat3 "Could not find the case-insensitive string " (quoteString s) ".")
 504    fun state ->
 505        let mutable foundString = false
 506        let state2 = state.SkipToStringCI(cfs, maxChars, &foundString)
 507        if foundString then Reply<_,_>((), state2.Advance(s.Length))
 508        else Reply<_,_>(Error, error, state2)
 509
 510
 511let inline internal manySatisfyImpl require1 f1 f error : Parser<string,'u> =
 512    fun state ->
 513        let mutable str = null
 514        let newState = state.SkipCharsOrNewlinesWhile(f1, f, &str)
 515        if not require1 || not (referenceEquals newState state) then Reply<_,_>(str, newState)
 516        else Reply<_,_>(Error, error, newState)
 517
 518let inline internal skipManySatisfyImpl require1 f1 f error : Parser<unit,'u> =
 519    fun state ->
 520        let newState = state.SkipCharsOrNewlinesWhile(f1, f)
 521        if not require1 || not (referenceEquals newState state) then Reply<_,_>((), newState)
 522        else Reply<_,_>(Error, error, newState)
 523
 524let manySatisfy2   f1 f       = manySatisfyImpl false f1 f NoErrorMessages
 525let many1Satisfy2  f1 f       = manySatisfyImpl true  f1 f NoErrorMessages
 526let many1Satisfy2L f1 f label = manySatisfyImpl true  f1 f (expectedError label)
 527
 528let skipManySatisfy2   f1 f       = skipManySatisfyImpl false f1 f NoErrorMessages
 529let skipMany1Satisfy2  f1 f       = skipManySatisfyImpl true  f1 f NoErrorMessages
 530let skipMany1Satisfy2L f1 f label = skipManySatisfyImpl true  f1 f (expectedError label)
 531
 532let manySatisfy   f       = manySatisfy2   f f
 533let many1Satisfy  f       = many1Satisfy2  f f
 534let many1SatisfyL f label = many1Satisfy2L f f label
 535
 536let skipManySatisfy   f       = skipManySatisfy2   f f
 537let skipMany1Satisfy  f       = skipMany1Satisfy2  f f
 538let skipMany1SatisfyL f label = skipMany1Satisfy2L f f label
 539
 540
 541let internal manyMinMaxSatisfy2E minChars maxChars f1 f error : Parser<string,'u> =
 542    if maxChars < 0 then raise (System.ArgumentOutOfRangeException("maxChars", "maxChars is negative."))
 543    if minChars > 0 then
 544        fun state ->
 545            let mutable str = null
 546            let newState = state.SkipCharsOrNewlinesWhile(f1, f, minChars, maxChars, &str)
 547            if not (referenceEquals newState state) then Reply<_,_>(str, newState)
 548            else Reply<_,_>(Error, error, newState)
 549    else
 550        fun state ->
 551            let mutable str = null
 552            let newState = state.SkipCharsOrNewlinesWhile(f1, f, 0, maxChars, &str)
 553            Reply<_,_>(str, newState)
 554
 555let internal skipManyMinMaxSatisfy2E minChars maxChars f1 f error : Parser<unit,'u> =
 556    if maxChars < 0 then raise (System.ArgumentOutOfRangeException("maxChars", "maxChars is negative."))
 557    if minChars > 0 then
 558        fun state ->
 559            let newState = state.SkipCharsOrNewlinesWhile(f1, f, minChars, maxChars)
 560            if not (referenceEquals newState state) then Reply<_,_>((), newState)
 561            else Reply<_,_>(Error, error, newState)
 562    else
 563        fun state ->
 564            let mutable str = null
 565            let newState = state.SkipCharsOrNewlinesWhile(f1, f, 0, maxChars)
 566            Reply<_,_>((), newState)
 567
 568let manyMinMaxSatisfy   minChars maxChars    f       = manyMinMaxSatisfy2E minChars maxChars f  f NoErrorMessages
 569let manyMinMaxSatisfyL  minChars maxChars    f label = manyMinMaxSatisfy2E minChars maxChars f  f (expectedError label)
 570let manyMinMaxSatisfy2  minChars maxChars f1 f       = manyMinMaxSatisfy2E minChars maxChars f1 f NoErrorMessages
 571let manyMinMaxSatisfy2L minChars maxChars f1 f label = manyMinMaxSatisfy2E minChars maxChars f1 f (expectedError label)
 572
 573let skipManyMinMaxSatisfy   minChars maxChars    f       = skipManyMinMaxSatisfy2E minChars maxChars f  f NoErrorMessages
 574let skipManyMinMaxSatisfyL  minChars maxChars    f label = skipManyMinMaxSatisfy2E minChars maxChars f  f (expectedError label)
 575let skipManyMinMaxSatisfy2  minChars maxChars f1 f       = skipManyMinMaxSatisfy2E minChars maxChars f1 f NoErrorMessages
 576let skipManyMinMaxSatisfy2L minChars maxChars f1 f label = skipManyMinMaxSatisfy2E minChars maxChars f1 f (expectedError label)
 577
 578
 579let internal regexE pattern error : Parser<string,'u> =
 580    let regex = new Regex("\A" + pattern, RegexOptions.Multiline |||
 581                                          RegexOptions.ExplicitCapture)
 582    fun state ->
 583        let m = state.Iter.Match(regex)
 584        if m.Success then
 585            let s = m.Value
 586            if not (containsNewlineChar s) then Reply<_,_>(s, if s.Length > 0 then state.Advance(s.Length) else state)
 587            else
 588                let s2 = normalizeNewlines s
 589                let mutable nSkippedChars = 0
 590                let newState = state.SkipCharsOrNewlines(s2.Length, &nSkippedChars)
 591                if nSkippedChars = s2.Length then Reply<_,_>(s2, newState)
 592                else Reply<_,_>(FatalError, messageError "Internal error in the regex parser. Please report this error to fparsec@quanttec.com.", newState)
 593        else Reply<_,_>(Error, error, state)
 594
 595let regex  pattern       = regexE pattern (expectedError ("string matching the regex " + quoteString pattern))
 596let regexL pattern label = regexE pattern (expectedError label)
 597
 598// ----------------------------------------------
 599// Parsing strings with the help of other parsers
 600// ----------------------------------------------
 601
 602type internal StructCharList = struct
 603    val mutable buffer_ui64_0: uint64
 604    val mutable buffer_ui64_1: uint64
 605    val mutable buffer_ui64_2: uint64
 606    val mutable buffer_ui64_3: uint64
 607
 608    val mutable chars: char[]
 609    val mutable count: int
 610
 611    member inline t.BufferPtr =
 612        NativePtr.of_nativeint<char> (NativePtr.to_nativeint (&&t.buffer_ui64_0))
 613
 614    /// an optimized version of Append(c) for the first char
 615    member inline t.AppendFirst(c) =
 616        Debug.Assert(t.count = 0)
 617        let p = t.BufferPtr
 618        NativePtr.set p 0 c
 619        t.count <- 1
 620
 621    member inline t.Append(c) =
 622        let i = t.count &&& 0xf
 623        t.count <- t.count + 1
 624        if i <> 0 then
 625            let p = t.BufferPtr
 626            NativePtr.set p i c
 627        else
 628            t._AppendContinue(c)
 629
 630    /// append char with index%16 = 0
 631    member t._AppendContinue(c) =
 632        let p = t.BufferPtr
 633        let count = t.count - 1
 634        Debug.Assert(count%16 = 0 || count = -1)
 635        let mutable chars = t.chars
 636        if isNotNull chars then
 637            if count = chars.Length then
 638                let newChars = Array.zeroCreate (count*2)
 639                System.Buffer.BlockCopy(chars, 0, newChars, 0, (count - 16)*sizeof<char>)
 640                t.chars <- newChars
 641                chars   <- newChars
 642            for i = 0 to 15 do
 643                chars.[count - 16 + i] <- NativePtr.get p i
 644        elif count <> 0 then
 645            chars   <- Array.zeroCreate 48
 646            t.chars <- chars
 647            for i = 0 to 15 do
 648                chars.[i] <- NativePtr.get p i
 649        NativePtr.set p 0 c
 650
 651    override t.ToString() =
 652        let p = t.BufferPtr
 653        let count = t.count
 654        if count <= 16 then new string(p, 0, count)
 655        else
 656            let chars = t.chars
 657            for i = (count - 1) &&& 0x7ffffff0 to count - 1 do
 658                chars.[i] <- NativePtr.get p (i &&& 0xf)
 659            new string(chars, 0, count)
 660end
 661
 662
 663let inline internal manyCharsImpl require1 (p1: Parser<char,'u>) (p: Parser<char,'u>) : Parser<string,'u> =
 664    fun state ->
 665        let mutable reply = p1 state
 666        if reply.Status = Ok then
 667            let mutable cl = new StructCharList()
 668            cl.AppendFirst(reply.Result)
 669            let mutable state = reply.State
 670            reply <- p state
 671            while reply.Status = Ok do
 672                if referenceEquals reply.State state then
 673                    _raiseInfiniteLoopException "manyChars" state
 674                cl.Append(reply.Result)
 675                state <- reply.State
 676                reply <- p state
 677            let error = if reply.State == state then reply.Error
 678                        else backtrackError reply.State reply.Error
 679            Reply<_,_>(Ok, cl.ToString(), error, state)
 680        else
 681            let error = if reply.State == state then reply.Error
 682                        else backtrackError reply.State reply.Error
 683            if require1 then Reply<_,_>(Error, error, state)
 684            else Reply<_,_>(Ok, "", error, state)
 685
 686let inline internal skipManyCharsImpl require1 (p1: Parser<'a,'u>) (p: Parser<'a,'u>) : Parser<unit,'u> =
 687    fun state ->
 688        let mutable reply = p1 state
 689        if reply.Status = Ok then
 690            let mutable state = reply.State
 691            reply <- p state
 692            while reply.Status = Ok do
 693                if referenceEquals reply.State state then
 694                    _raiseInfiniteLoopException "skipManyChars" state
 695                state <- reply.State
 696                reply <- p state
 697            let error = if reply.State == state then reply.Error
 698                        else backtrackError reply.State reply.Error
 699            Reply<_,_>(Ok, (), error, state)
 700         else
 701            let error = if reply.State == state then reply.Error
 702                        else backtrackError reply.State reply.Error
 703            if require1 then Reply<_,_>(Error, error, state)
 704            else Reply<_,_>(Ok, (), error, state)
 705
 706
 707let manyChars2 p1 p = manyCharsImpl false p1 p
 708let manyChars p = manyChars2 p p
 709
 710let many1Chars2 p1 p = manyCharsImpl true p1 p
 711let many1Chars p = many1Chars2 p p
 712
 713let skipManyChars2 (p1: Parser<'a,'u>) (p: Parser<'a,'u>) = skipManyCharsImpl false p1 p
 714let skipManyChars p = skipManyChars2 p p
 715
 716let skipMany1Chars2 (p1: Parser<'a,'u>) (p: Parser<'a,'u>) = skipManyCharsImpl true p1 p
 717let skipMany1Chars p = skipMany1Chars2 p p
 718
 719
 720let inline inlineManyCharsTillApply (p: Parser<char,'u>) (endp: Parser<'b,'u>) (f: string -> 'b -> 'c) =
 721    fun state ->
 722        let mutable state  = state
 723        let mutable reply2 = endp state
 724        if reply2.Status <> Ok then
 725            let mutable reply1 = p state
 726            let mutable cl = new StructCharList()
 727            if reply1.Status = Ok then
 728                cl.AppendFirst(reply1.Result)
 729                state <- reply1.State
 730                reply2 <- endp state
 731                while reply2.Status <> Ok && (reply1 <- p state; reply1.Status = Ok) do
 732                    if referenceEquals reply1.State state then
 733                        _raiseInfiniteLoopException "manyCharsTill" state
 734                    cl.Append(reply1.Result)
 735                    state  <- reply1.State
 736                    reply2 <- endp state
 737            if reply2.Status = Ok then
 738                let error = if not (referenceEquals reply2.State state) then reply2.Error
 739                            else mergeErrors reply1.Error reply2.Error
 740                Reply<_,_>(Ok, f (cl.ToString()) reply2.Result, error, reply2.State)
 741            elif reply1.Status = Error && reply1.State == state then
 742                let error = if reply2.State != state then reply2.Error
 743                            else mergeErrors reply1.Error reply2.Error
 744                Reply<_,_>(reply2.Status, error, reply2.State)
 745            else
 746                Reply<_,_>(reply1.Status, reply1.Error, reply1.State)
 747        else
 748            Reply<_,_>(Ok, f "" reply2.Result, reply2.Error, reply2.State)
 749
 750let inline inlineMany1CharsTill2Apply (p1: Parser<char,'u>) (p: Parser<char,'u>) (endp: Parser<'b,'u>) (f: string -> 'b -> 'c) =
 751    fun state ->
 752        let mutable reply1 = p1 state
 753        if reply1.Status = Ok then
 754            let mutable cl = new StructCharList()
 755            cl.AppendFirst(reply1.Result)
 756            let mutable state = reply1.State
 757            let mutable reply2 = endp state
 758            while reply2.Status <> Ok && (reply1 <- p state; reply1.Status = Ok) do
 759                if referenceEquals reply1.State state then
 760                    _raiseInfiniteLoopException "manyCharsTill" state
 761                cl.Append(reply1.Result)
 762                state  <- reply1.State
 763                reply2 <- endp state
 764            if reply2.Status = Ok then
 765                let error = if not (referenceEquals reply2.State state) then reply2.Error
 766                            else mergeErrors reply1.Error reply2.Error
 767                Reply<_,_>(Ok, f (cl.ToString()) reply2.Result, error, reply2.State)
 768            elif reply1.Status = Error && reply1.State == state then
 769                let error = if reply2.State != state then reply2.Error
 770                            else mergeErrors reply1.Error reply2.Error
 771                Reply<_,_>(reply2.Status, error, reply2.State)
 772            else
 773                Reply<_,_>(reply1.Status, reply1.Error, reply1.State)
 774        else
 775            Reply<_,_>(reply1.Status, reply1.Error, reply1.State)
 776
 777
 778let manyCharsTill      p endp   = inlineManyCharsTillApply p endp (fun str _ -> str)
 779let manyCharsTillApply p endp f = let optF = OptimizedClosures.FastFunc2.Adapt(f)
 780                                  inlineManyCharsTillApply p endp (fun str x -> optF.Invoke(str, x))
 781let skipManyCharsTill  p endp   = skipManyTill p endp
 782
 783let many1CharsTill2      p1 p endp   = inlineMany1CharsTill2Apply p1 p endp (fun str _ -> str)
 784let many1CharsTillApply2 p1 p endp f = let optF = OptimizedClosures.FastFunc2.Adapt(f)
 785                                       inlineMany1CharsTill2Apply p1 p endp (fun str x -> optF.Invoke(str, x))
 786let many1CharsTill          p endp   = many1CharsTill2 p p endp
 787let many1CharsTillApply     p endp f = many1CharsTillApply2 p p endp f
 788
 789let skipMany1CharsTill2  (p1: Parser<'a,'u>) (p: Parser<'a,'u>) endp   = p1 >>. skipManyTill p endp
 790let skipMany1CharsTill   p    endp   = skipMany1CharsTill2 p p endp
 791
 792
 793let inline manyStringsImpl require1 (p1: Parser<string,'u>) (p: Parser<string,'u>) : Parser<string,'u> =
 794    fun state ->
 795        let mutable reply = p1 state
 796        if reply.Status = Ok then
 797            let result1 = reply.Result
 798            let mutable error  = reply.Error
 799            let mutable state  = reply.State
 800            reply <- p state
 801            if reply.Status <> Ok then reply.Result <- result1
 802            else
 803                let result2 = reply.Result
 804                error <- reply.Error
 805                state <- reply.State
 806                reply <- p state
 807                if reply.Status <> Ok then reply.Result <- result1 + result2
 808                else
 809                    let result3 = reply.Result
 810                    error <- reply.Error
 811                    state <- reply.State
 812                    reply <- p state
 813                    if reply.Status <> Ok then reply.Result <- concat3 result1 result2 result3
 814                    else
 815                        let result4 = reply.Result
 816                        error <- reply.Error
 817                        state <- reply.State
 818                        reply <- p state
 819                        if reply.Status <> Ok then reply.Result <- concat4 result1 result2 result3 result4
 820                        else
 821                            let n = 2*(result1.Length + result2.Length + result3.Length + result4.Length) + reply.Result.Length
 822                            let sb = new StringBuilder(n)
 823                            sb.Append(result1).Append(result2).Append(result3).Append(result4).Append(reply.Result) |> ignore
 824                            error <- reply.Error
 825                            state <- reply.State
 826                            reply <- p state
 827                            while reply.Status = Ok do
 828                                if reply.State == state then
 829                                    _raiseInfiniteLoopException "manyStrings" state
 830                                error <- reply.Error
 831                                sb.Append(reply.Result) |> ignore
 832                                state <- reply.State
 833                                reply <- p state
 834                            reply.Result <- sb.ToString()
 835            // we assume that the string parser changes the state when it succeeds, so we don't need to merge more than one error
 836            if reply.Status = Error then
 837                if reply.State == state then
 838                    reply.Status <- Ok
 839                    if isNotNull error then
 840                        reply.Error <- concatErrorMessages error reply.Error
 841            else
 842                reply.Error <- mergeErrorsIfNeeded state error reply.State reply.Error
 843        elif not require1 && reply.Status = Error && reply.State == state then
 844            reply.Status <- Ok
 845            reply.Result <- ""
 846        reply
 847
 848let manyStrings2 p1 p = manyStringsImpl false p1 p
 849let manyStrings p = manyStrings2 p p
 850let many1Strings2 p1 p = manyStringsImpl true p1 p
 851let many1Strings p = many1Strings2 p p
 852
 853
 854let skipped (p: Parser<unit,'u>) : Parser<string,'u> =
 855    fun state ->
 856        let reply = p state
 857        let result = if reply.Status = Ok then state.ReadUntil(reply.State)  else ""
 858        Reply<_,_>(reply.Status, result, reply.Error, reply.State)
 859
 860let withSkippedString (f: string -> 'a -> 'b) (p: Parser<'a,'u>) : Parser<'b,'u> =
 861    let optF = OptimizedClosures.FastFunc2<_,_,_>.Adapt(f)
 862    fun state ->
 863        let reply = p state
 864        let result = if reply.Status = Ok then
 865                         optF.Invoke(state.ReadUntil(reply.State), reply.Result)
 866                     else Unchecked.defaultof<_>
 867        Reply<_,_>(reply.Status, result, reply.Error, reply.State)
 868
 869
 870// ---------------
 871// Parsing numbers
 872// ---------------
 873
 874[<System.Flags>]
 875type NumberLiteralOptions =
 876     | None                             = 0
 877     | AllowSuffix                      = 0b000000000001
 878     | AllowMinusSign                   = 0b000000000010
 879     | AllowPlusSign                    = 0b000000000100
 880     | AllowFraction                    = 0b000000001000
 881     | AllowFractionWOIntegerPart       = 0b000000010000
 882     | AllowExponent                    = 0b000000100000
 883     | AllowHexadecimal                 = 0b000001000000
 884     | AllowBinary                      = 0b000010000000
 885     | AllowOctal                       = 0b000100000000
 886     | AllowInfinity                    = 0b001000000000
 887     | AllowNaN                         = 0b010000000000
 888
 889     | DefaultInteger                   = 0b000111000110
 890     | DefaultUnsignedInteger           = 0b000111000000
 891     | DefaultFloat                     = 0b011001101110
 892
 893type internal NLO = NumberLiteralOptions
 894
 895[<System.Flags>]
 896type NumberLiteralResultFlags =
 897     | None             = 0
 898     | SuffixLengthMask = 0b0000000000001111
 899     | HasMinusSign     = 0b0000000000010000
 900     | HasPlusSign      = 0b0000000000100000
 901     | HasIntegerPart   = 0b0000000001000000
 902     | HasFraction      = 0b0000000010000000
 903     | HasExponent      = 0b0000000100000000
 904     | IsDecimal        = 0b0000001000000000
 905     | IsHexadecimal    = 0b0000010000000000
 906     | IsBinary         = 0b0000100000000000
 907     | IsOctal          = 0b0001000000000000
 908     | BaseMask         = 0b0001111000000000
 909     | IsInfinity       = 0b0010000000000000
 910     | IsNaN            = 0b0100000000000000
 911
 912type internal NLF = NumberLiteralResultFlags
 913
 914type NumberLiteral(string, info, suffixChar1, suffixChar2, suffixChar3, suffixChar4) = struct
 915    member t.String = string
 916
 917    member t.SuffixLength = int (info &&& NLF.SuffixLengthMask)
 918    member t.SuffixChar1  = suffixChar1
 919    member t.SuffixChar2  = suffixChar2
 920    member t.SuffixChar3  = suffixChar3
 921    member t.SuffixChar4  = suffixChar4
 922
 923    member t.Info = info
 924
 925    member t.HasMinusSign   = int (info &&& NLF.HasMinusSign) <> 0
 926    member t.HasPlusSign    = int (info &&& NLF.HasPlusSign) <> 0
 927    member t.HasIntegerPart = int (info &&& NLF.HasIntegerPart) <> 0
 928    member t.HasFraction    = int (info &&& NLF.HasFraction) <> 0
 929    member t.HasExponent    = int (info &&& NLF.HasExponent) <> 0
 930    member t.IsInteger      = info &&& (NLF.HasIntegerPart ||| NLF.HasFraction ||| NLF.HasExponent) = NLF.HasIntegerPart
 931    member t.IsDecimal      = int (info &&& NLF.IsDecimal) <> 0
 932    member t.IsHexadecimal  = int (info &&& NLF.IsHexadecimal) <> 0
 933    member t.IsBinary       = int (info &&& NLF.IsBinary) <> 0
 934    member t.IsOctal        = int (info &&& NLF.IsOctal) <> 0
 935    member t.IsNaN          = int (info &&& NLF.IsNaN) <> 0
 936    member t.IsInfinity     = int (info &&& NLF.IsInfinity) <> 0
 937end
 938
 939
 940
 941let numberLiteralE (opt: NumberLiteralOptions) (errorInCaseNoLiteralFound: ErrorMessageList) (state: State<'u>) =
 942    let mutable iter = state.Iter
 943    let mutable c = iter.Read()
 944    let mutable error = NoErrorMessages
 945    let mutable flags = NLF.None
 946
 947    if c = '-' && int (opt &&& NLO.AllowMinusSign) <> 0 then
 948        flags <- NLF.HasMinusSign
 949        c <- iter._Increment()
 950    elif c = '+' && int (opt &&& NLO.AllowPlusSign) <> 0 then
 951        flags <- NLF.HasPlusSign
 952        c <- iter._Increment()
 953
 954    let allowStartingPoint = NLO.AllowFraction ||| NLO.AllowFractionWOIntegerPart // for starting point both flags are required
 955
 956    if isDigit c || (c = '.' && (opt &&& allowStartingPoint = allowStartingPoint)) then
 957        if    int (opt &&& (NLO.AllowBinary ||| NLO.AllowOctal ||| NLO.AllowHexadecimal)) <> 0
 958           && c = '0'
 959        then
 960            match iter.Peek() with
 961            | 'b' | 'B' ->
 962                if int (opt &&& NLO.AllowBinary) <> 0 then
 963                    flags <- flags ||| NLF.IsBinary
 964                    c <- iter._Increment(2u)
 965                    if c = '0' || c = '1' then
 966                        flags <- flags ||| NLF.HasIntegerPart
 967                        c <- iter._Increment()
 968                    else
 969                        error <- expectedBinaryDigit
 970                    while c = '0' || c = '1' do
 971                        c <- iter._Increment()
 972            | 'o' | 'O' ->
 973                if int (opt &&& NLO.AllowOctal) <> 0 then
 974                    flags <- flags ||| NLF.IsOctal
 975                    c <- iter._Increment(2u)
 976                    if isOctal c then
 977                        flags <- flags ||| NLF.HasIntegerPart
 978                        c <- iter._Increment()
 979                    else
 980                        error <- expectedOctalDigit
 981                    while isOctal c do
 982                        c <- iter._Increment()
 983            | 'x' | 'X' ->
 984                if int (opt &&& NLO.AllowHexadecimal) <> 0 then
 985                    flags <- flags ||| NLF.IsHexadecimal
 986                    c <- iter._Increment(2u)
 987                    if isHex c then
 988                        flags <- flags ||| NLF.HasIntegerPart
 989                        c <- iter._Increment()
 990                    elif int (opt &&& NLO.AllowFractionWOIntegerPart) = 0 then
 991                        // integer part required
 992                        error <- expectedHexadecimalDigit
 993                    while isHex c do
 994                        c <- iter._Increment()
 995                    if c = '.' && isNull error && int (opt &&& NLO.AllowFraction) <> 0 then
 996                        flags <- flags ||| NLF.HasFraction
 997                        c <- iter._Increment()
 998                        if isHex c then
 999                            c <- iter._Increment()
1000                        elif int (flags &&& NLF.HasIntegerPart) = 0 then
1001                            // at least one digit before or after the . is required
1002                            error <- expectedHexadecimalDigit
1003                        while isHex c do
1004                            c <- iter._Increment()
1005                    elif int (flags &&& NLF.HasIntegerPart) = 0 then
1006                        // we neither have an integer part nor a fraction
1007                        error <- expectedHexadecimalDigit
1008                    if (c = 'p' || c = 'P') && isNull error && int (opt &&& NLO.AllowExponent) <> 0  then
1009                        flags <- flags ||| NLF.HasExponent
1010                        c <- iter._Increment()
1011                        if c = '-' || c = '+' then
1012                            c <- iter._Increment()
1013                        if not (isDigit c) then
1014                            error <- expectedDecimalDigit
1015                        while isDigit c do
1016                            c <- iter._Increment()
1017            | _ -> ()
1018
1019        if int (flags &&& (NLF.IsBinary ||| NLF.IsOctal ||| NLF.IsHexadecimal)) = 0 then
1020            flags <- flags ||| NLF.IsDecimal
1021            if c <> '.' then
1022                flags <- flags ||| NLF.HasIntegerPart
1023                c <- iter._Increment()
1024                while isDigit c do
1025                    c <- iter._Increment()
1026            if c = '.' && int (opt &&& NLO.AllowFraction) <> 0 then
1027                flags <- flags ||| NLF.HasFraction
1028                c <- iter._Increment()
1029                if isDigit c then
1030                    c <- iter._Increment()
1031                elif int (flags &&& NLF.HasIntegerPart) = 0 then
1032                    // at least one digit before or after the . is required
1033                    error <- expectedDecimalDigit
1034                while isDigit c do
1035                    c <- iter._Increment()
1036            if (c = 'e' || c = 'E') && isNull error && int (opt &&& NLO.AllowExponent) <> 0 then
1037                flags <- flags ||| NLF.HasExponent
1038                c <- iter._Increment()
1039                if c = '-' || c = '+' then
1040                    c <- iter._Increment()
1041                if not (isDigit c) then
1042                    error <- expectedDecimalDigit
1043                while isDigit c do
1044                    c <- iter._Increment()
1045
1046        if isNull error then
1047            let str = state.Iter.ReadUntil(iter)
1048            let mutable nSuffix = 0
1049            let mutable s1 = EOS
1050            let mutable s2 = EOS
1051            let mutable s3 = EOS
1052            let mutable s4 = EOS
1053            if int (opt &&& NLO.AllowSuffix) <> 0 && isNull error then
1054                if isAsciiLetter c then
1055                    nSuffix <- 1
1056                    s1 <- c
1057                    c <- iter._Increment()
1058                    if isAsciiLetter c then
1059                        nSuffix <- nSuffix + 1
1060                        s2 <- c
1061                        c <- iter._Increment()
1062                        if isAsciiLetter c then
1063                            nSuffix <- nSuffix + 1
1064                            s3 <- c
1065                            c <- iter._Increment()
1066                            if isAsciiLetter c then
1067                                nSuffix <- nSuffix + 1
1068                                s4 <- c
1069                                c <- iter._Increment()
1070                    flags <- flags ||| (enum) nSuffix
1071            let nl = NumberLiteral(str, flags, s1, s2, s3, s4)
1072            Reply<_,_>(nl, state.AdvanceTo(iter))
1073        else
1074            Reply<_,_>(Error, error, state.AdvanceTo(iter))
1075    else
1076        if int (opt &&& (NLO.AllowInfinity ||| NLO.AllowNaN)) <> 0 then
1077            if c = 'i' || c = 'I' then
1078                if int (opt &&& NLO.AllowInfinity) <> 0 then
1079                    c <- iter.Peek(1u)
1080                    if c = 'n' || c = 'N' then
1081                        c <- iter.Peek(2u)
1082                        if c = 'f' || c = 'F' then
1083                            flags <- flags ||| NLF.IsInfinity
1084                            c <- iter._Increment(3u)
1085                            if c = 'i' || c = 'I' then
1086                                c <- iter.Peek(1u)
1087                                if c = 'n' || c = 'N' then
1088                                    c <- iter.Peek(2u)
1089                                    if c = 'i' || c = 'I' then
1090                                        c <- iter.Peek(3u)
1091                                        if c = 't' || c = 'T' then
1092                                            c <- iter.Peek(4u)
1093                                            if c = 'y' || c = 'Y' then
1094                                                iter._Increment(5u) |> ignore
1095
1096            elif (c = 'n' || c = 'N') && int (opt &&& NLO.AllowNaN) <> 0 then
1097                c <- iter.Peek(1u)
1098                if c = 'a' || c = 'A' then
1099                    c <- iter.Peek(2u)
1100                    if c = 'n' || c = 'N' then
1101                        flags <- flags ||| NLF.IsNaN
1102                        iter._Increment(3u) |> ignore
1103
1104        if int (flags &&& (NLF.IsInfinity ||| NLF.IsNaN)) <> 0 then
1105            Reply<_,_>(NumberLiteral(state.Iter.ReadUntil(iter), flags, EOS, EOS, EOS, EOS), state.AdvanceTo(iter))
1106        else

Large files files are truncated, but you can click here to view the full file