summaryrefslogtreecommitdiff
path: root/lib/irc/parser/prefix.ex
diff options
context:
space:
mode:
Diffstat (limited to 'lib/irc/parser/prefix.ex')
-rw-r--r--lib/irc/parser/prefix.ex47
1 files changed, 47 insertions, 0 deletions
diff --git a/lib/irc/parser/prefix.ex b/lib/irc/parser/prefix.ex
new file mode 100644
index 0000000..e446d7c
--- /dev/null
+++ b/lib/irc/parser/prefix.ex
@@ -0,0 +1,47 @@
+defmodule Irc.Parser.Prefix do
+
+ @moduledoc """
+ Parser for prefixes.
+
+ Supports multi-prefix.
+ """
+
+ @spec parse(String.t, Irc.Connection.t) :: {modes :: [String.t], rest :: nil | String.t}
+ @doc """
+ If `lax` is set to true, the parser will ignore chars until it meets a known prefix.
+ """
+ def parse(string, conn, lax \\ false) do
+ map = Map.get(conn.isupport, "PREFIX") || %{}
+ {prefixes, rest} = parse_prefix(string, Map.keys(map), lax)
+ modes = Enum.map(prefixes, fn(p) -> Map.get(map, p) end)
+ |> Enum.filter(fn(p) -> p end)
+ {Enum.reverse(modes), to_string(Enum.reverse(rest))}
+ end
+
+ defp parse_prefix(string, all_prefixes, lax) do
+ parse_prefix(to_charlist(string), to_charlist(all_prefixes), [], [], lax)
+ end
+
+ defp parse_prefix(all = [prefix | rest], all_prefixes, acc, ign, lax) do
+ prefix_str = to_string([prefix])
+ cond do
+ Enum.member?(all_prefixes, prefix_str) -> parse_prefix(rest, all_prefixes, [prefix_str | acc], ign, lax)
+ lax && acc == [] -> parse_prefix(rest, all_prefixes, acc, [prefix | ign], lax)
+ true -> parse_lax(all, acc, [])
+ end
+ end
+
+ defp parse_prefix([], _, acc, ign, _) do
+ {acc, ign}
+ end
+
+ defp parse_lax([a | rest], prefixes, acc) do
+ parse_lax(rest, prefixes, [a | acc])
+ end
+
+ defp parse_lax([], prefixes, acc) do
+ {prefixes, acc}
+ end
+
+end
+