Skip to content

Commit f272dba

Browse files
committed
parse_integers_using_lower_nibble
1 parent 0faac64 commit f272dba

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
@@ -691,6 +691,13 @@ defmodule NimbleParsec do
691691
bin_segment(combinator, inclusive, exclusive, :integer)
692692
end
693693

694+
@spec integer_nibble() :: t
695+
@spec integer_nibble(t) :: t
696+
def integer_nibble(combinator \\ empty())
697+
when is_combinator(combinator) do
698+
[{:integer_nibble} | combinator]
699+
end
700+
694701
@doc ~S"""
695702
Defines a single UTF-8 codepoint in the given ranges.
696703
@@ -812,7 +819,7 @@ defmodule NimbleParsec do
812819

813820
min_max_compile_runtime_chars(
814821
combinator,
815-
ascii_char([?0..?9]),
822+
integer_nibble(),
816823
count,
817824
:__compile_integer__,
818825
:__runtime_integer__,
@@ -828,7 +835,7 @@ defmodule NimbleParsec do
828835

829836
min_max_compile_runtime_chars(
830837
combinator,
831-
ascii_char([?0..?9]),
838+
integer_nibble(),
832839
opts,
833840
:__compile_integer__,
834841
:__runtime_integer__,
@@ -2083,7 +2090,7 @@ defmodule NimbleParsec do
20832090
ast =
20842091
quote do
20852092
[head | tail] = unquote(reverse_now_or_later(acc))
2086-
[:lists.foldl(fn x, acc -> x - ?0 + acc * 10 end, head, tail)]
2093+
[:lists.foldl(fn x, acc -> x + acc * 10 end, head, tail)]
20872094
end
20882095

20892096
{:{}, [], [rest, ast, context]}
@@ -2093,7 +2100,7 @@ defmodule NimbleParsec do
20932100
ast =
20942101
quote do
20952102
[head | tail] = unquote(reverse_now_or_later(acc))
2096-
[:lists.foldl(fn x, acc -> x - ?0 + acc * 10 end, head - ?0, tail)]
2103+
[:lists.foldl(fn x, acc -> x + acc * 10 end, head, tail)]
20972104
end
20982105

20992106
{:{}, [], [rest, ast, context]}
@@ -2113,11 +2120,11 @@ defmodule NimbleParsec do
21132120
defp reverse_now_or_later(expr), do: quote(do: :lists.reverse(unquote(expr)))
21142121

21152122
defp quoted_ascii_to_integer([var | vars], 1) do
2116-
[quote(do: unquote(var) - ?0) | quoted_ascii_to_integer(vars, 10)]
2123+
[quote(do: unquote(var)) | quoted_ascii_to_integer(vars, 10)]
21172124
end
21182125

21192126
defp quoted_ascii_to_integer([var | vars], index) do
2120-
[quote(do: (unquote(var) - ?0) * unquote(index)) | quoted_ascii_to_integer(vars, index * 10)]
2127+
[quote(do: unquote(var) * unquote(index)) | quoted_ascii_to_integer(vars, index * 10)]
21212128
end
21222129

21232130
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
@@ -856,6 +856,26 @@ defmodule NimbleParsec.Compiler do
856856
{:ok, [string], [], [string], %{metadata | line: line, offset: offset}}
857857
end
858858

859+
defp bound_combinator({:integer_nibble}, metadata) do
860+
%{offset: offset, counter: counter} = metadata
861+
{inputs, vars, guards} = build_integer_nibble(counter)
862+
counter = counter + 1
863+
offset = add_offset(offset, length(vars))
864+
865+
metadata = %{metadata | offset: offset, counter: counter}
866+
{:ok, inputs, guards, vars, metadata}
867+
end
868+
869+
@nibble_size 4
870+
@integer_hi_nibble 3
871+
defp build_integer_nibble(counter) do
872+
lo_nibble = {:"x#{counter}", [], Elixir}
873+
guard = quote(do: unquote(lo_nibble) < unquote(10))
874+
875+
{[{:"::", [], [@integer_hi_nibble, @nibble_size]}, {:"::", [], [lo_nibble, @nibble_size]}],
876+
[lo_nibble], [guard]}
877+
end
878+
859879
defp bound_combinator({:bin_segment, inclusive, exclusive, modifier}, metadata) do
860880
%{line: line, offset: offset, counter: counter} = metadata
861881

@@ -986,6 +1006,10 @@ defmodule NimbleParsec.Compiler do
9861006
"string #{inspect(binary)}"
9871007
end
9881008

1009+
defp label({:integer_nibble}) do
1010+
"ASCII character in the range \"0\" to \"9\""
1011+
end
1012+
9891013
defp label({:label, _combinator, label}) do
9901014
label
9911015
end

0 commit comments

Comments
 (0)