I am trying to write a macro preprocessor using NimleParsec.
The idea is that it should parse a file replacing directives with a structure that can be used to post-process them. A directive looks like @<name>(…)
for example @import(../libs/foo.bar)
.
I’m including what I have so far. The directive parsing works but, once the text
cominator gets rolling there’s no stopping it. At this point I have tried using lookahead_not
in every place and with every combinator I can think of and no dice.
I’ve read & re-read the docs around lookahead
and something clearly is landing. Can anyone help me understand what I am missing?
Thanks.
Matt
defmodule MacroParser do
import NimbleParsec
dir_char = ascii_char([?@])
open_paren = ascii_char([?(])
close_paren = ascii_char([?)])
directive_name = ascii_string([?a..?z], min: 2)
# directive = @<name>(…<optional args>…)
# e.g. @import("../libs/foo.bar")
directive =
ignore(dir_char)
|> concat(directive_name)
|> ignore(open_paren)
|> optional(ascii_string([not: ?)], min: 1))
|> ignore(close_paren)
|> tag(:directive)
text = ascii_string([], min: 1) |> lookahead_not(dir_char |> concat(directive_name))
input =
repeat(
choice([
directive,
text
])
)
defparsec(:parse_macros, input, debug: false)
end
iex(159)> MacroParser.parse_macros("@import(../libs/foo.baz)___@import(../libs/bar.qux)")
{:ok,
[{:directive, ["import", "../libs/foo.baz"]}, "___@import(../libs/bar.qux)"],
"", %{}, {1, 0}, 51}