class JSON::Pure::Parser

into a Ruby data structure.
This class implements the JSON parser that is used to parse a JSON string

def convert_encoding(source)

def convert_encoding(source)
  if source.respond_to?(:to_str)
    source = source.to_str
  else
    raise TypeError,
      "#{source.inspect} is not like a string"
  end
  if source.encoding != ::Encoding::ASCII_8BIT
    source = source.encode(::Encoding::UTF_8)
    source.force_encoding(::Encoding::ASCII_8BIT)
  end
  source
end

def initialize(source, opts = {})

string argument in its constructor.
(Float) when parsing decimal numbers. This class must accept a single
* *decimal_class*: Specifies which class to use instead of the default
* *array_class*: Defaults to Array
* *object_class*: Defaults to Hash
option defaults to false.
additions when a matching class and create_id are found. This
* *create_additions*: If set to true, the Parser creates
conjunction with the *create_additions* option.
also the default. It's not possible to use this option in
(keys) in a JSON object. Otherwise strings are returned, which is
* *symbolize_names*: If set to true, returns symbols for the names
string will be deduplicated if possible.
* *freeze*: If set to true, all parsed objects will be frozen. Parsed
to false.
defiance of RFC 7159 to be parsed by the Parser. This option defaults
* *allow_nan*: If set to true, allow NaN, Infinity and -Infinity in
it defaults to 100.
structures. Disable depth checking with :max_nesting => false|nil|0,
* *max_nesting*: The maximum depth of nesting allowed in the parsed data
keys:
It will be configured by the _opts_ hash. _opts_ can have the following

Creates a new JSON::Pure::Parser instance for the string _source_.
def initialize(source, opts = {})
  opts ||= {}
  source = convert_encoding source
  super source
  if !opts.key?(:max_nesting) # defaults to 100
    @max_nesting = 100
  elsif opts[:max_nesting]
    @max_nesting = opts[:max_nesting]
  else
    @max_nesting = 0
  end
  @allow_nan = !!opts[:allow_nan]
  @symbolize_names = !!opts[:symbolize_names]
  @freeze = !!opts[:freeze]
  if opts.key?(:create_additions)
    @create_additions = !!opts[:create_additions]
  else
    @create_additions = false
  end
  @symbolize_names && @create_additions and raise ArgumentError,
    'options :symbolize_names and :create_additions cannot be used '\
    'in conjunction'
  @create_id = @create_additions ? JSON.create_id : nil
  @object_class = opts[:object_class] || Hash
  @array_class  = opts[:array_class] || Array
  @decimal_class = opts[:decimal_class]
  @match_string = opts[:match_string]
end

def parse

complete data structure as a result.
Parses the current JSON string _source_ and returns the
def parse
  reset
  obj = nil
  while !eos? && skip(IGNORE) do end
  if eos?
    raise ParserError, "source is not valid JSON!"
  else
    obj = parse_value
    UNPARSED.equal?(obj) and raise ParserError,
      "source is not valid JSON!"
    obj.freeze if @freeze
  end
  while !eos? && skip(IGNORE) do end
  eos? or raise ParserError, "source is not valid JSON!"
  obj
end

def parse_array

def parse_array
  raise NestingError, "nesting of #@current_nesting is too deep" if
    @max_nesting.nonzero? && @current_nesting > @max_nesting
  result = @array_class.new
  delim = false
  loop do
    case
    when eos?
      raise ParserError, "unexpected end of string while parsing array"
    when !UNPARSED.equal?(value = parse_value)
      delim = false
      result << value
      skip(IGNORE)
      if scan(COLLECTION_DELIMITER)
        delim = true
      elsif match?(ARRAY_CLOSE)
        ;
      else
        raise ParserError, "expected ',' or ']' in array at '#{peek(20)}'!"
      end
    when scan(ARRAY_CLOSE)
      if delim
        raise ParserError, "expected next element in array at '#{peek(20)}'!"
      end
      break
    when skip(IGNORE)
      ;
    else
      raise ParserError, "unexpected token in array at '#{peek(20)}'!"
    end
  end
  result
