jackalcooper
Is it possible to define recursive/inter-dependent parse combinators in NimbleParsec?
I’m trying to parse Zig source with NimbleParsec and come across some cases like these:
- in the definition of
containerdeclarations, it uses itself
containerdeclarations = choice(
testdecl |> concat(containerdeclarations),
toplevelcomptime |> concat(containerdeclarations),
optional(doc_comment) |> optional(keyword_pub) |> concat(topleveldecl) |> concat(containerdeclarations)
)
-
exprusesasmexprindirectly whileasmexprusesexpr
asmexpr =
keyword_asm
|> optional(keyword_volatile)
|> concat(lparen)
|> concat(expr)
|> optional(asmoutput)
|> concat(rparen)
primaryexpr =
choice([
asmexpr,
ifexpr,
keyword_break |> optional(breaklabel) |> optional(expr),
keyword_comptime |> concat(expr),
keyword_nosuspend |> concat(expr),
keyword_continue |> optional(breaklabel),
keyword_resume |> concat(expr),
keyword_return |> optional(expr),
optional(blocklabel) |> concat(loopexpr),
block,
curlysuffixexpr
])
prefixexpr = repeat(prefixop) |> concat(primaryexpr)
multiplyexpr = prefixexpr |> optional(multiplyop |> concat(prefixexpr))
additionexpr = multiplyexpr |> optional(additionop |> concat(multiplyexpr))
bitshiftexpr = additionexpr |> optional(bitshiftop |> concat(additionexpr))
bitwiseexpr = bitshiftexpr |> optional(bitwiseop |> concat(bitshiftexpr))
compareexpr = bitwiseexpr |> optional(compareop |> concat(bitwiseexpr))
boolandexpr = compareexpr |> optional(keyword_and |> concat(compareexpr))
boolorexpr = boolandexpr |> optional(keyword_or |> concat(boolandexpr))
expr = boolorexpr
Marked As Solved
kip
ex_cldr Core Team
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
5
Also Liked
jackalcooper
update:
- after changing all combinators from variable to
defcombinatorp, it compiles fast - the parsing doesn’t terminate now, there should be some other bugs
- new version: Zig parser in elixir based on https://github.com/ziglang/zig-spec/blob/master/grammar/grammar.y · GitHub
1
100phlecs
This may be of interest to you, though I’m not certain on its status: GitHub - ityonemo/zig_parser: Zig Parser for Elixir
It is created with GitHub - ityonemo/pegasus: peg -> nimbleparsec
An unrelated thought, but curious of the advantages and disadvantages of the PEG route vs a traditional lexer + parser
1
ityonemo
It works (well enough for my zigler 0.10.x development branch) and is currently designed to parse zig 0.10.x
1
Popular in Questions
can someone please explain to me how Enum.reduce works with maps
New
In asking this question I am more interested about the expressiveness of the language itself and less concerned about the availability of...
New
Hello all!
I am typing this post from my new MacBook Pro with the M1 chip. I’m loving it so far, and will probably use it as my daily dr...
New
i’m a new one to elixir
which editor can i use
vs code? or atom?
Thanks! :smiley:
New
If I have a string “1000 cfu/ml” . I want to remove the characters and / and space . So the string is like this
"1000"
What is the ...
New
What is the difference between System.get_env and Application.get_env? For example, what are best practices to use one versus another.
New
Forgive me if this is obvious, but how does one delete a database record WITHOUT selecting it first? https://hexdocs.pm/ecto/Ecto.Repo.h...
New
Sometimes I want to check if the input into a function is not a blank string.
My first approach:
defmodule Example do
def do_stuff(s...
New
I have a super simple question about elixir - how would I take a file like this
foo bar baz
and output a new file that enumerates th...
New
Hello again - after a longish gap I’ve decided I really must dig into Elixir and see what’s been happening here - so I have a few questio...
New
Other popular topics
TL;DR: I’ve just released an implementation of Microsoft’s IDE-independent Language Server Protocol for Elixir. It adds language support ...
New
Hello!
tl;dr Announcing Oban, an Ecto based job processing library with a focus on reliability and historical observability.
After spen...
New
Hello!
Sorry for this astonishing simple question, but I’m really stuck. I try to set up the intellij-elixir plugin, but I don’t know ho...
New
Hi there,
I am working with Ecto-Postgresql and I need to call all of the records from a specific table but the table has 40,000 record...
New
You’re a programmer, so you don’t need spoon feeding with the conventional drivel about “this is an integer.” No. You need to know what’s...
New
i’m a new one to elixir
which editor can i use
vs code? or atom?
Thanks! :smiley:
New
The Elixir Typespec docs show the following syntax for keyword lists in typespecs:
# ...
| [key: type] # keyword lis...
New
To my knowledge, put_in, Map.update etc. all have the one limitation of not automatically creating intermediate keys when needed (for exa...
New
Hi everyone!
I need implement if…else if…else condition from my elixir code, and anymore of this control flow structures not work proper...
New
Hello again - after a longish gap I’ve decided I really must dig into Elixir and see what’s been happening here - so I have a few questio...
New







