diego.bernardes
How to force NimbleParsec to use labels?
I’m using NimbleParsec to parse a protocol and I would like to know if there is anyway to force a combinator to use labels.
For example, if I have this integer(min: 1) |> label("protocol"), the library will return an random error and not the protocol one in case I don’t send an integer. I would like to known if there is anyway to encapsulate a logic to guarantee that in case it fails, I can get a label to then pattern match later on the exact part it failed.
Thanks!
Marked As Solved
kip
Using your example parser, I see:
iex> defmodule Parser do
...> import NimbleParsec
...>
...> defparsec :number,
...> integer(min: 1)
...> |> label("protocol")
...> end
{:module, Parser, <<70, 79, 82, 49, 0, 0, 19, ...>>,.....
iex> Parser.number "3"
{:ok, [3], "", %{}, {1, 0}, 1
iex> Parser.number "a"
{:error, "expected protocol", "a", %{}, {1, 0}, 0}
Which seems pretty reasonable to me. I do find returning meaningful parsing errors a bit tricky at times - but typically not an issue in this simple kind of case.
What are you expecting, and what are you seeing?
Also Liked
kip
Glad you’re up and running. I typically try to make the grammar as explicit as possible and avoid lookahead unless really necessary. Perhaps thats just my preference. For example:
defmodule Parser do
import NimbleParsec
preamble =
string("*HQ")
|> label("preamble")
device_id =
integer(min: 1)
|> label("device id")
version =
string("V")
|> integer(1)
|> reduce({Enum, :join, []})
|> label("version")
separator =
string(",")
|> label("separator")
defparsec :number,
preamble
|> ignore(separator)
|> concat(device_id)
|> ignore(separator)
|> concat(version)
end
Examples
iex> Parser.number "*HQ,1234567890,V1"
{:ok, ["*HQ", 1234567890, "V1"], "", %{}, {1, 0}, 17}
iex> Parser.number "*HQ,A1234567890,V1"
{:error, "expected device id", "A1234567890,V1", %{}, {1, 0}, 4}
Which still gives an appropriate error message and makes it easy to expand the grammar imo.







