jackalcooper

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)
)
  • expr uses asmexpr indirectly while asmexpr uses expr
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

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

Also Liked

jackalcooper

jackalcooper

update:

100phlecs

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

ityonemo

ityonemo

It works (well enough for my zigler 0.10.x development branch) and is currently designed to parse zig 0.10.x

Where Next?

Popular in Questions Top

Tee
can someone please explain to me how Enum.reduce works with maps
New
vonH
In asking this question I am more interested about the expressiveness of the language itself and less concerned about the availability of...
New
albydarned
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
SoCreat
i’m a new one to elixir which editor can i use vs code? or atom? Thanks! :smiley:
New
script
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
mcarvalho
What is the difference between System.get_env and Application.get_env? For example, what are best practices to use one versus another.
New
fireproofsocks
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
Exadra37
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
lucidguppy
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
joeerl
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 Top

JakeBecker
TL;DR: I’ve just released an implementation of Microsoft’s IDE-independent Language Server Protocol for Elixir. It adds language support ...
1140 51847 244
New
sorentwo
Hello! tl;dr Announcing Oban, an Ecto based job processing library with a focus on reliability and historical observability. After spen...
977 41022 311
New
openscript
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
joaquinalcerro
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
AstonJ
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
SoCreat
i’m a new one to elixir which editor can i use vs code? or atom? Thanks! :smiley:
New
myronmarston
The Elixir Typespec docs show the following syntax for keyword lists in typespecs: # ... | [key: type] # keyword lis...
New
skosch
To my knowledge, put_in, Map.update etc. all have the one limitation of not automatically creating intermediate keys when needed (for exa...
New
lanycrost
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
joeerl
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

We're in Beta

About us Mission Statement