MatchError from choice with integer and string.
thebearmayor opened this issue · comments
Bradley Peterson commented
choice
with integer
and string
choices throws a MatchError
when integer
is first and the input is a string. When the string
is first, it does not error, nor does it error when matching an integer.
This is my first time using the library, so apologies if I've misunderstood how to use it.
Parser
defparsec(:int_or_test, choice([integer(max: 2), string("test")]), debug: true)
Use
iex(1)> Parsertest.int_or_test("test")
** (MatchError) no match of right hand side value: []
(parsertest 0.1.0) Parsertest.int_or_test__10/6
(parsertest 0.1.0) Parsertest.int_or_test/2
iex:1: (file)
iex(1)> Parsertest.int_or_test("99")
{:ok, 'c', "", %{}, {1, 0}, 2}
Debug
defp int_or_test__0(rest, acc, stack, context, line, offset) do
int_or_test__5(rest, [], [{rest, context, line, offset}, acc | stack], context, line, offset)
end
defp int_or_test__2(<<"test", rest::binary>>, acc, stack, context, comb__line, comb__offset) do
int_or_test__3(rest, ["test"] ++ acc, stack, context, comb__line, comb__offset + 4)
end
defp int_or_test__2(rest, _acc, _stack, context, line, offset) do
{:error, "expected ASCII character in the range '0' to '9' or string \"test\"", rest, context,
line, offset}
end
defp int_or_test__3(rest, acc, [_, previous_acc | stack], context, line, offset) do
int_or_test__1(rest, acc ++ previous_acc, stack, context, line, offset)
end
defp int_or_test__4(_, _, [{rest, context, line, offset} | _] = stack, _, _, _) do
int_or_test__2(rest, [], stack, context, line, offset)
end
defp int_or_test__5(rest, acc, stack, context, line, offset) do
int_or_test__6(rest, [], [acc | stack], context, line, offset)
end
defp int_or_test__6(rest, acc, stack, context, line, offset) do
int_or_test__8(rest, acc, [2 | stack], context, line, offset)
end
defp int_or_test__8(<<x0, rest::binary>>, acc, stack, context, comb__line, comb__offset) when x0 >= 48 and x0 <= 57 do
int_or_test__9(rest, [x0] ++ acc, stack, context, comb__line, comb__offset + 1)
end
defp int_or_test__8(rest, acc, stack, context, line, offset) do
int_or_test__7(rest, acc, stack, context, line, offset)
end
defp int_or_test__7(rest, acc, [_ | stack], context, line, offset) do
int_or_test__10(rest, acc, stack, context, line, offset)
end
defp int_or_test__9(rest, acc, [1 | stack], context, line, offset) do
int_or_test__10(rest, acc, stack, context, line, offset)
end
defp int_or_test__9(rest, acc, [count | stack], context, line, offset) do
int_or_test__8(rest, acc, [count - 1 | stack], context, line, offset)
end
defp int_or_test__10(rest, user_acc, [acc | stack], context, line, offset) do
_ = user_acc
int_or_test__11(
rest,
(
[head | tail] = :lists.reverse(user_acc)
[:lists.foldl(fn x, acc -> x - 48 + acc * 10 end, head - 48, tail)]
) ++ acc,
stack,
context,
line,
offset
)
end
defp int_or_test__11(rest, acc, [_, previous_acc | stack], context, line, offset) do
int_or_test__1(rest, acc ++ previous_acc, stack, context, line, offset)
end
defp int_or_test__1(rest, acc, _stack, context, line, offset) do
{:ok, acc, rest, context, line, offset}
end
José Valim commented
Yup, definitely looks like a bug. Thanks for breaking it down and the report!