Yes, you can have recursive combinators. But they need to be defined as defparsec in order to create their own context. They will need to be defined in their own module since they become functions. Something like (not complete):
defmodule Combinators do
import NimbleParsec
defparsec :asmexpr,
keyword_asm
|> optional(keyword_volatile)
|> concat(lparen)
|> parsec(:expr)
|> optional(asmoutput)
|> concat(rparen)
defparsec :primaryexpr,
choice([
parsec(:asmexpr),
ifexpr,
keyword_break |> optional(breaklabel) |> optional(parsec(:expr)),
keyword_comptime |> parsec(:expr),
keyword_nosuspend |> parsec(:expr),
keyword_continue |> optional(breaklabel),
keyword_resume |> parsec(Lexpr),
keyword_return |> optional(parsec(:expr)),
optional(blocklabel) |> concat(loopexpr),
block,
curlysuffixexpr
])
# Other combinators
end


















