Skip to content

Commit

Permalink
add nimble_parsec
Browse files Browse the repository at this point in the history
  • Loading branch information
palm86 committed Apr 1, 2022
1 parent da9b818 commit bdd3c69
Show file tree
Hide file tree
Showing 5 changed files with 117 additions and 2 deletions.
3 changes: 2 additions & 1 deletion lib/joy/interpreter.ex
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,8 @@ defmodule Joy.Interpreter do
" ",
IO.ANSI.white(),
Joy.Formatter.format(program),
IO.ANSI.normal()
IO.ANSI.normal(),
"\n"
])
end

Expand Down
23 changes: 23 additions & 0 deletions lib/joy/parsec.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
defmodule Joy.Parsec do
import NimbleParsec

func = ascii_string([?0..?9, ?a..?z, ?!, ?^, ?%, ?*, ?+, ?-, ?/, ?<..??], min: 1)

whitespace = repeat(ascii_char([?\n, ?\t, ?\s]))

quotation =
ignore(string("["))
|> ignore(whitespace)
|> repeat(parsec(:element))
|> ignore(string("]"))
|> wrap()

defcombinatorp(
:element,
choice([func, quotation]) |> ignore(whitespace),
inline: true,
export_metadata: true
)

defparsec(:parse!, ignore(whitespace) |> repeat(parsec(:element)), inline: true, export_metadata: true)
end
3 changes: 2 additions & 1 deletion mix.exs
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,8 @@ defmodule Joy.MixProject do
# Run "mix help deps" to learn about dependencies.
defp deps do
[
{:eliver, "~> 2.0", only: :dev}
{:eliver, "~> 2.0", only: :dev},
{:nimble_parsec, "~> 1.2"}
# {:dep_from_hexpm, "~> 0.3.0"},
# {:dep_from_git, git: "https://github.com/elixir-lang/my_dep.git", tag: "0.1.0"}
]
Expand Down
1 change: 1 addition & 0 deletions mix.lock
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
%{
"eliver": {:hex, :eliver, "2.0.3", "ddfb3a9e77028298dd8cb9d91bfe16a39db67a1f43830bb8f1c3ad085a9c96fe", [:mix], [{:enquirer, "~> 0.1.0", [hex: :enquirer, repo: "hexpm", optional: false]}], "hexpm", "bd2434db0bb850f2b304e77b29565646411235fadff89ad023787e6f52ce1e87"},
"enquirer": {:hex, :enquirer, "0.1.0", "96ca1a330c919652db4baed6cf572d8c9957a8a305365c54490262c337996a18", [:mix], [], "hexpm", "59445208ad96171f10b2d21bc35032f6f7a49aa4cfd5d13d18f93730c49140bb"},
"nimble_parsec": {:hex, :nimble_parsec, "1.2.0", "b44d75e2a6542dcb6acf5d71c32c74ca88960421b6874777f79153bbbbd7dccc", [:mix], [], "hexpm", "52b2871a7515a5ac49b00f214e4165a40724cf99798d8e4a65e4fd64ebd002c1"},
}
89 changes: 89 additions & 0 deletions test/joy/parsec_test.exs
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
defmodule Joy.ParsecTest do
alias Joy.Parsec
use ExUnit.Case

