     {result, data, pos}
   end
 
-  defp parse_string(<<@quotation_mark>> <> data, pos, chars) do
+  defp string(<<@quotation_mark>> <> data, pos, chars) do
     result = chars
              |> Enum.reverse
              |> IO.iodata_to_binary
     {result, data, pos}
   end
-  defp parse_string(<<@escape, @solidus>> <> data, pos, chars),
-    do: parse_string(data, pos + 2, [@solidus|chars])
-  defp parse_string(<<@escape, char>> <> data, pos, chars)
+  defp string(<<@escape, @solidus>> <> data, pos, chars),
+    do: string(data, pos + 2, [@solidus|chars])
+  defp string(<<@escape, char>> <> data, pos, chars)
     when char in @escape_chars,
-    do: parse_string(data, pos + 2, [Map.get(@escapes, char)|chars])
-  defp parse_string(
+    do: string(data, pos + 2, [Map.get(@escapes, char)|chars])
+  defp string(
              <<@escape, @unicode, a1, b1, c1, d1, @escape, @unicode, a2, b2, c2, d2>> <> data,
              pos, chars)
     when a1 in @surrogate_a and a2 in @surrogate_a and b1 in @surrogate_b1 and b2 in @surrogate_b2 do
     hi = List.to_integer([a1, b1, c1, d1], 16)
     lo = List.to_integer([a2, b2, c2, d2], 16)
     codepoint = 0x10000 + ((hi &&& 0x03FF) <<< 10) + (lo &&& 0x03FF)
-    parse_string(data, pos + 11, [<<codepoint :: utf8>>|chars])
-  end
-  defp parse_string(<<@escape, @unicode, seq :: binary-size(4)>> <> data, pos, chars),
-    do: parse_string(data, pos + 6, [<<String.to_integer(seq, 16) :: utf8>>|chars])
-  defp parse_string(<<@escape>> <> _data, pos, _chars),
+    string(data, pos + 11, [<<codepoint :: utf8>>|chars])
+  end
+  defp string(<<@escape, @unicode, seq :: binary-size(4)>> <> data, pos, chars),
+    do: string(data, pos + 6, [<<String.to_integer(seq, 16) :: utf8>>|chars])
+  defp string(<<@escape>> <> _data, pos, _chars),
     do: throw {:string, pos}
-  defp parse_string(<<char>> <> data, pos, chars),
-    do: parse_string(data, pos + 1, [char|chars])
-
-  defp parse_list(<<char>> <> data, pos, list)
+  defp string(<<char>> <> data, pos, chars),
+    do: string(data, pos + 1, [char|chars])
+
+  defp list(<<char>> <> data, pos, list)
     when char in @whitespace,
-    do: parse_list(data, pos + 1, list)
-  defp parse_list(<<@right_square_bracket>> <> data, pos, list),
+    do: list(data, pos + 1, list)
+  defp list(<<@right_square_bracket>> <> data, pos, list),
     do: {Enum.reverse(list), data, pos + 1}
-  defp parse_list(<<@comma>> <> _data, pos, []),
+  defp list(<<@comma>> <> _data, pos, []),
     do: throw {:list, pos}
-  defp parse_list(<<@comma>> <> data, pos, list) do
-    {result, data, pos} = parse_json(data, pos + 1)
-    parse_list(data, pos, [result|list])
-  end
-  defp parse_list(data, pos, []) do
-    {result, data, pos} = parse_json(data, pos)
-    parse_list(data, pos, [result])
-  end
-  defp parse_list(_data, pos, _list),
+  defp list(<<@comma>> <> data, pos, list) do
+    {result, data, pos} = json(data, pos + 1)
+    list(data, pos, [result|list])
+  end
+  defp list(data, pos, []) do
+    {result, data, pos} = json(data, pos)
+    list(data, pos, [result])
+  end
+  defp list(_data, pos, _list),
     do: throw{:list, pos}
 
-  defp parse_map(<<char>> <> data, pos, list)
+  defp map(<<char>> <> data, pos, list)
     when char in @whitespace,
-    do: parse_map(data,  pos + 1, list)
-  defp parse_map(<<@right_curly_bracket>> <> data, pos, list) do
+    do: map(data,  pos + 1, list)
+  defp map(<<@right_curly_bracket>> <> data, pos, list) do
     result = for [value, key] <- Enum.chunk(list, 2), into: %{}, do: {key, value}
     {result, data, pos + 1}
   end
-  defp parse_map(<<@comma>> <> _data, pos, []),
+  defp map(<<@comma>> <> _data, pos, []),
     do: throw {:map, pos + 1}
-  defp parse_map(<<@comma>> <> data, pos, list) do
-    {result, data, pos} = parse_key(data, pos + 1)
-    parse_map(data, pos + 1, [result|list])
-  end
-  defp parse_map(<<@colon>> <> _data, pos, []),
+  defp map(<<@comma>> <> data, pos, list) do
+    {result, data, pos} = key(data, pos + 1)
+    map(data, pos + 1, [result|list])
+  end
+  defp map(<<@colon>> <> _data, pos, []),
     do: throw {:map, pos + 1}
-  defp parse_map(<<@colon>> <> data, pos, list) do
-    {result, data, pos} = parse_json(data, pos + 1)
-    parse_map(data, pos + 1, [result|list])
-  end
-  defp parse_map(data, pos, []) do
-    {result, data, pos} = parse_key(data, pos)
-    parse_map(data, pos, [result])
-  end
-  defp parse_map(_data, pos, _list),
+  defp map(<<@colon>> <> data, pos, list) do
+    {result, data, pos} = json(data, pos + 1)
+    map(data, pos + 1, [result|list])
+  end
+  defp map(data, pos, []) do
+    {result, data, pos} = key(data, pos)
+    map(data, pos, [result])
+  end
+  defp map(_data, pos, _list),
     do: throw {:map, pos + 1}
 
 end

    {result, data, pos}
  end

  defp parse_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)
    when char in @digits,
    do: parse_float(data, pos + 1, [char|chars])
  defp parse_float(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
