Skip to content

Commit

Permalink
parse_integers_using_lower_nibble
Browse files Browse the repository at this point in the history
  • Loading branch information
dkuku committed Jan 6, 2025
1 parent 0faac64 commit f272dba
Show file tree
Hide file tree
Showing 2 changed files with 37 additions and 6 deletions.
19 changes: 13 additions & 6 deletions lib/nimble_parsec.ex
Original file line number Diff line number Diff line change
Expand Up @@ -691,6 +691,13 @@ defmodule NimbleParsec do
bin_segment(combinator, inclusive, exclusive, :integer)
end

@spec integer_nibble() :: t
@spec integer_nibble(t) :: t
def integer_nibble(combinator \\ empty())
when is_combinator(combinator) do
[{:integer_nibble} | combinator]
end

@doc ~S"""
Defines a single UTF-8 codepoint in the given ranges.
Expand Down Expand Up @@ -812,7 +819,7 @@ defmodule NimbleParsec do

min_max_compile_runtime_chars(
combinator,
ascii_char([?0..?9]),
integer_nibble(),
count,
:__compile_integer__,
:__runtime_integer__,
Expand All @@ -828,7 +835,7 @@ defmodule NimbleParsec do

min_max_compile_runtime_chars(
combinator,
ascii_char([?0..?9]),
integer_nibble(),
opts,
:__compile_integer__,
:__runtime_integer__,
Expand Down Expand Up @@ -2083,7 +2090,7 @@ defmodule NimbleParsec do
ast =
quote do
[head | tail] = unquote(reverse_now_or_later(acc))
[:lists.foldl(fn x, acc -> x - ?0 + acc * 10 end, head, tail)]
[:lists.foldl(fn x, acc -> x + acc * 10 end, head, tail)]
end

{:{}, [], [rest, ast, context]}
Expand All @@ -2093,7 +2100,7 @@ defmodule NimbleParsec do
ast =
quote do
[head | tail] = unquote(reverse_now_or_later(acc))
[:lists.foldl(fn x, acc -> x - ?0 + acc * 10 end, head - ?0, tail)]
[:lists.foldl(fn x, acc -> x + acc * 10 end, head, tail)]
end

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

defp quoted_ascii_to_integer([var | vars], 1) do
[quote(do: unquote(var) - ?0) | quoted_ascii_to_integer(vars, 10)]
[quote(do: unquote(var)) | quoted_ascii_to_integer(vars, 10)]
end

defp quoted_ascii_to_integer([var | vars], index) do
[quote(do: (unquote(var) - ?0) * unquote(index)) | quoted_ascii_to_integer(vars, index * 10)]
[quote(do: unquote(var) * unquote(index)) | quoted_ascii_to_integer(vars, index * 10)]
end

defp quoted_ascii_to_integer([], _index) do
Expand Down
24 changes: 24 additions & 0 deletions lib/nimble_parsec/compiler.ex
Original file line number Diff line number Diff line change
Expand Up @@ -856,6 +856,26 @@ defmodule NimbleParsec.Compiler do
{:ok, [string], [], [string], %{metadata | line: line, offset: offset}}
end

defp bound_combinator({:integer_nibble}, metadata) do
%{offset: offset, counter: counter} = metadata
{inputs, vars, guards} = build_integer_nibble(counter)
counter = counter + 1
offset = add_offset(offset, length(vars))

metadata = %{metadata | offset: offset, counter: counter}
{:ok, inputs, guards, vars, metadata}
end

@nibble_size 4
@integer_hi_nibble 3
defp build_integer_nibble(counter) do
lo_nibble = {:"x#{counter}", [], Elixir}
guard = quote(do: unquote(lo_nibble) < unquote(10))

{[{:"::", [], [@integer_hi_nibble, @nibble_size]}, {:"::", [], [lo_nibble, @nibble_size]}],
[lo_nibble], [guard]}
end

defp bound_combinator({:bin_segment, inclusive, exclusive, modifier}, metadata) do
%{line: line, offset: offset, counter: counter} = metadata

Expand Down Expand Up @@ -986,6 +1006,10 @@ defmodule NimbleParsec.Compiler do
"string #{inspect(binary)}"
end

defp label({:integer_nibble}) do
"ASCII character in the range \"0\" to \"9\""
end

defp label({:label, _combinator, label}) do
label
end
Expand Down

0 comments on commit f272dba

Please sign in to comment.