test "parses various scenarios successfully" do
# {:ok, acc, rest, context, line, offset}
assert Parsec.parse!("") == {:ok, [], "", %{}, {1, 0}, 0}
assert Parsec.parse!(" ") == {:ok, [], "", %{}, {1, 0}, 1}
assert Parsec.parse!(" ") == {:ok, [], "", %{}, {1, 0}, 3}
assert Parsec.parse!("[]") == {:ok, [[]], "", %{}, {1, 0}, 2}
assert Parsec.parse!(" []") == {:ok, [[]], "", %{}, {1, 0}, 3}
assert Parsec.parse!("[] ") == {:ok, [[]], "", %{}, {1, 0}, 3}
assert Parsec.parse!(" [] ") == {:ok, [[]], "", %{}, {1, 0}, 4}
assert Parsec.parse!("[ ]") == {:ok, [[]], "", %{}, {1, 0}, 3}
assert Parsec.parse!("[ ]") == {:ok, [[]], "", %{}, {1, 0}, 4}
assert Parsec.parse!("[ ]") == {:ok, [[]], "", %{}, {1, 0}, 5}
assert Parsec.parse!("a") == {:ok, ["a"], "", %{}, {1, 0}, 1}
assert Parsec.parse!(" a") == {:ok, ["a"], "", %{}, {1, 0}, 2}
assert Parsec.parse!("a ") == {:ok, ["a"], "", %{}, {1, 0}, 2}
assert Parsec.parse!(" a ") == {:ok, ["a"], "", %{}, {1, 0}, 3}
assert Parsec.parse!(" a ") == {:ok, ["a"], "", %{}, {1, 0}, 4}
assert Parsec.parse!(" a") == {:ok, ["a"], "", %{}, {1, 0}, 4}
assert Parsec.parse!("[ a]") == {:ok, [["a"]], "", %{}, {1, 0}, 4}
assert Parsec.parse!("[a ]") == {:ok, [["a"]], "", %{}, {1, 0}, 6}
assert Parsec.parse!("[ a ]") == {:ok, [["a"]], "", %{}, {1, 0}, 6}
assert Parsec.parse!("[ a ]") == {:ok, [["a"]], "", %{}, {1, 0}, 6}
assert Parsec.parse!("[ a]") == {:ok, [["a"]], "", %{}, {1, 0}, 6}
assert Parsec.parse!(" [a]") == {:ok, [["a"]], "", %{}, {1, 0}, 4}
assert Parsec.parse!("[a] ") == {:ok, [["a"]], "", %{}, {1, 0}, 4}
assert Parsec.parse!(" [a] ") == {:ok, [["a"]], "", %{}, {1, 0}, 5}
assert Parsec.parse!(" [ a ]") == {:ok, [["a"]], "", %{}, {1, 0}, 6}
assert Parsec.parse!("[ a ] ") == {:ok, [["a"]], "", %{}, {1, 0}, 6}
assert Parsec.parse!(" [ a ] ") == {:ok, [["a"]], "", %{}, {1, 0}, 7}
assert Parsec.parse!("[ a a]") == {:ok, [["a", "a"]], "", %{}, {1, 0}, 6}
assert Parsec.parse!("[a a ]") == {:ok, [["a", "a"]], "", %{}, {1, 0}, 6}
assert Parsec.parse!("[ a a ]") == {:ok, [["a", "a"]], "", %{}, {1, 0}, 7}
assert Parsec.parse!("[ a []]") == {:ok, [["a", []]], "", %{}, {1, 0}, 7}
assert Parsec.parse!("[a [] ]") == {:ok, [["a", []]], "", %{}, {1, 0}, 7}
assert Parsec.parse!("[ a [] ]") == {:ok, [["a", []]], "", %{}, {1, 0}, 8}
assert Parsec.parse!("[ a [a]]") == {:ok, [["a", ["a"]]], "", %{}, {1, 0}, 8}
assert Parsec.parse!("[a [a] ]") == {:ok, [["a", ["a"]]], "", %{}, {1, 0}, 8}
assert Parsec.parse!("[ a [a] ]") == {:ok, [["a", ["a"]]], "", %{}, {1, 0}, 9}
assert Parsec.parse!("[ [] a]") == {:ok, [[[], "a"]], "", %{}, {1, 0}, 7}
assert Parsec.parse!("[[] a ]") == {:ok, [[[], "a"]], "", %{}, {1, 0}, 7}
assert Parsec.parse!("[ [] a ]") == {:ok, [[[], "a"]], "", %{}, {1, 0}, 8}
assert Parsec.parse!("[ [a] []]") == {:ok, [[["a"], []]], "", %{}, {1, 0}, 9}
assert Parsec.parse!("[[a] [] ]") == {:ok, [[["a"], []]], "", %{}, {1, 0}, 9}
assert Parsec.parse!("[ [a] [] ]") == {:ok, [[["a"], []]], "", %{}, {1, 0}, 10}

multiline = """
a
a
[
a
]
"""

assert Parsec.parse!(multiline) == {:ok, ["a", "a", ["a"]], "", %{}, {7, 13}, 13}

multiline = """
[
a
[]
]
"""

assert Parsec.parse!(multiline) == {:ok, [["a", []]], "", %{}, {5, 9}, 9}

multiline = """
[
a
[
a
[
a
]
]
]
"""

assert Parsec.parse!(multiline) == {:ok, [["a", ["a", ["a"]]]], "", %{}, {10, 106}, 106}
end

test "parses and fails in some cases" do
# TODO fail if rest is not empty
assert Parsec.parse!("[") == {:ok, [], "[", %{}, {1, 0}, 0}
end
end

0 comments on commit bdd3c69

Please sign in to comment.