end

def parse_object

def parse_object
  raise NestingError, "nesting of #@current_nesting is too deep" if
    @max_nesting.nonzero? && @current_nesting > @max_nesting
  result = @object_class.new
  delim = false
  loop do
    case
    when eos?
      raise ParserError, "unexpected end of string while parsing object"
    when !UNPARSED.equal?(string = parse_string)
      skip(IGNORE)
      unless scan(PAIR_DELIMITER)
        raise ParserError, "expected ':' in object at '#{peek(20)}'!"
      end
      skip(IGNORE)
      unless UNPARSED.equal?(value = parse_value)
        result[@symbolize_names ? string.to_sym : string] = value
        delim = false
        skip(IGNORE)
        if scan(COLLECTION_DELIMITER)
          delim = true
        elsif match?(OBJECT_CLOSE)
          ;
        else
          raise ParserError, "expected ',' or '}' in object at '#{peek(20)}'!"
        end
      else
        raise ParserError, "expected value in object at '#{peek(20)}'!"
      end
    when scan(OBJECT_CLOSE)
      if delim
        raise ParserError, "expected next name, value pair in object at '#{peek(20)}'!"
      end
      if @create_additions and klassname = result[@create_id]
        klass = JSON.deep_const_get klassname
        break unless klass and klass.json_creatable?
        result = klass.json_create(result)
      end
      break
    when skip(IGNORE)
      ;
    else
      raise ParserError, "unexpected token in object at '#{peek(20)}'!"
    end
  end
  result
end

def parse_string

def parse_string
  if scan(STRING)
    return '' if self[1].empty?
    string = self[1].gsub(%r((?:\\[\\bfnrt"/]|(?:\\u(?:[A-Fa-f\d]{4}))+|\\[\x20-\xff]))n) do |c|
      if u = UNESCAPE_MAP[$&[1]]
        u
      else # \uXXXX
        bytes = EMPTY_8BIT_STRING.dup
        i = 0
        while c[6 * i] == ?\\ && c[6 * i + 1] == ?u
          bytes << c[6 * i + 2, 2].to_i(16) << c[6 * i + 4, 2].to_i(16)
          i += 1
        end
        JSON.iconv('utf-8', 'utf-16be', bytes).force_encoding(::Encoding::ASCII_8BIT)
      end
    end
    if string.respond_to?(:force_encoding)
      string.force_encoding(::Encoding::UTF_8)
    end
    if @freeze
      if STR_UMINUS
        string = -string
      else
        string.freeze
      end
    end
    if @create_additions and @match_string
      for (regexp, klass) in @match_string
        klass.json_creatable? or next
        string =~ regexp and return klass.json_create(string)
      end
    end
    string
  else
    UNPARSED
  end
rescue => e
  raise ParserError, "Caught #{e.class} at '#{peek(20)}': #{e}"
end

def parse_value

def parse_value
  case
  when scan(FLOAT)
    if @decimal_class then
      if @decimal_class == BigDecimal then
        BigDecimal(self[1])
      else
        @decimal_class.new(self[1]) || Float(self[1])
      end
    else
      Float(self[1])
    end
  when scan(INTEGER)
    Integer(self[1])
  when scan(TRUE)
    true
  when scan(FALSE)
    false
  when scan(NULL)
    nil
  when !UNPARSED.equal?(string = parse_string)
    string
  when scan(ARRAY_OPEN)
    @current_nesting += 1
    ary = parse_array
    @current_nesting -= 1
    ary
  when scan(OBJECT_OPEN)
    @current_nesting += 1
    obj = parse_object
    @current_nesting -= 1
    obj
  when @allow_nan && scan(NAN)
    NaN
  when @allow_nan && scan(INFINITY)
    Infinity
  when @allow_nan && scan(MINUS_INFINITY)
    MinusInfinity
  else
    UNPARSED
  end
end

def reset

def reset
  super
  @current_nesting = 0
end