anchor.diff:  
     let inline pow10 n = Pow10Table.[clamp (n - MinimumPow10) 0 (Pow10Table.Length - 1)]
   
  -  let inline neos (s : string) (pos : int) : bool = pos < s.Length
  -  let inline eos  (s : string) (pos : int) : bool = pos >= s.Length
  -  let inline ch   (s : string) (pos : int) : char = s.[pos]
  -  let inline adv  (p : byref<int>)                = p <- p + 1
  -
  -  let inline raiseEos (v : IParseVisitor) (pos : int) : bool =
  -    v.Unexpected (pos, Tokens.EOS)
  -    false
  +  let inline isWhiteSpace (c : char) : bool =
  +    c = ' ' || c = '\t' || c = '\n' || c = '\r'
  +
  +  let inline isDigit (c : char) : bool =
  +    c >= '0' && c <= '9'
   
     let rec charsContains (i : int) (v : char) (vs : char []) : bool =
       if i < vs.Length then
  
positive.code: /// Attempts to parse a JSON document from a string
  ///   visitor : Parser visitor object
  ///   input   : Input string
  let tryParse (visitor : IParseVisitor) (input : string) (pos : byref<int>) : bool =
    let sb = StringBuilder DefaultSize
    consume_WhiteSpace                input &pos
    && tryParse_RootValue sb  visitor input &pos
    && tryParse_Eos           visitor input &pos
  
  /// Returned by parse function
  type ParseResult =
  
