tmbb

tmbb

NimbleRegex - compile regular expressions into NimbleParsec combinators

I’ve started working on a toy project to compile extended POSIX-compatible regular expressions into NimbleParsec combinators. These combnators can be used to match on strings directly (only on the start of the strings, though) or as part of a bigger parser.I don’t support all of the POSIX standard yet. The goal is to help converting regex-based programing language highlighter into makeup lexers.

Example:

defmodule NimbleRegex.PosixExtended.CompilerTest do
  use ExUnit.Case

  alias NimbleRegex.PosixExtended.Parser
  alias NimbleRegex.PosixExtended.Compiler

  import NimbleParsec

  def simplify_result({:ok, result, rest, _, _, _}), do: {:ok, to_string(result), rest}
  def simplify_result({:error, _result, _rest, _, _, _}), do: :error

  test "simplify" do
    parsed = Parser.regex!("a|b|c")

    assert Compiler.simplify_alternatives(parsed) == [
             alternatives: [
               literal_char: ?a,
               literal_char: ?b,
               literal_char: ?c
             ]
           ]
  end

  defparsec(:comb1, Compiler.parsed_to_combinator("a|b|c"))

  test "example - comb1" do
    assert comb1("a") |> simplify_result() == {:ok, "a", ""}
    assert comb1("b") |> simplify_result() == {:ok, "b", ""}
    assert comb1("c") |> simplify_result() == {:ok, "c", ""}
    assert comb1("x") |> simplify_result() == :error
    assert comb1("xy") |> simplify_result() == :error
  end

  defparsec(:comb2, Compiler.compile_to_combinator("(ax)|b|c"))

  test "example - comb2" do
    assert comb2("a") |> simplify_result() == :error
    assert comb2("b") |> simplify_result() == {:ok, "b", ""}
    assert comb2("c") |> simplify_result() == {:ok, "c", ""}
    assert comb2("ax") |> simplify_result() == {:ok, "ax", ""}
  end

  defparsec(:comb3, Compiler.compile_to_combinator("ax|b"))

  test "example - comb3" do
    assert comb3("a") |> simplify_result() == :error
    assert comb3("ax") |> simplify_result() == {:ok, "ax", ""}
    assert comb3("ab") |> simplify_result() == {:ok, "ab", ""}
    assert comb3("b") |> simplify_result() == :error
  end

  defparsec(:comb4, Compiler.compile_to_combinator("[[:word:]]+"))

  test "example - comb4" do
    assert comb4("ábç") |> simplify_result() == {:ok, "ábç", ""}
  end
end

It’s currently 3x as fast as the Regex module when matching the beginning of a string (I’m not sure this is a fair comparison)

Where Next?

Popular in RFCs Top

brettbeatty
At my work we build a lot of mix tasks for backfills and other maintenance tasks. Even with OptionParser we seem to copy a lot of boilerp...
New
dimamik
Hi! I’ve been working with Pipecat in Python for quite a while now, and while it’s effortless to set up, when building AI voice agents at...
New
KristerV
I got fed up with removing unused aliases manually so made a package for it: GitHub - KristerV/remove_unused_ex: Remove unused aliases an...
New
borodark
Hey folks, I’m building Zed (not editor) a declarative BEAM deploy tool for FreeBSD and illumos that uses ZFS user properties as the stat...
New
miolini
Hi :waving_hand: I’ve been working on CanvasCraft, a 2D drawing library for Elixir built on top of Skia via Rustler. It provides a decla...
New
pepicrft
Hey folks :wave: I implemented a library that uses macros extensively, and I’d appreciate feedback from people that are more versed at w...
New
tmbb
SciEx - Scientific programming Code here (very early stage): GitHub - tmbb/sci_ex: Scientific programming for Elixir · GitHub I have dec...
New
BartOtten
This lib is now published and has a new topic. Once this topic was about PhxAltRoutes. A lib pioneering localized routes for Phoenix. I...
New
bortzmeyer
Not a replacement for serious authoritative DNS servers, of course, but useful for some uses (such as returning the IP address of the DNS...
New
sodapopcan
EDIT: I forgot to link the repo, ha: GitHub - sodapopcan/vials: Tweak your mix generators · GitHub This project is not quite ready for p...
New

Other popular topics Top

9mm
I am constructing a JSON object (map) and I need to conditionally set a field. I’m trying to write proper elixir-way code… and I’m at a l...
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
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
Nvim
Anybody knows a comprehensive comparison of Django and Phoenix, thanks for the help. Where are they similar? Where do they differ the m...
New
msaraiva
Surface is an experimental library built on top of Phoenix LiveView and its new LiveComponent API that aims to provide a more declarative...
564 43806 214
New
Lily
In templates/appointment/index.html.eex: <%= for appointment <- @appointments do %> <tr> <td><%= appoi...
New
AstonJ
Please see the new poll here: Which code editor or IDE do you use? (Poll) (2022 Edition) It’s been a while since we first asked this, I...
208 31307 143
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 records...
New
AstonJ
Seen any cool LiveView demos, sample apps or examples? Please post them here! :003:
New
dogweather
I wrote this comment on r/haskell, and it’s not popular there. :wink: But I think I’m on to something… Haskell reminds me of Java, and e...
New

We're in Beta

About us Mission Statement