# Generated by Snowball.Generator — do not edit by hand. defmodule Text.Stemmer.Stemmers.Finnish do @moduledoc """ Snowball stemmer for finnish. Generated from the canonical Snowball algorithm source. """ alias Snowball.Runtime alias Snowball.Grouping # Groupings @g_AEI Grouping.from_string("aäei") @g_C Grouping.from_string("bcdfghjklmnpqrstvwxz") @g_V1 Grouping.from_string("aeiouyäö") @g_V2 Grouping.from_string("aeiouäö") @g_particle_end Grouping.from_string("aeiouyäönt") # Among tables @a_0 [ {"mma", -1, 1, nil}, {"imma", 0, -1, nil} ] @a_1 [ {"i", -1, -1, nil}, {"j", -1, -1, nil} ] @a_2 [ {"eja", -1, -1, nil}, {"mma", -1, 1, nil}, {"imma", 1, -1, nil}, {"mpa", -1, 1, nil}, {"impa", 3, -1, nil}, {"mmi", -1, 1, nil}, {"immi", 5, -1, nil}, {"mpi", -1, 1, nil}, {"impi", 7, -1, nil}, {"ejä", -1, -1, nil}, {"mmä", -1, 1, nil}, {"immä", 10, -1, nil}, {"mpä", -1, 1, nil}, {"impä", 12, -1, nil} ] defp a_3 do [ {"a", -1, 8, nil}, {"lla", 0, -1, nil}, {"na", 0, -1, nil}, {"ssa", 0, -1, nil}, {"ta", 0, -1, nil}, {"lta", 4, -1, nil}, {"sta", 4, -1, nil}, {"tta", 4, 9, nil}, {"lle", -1, -1, nil}, {"ine", -1, -1, nil}, {"ksi", -1, -1, nil}, {"n", -1, 7, nil}, {"han", 11, 1, nil}, {"den", 11, -1, fn state -> case r_VI(state) do {:ok, s} -> s; _ -> :fail end end}, {"seen", 11, -1, fn state -> case r_LONG(state) do {:ok, s} -> s; _ -> :fail end end}, {"hen", 11, 2, nil}, {"tten", 11, -1, fn state -> case r_VI(state) do {:ok, s} -> s; _ -> :fail end end}, {"hin", 11, 3, nil}, {"siin", 11, -1, fn state -> case r_VI(state) do {:ok, s} -> s; _ -> :fail end end}, {"hon", 11, 4, nil}, {"hän", 11, 5, nil}, {"hön", 11, 6, nil}, {"ä", -1, 8, nil}, {"llä", 22, -1, nil}, {"nä", 22, -1, nil}, {"ssä", 22, -1, nil}, {"tä", 22, -1, nil}, {"ltä", 26, -1, nil}, {"stä", 26, -1, nil}, {"ttä", 26, 9, nil} ] end @a_4 [ {"aa", -1, -1, nil}, {"ee", -1, -1, nil}, {"ii", -1, -1, nil}, {"oo", -1, -1, nil}, {"uu", -1, -1, nil}, {"ää", -1, -1, nil}, {"öö", -1, -1, nil} ] @a_5 [ {"lla", -1, -1, nil}, {"na", -1, -1, nil}, {"ssa", -1, -1, nil}, {"ta", -1, -1, nil}, {"lta", 3, -1, nil}, {"sta", 3, -1, nil} ] @a_6 [ {"llä", -1, -1, nil}, {"nä", -1, -1, nil}, {"ssä", -1, -1, nil}, {"tä", -1, -1, nil}, {"ltä", 3, -1, nil}, {"stä", 3, -1, nil} ] @a_7 [ {"lle", -1, -1, nil}, {"ine", -1, -1, nil} ] @a_8 [ {"nsa", -1, 3, nil}, {"mme", -1, 3, nil}, {"nne", -1, 3, nil}, {"ni", -1, 2, nil}, {"si", -1, 1, nil}, {"an", -1, 4, nil}, {"en", -1, 6, nil}, {"än", -1, 5, nil}, {"nsä", -1, 3, nil} ] @a_9 [ {"pa", -1, 1, nil}, {"sti", -1, 2, nil}, {"kaan", -1, 1, nil}, {"han", -1, 1, nil}, {"kin", -1, 1, nil}, {"hän", -1, 1, nil}, {"kään", -1, 1, nil}, {"ko", -1, 1, nil}, {"pä", -1, 1, nil}, {"kö", -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, p2: 0, ending_removed: false, x: ""}} 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_do_b(state, fun) do rel = state.limit - state.cursor {_, s} = fun.(state) %{s | cursor: s.limit - rel} 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 next_codepoint_b(%Runtime{cursor: c, limit_backward: lb, current: cur} = state) do case Runtime.codepoint_before(cur, c, lb) do {_cp, size} -> {:ok, %{state | cursor: c - size}} :error -> {:fail, state} end end defp r_tidy(%Runtime{} = state) do case (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 -> case (fn state -> {:ok, snowball_do_b(state, fn state -> case (fn state -> snowball_test_b(state, fn state -> r_LONG(state) end) end).(state) do {:ok, state} -> case (fn state -> {:ok, %{state | ket: state.cursor}} end).(state) do {:ok, state} -> case (fn state -> next_codepoint_b(state) end).(state) do {:ok, state} -> case (fn state -> {:ok, %{state | bra: state.cursor}} end).(state) do {:ok, state} -> {:ok, Runtime.slice_del(state)} end r -> r end end r -> r end end)} end).(state) do {:ok, state} -> case (fn state -> {:ok, snowball_do_b(state, fn state -> case (fn state -> {:ok, %{state | ket: state.cursor}} end).(state) do {:ok, state} -> case (fn state -> lift(state, Runtime.in_grouping_b(state, @g_AEI)) end).(state) do {:ok, state} -> case (fn state -> {:ok, %{state | bra: state.cursor}} end).(state) do {:ok, state} -> case (fn state -> lift(state, Runtime.in_grouping_b(state, @g_C)) end).(state) do {:ok, state} -> {:ok, Runtime.slice_del(state)} r -> r end end r -> r end end end)} end).(state) do {:ok, state} -> case (fn state -> {:ok, snowball_do_b(state, fn state -> case (fn state -> {:ok, %{state | ket: state.cursor}} end).(state) do {:ok, state} -> case (fn state -> lift(state, Runtime.eq_s_b(state, "j")) end).(state) do {:ok, state} -> case (fn state -> {:ok, %{state | bra: state.cursor}} end).(state) do {:ok, state} -> case (fn state -> snowball_or(state, fn state -> lift(state, Runtime.eq_s_b(state, "o")) end, fn state -> lift(state, Runtime.eq_s_b(state, "u")) end) end).(state) do {:ok, state} -> {:ok, Runtime.slice_del(state)} r -> r end end r -> r end end end)} end).(state) do {:ok, state} -> {:ok, snowball_do_b(state, fn state -> case (fn state -> {:ok, %{state | ket: state.cursor}} end).(state) do {:ok, state} -> case (fn state -> lift(state, Runtime.eq_s_b(state, "o")) end).(state) do {:ok, state} -> case (fn state -> {:ok, %{state | bra: state.cursor}} end).(state) do {:ok, state} -> case (fn state -> lift(state, Runtime.eq_s_b(state, "j")) end).(state) do {:ok, state} -> {:ok, Runtime.slice_del(state)} r -> r end end r -> r end end end)} end end end end).(state) do {:ok, s} -> {:ok, %{s | limit_backward: old_lb}} end end end).() end).(state) do {:ok, state} -> case (fn state -> lift(state, Runtime.go_in_grouping_b(state, @g_V1)) end).(state) do {:ok, state} -> case (fn state -> {:ok, %{state | ket: state.cursor}} end).(state) do {:ok, state} -> case (fn state -> lift(state, Runtime.in_grouping_b(state, @g_C)) end).(state) do {:ok, state} -> case (fn state -> {:ok, %{state | bra: state.cursor}} end).(state) do {:ok, state} -> case (fn state -> {:ok, put_in(state.vars[:x], Runtime.slice_to(state))} end).(state) do {:ok, state} -> case (fn state -> lift(state, Runtime.eq_s_b(state, state.vars[:x])) end).(state) do {:ok, state} -> {:ok, Runtime.slice_del(state)} r -> r end end end r -> r end end r -> r end r -> r end end defp r_t_plural(%Runtime{} = state) do case (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 -> case (fn state -> {:ok, %{state | ket: state.cursor}} end).(state) do {:ok, state} -> case (fn state -> lift(state, Runtime.eq_s_b(state, "t")) end).(state) do {:ok, state} -> case (fn state -> {:ok, %{state | bra: state.cursor}} end).(state) do {:ok, state} -> case (fn state -> snowball_test_b(state, fn state -> lift(state, Runtime.in_grouping_b(state, @g_V1)) end) end).(state) do {:ok, state} -> {:ok, Runtime.slice_del(state)} r -> r end end r -> r 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).(state) do {:ok, state} -> case (fn state -> (fn -> old_limit = state.limit_backward case (fn state -> (fn -> target = state.vars[:p2] 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} -> state = %{state | ket: state.cursor, limit_backward: limit_state.cursor} case Runtime.find_among_b(state, @a_0) do :fail -> {:fail, %{state | limit_backward: old_limit}} {%Runtime{} = s, result} -> state = %{s | bra: s.cursor, limit_backward: old_limit} case result do 1 -> (fn state -> saved_c = state.cursor case (fn state -> lift(state, Runtime.eq_s_b(state, "po")) end).(state) do {:ok, s} -> {:fail, %{s | cursor: saved_c}} {:fail, s} -> {:ok, %{s | cursor: saved_c}} end end).(state) _ -> {:ok, state} end end end end).() end).(state) do {:ok, state} -> {:ok, Runtime.slice_del(state)} r -> r end r -> r end end defp r_i_plural(%Runtime{} = state) do case (fn state -> (fn -> old_limit = state.limit_backward 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} -> state = %{state | ket: state.cursor, limit_backward: limit_state.cursor} case Runtime.find_among_b(state, @a_1) do :fail -> {:fail, %{state | limit_backward: old_limit}} {%Runtime{} = s, _result} -> state = %{s | bra: s.cursor, limit_backward: old_limit} {:ok, state} end end end).() end).(state) do {:ok, state} -> {:ok, Runtime.slice_del(state)} r -> r end end defp r_other_endings(%Runtime{} = state) do case (fn state -> (fn -> old_limit = state.limit_backward case (fn state -> (fn -> target = state.vars[:p2] 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} -> state = %{state | ket: state.cursor, limit_backward: limit_state.cursor} case Runtime.find_among_b(state, @a_2) do :fail -> {:fail, %{state | limit_backward: old_limit}} {%Runtime{} = s, result} -> state = %{s | bra: s.cursor, limit_backward: old_limit} case result do 1 -> (fn state -> saved_c = state.cursor case (fn state -> lift(state, Runtime.eq_s_b(state, "po")) end).(state) do {:ok, s} -> {:fail, %{s | cursor: saved_c}} {:fail, s} -> {:ok, %{s | cursor: saved_c}} end end).(state) _ -> {:ok, state} end end end end).() end).(state) do {:ok, state} -> {:ok, Runtime.slice_del(state)} r -> r end end defp r_case_ending(%Runtime{} = state) do case (fn state -> (fn -> old_limit = state.limit_backward 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} -> state = %{state | ket: state.cursor, limit_backward: limit_state.cursor} case Runtime.find_among_b(state, a_3()) do :fail -> {:fail, %{state | limit_backward: old_limit}} {%Runtime{} = s, result} -> state = %{s | bra: s.cursor, limit_backward: old_limit} case result do 1 -> lift(state, Runtime.eq_s_b(state, "a")) 2 -> lift(state, Runtime.eq_s_b(state, "e")) 3 -> lift(state, Runtime.eq_s_b(state, "i")) 4 -> lift(state, Runtime.eq_s_b(state, "o")) 5 -> lift(state, Runtime.eq_s_b(state, "ä")) 6 -> lift(state, Runtime.eq_s_b(state, "ö")) 7 -> {:ok, snowball_try(state, fn state -> case (fn state -> case (fn state -> snowball_test_b(state, fn state -> snowball_or(state, fn state -> r_LONG(state) end, fn state -> lift(state, Runtime.eq_s_b(state, "ie")) end) end) end).(state) do {:ok, state} -> next_codepoint_b(state) r -> r end end).(state) do {:ok, state} -> {:ok, %{state | bra: state.cursor}} r -> r end end)} 8 -> case (fn state -> lift(state, Runtime.in_grouping_b(state, @g_V1)) end).(state) do {:ok, state} -> lift(state, Runtime.in_grouping_b(state, @g_C)) r -> r end 9 -> lift(state, Runtime.eq_s_b(state, "e")) _ -> {:ok, state} end 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[:ending_removed], true)} end r -> r end end defp r_VI(%Runtime{} = state) do case (fn state -> lift(state, Runtime.eq_s_b(state, "i")) end).(state) do {:ok, state} -> lift(state, Runtime.in_grouping_b(state, @g_V2)) r -> r end end defp r_LONG(%Runtime{} = state) do (fn -> case Runtime.find_among_b(state, @a_4) do :fail -> {:fail, state} {%Runtime{} = s, _} -> {:ok, s} end end).() end defp r_possessive(%Runtime{} = state) do (fn -> old_limit = state.limit_backward 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} -> state = %{state | ket: state.cursor, limit_backward: limit_state.cursor} case Runtime.find_among_b(state, @a_8) do :fail -> {:fail, %{state | limit_backward: old_limit}} {%Runtime{} = s, result} -> state = %{s | bra: s.cursor, limit_backward: old_limit} case result do 1 -> case (fn state -> (fn state -> saved_c = state.cursor case (fn state -> lift(state, Runtime.eq_s_b(state, "k")) 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 2 -> case (fn state -> {:ok, Runtime.slice_del(state)} end).(state) do {:ok, state} -> case (fn state -> {:ok, %{state | ket: state.cursor}} end).(state) do {:ok, state} -> case (fn state -> lift(state, Runtime.eq_s_b(state, "kse")) end).(state) do {:ok, state} -> case (fn state -> {:ok, %{state | bra: state.cursor}} end).(state) do {:ok, state} -> {:ok, Runtime.slice_from(state, "ksi")} end r -> r end end end 3 -> {:ok, Runtime.slice_del(state)} 4 -> 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, state} -> {:ok, Runtime.slice_del(state)} r -> r end 5 -> case (fn state -> (fn -> case Runtime.find_among_b(state, @a_6) do :fail -> {:fail, state} {%Runtime{} = s, _} -> {:ok, s} end end).() end).(state) do {:ok, state} -> {:ok, Runtime.slice_del(state)} r -> r end 6 -> case (fn state -> (fn -> case Runtime.find_among_b(state, @a_7) do :fail -> {:fail, state} {%Runtime{} = s, _} -> {:ok, s} end end).() end).(state) do {:ok, state} -> {:ok, Runtime.slice_del(state)} r -> r end _ -> {:ok, state} end end end end).() end defp r_particle_etc(%Runtime{} = state) do case (fn state -> (fn -> old_limit = state.limit_backward 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} -> state = %{state | ket: state.cursor, limit_backward: limit_state.cursor} case Runtime.find_among_b(state, @a_9) do :fail -> {:fail, %{state | limit_backward: old_limit}} {%Runtime{} = s, result} -> state = %{s | bra: s.cursor, limit_backward: old_limit} case result do 1 -> lift(state, Runtime.in_grouping_b(state, @g_particle_end)) 2 -> r_R2(state) _ -> {:ok, state} end end end end).() end).(state) do {:ok, state} -> {:ok, Runtime.slice_del(state)} r -> r end end defp r_R2(%Runtime{} = state) do if state.vars[:p2] <= state.cursor, do: {:ok, state}, else: {:fail, state} end defp r_mark_regions(%Runtime{} = state) do case (fn state -> {:ok, put_in(state.vars[:p1], state.limit)} end).(state) do {:ok, state} -> case (fn state -> {:ok, put_in(state.vars[:p2], state.limit)} end).(state) do {:ok, state} -> case (fn state -> case Runtime.go_out_grouping(state, @g_V1) do :fail -> {:fail, state} %Runtime{} = s -> next_codepoint(s) end end).(state) do {:ok, state} -> case (fn state -> case Runtime.go_in_grouping(state, @g_V1) do :fail -> {:fail, state} %Runtime{} = s -> next_codepoint(s) end end).(state) do {:ok, state} -> case (fn state -> {:ok, put_in(state.vars[:p1], state.cursor)} end).(state) do {:ok, state} -> case (fn state -> case Runtime.go_out_grouping(state, @g_V1) do :fail -> {:fail, state} %Runtime{} = s -> next_codepoint(s) end end).(state) do {:ok, state} -> case (fn state -> case Runtime.go_in_grouping(state, @g_V1) do :fail -> {:fail, state} %Runtime{} = s -> next_codepoint(s) end end).(state) do {:ok, state} -> {:ok, put_in(state.vars[:p2], state.cursor)} r -> r end r -> r end end r -> r end r -> r end end end end defp r_stem(%Runtime{} = state) do case (fn state -> {:ok, snowball_do_f(state, fn state -> r_mark_regions(state) end)} end).(state) do {:ok, state} -> case (fn state -> {:ok, put_in(state.vars[:ending_removed], false)} 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 -> case (fn state -> {:ok, snowball_do_b(state, fn state -> r_particle_etc(state) end)} end).(state) do {:ok, state} -> case (fn state -> {:ok, snowball_do_b(state, fn state -> r_possessive(state) end)} end).(state) do {:ok, state} -> case (fn state -> {:ok, snowball_do_b(state, fn state -> r_case_ending(state) end)} end).(state) do {:ok, state} -> case (fn state -> {:ok, snowball_do_b(state, fn state -> r_other_endings(state) end)} end).(state) do {:ok, state} -> case (fn state -> snowball_or(state, fn state -> case (fn state -> if state.vars[:ending_removed], do: {:ok, state}, else: {:fail, state} end).(state) do {:ok, state} -> {:ok, snowball_do_b(state, fn state -> r_i_plural(state) end)} r -> r end end, fn state -> {:ok, snowball_do_b(state, fn state -> r_t_plural(state) end)} end) end).(state) do {:ok, state} -> {:ok, snowball_do_b(state, fn state -> r_tidy(state) end)} r -> r end end end end end end).(state) {tag, %{s | cursor: old_cursor, limit_backward: old_lb}} end).(state) end end end end