negative.code:     else
        false
  
    type IParseVisitor with
      member x.ExpectedChars (p : int, chars : string) : unit =
        let e = chars.Length - 1
        for i = 0 to e do
          x.ExpectedChar (p, chars.[i])
  
    type JsonParser(s : string, v : IParseVisitor) =
      let sb          = StringBuilder DefaultSize
      let mutable pos = 0
  
      member x.position           :int   = pos
  
      member inline x.neos        : bool = pos < s.Length
      member inline x.eos         : bool = pos >= s.Length
      member inline x.ch          : char = s.[pos]
      member inline x.adv ()      : unit = pos <- pos + 1
  
      member x.raise_Eos ()       : bool =
        v.Unexpected (pos, Tokens.EOS)
        false
  
      member x.raise_Value ()     : bool =
        v.Expected      (pos, Tokens.Null )
        v.Expected      (pos, Tokens.True )
        v.Expected      (pos, Tokens.False)
        v.Expected      (pos, Tokens.Digit)
        v.ExpectedChars (pos, "\"{[-")
        false
  
      member x.raise_RootValue () : bool =
        v.ExpectedChars (pos, "{[")
        false
  
      member inline x.consume_WhiteSpace () : bool =
        let l = s.Length
        while pos < l && (isWhiteSpace s.[pos]) do
          x.adv ()
        true
  
      member inline x.test_Char (c : char) : bool =
        x.neos && x.ch  = c
  
      member inline x.tryConsume_Char (c : char) : bool =
        if x.eos then x.raise_Eos ()
        elif x.ch = c then
          x.adv ()
          true
        else
          v.ExpectedChar (pos, c)
          false
  
  // inline causes DEBUG mode to crash (because F# creates tuples of pointers
  #if DEBUG
      member x.tryParse_AnyOf2 (first : char, second : char, r : char byref) : bool =
  #else
      member inline x.tryParse_AnyOf2 (first : char, second : char, r : char byref) : bool =
  #endif
        if x.eos then x.raise_Eos ()
        else
          let c = x.ch
          if c = first || c = second then
            r <- c
            x.adv ()
            true
          else
            v.ExpectedChar (pos, first)
            v.ExpectedChar (pos, second)
            false
  
      member inline x.tryConsume_Token (tk : string) : bool =
        let tkl           = tk.Length
        let spos          = pos
        let mutable tpos  = 0
  
        while tpos < tkl && tk.[tpos] = s.[pos] do
          tpos <- tpos + 1
          x.adv ()
  
        if tpos = tkl then true
        else
          // To support error reporting, move back on failure
          pos <- spos
          false
  
      member x.tryParse_Null () : bool =
        if x.tryConsume_Token Tokens.Null then
          v.NullValue ()
        else
          x.raise_Value ()
  
      member x.tryParse_True () : bool =
        if x.tryConsume_Token Tokens.True then
          v.BoolValue true
        else
          x.raise_Value ()
  
      member x.tryParse_False () : bool =
        if x.tryConsume_Token Tokens.False then
          v.BoolValue false
        else
          x.raise_Value ()
  
      member x.tryParse_UInt (first : bool, r : float byref) : bool =
        let z = float '0'
        if x.eos then ignore <| x.raise_Eos (); not first
        else
          let c = x.ch
          if c >= '0' && c <= '9' then
            x.adv ()
            r <- 10.0*r + (float c - z)
            x.tryParse_UInt (false, &r)
          else
            v.Expected (pos, Tokens.Digit)
            not first
  
      member x.tryParse_UInt0 (r : float byref) : bool =
        // tryParse_UInt0 only consumes 0 if input is 0123, this in order to be conformant with spec
        let zero = x.tryConsume_Char '0'
  
        if zero then
          r <- 0.0
          true
        else
          x.tryParse_UInt (true, &r)
  
      member x.tryParse_Fraction (r : float byref) : bool =
        if x.tryConsume_Char '.' then
          let spos        = pos
          let mutable uf  = 0.0
          if x.tryParse_UInt (true, &uf) then
            r <- (float uf) * (pow10 (spos - pos))
            true
          else
            false
        else
          true  // Fraction is optional
  
      member x.tryParse_Exponent (r : int byref) : bool =
        let mutable exp = ' '
        if x.tryParse_AnyOf2 ('e', 'E', &exp) then
          let mutable sign = '+'
          // Ignore as sign is optional
          ignore <| x.tryParse_AnyOf2 ('+', '-', &sign)
          // TODO: Parsing exponent as float seems unnecessary
          let mutable ue = 0.0
          if x.tryParse_UInt (true, &ue) then
            let inline sign v = if sign = '-' then -v else v
            r <- sign (int ue)
            true
          else
            false
        else
          true  // Fraction is optional
  
      member x.tryParse_Number () : bool =
        let hasSign       = x.tryConsume_Char '-'
        let inline sign v = if hasSign then -v else v
  
        let mutable i = 0.0
        let mutable f = 0.0
        let mutable e = 0
  
        let result =
          x.tryParse_UInt0        (&i)
          && x.tryParse_Fraction  (&f)
          && x.tryParse_Exponent  (&e)
  
        if result then
          v.NumberValue (sign ((i + f) * (pow10 e)))
        else
          false
  
      member x.tryParse_UnicodeChar (n : int, r : int) : bool =
        if n = 0 then
          ignore <| sb.Append (char r)
          true
        elif x.eos then x.raise_Eos ()
        else
          let sr  = r <<< 4
          let   c = x.ch
          if    c >= '0' && c <= '9'  then x.adv () ; x.tryParse_UnicodeChar (n - 1, sr + (int c - int '0'))
          elif  c >= 'A' && c <= 'F'  then x.adv () ; x.tryParse_UnicodeChar (n - 1, sr + (int c - int 'A' + 10))
          elif  c >= 'a' && c <= 'f'  then x.adv () ; x.tryParse_UnicodeChar (n - 1, sr + (int c - int 'a' + 10))
          else
            v.Expected (pos, Tokens.HexDigit)
            false
  
      member x.tryParse_Chars () : bool =
        let inline app (c : char) = ignore <| sb.Append c
  
        if x.eos then x.raise_Eos ()
        else
          let c = x.ch
          match c with
          | '"'         -> true
          | '\r' | '\n' -> v.Unexpected (pos, Tokens.NewLine); false
          | '\\'        ->
            x.adv ()
            if x.eos then x.raise_Eos ()
            else
              let e = x.ch
              let result =
                match e with
                | '"'
                | '\\'
                | '/' -> app e    ; x.adv (); true
                | 'b' -> app '\b' ; x.adv (); true
                | 'f' -> app '\f' ; x.adv (); true
                | 'n' -> app '\n' ; x.adv (); true
                | 'r' -> app '\r' ; x.adv (); true
                | 't' -> app '\t' ; x.adv (); true
                | 'u' ->
                  x.adv ()
                  x.tryParse_UnicodeChar (4, 0)
                | _ ->
                  v.ExpectedChars (pos, "\"\\/bfnrtu")
                  false
              result && x.tryParse_Chars ()
          | _           ->
            x.adv ()
            app c
            x.tryParse_Chars ()
  
      member x.tryParse_ToStringBuilder () : bool =
        ignore <| sb.Clear ()
        x.tryConsume_Char     '"'
        && x.tryParse_Chars   ()
        && x.tryConsume_Char  '"'
  
      member x.tryParse_String () : bool =
        x.tryParse_ToStringBuilder ()
        && v.StringValue sb
  
      member x.tryParse_MemberKey () : bool =
        x.tryParse_ToStringBuilder ()
        && v.MemberKey sb
  
      member inline x.tryConsume_Delimiter (first : bool) : bool =
        if first then true
        else
          x.tryConsume_Char       ','
          && x.consume_WhiteSpace ()
  
      member x.tryParse_ArrayValues (first : bool) : bool =
        if x.test_Char ']' then
          true
        else
          x.tryConsume_Delimiter    first
          && x.tryParse_Value       ()
          && x.tryParse_ArrayValues false
  
      member x.tryParse_Array () : bool =
        x.tryConsume_Char         '['
        && x.consume_WhiteSpace   ()
        && v.ArrayBegin           ()
        && x.tryParse_ArrayValues true
        && x.tryConsume_Char      ']'
        && v.ArrayEnd             ()
  
      member x.tryParse_ObjectMembers (first : bool) : bool =
        if x.test_Char '}' then
          true
        else
          x.tryConsume_Delimiter      first
          && x.tryParse_MemberKey     ()
          && x.consume_WhiteSpace     ()
          && x.tryConsume_Char        ':'
          && x.consume_WhiteSpace     ()
          && x.tryParse_Value         ()
          && x.tryParse_ObjectMembers false
  
      member x.tryParse_Object () : bool =
        x.tryConsume_Char           '{'
        && x.consume_WhiteSpace     ()
        && v.ObjectBegin            ()
        && x.tryParse_ObjectMembers true
        && x.tryConsume_Char        '}'
        && v.ObjectEnd              ()
  
      member x.tryParse_Value (): bool =
        if x.eos then x.raise_Eos ()
        else
          let result =
            match x.ch with
            | 'n'                 -> x.tryParse_Null    ()
            | 't'                 -> x.tryParse_True    ()
            | 'f'                 -> x.tryParse_False   ()
            | '['                 -> x.tryParse_Array   ()
            | '{'                 -> x.tryParse_Object  ()
            | '"'                 -> x.tryParse_String  ()
            | '-'                 -> x.tryParse_Number  ()
            | c when isDigit c    -> x.tryParse_Number  ()
            | _                   -> x.raise_Value      ()
          result && x.consume_WhiteSpace ()
  
      member x.tryParse_RootValue () : bool =
        if x.eos then x.raise_Eos ()
        else
          let result =
            match x.ch with
            | '['                 -> x.tryParse_Array  ()
            | '{'                 -> x.tryParse_Object ()
            | _                   -> x.raise_RootValue ()
          result && x.consume_WhiteSpace ()
  
      member x.tryParse_Eos () : bool =
        if x.eos then
          true
        else
          v.Expected (pos, Tokens.EOS)
          false
  
    [<AbstractClass>]
    [<NoEquality>]
  