Packages

Pre-compiled Snowball stemmers for Elixir. Ships 36 stemming algorithms covering a wide range of natural languages, accessible through a single `Text.Stemmer.stem/2` entry point.

Current section

Files

Jump to
text_stemmer lib text stemmer stemmers persian.ex
Raw

lib/text/stemmer/stemmers/persian.ex

# Generated by Snowball.Generator — do not edit by hand.
defmodule Text.Stemmer.Stemmers.Persian do
@moduledoc """
Snowball stemmer for persian.
Generated from the canonical Snowball algorithm source.
"""
alias Snowball.Runtime
# Among tables
@a_0 [
{"یم", -1, 1, nil},
{"ایم", 0, 1, nil},
{"ای", -1, 1, nil},
{"است", -1, 1, nil},
{"اند", -1, 1, nil},
{"ید", -1, 1, nil},
{"اید", 5, 1, nil},
{"اس", -1, 1, nil}
]
@a_1 [
{"م", -1, 1, nil},
{"یم", 0, 1, nil},
{"رفتیم", 1, 2, nil},
{"ام", 0, 1, nil},
{"رفتم", 0, 2, nil},
{"ان", -1, 3, nil},
{"ته", -1, 5, nil},
{"ده", -1, 4, nil},
{"نده", 7, 3, nil},
{"رفتی", -1, 2, nil},
{"د", -1, 1, nil},
{"اند", 10, 1, nil},
{"رفتاند", 11, 2, nil},
{"ید", 10, 1, nil},
{"رفتید", 13, 2, nil}
]
@a_2 [
{"ام", -1, 1, nil},
{"ین", -1, 10, nil},
{"ترین", 1, 16, nil},
{"ان", -1, 9, nil},
{"یان", 3, 3, nil},
{"بان", 3, 12, nil},
{"گان", 3, 4, nil},
{"انه", -1, 18, nil},
{"گاه", -1, 11, nil},
{"انی", -1, 6, nil},
{"یی", -1, 15, nil},
{"های", -1, 5, nil},
{"گی", -1, 13, nil},
{"ها", -1, 7, nil},
{"ناک", -1, 21, nil},
{"یت", -1, 14, nil},
{"ات", -1, 8, nil},
{"مند", -1, 19, nil},
{"وار", -1, 20, nil},
{"گار", -1, 22, nil},
{"تر", -1, 17, nil},
{"اش", -1, 2, nil}
]
@a_3 [
{"اساتید", -1, 2, nil},
{"اخبار", -1, 1, nil}
]
@a_4 [
{"گیلان", -1, 1, nil},
{"آلمان", -1, 1, nil},
{"مسلمان", -1, 1, nil},
{"سلیمان", -1, 1, nil},
{"ایمان", -1, 1, nil},
{"پیمان", -1, 1, nil},
{"ساختمان", -1, 1, nil},
{"رمان", -1, 1, nil},
{"قهرمان", 7, 1, nil},
{"کرمان", 7, 1, nil},
{"درمان", 7, 1, nil},
{"همزمان", -1, 1, nil},
{"سازمان", -1, 1, nil},
{"آسمان", -1, 1, nil},
{"یونان", -1, 1, nil},
{"لبنان", -1, 1, nil},
{"اصفهان", -1, 1, nil},
{"پایان", -1, 1, nil},
{"بیان", -1, 1, nil},
{"جریان", -1, 1, nil},
{"امکان", -1, 1, nil},
{"آذربایجان", -1, 1, nil},
{"همدان", -1, 1, nil},
{"خاندان", -1, 1, nil},
{"زندان", -1, 1, nil},
{"میزان", -1, 1, nil},
{"آتشفشان", -1, 1, nil},
{"نشان", -1, 1, nil},
{"ایشان", -1, 1, nil},
{"پریشان", -1, 1, nil},
{"کهکشان", -1, 1, nil},
{"درخشان", -1, 1, nil},
{"سلطان", -1, 1, nil}
]
@a_5 [
{"وان", -1, -1, nil},
{"ستان", -1, -1, nil},
{"ران", -1, -1, nil},
{"سان", -1, -1, nil}
]
@a_6 [
{"", -1, 8, nil},
{" ", 0, 7, nil},
{"أ", 0, 4, nil},
{"ؤ", 0, 5, nil},
{"إ", 0, 4, nil},
{"ئ", 0, 2, nil},
{"ة", 0, 3, nil},
{"ك", 0, 1, nil},
{"ي", 0, 2, nil},
{"ہ", 0, 3, nil},
{"\u200D", 0, 6, nil}
]
@a_7 [
{"می\u200C", -1, 2, nil},
{"نمی\u200C", -1, 1, nil}
]
@doc """
Stem a word.
### Arguments
* `word` is a UTF-8 binary.
### Returns
* The stemmed UTF-8 binary.
"""
@spec stem(binary()) :: binary()
def stem(word) when is_binary(word) do
state = Runtime.new(word) |> init_vars()
state = run_stem(state)
Runtime.assign_to(state)
end
defp init_vars(state), do: %{state | vars: %{p1: 0, remove_verb_person_endings: false, saw_present_prefix: false}}
defp run_stem(%Runtime{} = state) do
{_, state} = r_stem(state)
state
end
# Snowball runtime helpers.
defp snowball_do_f(state, fun) do
saved_c = state.cursor
{_, s} = fun.(state)
%{s | cursor: saved_c}
end
defp snowball_test_b(state, fun) do
rel = state.limit - state.cursor
case fun.(state) do
{:ok, s} -> {:ok, %{s | cursor: s.limit - rel}}
{:fail, s} -> {:fail, %{s | cursor: s.limit - rel}}
end
end
defp snowball_try(state, fun) do
rel = state.limit - state.cursor
case fun.(state) do
{:ok, s} -> s
{:fail, s} -> %{s | cursor: s.limit - rel}
end
end
defp snowball_or(state, fun1, fun2) do
rel = state.limit - state.cursor
case fun1.(state) do
{:ok, s} -> {:ok, s}
{:fail, s} -> fun2.(%{s | cursor: s.limit - rel})
end
end
defp lift(state, :fail), do: {:fail, state}
defp lift(_state, %Runtime{} = s), do: {:ok, s}
defp next_codepoint(%Runtime{cursor: c, limit: lim, current: cur} = state) do
case Runtime.codepoint_at(cur, c, lim) do
{_cp, size} -> {:ok, %{state | cursor: c + size}}
:error -> {:fail, state}
end
end
defp r_Stem_Verb(%Runtime{} = state) do
snowball_or(state,
fn state ->
(fn ->
state = %{state | ket: state.cursor}
case Runtime.find_among_b(state, @a_0) do
:fail -> {:fail, state}
{%Runtime{} = s, result} ->
state = %{s | bra: s.cursor}
case result do
1 ->
case (fn state ->
r_R1(state)
end).(state) do
{:ok, state} ->
{:ok, Runtime.slice_del(state)}
r -> r
end
_ -> {:ok, state}
end
end
end).()
end,
fn state ->
(fn ->
state = %{state | ket: state.cursor}
case Runtime.find_among_b(state, @a_1) do
:fail -> {:fail, state}
{%Runtime{} = s, result} ->
state = %{s | bra: s.cursor}
case result do
1 ->
case (fn state ->
if state.vars[:remove_verb_person_endings], do: {:ok, state}, else: {:fail, state}
end).(state) do
{:ok, state} ->
case (fn state ->
r_R1(state)
end).(state) do
{:ok, state} ->
{:ok, Runtime.slice_del(state)}
r -> r
end
r -> r
end
2 ->
{:ok, Runtime.slice_from(state, "رفت")}
3 ->
case (fn state ->
r_R1(state)
end).(state) do
{:ok, state} ->
case (fn state ->
{:ok, Runtime.slice_del(state)}
end).(state) do
{:ok, state} ->
{:ok, put_in(state.vars[:remove_verb_person_endings], true)}
end
r -> r
end
4 ->
case (fn state ->
(fn state ->
saved_c = state.cursor
case (fn state ->
if state.cursor <= state.limit_backward, do: {:ok, state}, else: {:fail, state}
end).(state) do
{:ok, s} -> {:fail, %{s | cursor: saved_c}}
{:fail, s} -> {:ok, %{s | cursor: saved_c}}
end
end).(state)
end).(state) do
{:ok, state} ->
case (fn state ->
{:ok, Runtime.slice_from(state, "د")}
end).(state) do
{:ok, state} ->
{:ok, put_in(state.vars[:remove_verb_person_endings], true)}
end
r -> r
end
5 ->
case (fn state ->
(fn state ->
saved_c = state.cursor
case (fn state ->
if state.cursor <= state.limit_backward, do: {:ok, state}, else: {:fail, state}
end).(state) do
{:ok, s} -> {:fail, %{s | cursor: saved_c}}
{:fail, s} -> {:ok, %{s | cursor: saved_c}}
end
end).(state)
end).(state) do
{:ok, state} ->
case (fn state ->
{:ok, Runtime.slice_from(state, "ت")}
end).(state) do
{:ok, state} ->
{:ok, put_in(state.vars[:remove_verb_person_endings], true)}
end
r -> r
end
_ -> {:ok, state}
end
end
end).()
end)
end
defp r_Stem_Noun_or_Adjective(%Runtime{} = state) do
snowball_or(state,
fn state ->
r_Irregular_Noun(state)
end,
fn state ->
(fn ->
case (fn state ->
(fn ->
target = state.vars[:p1]
if target < state.limit_backward or target > state.limit do
{:fail, state}
else
{:ok, %{state | cursor: target}}
end
end).()
end).(state) do
{:fail, _} -> {:fail, state}
{:ok, limit_state} ->
old_lb = state.limit_backward
state = %{state | limit_backward: limit_state.cursor}
case (fn state ->
(fn ->
state = %{state | ket: state.cursor}
case Runtime.find_among_b(state, @a_2) do
:fail -> {:fail, state}
{%Runtime{} = s, result} ->
state = %{s | bra: s.cursor}
case result do
1 ->
{:ok, Runtime.slice_del(state)}
2 ->
{:ok, Runtime.slice_del(state)}
3 ->
{:ok, Runtime.slice_del(state)}
4 ->
{:ok, Runtime.slice_del(state)}
5 ->
{:ok, Runtime.slice_del(state)}
6 ->
{:ok, Runtime.slice_del(state)}
7 ->
{:ok, Runtime.slice_del(state)}
8 ->
{:ok, Runtime.slice_del(state)}
9 ->
{:ok, Runtime.slice_del(state)}
10 ->
{:ok, Runtime.slice_del(state)}
11 ->
{:ok, Runtime.slice_del(state)}
12 ->
{:ok, Runtime.slice_del(state)}
13 ->
{:ok, Runtime.slice_del(state)}
14 ->
{:ok, Runtime.slice_del(state)}
15 ->
{:ok, Runtime.slice_del(state)}
16 ->
{:ok, Runtime.slice_del(state)}
17 ->
case (fn state ->
(fn state ->
saved_c = state.cursor
case (fn state ->
if state.cursor <= state.limit_backward, do: {:ok, state}, else: {:fail, state}
end).(state) do
{:ok, s} -> {:fail, %{s | cursor: saved_c}}
{:fail, s} -> {:ok, %{s | cursor: saved_c}}
end
end).(state)
end).(state) do
{:ok, state} ->
{:ok, Runtime.slice_del(state)}
r -> r
end
18 ->
{:ok, Runtime.slice_del(state)}
19 ->
{:ok, Runtime.slice_del(state)}
20 ->
{:ok, Runtime.slice_del(state)}
21 ->
{:ok, Runtime.slice_del(state)}
22 ->
{:ok, Runtime.slice_del(state)}
_ -> {:ok, state}
end
end
end).()
end).(state) do
{:ok, s} -> {:ok, %{s | limit_backward: old_lb}}
{:fail, s} -> {:fail, %{s | limit_backward: old_lb}}
end
end
end).()
end)
end
defp r_Irregular_Noun(%Runtime{} = state) do
(fn ->
state = %{state | ket: state.cursor}
case Runtime.find_among_b(state, @a_3) do
:fail -> {:fail, state}
{%Runtime{} = s, result} ->
state = %{s | bra: s.cursor}
case result do
1 ->
{:ok, Runtime.slice_from(state, "خبر")}
2 ->
{:ok, Runtime.slice_from(state, "استاد")}
_ -> {:ok, state}
end
end
end).()
end
defp r_AN_Exception(%Runtime{} = state) do
(fn ->
case Runtime.find_among_b(state, @a_4) do
:fail -> {:fail, state}
{%Runtime{} = s, result} ->
state = s
case result do
1 ->
if state.cursor <= state.limit_backward, do: {:ok, state}, else: {:fail, state}
_ -> {:ok, s}
end
end
end).()
end
defp r_Protect_Lexical_AN(%Runtime{} = state) do
case (fn state ->
(fn state ->
saved_c = state.cursor
case (fn state ->
r_AN_Exception(state)
end).(state) do
{:ok, s} -> {:fail, %{s | cursor: saved_c}}
{:fail, s} -> {:ok, %{s | cursor: saved_c}}
end
end).(state)
end).(state) do
{:ok, state} ->
(fn state ->
saved_c = state.cursor
case (fn state ->
(fn ->
case Runtime.find_among_b(state, @a_5) do
:fail -> {:fail, state}
{%Runtime{} = s, _} -> {:ok, s}
end
end).()
end).(state) do
{:ok, s} -> {:fail, %{s | cursor: saved_c}}
{:fail, s} -> {:ok, %{s | cursor: saved_c}}
end
end).(state)
r -> r
end
end
defp r_R1(%Runtime{} = state) do
if state.vars[:p1] <= state.cursor, do: {:ok, state}, else: {:fail, state}
end
defp r_Normalize_Characters(%Runtime{} = state) do
(fn loop_fn ->
loop_fn.(loop_fn, state)
end).(fn loop_fn, state ->
case (fn state ->
(fn ->
state = %{state | bra: state.cursor}
case Runtime.find_among(state, @a_6) do
:fail -> {:fail, state}
{%Runtime{} = s, result} ->
state = %{s | ket: s.cursor}
case result do
1 ->
{:ok, Runtime.slice_from(state, "ک")}
2 ->
{:ok, Runtime.slice_from(state, "ی")}
3 ->
{:ok, Runtime.slice_from(state, "ه")}
4 ->
{:ok, Runtime.slice_from(state, "ا")}
5 ->
{:ok, Runtime.slice_from(state, "و")}
6 ->
{:ok, Runtime.slice_del(state)}
7 ->
{:ok, Runtime.slice_del(state)}
8 ->
next_codepoint(state)
_ -> {:ok, state}
end
end
end).()
end).(state) do
{:ok, s} -> loop_fn.(loop_fn, s)
{:fail, s} -> {:ok, %{s | cursor: state.cursor}}
end
end)
end
defp r_Prefixes(%Runtime{} = state) do
(fn ->
state = %{state | bra: state.cursor}
case Runtime.find_among(state, @a_7) do
:fail -> {:fail, state}
{%Runtime{} = s, result} ->
state = %{s | ket: s.cursor}
case result do
1 ->
case (fn state ->
(fn ->
n = 2
Enum.reduce_while(1..max(n, 0)//1, {:ok, state}, fn _, {:ok, s} ->
case next_codepoint(s) do
{:ok, s2} -> {:cont, {:ok, s2}}
{:fail, _} -> {:halt, {:fail, state}}
end
end)
end).()
end).(state) do
{:ok, state} ->
{:ok, put_in(state.vars[:saw_present_prefix], true)}
r -> r
end
2 ->
case (fn state ->
(fn ->
n = 2
Enum.reduce_while(1..max(n, 0)//1, {:ok, state}, fn _, {:ok, s} ->
case next_codepoint(s) do
{:ok, s2} -> {:cont, {:ok, s2}}
{:fail, _} -> {:halt, {:fail, state}}
end
end)
end).()
end).(state) do
{:ok, state} ->
case (fn state ->
{:ok, Runtime.slice_del(state)}
end).(state) do
{:ok, state} ->
{:ok, put_in(state.vars[:saw_present_prefix], true)}
end
r -> r
end
_ -> {:ok, state}
end
end
end).()
end
defp r_Delete_ZWNJ(%Runtime{} = state) do
(fn loop_fn ->
loop_fn.(loop_fn, state)
end).(fn loop_fn, state ->
case (fn state ->
(fn loop_fn ->
loop_fn.(loop_fn, state)
end).(fn loop_fn, state ->
v = state.cursor
case (fn state ->
case (fn state ->
{:ok, %{state | bra: state.cursor}}
end).(state) do
{:ok, state} ->
case (fn state ->
lift(state, Runtime.eq_s(state, "\u200C"))
end).(state) do
{:ok, state} ->
case (fn state ->
{:ok, %{state | ket: state.cursor}}
end).(state) do
{:ok, state} ->
{:ok, Runtime.slice_del(state)}
end
r -> r
end
end
end).(state) do
{:ok, s} -> {:ok, %{s | cursor: v}}
{:fail, _} ->
case next_codepoint(%{state | cursor: v}) do
{:ok, s} -> loop_fn.(loop_fn, s)
{:fail, _} -> {:fail, state}
end
end
end)
end).(state) do
{:ok, s} -> loop_fn.(loop_fn, s)
{:fail, s} -> {:ok, %{s | cursor: state.cursor}}
end
end)
end
defp r_stem(%Runtime{} = state) do
case (fn state ->
{:ok, put_in(state.vars[:saw_present_prefix], false)}
end).(state) do
{:ok, state} ->
case (fn state ->
{:ok, snowball_do_f(state, fn state ->
r_Normalize_Characters(state)
end)}
end).(state) do
{:ok, state} ->
case (fn state ->
{:ok, snowball_do_f(state, fn state ->
r_Prefixes(state)
end)}
end).(state) do
{:ok, state} ->
case (fn state ->
{:ok, snowball_do_f(state, fn state ->
r_Delete_ZWNJ(state)
end)}
end).(state) do
{:ok, state} ->
case (fn state ->
{:ok, put_in(state.vars[:p1], state.limit)}
end).(state) do
{:ok, state} ->
case (fn state ->
{:ok, snowball_do_f(state, fn state ->
case (fn state ->
(fn ->
n = 3
Enum.reduce_while(1..max(n, 0)//1, {:ok, state}, fn _, {:ok, s} ->
case next_codepoint(s) do
{:ok, s2} -> {:cont, {:ok, s2}}
{:fail, _} -> {:halt, {:fail, state}}
end
end)
end).()
end).(state) do
{:ok, state} ->
{:ok, put_in(state.vars[:p1], state.cursor)}
r -> r
end
end)}
end).(state) do
{:ok, state} ->
(fn state ->
old_cursor = state.cursor
old_lb = state.limit_backward
state = %{state | cursor: state.limit, limit_backward: old_cursor}
{tag, s} = (fn state ->
(fn loop_fn ->
loop_fn.(loop_fn, state)
end).(fn loop_fn, state ->
case (fn state ->
snowball_test_b(state, fn state ->
case (fn state ->
{:ok, put_in(state.vars[:remove_verb_person_endings], false)}
end).(state) do
{:ok, state} ->
case (fn state ->
{:ok, snowball_try(state, fn state ->
case (fn state ->
if state.vars[:saw_present_prefix], do: {:ok, state}, else: {:fail, state}
end).(state) do
{:ok, state} ->
{:ok, put_in(state.vars[:remove_verb_person_endings], true)}
r -> r
end
end)}
end).(state) do
{:ok, state} ->
case (fn state ->
r_Protect_Lexical_AN(state)
end).(state) do
{:ok, state} ->
snowball_or(state,
fn state ->
r_Stem_Noun_or_Adjective(state)
end,
fn state ->
r_Stem_Verb(state)
end)
r -> r
end
end
end
end)
end).(state) do
{:ok, s} -> loop_fn.(loop_fn, s)
{:fail, s} -> {:ok, %{s | cursor: state.cursor}}
end
end)
end).(state)
{tag, %{s | cursor: old_cursor, limit_backward: old_lb}}
end).(state)
end
end
end
end
end
end
end
end