Skip to content

Instantly share code, notes, and snippets.

@Faheetah
Last active June 16, 2021 20:08
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Faheetah/24d6e12df1653bfdca0bb4064c0311e3 to your computer and use it in GitHub Desktop.
Save Faheetah/24d6e12df1653bfdca0bb4064c0311e3 to your computer and use it in GitHub Desktop.
Parsing a complex key = value structure with optional trailing comments
defmodule Test.Parser do
import NimbleParsec
# iex(9)> Test.Parser.parse """
# ...(9)> FOO = 1 (some foo)
# ...(9)> BAR = 2 (some
# ...(9)> bar)
# ...(9)> FAZ = 3 (some faz)
# ...(9)> """
# {:ok, ["FOO", 1, "somefoo", "BAR", 2, "somebar", "FAZ", 3, "somefaz"], "\n",
# %{}, {4, 55}, 75}
@space 0x0020
@tab 0x009
comment =
lookahead_not(string(")"))
|> optional(ignore(string(" ")))
|> choice([
ignore(string("(")),
ignore(string("\n")),
ignore(utf8_string([@space, @tab], min: 2)),
utf8_string([], 1)
])
|> repeat()
|> ignore(string(")"))
|> wrap()
|> reduce({Enum, :join, [""]})
start_comment =
lookahead_not(string("("))
|> concat(comment)
no_comment =
lookahead(string("\n"))
|> string("")
defparsec(
:parse,
eventually(utf8_string([?A..?Z, ?_], min: 1))
|> eventually(integer(min: 1))
|> choice([no_comment, start_comment])
|> repeat()
)
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment