lib/cldr/language_tag/rfc5646_parser.ex

# Generated from lib/cldr/language_tag/rfc5646_parser.ex.exs, do not edit.
# Generated at 2021-08-20 10:43:22Z.

defmodule Cldr.Rfc5646.Parser do
  @moduledoc """
  Implements parsing for [RFC5646](https://datatracker.ietf.org/doc/html/rfc5646) language
  tags with [BCP47](https://tools.ietf.org/search/bcp47) extensions.

  The primary interface to this module is the function
  `Cldr.LanguageTag.parse/1`.

  """

  alias Cldr.LanguageTag

  import Cldr.Rfc5646.Helpers

  def parse(rule \\ :language_tag, input) when is_atom(rule) and is_binary(input) do
    apply(__MODULE__, rule, [input])
    |> unwrap
  end

  defp unwrap({:ok, acc, "", _, _, _}) when is_list(acc),
    do: {:ok, acc}

  defp unwrap({:error, <<first::binary-size(1), reason::binary>>, rest, _, _, offset}),
    do:
      {:error,
       {LanguageTag.ParseError,
        "#{String.capitalize(first)}#{reason}. Could not parse the remaining #{inspect(rest)} " <>
          "starting at position #{offset + 1}"}}

  @doc """
  Parses the given `binary` as language_tag.

  Returns `{:ok, [token], rest, context, position, byte_offset}` or
  `{:error, reason, rest, context, line, byte_offset}` where `position`
  describes the location of the language_tag (start position) as `{line, column_on_line}`.

  ## Options

    * `:byte_offset` - the byte offset for the whole binary, defaults to 0
    * `:line` - the line and the byte offset into that line, defaults to `{1, byte_offset}`
    * `:context` - the initial context value. It will be converted to a map

  """
  @spec language_tag(binary, keyword) ::
          {:ok, [term], rest, context, line, byte_offset}
          | {:error, reason, rest, context, line, byte_offset}
        when line: {pos_integer, byte_offset},
             byte_offset: pos_integer,
             rest: binary,
             reason: String.t(),
             context: map()
  def language_tag(binary, opts \\ []) when is_binary(binary) do
    context = Map.new(Keyword.get(opts, :context, []))
    byte_offset = Keyword.get(opts, :byte_offset, 0)

    line =
      case(Keyword.get(opts, :line, 1)) do
        {_, _} = line ->
          line

        line ->
          {line, byte_offset}
      end

    case(language_tag__0(binary, [], [], context, line, byte_offset)) do
      {:ok, acc, rest, context, line, offset} ->
        {:ok, :lists.reverse(acc), rest, context, line, offset}

      {:error, _, _, _, _, _} = error ->
        error
    end
  end

  defp language_tag__0(rest, acc, stack, context, line, offset) do
    language_tag__39(
      rest,
      [],
      [{rest, context, line, offset}, acc | stack],
      context,
      line,
      offset
    )
  end

  defp language_tag__2(rest, acc, stack, context, line, offset) do
    language_tag__3(rest, [], [acc | stack], context, line, offset)
  end

  defp language_tag__3(rest, acc, stack, context, line, offset) do
    language_tag__10(
      rest,
      [],
      [{rest, context, line, offset}, acc | stack],
      context,
      line,
      offset
    )
  end

  defp language_tag__5(rest, acc, stack, context, line, offset) do
    language_tag__6(rest, [], [acc | stack], context, line, offset)
  end

  defp language_tag__6(
         <<"art-lojban", rest::binary>>,
         acc,
         stack,
         context,
         comb__line,
         comb__offset
       ) do
    language_tag__7(rest, ["art-lojban"] ++ acc, stack, context, comb__line, comb__offset + 10)
  end

  defp language_tag__6(
         <<"cel-gaulish", rest::binary>>,
         acc,
         stack,
         context,
         comb__line,
         comb__offset
       ) do
    language_tag__7(rest, ["cel-gaulish"] ++ acc, stack, context, comb__line, comb__offset + 11)
  end

  defp language_tag__6(<<"no-bok", rest::binary>>, acc, stack, context, comb__line, comb__offset) do
    language_tag__7(rest, ["no-bok"] ++ acc, stack, context, comb__line, comb__offset + 6)
  end

  defp language_tag__6(<<"no-nyn", rest::binary>>, acc, stack, context, comb__line, comb__offset) do
    language_tag__7(rest, ["no-nyn"] ++ acc, stack, context, comb__line, comb__offset + 6)
  end

  defp language_tag__6(
         <<"zh-guoyu", rest::binary>>,
         acc,
         stack,
         context,
         comb__line,
         comb__offset
       ) do
    language_tag__7(rest, ["zh-guoyu"] ++ acc, stack, context, comb__line, comb__offset + 8)
  end

  defp language_tag__6(
         <<"zh-hakka", rest::binary>>,
         acc,
         stack,
         context,
         comb__line,
         comb__offset
       ) do
    language_tag__7(rest, ["zh-hakka"] ++ acc, stack, context, comb__line, comb__offset + 8)
  end

  defp language_tag__6(<<"zh-min", rest::binary>>, acc, stack, context, comb__line, comb__offset) do
    language_tag__7(rest, ["zh-min"] ++ acc, stack, context, comb__line, comb__offset + 6)
  end

  defp language_tag__6(
         <<"zh-min-nan", rest::binary>>,
         acc,
         stack,
         context,
         comb__line,
         comb__offset
       ) do
    language_tag__7(rest, ["zh-min-nan"] ++ acc, stack, context, comb__line, comb__offset + 10)
  end

  defp language_tag__6(
         <<"zh-xiang", rest::binary>>,
         acc,
         stack,
         context,
         comb__line,
         comb__offset
       ) do
    language_tag__7(rest, ["zh-xiang"] ++ acc, stack, context, comb__line, comb__offset + 8)
  end

  defp language_tag__6(rest, _acc, _stack, context, line, offset) do
    {:error,
     "expected one of the regular language tags in BCP-47 while processing a grandfathered language tag inside a BCP47 language tag",
     rest, context, line, offset}
  end

  defp language_tag__7(rest, user_acc, [acc | stack], context, line, offset) do
    _ = user_acc

    language_tag__8(
      rest,
      [
        regular:
          case(:lists.reverse(user_acc)) do
            [one] ->
              one

            many ->
              raise("unwrap_and_tag/3 expected a single token, got: #{inspect(many)}")
          end
      ] ++ acc,
      stack,
      context,
      line,
      offset
    )
  end

  defp language_tag__8(rest, acc, [_, previous_acc | stack], context, line, offset) do
    language_tag__4(rest, acc ++ previous_acc, stack, context, line, offset)
  end

  defp language_tag__9(_, _, [{rest, context, line, offset} | _] = stack, _, _, _) do
    language_tag__5(rest, [], stack, context, line, offset)
  end

  defp language_tag__10(rest, acc, stack, context, line, offset) do
    language_tag__11(rest, [], [acc | stack], context, line, offset)
  end

  defp language_tag__11(
         <<"en-GB-oed", rest::binary>>,
         acc,
         stack,
         context,
         comb__line,
         comb__offset
       ) do
    language_tag__12(rest, ["en-GB-oed"] ++ acc, stack, context, comb__line, comb__offset + 9)
  end

  defp language_tag__11(<<"i-ami", rest::binary>>, acc, stack, context, comb__line, comb__offset) do
    language_tag__12(rest, ["i-ami"] ++ acc, stack, context, comb__line, comb__offset + 5)
  end

  defp language_tag__11(<<"i-bnn", rest::binary>>, acc, stack, context, comb__line, comb__offset) do
    language_tag__12(rest, ["i-bnn"] ++ acc, stack, context, comb__line, comb__offset + 5)
  end

  defp language_tag__11(
         <<"i-default", rest::binary>>,
         acc,
         stack,
         context,
         comb__line,
         comb__offset
       ) do
    language_tag__12(rest, ["i-default"] ++ acc, stack, context, comb__line, comb__offset + 9)
  end

  defp language_tag__11(
         <<"i-enochian", rest::binary>>,
         acc,
         stack,
         context,
         comb__line,
         comb__offset
       ) do
    language_tag__12(rest, ["i-enochian"] ++ acc, stack, context, comb__line, comb__offset + 10)
  end

  defp language_tag__11(<<"i-hak", rest::binary>>, acc, stack, context, comb__line, comb__offset) do
    language_tag__12(rest, ["i-hak"] ++ acc, stack, context, comb__line, comb__offset + 5)
  end

  defp language_tag__11(
         <<"i-klingon", rest::binary>>,
         acc,
         stack,
         context,
         comb__line,
         comb__offset
       ) do
    language_tag__12(rest, ["i-klingon"] ++ acc, stack, context, comb__line, comb__offset + 9)
  end

  defp language_tag__11(<<"i-lux", rest::binary>>, acc, stack, context, comb__line, comb__offset) do
    language_tag__12(rest, ["i-lux"] ++ acc, stack, context, comb__line, comb__offset + 5)
  end

  defp language_tag__11(
         <<"i-mingo", rest::binary>>,
         acc,
         stack,
         context,
         comb__line,
         comb__offset
       ) do
    language_tag__12(rest, ["i-mingo"] ++ acc, stack, context, comb__line, comb__offset + 7)
  end

  defp language_tag__11(
         <<"i-navajo", rest::binary>>,
         acc,
         stack,
         context,
         comb__line,
         comb__offset
       ) do
    language_tag__12(rest, ["i-navajo"] ++ acc, stack, context, comb__line, comb__offset + 8)
  end

  defp language_tag__11(<<"i-pwn", rest::binary>>, acc, stack, context, comb__line, comb__offset) do
    language_tag__12(rest, ["i-pwn"] ++ acc, stack, context, comb__line, comb__offset + 5)
  end

  defp language_tag__11(<<"i-tao", rest::binary>>, acc, stack, context, comb__line, comb__offset) do
    language_tag__12(rest, ["i-tao"] ++ acc, stack, context, comb__line, comb__offset + 5)
  end

  defp language_tag__11(<<"i-tay", rest::binary>>, acc, stack, context, comb__line, comb__offset) do
    language_tag__12(rest, ["i-tay"] ++ acc, stack, context, comb__line, comb__offset + 5)
  end

  defp language_tag__11(<<"i-tsu", rest::binary>>, acc, stack, context, comb__line, comb__offset) do
    language_tag__12(rest, ["i-tsu"] ++ acc, stack, context, comb__line, comb__offset + 5)
  end

  defp language_tag__11(
         <<"sgn-BE-FR", rest::binary>>,
         acc,
         stack,
         context,
         comb__line,
         comb__offset
       ) do
    language_tag__12(rest, ["sgn-BE-FR"] ++ acc, stack, context, comb__line, comb__offset + 9)
  end

  defp language_tag__11(
         <<"sgn-BE-NL", rest::binary>>,
         acc,
         stack,
         context,
         comb__line,
         comb__offset
       ) do
    language_tag__12(rest, ["sgn-BE-NL"] ++ acc, stack, context, comb__line, comb__offset + 9)
  end

  defp language_tag__11(
         <<"sgn-CH-DE", rest::binary>>,
         acc,
         stack,
         context,
         comb__line,
         comb__offset
       ) do
    language_tag__12(rest, ["sgn-CH-DE"] ++ acc, stack, context, comb__line, comb__offset + 9)
  end

  defp language_tag__11(rest, _acc, stack, context, line, offset) do
    [acc | stack] = stack
    language_tag__9(rest, acc, stack, context, line, offset)
  end

  defp language_tag__12(rest, user_acc, [acc | stack], context, line, offset) do
    _ = user_acc

    language_tag__13(
      rest,
      [
        irregular:
          case(:lists.reverse(user_acc)) do
            [one] ->
              one

            many ->
              raise("unwrap_and_tag/3 expected a single token, got: #{inspect(many)}")
          end
      ] ++ acc,
      stack,
      context,
      line,
      offset
    )
  end

  defp language_tag__13(rest, acc, [_, previous_acc | stack], context, line, offset) do
    language_tag__4(rest, acc ++ previous_acc, stack, context, line, offset)
  end

  defp language_tag__4(rest, user_acc, [acc | stack], context, line, offset) do
    _ = user_acc

    language_tag__14(
      rest,
      [grandfathered: :lists.reverse(user_acc)] ++ acc,
      stack,
      context,
      line,
      offset
    )
  end

  defp language_tag__14(rest, acc, [_, previous_acc | stack], context, line, offset) do
    language_tag__1(rest, acc ++ previous_acc, stack, context, line, offset)
  end

  defp language_tag__15(_, _, [{rest, context, line, offset} | _] = stack, _, _, _) do
    language_tag__2(rest, [], stack, context, line, offset)
  end

  defp language_tag__16(rest, acc, stack, context, line, offset) do
    language_tag__17(rest, [], [acc | stack], context, line, offset)
  end

  defp language_tag__17(
         <<x0::integer, x1::integer, rest::binary>>,
         acc,
         stack,
         context,
         comb__line,
         comb__offset
       )
       when (x0 === 120 or x0 === 88) and x1 === 45 do
    language_tag__18(rest, [] ++ acc, stack, context, comb__line, comb__offset + 2)
  end

  defp language_tag__17(rest, _acc, stack, context, line, offset) do
    [acc | stack] = stack
    language_tag__15(rest, acc, stack, context, line, offset)
  end

  defp language_tag__18(rest, acc, stack, context, line, offset) do
    language_tag__19(rest, [], [acc | stack], context, line, offset)
  end

  defp language_tag__19(
         <<x0::integer, rest::binary>>,
         acc,
         stack,
         context,
         comb__line,
         comb__offset
       )
       when (x0 >= 97 and x0 <= 122) or (x0 >= 65 and x0 <= 90) or (x0 >= 48 and x0 <= 57) do
    language_tag__20(rest, [<<x0::integer>>] ++ acc, stack, context, comb__line, comb__offset + 1)
  end

  defp language_tag__19(rest, _acc, stack, context, line, offset) do
    [_, acc | stack] = stack
    language_tag__15(rest, acc, stack, context, line, offset)
  end

  defp language_tag__20(rest, acc, stack, context, line, offset) do
    language_tag__22(rest, acc, [7 | stack], context, line, offset)
  end

  defp language_tag__22(
         <<x0::integer, rest::binary>>,
         acc,
         stack,
         context,
         comb__line,
         comb__offset
       )
       when (x0 >= 97 and x0 <= 122) or (x0 >= 65 and x0 <= 90) or (x0 >= 48 and x0 <= 57) do
    language_tag__23(rest, [x0] ++ acc, stack, context, comb__line, comb__offset + 1)
  end

  defp language_tag__22(rest, acc, stack, context, line, offset) do
    language_tag__21(rest, acc, stack, context, line, offset)
  end

  defp language_tag__21(rest, acc, [_ | stack], context, line, offset) do
    language_tag__24(rest, acc, stack, context, line, offset)
  end

  defp language_tag__23(rest, acc, [1 | stack], context, line, offset) do
    language_tag__24(rest, acc, stack, context, line, offset)
  end

  defp language_tag__23(rest, acc, [count | stack], context, line, offset) do
    language_tag__22(rest, acc, [count - 1 | stack], context, line, offset)
  end

  defp language_tag__24(rest, user_acc, [acc | stack], context, line, offset) do
    _ = user_acc

    language_tag__25(
      rest,
      [List.to_string(:lists.reverse(user_acc))] ++ acc,
      stack,
      context,
      line,
      offset
    )
  end

  defp language_tag__25(rest, acc, stack, context, line, offset) do
    language_tag__27(
      rest,
      [],
      [{rest, acc, context, line, offset} | stack],
      context,
      line,
      offset
    )
  end

  defp language_tag__27(
         <<x0::integer, rest::binary>>,
         acc,
         stack,
         context,
         comb__line,
         comb__offset
       )
       when x0 === 45 do
    language_tag__28(rest, [] ++ acc, stack, context, comb__line, comb__offset + 1)
  end

  defp language_tag__27(rest, acc, stack, context, line, offset) do
    language_tag__26(rest, acc, stack, context, line, offset)
  end

  defp language_tag__28(rest, acc, stack, context, line, offset) do
    language_tag__29(rest, [], [acc | stack], context, line, offset)
  end

  defp language_tag__29(
         <<x0::integer, rest::binary>>,
         acc,
         stack,
         context,
         comb__line,
         comb__offset
       )
       when (x0 >= 97 and x0 <= 122) or (x0 >= 65 and x0 <= 90) or (x0 >= 48 and x0 <= 57) do
    language_tag__30(rest, [<<x0::integer>>] ++ acc, stack, context, comb__line, comb__offset + 1)
  end

  defp language_tag__29(rest, _acc, stack, context, line, offset) do
    [acc | stack] = stack
    language_tag__26(rest, acc, stack, context, line, offset)
  end

  defp language_tag__30(rest, acc, stack, context, line, offset) do
    language_tag__32(rest, acc, [7 | stack], context, line, offset)
  end

  defp language_tag__32(
         <<x0::integer, rest::binary>>,
         acc,
         stack,
         context,
         comb__line,
         comb__offset
       )
       when (x0 >= 97 and x0 <= 122) or (x0 >= 65 and x0 <= 90) or (x0 >= 48 and x0 <= 57) do
    language_tag__33(rest, [x0] ++ acc, stack, context, comb__line, comb__offset + 1)
  end

  defp language_tag__32(rest, acc, stack, context, line, offset) do
    language_tag__31(rest, acc, stack, context, line, offset)
  end

  defp language_tag__31(rest, acc, [_ | stack], context, line, offset) do
    language_tag__34(rest, acc, stack, context, line, offset)
  end

  defp language_tag__33(rest, acc, [1 | stack], context, line, offset) do
    language_tag__34(rest, acc, stack, context, line, offset)
  end

  defp language_tag__33(rest, acc, [count | stack], context, line, offset) do
    language_tag__32(rest, acc, [count - 1 | stack], context, line, offset)
  end

  defp language_tag__34(rest, user_acc, [acc | stack], context, line, offset) do
    _ = user_acc

    language_tag__35(
      rest,
      [List.to_string(:lists.reverse(user_acc))] ++ acc,
      stack,
      context,
      line,
      offset
    )
  end

  defp language_tag__26(_, _, [{rest, acc, context, line, offset} | stack], _, _, _) do
    language_tag__36(rest, acc, stack, context, line, offset)
  end

  defp language_tag__35(
         inner_rest,
         inner_acc,
         [{rest, acc, context, line, offset} | stack],
         inner_context,
         inner_line,
         inner_offset
       ) do
    _ = {rest, acc, context, line, offset}

    language_tag__27(
      inner_rest,
      [],
      [{inner_rest, inner_acc ++ acc, inner_context, inner_line, inner_offset} | stack],
      inner_context,
      inner_line,
      inner_offset
    )
  end

  defp language_tag__36(rest, user_acc, [acc | stack], context, line, offset) do
    _ = user_acc

    language_tag__37(
      rest,
      [private_use: :lists.reverse(user_acc)] ++ acc,
      stack,
      context,
      line,
      offset
    )
  end

  defp language_tag__37(rest, acc, [_, previous_acc | stack], context, line, offset) do
    language_tag__1(rest, acc ++ previous_acc, stack, context, line, offset)
  end

  defp language_tag__38(_, _, [{rest, context, line, offset} | _] = stack, _, _, _) do
    language_tag__16(rest, [], stack, context, line, offset)
  end

  defp language_tag__39(rest, acc, stack, context, line, offset) do
    language_tag__40(rest, [], [acc | stack], context, line, offset)
  end

  defp language_tag__40(rest, acc, stack, context, line, offset) do
    language_tag__41(rest, [], [acc | stack], context, line, offset)
  end

  defp language_tag__41(rest, acc, stack, context, line, offset) do
    language_tag__42(rest, [], [acc | stack], context, line, offset)
  end

  defp language_tag__42(rest, acc, stack, context, line, offset) do
    language_tag__180(
      rest,
      [],
      [{rest, context, line, offset}, acc | stack],
      context,
      line,
      offset
    )
  end

  defp language_tag__44(rest, acc, stack, context, line, offset) do
    language_tag__45(rest, [], [acc | stack], context, line, offset)
  end

  defp language_tag__45(rest, acc, stack, context, line, offset) do
    language_tag__46(rest, [], [acc | stack], context, line, offset)
  end

  defp language_tag__46(
         <<x0::integer, x1::integer, rest::binary>>,
         acc,
         stack,
         context,
         comb__line,
         comb__offset
       )
       when ((x0 >= 97 and x0 <= 122) or (x0 >= 65 and x0 <= 90)) and
              ((x1 >= 97 and x1 <= 122) or (x1 >= 65 and x1 <= 90)) do
    language_tag__47(
      rest,
      [<<x0::integer, x1::integer>>] ++ acc,
      stack,
      context,
      comb__line,
      comb__offset + 2
    )
  end

  defp language_tag__46(rest, _acc, stack, context, line, offset) do
    [_, _, _, _, _, _, acc | stack] = stack
    language_tag__38(rest, acc, stack, context, line, offset)
  end

  defp language_tag__47(rest, acc, stack, context, line, offset) do
    language_tag__49(rest, acc, [1 | stack], context, line, offset)
  end

  defp language_tag__49(
         <<x0::integer, rest::binary>>,
         acc,
         stack,
         context,
         comb__line,
         comb__offset
       )
       when (x0 >= 97 and x0 <= 122) or (x0 >= 65 and x0 <= 90) do
    language_tag__50(rest, [x0] ++ acc, stack, context, comb__line, comb__offset + 1)
  end

  defp language_tag__49(rest, acc, stack, context, line, offset) do
    language_tag__48(rest, acc, stack, context, line, offset)
  end

  defp language_tag__48(rest, acc, [_ | stack], context, line, offset) do
    language_tag__51(rest, acc, stack, context, line, offset)
  end

  defp language_tag__50(rest, acc, [1 | stack], context, line, offset) do
    language_tag__51(rest, acc, stack, context, line, offset)
  end

  defp language_tag__50(rest, acc, [count | stack], context, line, offset) do
    language_tag__49(rest, acc, [count - 1 | stack], context, line, offset)
  end

  defp language_tag__51(rest, user_acc, [acc | stack], context, line, offset) do
    _ = user_acc

    language_tag__52(
      rest,
      [List.to_string(:lists.reverse(user_acc))] ++ acc,
      stack,
      context,
      line,
      offset
    )
  end

  defp language_tag__52(rest, user_acc, [acc | stack], context, line, offset) do
    _ = user_acc

    language_tag__53(
      rest,
      [
        language:
          case(:lists.reverse(user_acc)) do
            [one] ->
              one

            many ->
              raise("unwrap_and_tag/3 expected a single token, got: #{inspect(many)}")
          end
      ] ++ acc,
      stack,
      context,
      line,
      offset
    )
  end

  defp language_tag__53(rest, acc, stack, context, line, offset) do
    language_tag__57(
      rest,
      [],
      [{rest, context, line, offset}, acc | stack],
      context,
      line,
      offset
    )
  end

  defp language_tag__55(rest, acc, [_, previous_acc | stack], context, line, offset) do
    language_tag__54(rest, acc ++ previous_acc, stack, context, line, offset)
  end

  defp language_tag__56(_, _, [{rest, context, line, offset} | _] = stack, _, _, _) do
    language_tag__55(rest, [], stack, context, line, offset)
  end

  defp language_tag__57(
         <<x0::integer, rest::binary>>,
         acc,
         stack,
         context,
         comb__line,
         comb__offset
       )
       when x0 === 45 do
    language_tag__58(rest, [] ++ acc, stack, context, comb__line, comb__offset + 1)
  end

  defp language_tag__57(rest, acc, stack, context, line, offset) do
    language_tag__56(rest, acc, stack, context, line, offset)
  end

  defp language_tag__58(rest, acc, stack, context, line, offset) do
    language_tag__59(
      rest,
      [],
      [{rest, acc, context, line, offset} | stack],
      context,
      line,
      offset
    )
  end

  defp language_tag__59(rest, acc, stack, context, line, offset) do
    language_tag__61(rest, [], [acc | stack], context, line, offset)
  end

  defp language_tag__61(rest, acc, stack, context, line, offset) do
    language_tag__66(
      rest,
      [],
      [{rest, context, line, offset}, acc | stack],
      context,
      line,
      offset
    )
  end

  defp language_tag__63(
         <<x0::integer, x1::integer, x2::integer, x3::integer, rest::binary>>,
         acc,
         stack,
         context,
         comb__line,
         comb__offset
       )
       when x0 >= 48 and x0 <= 57 and
              ((x1 >= 97 and x1 <= 122) or (x1 >= 65 and x1 <= 90) or (x1 >= 48 and x1 <= 57)) and
              ((x2 >= 97 and x2 <= 122) or (x2 >= 65 and x2 <= 90) or (x2 >= 48 and x2 <= 57)) and
              ((x3 >= 97 and x3 <= 122) or (x3 >= 65 and x3 <= 90) or (x3 >= 48 and x3 <= 57)) do
    language_tag__64(
      rest,
      [Enum.join([<<x0::integer>>, <<x1::integer, x2::integer, x3::integer>>])] ++ acc,
      stack,
      context,
      comb__line,
      comb__offset + 4
    )
  end

  defp language_tag__63(rest, _acc, stack, context, line, offset) do
    [_, _, acc | stack] = stack
    language_tag__60(rest, acc, stack, context, line, offset)
  end

  defp language_tag__64(rest, acc, [_, previous_acc | stack], context, line, offset) do
    language_tag__62(rest, acc ++ previous_acc, stack, context, line, offset)
  end

  defp language_tag__65(_, _, [{rest, context, line, offset} | _] = stack, _, _, _) do
    language_tag__63(rest, [], stack, context, line, offset)
  end

  defp language_tag__66(rest, acc, stack, context, line, offset) do
    language_tag__67(rest, [], [acc | stack], context, line, offset)
  end

  defp language_tag__67(
         <<x0::integer, x1::integer, x2::integer, x3::integer, x4::integer, rest::binary>>,
         acc,
         stack,
         context,
         comb__line,
         comb__offset
       )
       when ((x0 >= 97 and x0 <= 122) or (x0 >= 65 and x0 <= 90) or (x0 >= 48 and x0 <= 57)) and
              ((x1 >= 97 and x1 <= 122) or (x1 >= 65 and x1 <= 90) or (x1 >= 48 and x1 <= 57)) and
              ((x2 >= 97 and x2 <= 122) or (x2 >= 65 and x2 <= 90) or (x2 >= 48 and x2 <= 57)) and
              ((x3 >= 97 and x3 <= 122) or (x3 >= 65 and x3 <= 90) or (x3 >= 48 and x3 <= 57)) and
              ((x4 >= 97 and x4 <= 122) or (x4 >= 65 and x4 <= 90) or (x4 >= 48 and x4 <= 57)) do
    language_tag__68(
      rest,
      [<<x0::integer, x1::integer, x2::integer, x3::integer, x4::integer>>] ++ acc,
      stack,
      context,
      comb__line,
      comb__offset + 5
    )
  end

  defp language_tag__67(rest, _acc, stack, context, line, offset) do
    [acc | stack] = stack
    language_tag__65(rest, acc, stack, context, line, offset)
  end

  defp language_tag__68(rest, acc, stack, context, line, offset) do
    language_tag__70(rest, acc, [3 | stack], context, line, offset)
  end

  defp language_tag__70(
         <<x0::integer, rest::binary>>,
         acc,
         stack,
         context,
         comb__line,
         comb__offset
       )
       when (x0 >= 97 and x0 <= 122) or (x0 >= 65 and x0 <= 90) or (x0 >= 48 and x0 <= 57) do
    language_tag__71(rest, [x0] ++ acc, stack, context, comb__line, comb__offset + 1)
  end

  defp language_tag__70(rest, acc, stack, context, line, offset) do
    language_tag__69(rest, acc, stack, context, line, offset)
  end

  defp language_tag__69(rest, acc, [_ | stack], context, line, offset) do
    language_tag__72(rest, acc, stack, context, line, offset)
  end

  defp language_tag__71(rest, acc, [1 | stack], context, line, offset) do
    language_tag__72(rest, acc, stack, context, line, offset)
  end

  defp language_tag__71(rest, acc, [count | stack], context, line, offset) do
    language_tag__70(rest, acc, [count - 1 | stack], context, line, offset)
  end

  defp language_tag__72(rest, user_acc, [acc | stack], context, line, offset) do
    _ = user_acc

    language_tag__73(
      rest,
      [List.to_string(:lists.reverse(user_acc))] ++ acc,
      stack,
      context,
      line,
      offset
    )
  end

  defp language_tag__73(rest, acc, [_, previous_acc | stack], context, line, offset) do
    language_tag__62(rest, acc ++ previous_acc, stack, context, line, offset)
  end

  defp language_tag__62(rest, user_acc, [acc | stack], context, line, offset) do
    _ = user_acc

    language_tag__74(
      rest,
      [
        language_variant:
          case(:lists.reverse(user_acc)) do
            [one] ->
              one

            many ->
              raise("unwrap_and_tag/3 expected a single token, got: #{inspect(many)}")
          end
      ] ++ acc,
      stack,
      context,
      line,
      offset
    )
  end

  defp language_tag__74(_, _, [{rest, acc, context, line, offset} | stack], _, _, _) do
    language_tag__56(rest, acc, stack, context, line, offset)
  end

  defp language_tag__60(_, _, [{rest, acc, context, line, offset} | stack], _, _, _) do
    language_tag__75(rest, acc, stack, context, line, offset)
  end

  defp language_tag__75(rest, acc, stack, context, line, offset) do
    language_tag__155(
      rest,
      [],
      [{rest, context, line, offset}, acc | stack],
      context,
      line,
      offset
    )
  end

  defp language_tag__77(
         <<x0::integer, x1::integer, x2::integer, rest::binary>>,
         acc,
         stack,
         context,
         comb__line,
         comb__offset
       )
       when ((x0 >= 97 and x0 <= 122) or (x0 >= 65 and x0 <= 90)) and
              ((x1 >= 97 and x1 <= 122) or (x1 >= 65 and x1 <= 90)) and
              ((x2 >= 97 and x2 <= 122) or (x2 >= 65 and x2 <= 90)) do
    language_tag__78(
      rest,
      [language_subtags: [<<x0::integer, x1::integer, x2::integer>>]] ++ acc,
      stack,
      context,
      comb__line,
      comb__offset + 3
    )
  end

  defp language_tag__77(rest, _acc, stack, context, line, offset) do
    [_, acc | stack] = stack
    language_tag__56(rest, acc, stack, context, line, offset)
  end

  defp language_tag__78(rest, acc, [_, previous_acc | stack], context, line, offset) do
    language_tag__76(rest, acc ++ previous_acc, stack, context, line, offset)
  end

  defp language_tag__79(_, _, [{rest, context, line, offset} | _] = stack, _, _, _) do
    language_tag__77(rest, [], stack, context, line, offset)
  end

  defp language_tag__80(
         <<x0::integer, x1::integer, x2::integer, x3::integer, x4::integer, x5::integer,
           x6::integer, rest::binary>>,
         acc,
         stack,
         context,
         comb__line,
         comb__offset
       )
       when ((x0 >= 97 and x0 <= 122) or (x0 >= 65 and x0 <= 90)) and
              ((x1 >= 97 and x1 <= 122) or (x1 >= 65 and x1 <= 90)) and
              ((x2 >= 97 and x2 <= 122) or (x2 >= 65 and x2 <= 90)) and x3 === 45 and
              ((x4 >= 97 and x4 <= 122) or (x4 >= 65 and x4 <= 90)) and
              ((x5 >= 97 and x5 <= 122) or (x5 >= 65 and x5 <= 90)) and
              ((x6 >= 97 and x6 <= 122) or (x6 >= 65 and x6 <= 90)) do
    language_tag__81(
      rest,
      [<<x4::integer, x5::integer, x6::integer>>, <<x0::integer, x1::integer, x2::integer>>] ++
        acc,
      stack,
      context,
      comb__line,
      comb__offset + 7
    )
  end

  defp language_tag__80(rest, acc, stack, context, line, offset) do
    language_tag__79(rest, acc, stack, context, line, offset)
  end

  defp language_tag__81(rest, acc, [_, previous_acc | stack], context, line, offset) do
    language_tag__76(rest, acc ++ previous_acc, stack, context, line, offset)
  end

  defp language_tag__82(_, _, [{rest, context, line, offset} | _] = stack, _, _, _) do
    language_tag__80(rest, [], stack, context, line, offset)
  end

  defp language_tag__83(
         <<x0::integer, x1::integer, x2::integer, x3::integer, x4::integer, x5::integer,
           x6::integer, x7::integer, x8::integer, x9::integer, x10::integer, rest::binary>>,
         acc,
         stack,
         context,
         comb__line,
         comb__offset
       )
       when ((x0 >= 97 and x0 <= 122) or (x0 >= 65 and x0 <= 90)) and
              ((x1 >= 97 and x1 <= 122) or (x1 >= 65 and x1 <= 90)) and
              ((x2 >= 97 and x2 <= 122) or (x2 >= 65 and x2 <= 90)) and x3 === 45 and
              ((x4 >= 97 and x4 <= 122) or (x4 >= 65 and x4 <= 90)) and
              ((x5 >= 97 and x5 <= 122) or (x5 >= 65 and x5 <= 90)) and
              ((x6 >= 97 and x6 <= 122) or (x6 >= 65 and x6 <= 90)) and x7 === 45 and
              ((x8 >= 97 and x8 <= 122) or (x8 >= 65 and x8 <= 90)) and
              ((x9 >= 97 and x9 <= 122) or (x9 >= 65 and x9 <= 90)) and
              ((x10 >= 97 and x10 <= 122) or (x10 >= 65 and x10 <= 90)) do
    language_tag__84(
      rest,
      [
        <<x8::integer, x9::integer, x10::integer>>,
        <<x4::integer, x5::integer, x6::integer>>,
        <<x0::integer, x1::integer, x2::integer>>
      ] ++ acc,
      stack,
      context,
      comb__line,
      comb__offset + 11
    )
  end

  defp language_tag__83(rest, acc, stack, context, line, offset) do
    language_tag__82(rest, acc, stack, context, line, offset)
  end

  defp language_tag__84(rest, acc, [_, previous_acc | stack], context, line, offset) do
    language_tag__76(rest, acc ++ previous_acc, stack, context, line, offset)
  end

  defp language_tag__85(_, _, [{rest, context, line, offset} | _] = stack, _, _, _) do
    language_tag__83(rest, [], stack, context, line, offset)
  end

  defp language_tag__86(
         <<x0::integer, x1::integer, x2::integer, x3::integer, rest::binary>>,
         acc,
         stack,
         context,
         comb__line,
         comb__offset
       )
       when ((x0 >= 97 and x0 <= 122) or (x0 >= 65 and x0 <= 90)) and
              ((x1 >= 97 and x1 <= 122) or (x1 >= 65 and x1 <= 90)) and
              ((x2 >= 97 and x2 <= 122) or (x2 >= 65 and x2 <= 90)) and x3 === 45 do
    language_tag__87(
      rest,
      [language_subtags: [<<x0::integer, x1::integer, x2::integer>>]] ++ acc,
      stack,
      context,
      comb__line,
      comb__offset + 4
    )
  end

  defp language_tag__86(rest, acc, stack, context, line, offset) do
    language_tag__85(rest, acc, stack, context, line, offset)
  end

  defp language_tag__87(rest, acc, stack, context, line, offset) do
    language_tag__88(rest, [], [acc | stack], context, line, offset)
  end

  defp language_tag__88(rest, acc, stack, context, line, offset) do
    language_tag__89(
      rest,
      [],
      [{rest, acc, context, line, offset} | stack],
      context,
      line,
      offset
    )
  end

  defp language_tag__89(rest, acc, stack, context, line, offset) do
    language_tag__91(rest, [], [acc | stack], context, line, offset)
  end

  defp language_tag__91(rest, acc, stack, context, line, offset) do
    language_tag__96(
      rest,
      [],
      [{rest, context, line, offset}, acc | stack],
      context,
      line,
      offset
    )
  end

  defp language_tag__93(
         <<x0::integer, x1::integer, x2::integer, x3::integer, rest::binary>>,
         acc,
         stack,
         context,
         comb__line,
         comb__offset
       )
       when x0 >= 48 and x0 <= 57 and
              ((x1 >= 97 and x1 <= 122) or (x1 >= 65 and x1 <= 90) or (x1 >= 48 and x1 <= 57)) and
              ((x2 >= 97 and x2 <= 122) or (x2 >= 65 and x2 <= 90) or (x2 >= 48 and x2 <= 57)) and
              ((x3 >= 97 and x3 <= 122) or (x3 >= 65 and x3 <= 90) or (x3 >= 48 and x3 <= 57)) do
    language_tag__94(
      rest,
      [Enum.join([<<x0::integer>>, <<x1::integer, x2::integer, x3::integer>>])] ++ acc,
      stack,
      context,
      comb__line,
      comb__offset + 4
    )
  end

  defp language_tag__93(rest, _acc, stack, context, line, offset) do
    [_, _, acc | stack] = stack
    language_tag__90(rest, acc, stack, context, line, offset)
  end

  defp language_tag__94(rest, acc, [_, previous_acc | stack], context, line, offset) do
    language_tag__92(rest, acc ++ previous_acc, stack, context, line, offset)
  end

  defp language_tag__95(_, _, [{rest, context, line, offset} | _] = stack, _, _, _) do
    language_tag__93(rest, [], stack, context, line, offset)
  end

  defp language_tag__96(rest, acc, stack, context, line, offset) do
    language_tag__97(rest, [], [acc | stack], context, line, offset)
  end

  defp language_tag__97(
         <<x0::integer, x1::integer, x2::integer, x3::integer, x4::integer, rest::binary>>,
         acc,
         stack,
         context,
         comb__line,
         comb__offset
       )
       when ((x0 >= 97 and x0 <= 122) or (x0 >= 65 and x0 <= 90) or (x0 >= 48 and x0 <= 57)) and
              ((x1 >= 97 and x1 <= 122) or (x1 >= 65 and x1 <= 90) or (x1 >= 48 and x1 <= 57)) and
              ((x2 >= 97 and x2 <= 122) or (x2 >= 65 and x2 <= 90) or (x2 >= 48 and x2 <= 57)) and
              ((x3 >= 97 and x3 <= 122) or (x3 >= 65 and x3 <= 90) or (x3 >= 48 and x3 <= 57)) and
              ((x4 >= 97 and x4 <= 122) or (x4 >= 65 and x4 <= 90) or (x4 >= 48 and x4 <= 57)) do
    language_tag__98(
      rest,
      [<<x0::integer, x1::integer, x2::integer, x3::integer, x4::integer>>] ++ acc,
      stack,
      context,
      comb__line,
      comb__offset + 5
    )
  end

  defp language_tag__97(rest, _acc, stack, context, line, offset) do
    [acc | stack] = stack
    language_tag__95(rest, acc, stack, context, line, offset)
  end

  defp language_tag__98(rest, acc, stack, context, line, offset) do
    language_tag__100(rest, acc, [3 | stack], context, line, offset)
  end

  defp language_tag__100(
         <<x0::integer, rest::binary>>,
         acc,
         stack,
         context,
         comb__line,
         comb__offset
       )
       when (x0 >= 97 and x0 <= 122) or (x0 >= 65 and x0 <= 90) or (x0 >= 48 and x0 <= 57) do
    language_tag__101(rest, [x0] ++ acc, stack, context, comb__line, comb__offset + 1)
  end

  defp language_tag__100(rest, acc, stack, context, line, offset) do
    language_tag__99(rest, acc, stack, context, line, offset)
  end

  defp language_tag__99(rest, acc, [_ | stack], context, line, offset) do
    language_tag__102(rest, acc, stack, context, line, offset)
  end

  defp language_tag__101(rest, acc, [1 | stack], context, line, offset) do
    language_tag__102(rest, acc, stack, context, line, offset)
  end

  defp language_tag__101(rest, acc, [count | stack], context, line, offset) do
    language_tag__100(rest, acc, [count - 1 | stack], context, line, offset)
  end

  defp language_tag__102(rest, user_acc, [acc | stack], context, line, offset) do
    _ = user_acc

    language_tag__103(
      rest,
      [List.to_string(:lists.reverse(user_acc))] ++ acc,
      stack,
      context,
      line,
      offset
    )
  end

  defp language_tag__103(rest, acc, [_, previous_acc | stack], context, line, offset) do
    language_tag__92(rest, acc ++ previous_acc, stack, context, line, offset)
  end

  defp language_tag__92(rest, user_acc, [acc | stack], context, line, offset) do
    _ = user_acc

    language_tag__104(
      rest,
      [
        language_variant:
          case(:lists.reverse(user_acc)) do
            [one] ->
              one

            many ->
              raise("unwrap_and_tag/3 expected a single token, got: #{inspect(many)}")
          end
      ] ++ acc,
      stack,
      context,
      line,
      offset
    )
  end

  defp language_tag__104(_, _, [{rest, _acc, context, line, offset} | stack], _, _, _) do
    [acc | stack] = stack
    language_tag__85(rest, acc, stack, context, line, offset)
  end

  defp language_tag__90(_, _, [{rest, acc, context, line, offset} | stack], _, _, _) do
    language_tag__105(rest, acc, stack, context, line, offset)
  end

  defp language_tag__105(
         <<x0::integer, x1::integer, x2::integer, x3::integer, rest::binary>>,
         acc,
         stack,
         context,
         comb__line,
         comb__offset
       )
       when ((x0 >= 97 and x0 <= 122) or (x0 >= 65 and x0 <= 90)) and
              ((x1 >= 97 and x1 <= 122) or (x1 >= 65 and x1 <= 90)) and
              ((x2 >= 97 and x2 <= 122) or (x2 >= 65 and x2 <= 90)) and
              ((x3 >= 97 and x3 <= 122) or (x3 >= 65 and x3 <= 90)) do
    language_tag__106(
      rest,
      [<<x0::integer, x1::integer, x2::integer, x3::integer>>] ++ acc,
      stack,
      context,
      comb__line,
      comb__offset + 4
    )
  end

  defp language_tag__105(rest, _acc, stack, context, line, offset) do
    [acc | stack] = stack
    language_tag__85(rest, acc, stack, context, line, offset)
  end

  defp language_tag__106(rest, user_acc, [acc | stack], context, line, offset) do
    _ = user_acc

    language_tag__107(
      rest,
      [
        script:
          case(:lists.reverse(user_acc)) do
            [one] ->
              one

            many ->
              raise("unwrap_and_tag/3 expected a single token, got: #{inspect(many)}")
          end
      ] ++ acc,
      stack,
      context,
      line,
      offset
    )
  end

  defp language_tag__107(rest, acc, [_, previous_acc | stack], context, line, offset) do
    language_tag__76(rest, acc ++ previous_acc, stack, context, line, offset)
  end

  defp language_tag__108(_, _, [{rest, context, line, offset} | _] = stack, _, _, _) do
    language_tag__86(rest, [], stack, context, line, offset)
  end

  defp language_tag__109(
         <<x0::integer, x1::integer, x2::integer, x3::integer, x4::integer, x5::integer,
           x6::integer, x7::integer, rest::binary>>,
         acc,
         stack,
         context,
         comb__line,
         comb__offset
       )
       when ((x0 >= 97 and x0 <= 122) or (x0 >= 65 and x0 <= 90)) and
              ((x1 >= 97 and x1 <= 122) or (x1 >= 65 and x1 <= 90)) and
              ((x2 >= 97 and x2 <= 122) or (x2 >= 65 and x2 <= 90)) and x3 === 45 and
              ((x4 >= 97 and x4 <= 122) or (x4