Skip to content

Commit f307308

Browse files
committed
parse_integers_using_lower_nibble
1 parent ae840c8 commit f307308

File tree

2 files changed

+37
-6
lines changed

2 files changed

+37
-6
lines changed

lib/nimble_parsec.ex

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -681,6 +681,13 @@ defmodule NimbleParsec do
681681
bin_segment(combinator, inclusive, exclusive, :integer)
682682
end
683683

684+
@spec integer_nibble() :: t
685+
@spec integer_nibble(t) :: t
686+
def integer_nibble(combinator \\ empty())
687+
when is_combinator(combinator) do
688+
[{:integer_nibble} | combinator]
689+
end
690+
684691
@doc ~S"""
685692
Defines a single UTF-8 codepoint in the given ranges.
686693
@@ -802,7 +809,7 @@ defmodule NimbleParsec do
802809

803810
min_max_compile_runtime_chars(
804811
combinator,
805-
ascii_char([?0..?9]),
812+
integer_nibble(),
806813
count,
807814
:__compile_integer__,
808815
:__runtime_integer__,
@@ -818,7 +825,7 @@ defmodule NimbleParsec do
818825

819826
min_max_compile_runtime_chars(
820827
combinator,
821-
ascii_char([?0..?9]),
828+
integer_nibble(),
822829
opts,
823830
:__compile_integer__,
824831
:__runtime_integer__,
@@ -2035,7 +2042,7 @@ defmodule NimbleParsec do
20352042
ast =
20362043
quote do
20372044
[head | tail] = unquote(reverse_now_or_later(acc))
2038-
[:lists.foldl(fn x, acc -> x - ?0 + acc * 10 end, head, tail)]
2045+
[:lists.foldl(fn x, acc -> x + acc * 10 end, head, tail)]
20392046
end
20402047

20412048
{:{}, [], [rest, ast, context]}
@@ -2045,7 +2052,7 @@ defmodule NimbleParsec do
20452052
ast =
20462053
quote do
20472054
[head | tail] = unquote(reverse_now_or_later(acc))
2048-
[:lists.foldl(fn x, acc -> x - ?0 + acc * 10 end, head - ?0, tail)]
2055+
[:lists.foldl(fn x, acc -> x + acc * 10 end, head, tail)]
20492056
end
20502057

20512058
{:{}, [], [rest, ast, context]}
@@ -2065,11 +2072,11 @@ defmodule NimbleParsec do
20652072
defp reverse_now_or_later(expr), do: quote(do: :lists.reverse(unquote(expr)))
20662073

20672074
defp quoted_ascii_to_integer([var | vars], 1) do
2068-
[quote(do: unquote(var) - ?0) | quoted_ascii_to_integer(vars, 10)]
2075+
[quote(do: unquote(var)) | quoted_ascii_to_integer(vars, 10)]
20692076
end
20702077

20712078
defp quoted_ascii_to_integer([var | vars], index) do
2072-
[quote(do: (unquote(var) - ?0) * unquote(index)) | quoted_ascii_to_integer(vars, index * 10)]
2079+
[quote(do: unquote(var) * unquote(index)) | quoted_ascii_to_integer(vars, index * 10)]
20732080
end
20742081

20752082
defp quoted_ascii_to_integer([], _index) do

lib/nimble_parsec/compiler.ex

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -846,6 +846,26 @@ defmodule NimbleParsec.Compiler do
846846
{:ok, [string], [], [string], %{metadata | line: line, offset: offset}}
847847
end
848848

849+
defp bound_combinator({:integer_nibble}, metadata) do
850+
%{offset: offset, counter: counter} = metadata
851+
{inputs, vars, guards} = build_integer_nibble(counter)
852+
counter = counter + 1
853+
offset = add_offset(offset, length(vars))
854+
855+
metadata = %{metadata | offset: offset, counter: counter}
856+
{:ok, inputs, guards, vars, metadata}
857+
end
858+
859+
@nibble_size 4
860+
@integer_hi_nibble 3
861+
defp build_integer_nibble(counter) do
862+
lo_nibble = {:"x#{counter}", [], Elixir}
863+
guard = quote(do: unquote(lo_nibble) < unquote(10))
864+
865+
{[{:"::", [], [@integer_hi_nibble, @nibble_size]}, {:"::", [], [lo_nibble, @nibble_size]}],
866+
[lo_nibble], [guard]}
867+
end
868+
849869
defp bound_combinator({:bin_segment, inclusive, exclusive, modifier}, metadata) do
850870
%{line: line, offset: offset, counter: counter} = metadata
851871

@@ -967,6 +987,10 @@ defmodule NimbleParsec.Compiler do
967987
"string #{inspect(binary)}"
968988
end
969989

990+
defp label({:integer_nibble}) do
991+
"ASCII character in the range \"0\" to \"9\""
992+
end
993+
970994
defp label({:label, _combinator, label}) do
971995
label
972996
end

0 commit comments

Comments
 (0)