     {result, data, pos}
   end
 
-  defp parse_float(<<char>> <> _data, pos, [@full_stop|_])
+  defp float(<<char>> <> _data, pos, [@full_stop|_])
     when char in @exps,
     do: throw {:float, pos}
-  defp parse_float(<<char>> <> data, pos, chars)
-    when char in @exps,
-    do: parse_exponential(data, pos + 1, [@exp|chars])
-  defp parse_float(<<char>> <> data, pos, chars)
+  defp float(<<char>> <> data, pos, chars)
+    when char in @exps,
+    do: exponential(data, pos + 1, [@exp|chars])
+  defp float(<<char>> <> data, pos, chars)
     when char in @digits,
-    do: parse_float(data, pos + 1, [char|chars])
-  defp parse_float(data, pos, chars) do
+    do: float(data, pos + 1, [char|chars])
+  defp float(data, pos, chars) do
     result = chars
              |> Enum.reverse
              |> IO.iodata_to_binary

    {token, pos} -> {:error, token, pos}
  end

  defp parse_json(<<char>> <> data, pos) do
    pos = pos + 1
    cond do
      char in @whitespace -> parse_json(data, pos)
      char == @quotation_mark -> parse_string(data, pos, [])
      char == @left_square_bracket -> parse_list(data, pos, [])
      char == @left_curly_bracket-> parse_map(data, pos, [])
      char == @minus_sign or char in @digits -> parse_number(data, pos, [char])
      char == ?t -> parse_true(data, pos)
      char == ?f -> parse_false(data, pos)
      char == ?n -> parse_null(data, pos)
      true -> throw {:json, pos}
    end
  end

  defp parse_true(<<"rue">> <> data, pos), do: {true, data, pos + 3}
  defp parse_true(_data, pos), do: throw {:true, pos}

  defp parse_false(<<"alse">> <> data, pos), do: {false, data, pos + 4}
  defp parse_false(_data, pos), do: throw {:false, pos}

  defp parse_null(<<"ull">> <> data, pos), do: {nil, data, pos + 3}
  defp parse_null(_data, pos), do: throw {:null, pos}

  defp parse_key(<<char>> <> data, pos) do
    pos = pos + 1
    cond do
      char in @whitespace -> parse_key(data, pos)
      char == @quotation_mark -> parse_string(data, pos, [])
      true -> throw {:key, pos}
    end
  end

  defp parse_number(<<char>> <> data, pos, chars)
    when char in @digits,
    do: parse_number(data, pos + 1, [char|chars])
  defp parse_number(<<@full_stop>> <> _data, pos, [@minus_sign]),
    do: throw {:number, pos}
  defp parse_number(<<@full_stop>> <> data, pos, chars),
    do: parse_float(data, pos + 1, [@full_stop|chars])
  defp parse_number(<<char>> <> _data, pos, [@minus_sign])
    when char in @exps,
    do: throw {:number, pos}
  defp parse_number(<<char>> <> data, pos, chars)
    when char in @exps,
    do: parse_exponential(data, pos + 1, [@exp|['.0'|chars]])
  defp parse_number(_data, pos, [@minus_sign]),
    do: throw {:number, pos}
  defp parse_number(data, pos, chars) do
    result = chars
             |> Enum.reverse
             |> IO.iodata_to_binary

    {result, data, pos}
  end

  defp exponential(<<@minus_sign>> <> data, pos, [@exp|_] = chars),
    do: exponential(data, pos + 1, [@minus_sign|chars])
  defp exponential(<<char>> <> data, pos, chars)
    when char in @digits,
    do: exponential(data, pos + 1, [char|chars])
  defp exponential(_data, pos, [@exp|_]),
    do: throw {:exponential, pos}
  defp exponential(_data, pos, [@minus_sign|_]),
    do: throw {:exponential, pos}
  defp exponential(data, pos, chars) do
    result = chars
        |> Enum.reverse
        |> IO.iodata_to_binary
