   @minus_sign ?-
   @full_stop ?.
   @exps 'eE'
-  @exp ?e
   @quotation_mark ?"
   @escape ?\\
   @escapes %{

  defp key(<<char>> <> data, pos)
    when char == @quotation_mark,
    do: string(data, pos + 1, [])
  defp key(_data, pos), do: throw {:key, pos}

  defp number(<<char>> <> data, pos, chars)
    when char in @digits,
    do: number(data, pos + 1, [chars,char])
  defp number(<<@full_stop>> <> _data, pos, [@minus_sign]),
    do: throw {:number, pos + 1}
  defp number(<<@full_stop>> <> data, pos, chars),
    do: float(data, pos + 1, [chars, @full_stop])
  defp number(<<char>> <> _data, pos, [@minus_sign])
    when char in @exps,
    do: throw {:number, pos}
  defp number(<<char>> <> data, pos, chars)
    when char in @exps,
    do: exponential(data, pos + 1, [chars, '.0e'], :exp)
  defp number(_data, pos, [@minus_sign]),
    do: throw {:number, pos}
  defp number(data, pos, chars) do
    result = chars
             |> IO.iodata_to_binary
             |> String.to_integer

    do: map(data, pos + 1, [])
  defp json(<<char>> <> data, pos)
    when char in '-0123456789',
    do: number(data, pos + 1, [char], (if char == ?-, do: :minus, else: :digit))
  defp json(<<"true">> <> data, pos),
    do: {true, data, pos + 4}
  defp json(<<"false">> <> data, pos),
