# po_parser.rb - Generate a .mo
#
# Copyright (C) 2003-2009 Masao Mutoh <mutomasa at gmail.com>
# Copyright (C) 2012-2023 Sutou Kouhei <kou@clear-code.com>
#
# You may redistribute it and/or modify it under the same
# license terms as Ruby or LGPL.

#
# DO NOT MODIFY!!!!
# This file is automatically generated by Racc 1.7.1
# from Racc grammar file "".
#

require 'racc/parser.rb'

require "gettext/po"

module GetText
  class POParser < Racc::Parser

module_eval(<<'...end po_parser.ry/module_eval...', 'po_parser.ry', 126)
  if GetText.respond_to?(:bindtextdomain)
    include GetText
    GetText.bindtextdomain("gettext")
  else
    def _(message_id)
      message_id
    end
    private :_
  end

  attr_writer :ignore_fuzzy, :report_warning
  def initialize
    @ignore_fuzzy = true
    @report_warning = true
  end

  def ignore_fuzzy?
    @ignore_fuzzy
  end

  def report_warning?
    @report_warning
  end

  def unescape(string)
    string.gsub(/\\(.)/) do
      escaped_character = $1
      case escaped_character
      when "t"
        "\t"
      when "r"
        "\r"
      when "n"
        "\n"
      else
        escaped_character
      end
    end
  end
  private :unescape

  def parse(str, data)
    clear
    @data = data

    str = str.strip
    @q = []
    until str.empty? do
      case str
      when /\A\s+/
        str = $'
      when /\Amsgctxt/
        @q.push [:MSGCTXT, $&]
        str = $'
      when /\Amsgid_plural/
        @q.push [:MSGID_PLURAL, $&]
        str = $'
      when /\Amsgid/
        @q.push [:MSGID, $&]
        str = $'
      when /\Amsgstr/
        @q.push [:MSGSTR, $&]
        str = $'
      when /\A\[(\d+)\]/
        @q.push [:PLURAL_NUM, $1]
        str = $'
      when /\A\#~(.*)/
        if report_warning?
          $stderr.print _("Warning: obsolete msgid exists.\n")
          $stderr.print "         #{$&}\n"
        end
        @q.push [:COMMENT, $&]
        str = $'
      when /\A\#(.*)/
        @q.push [:COMMENT, $&]
        str = $'
      when /\A\"(.*)\"/
        @q.push [:STRING, unescape($1)]
        str = $'
      else
        #c = str[0,1]
        #@q.push [:STRING, c]
        str = str[1..-1]
      end
    end
    @q.push [false, "$end"]
    if $DEBUG
      @q.each do |a,b|
      puts "[#{a}, #{b}]"
      end
    end
    @yydebug = true if $DEBUG
    do_parse

    if @comments.size > 0
      @data.set_comment(:last, @comments.join("\n"))
    end
    @data
  end

  def next_token
    @q.shift
  end

  def on_message(msgid, msgstr)
    msgstr = nil if msgstr.empty?

    if @data.instance_of?(PO)
      type = detect_entry_type
      entry = POEntry.new(type)
      entry.translator_comment = format_comment(@translator_comments)
      entry.extracted_comment = format_comment(@extracted_comments)
      entry.flags = @flags
      entry.previous = format_comment(@previous)
      entry.references = @references
      entry.msgctxt = @msgctxt
      entry.msgid = msgid
      entry.msgid_plural = @msgid_plural
      entry.msgstr = msgstr

      @data[@msgctxt, msgid] = entry
    else
      options = {}
      options[:msgctxt] = @msgctxt
      options[:msgid_plural] = @msgid_plural
      @data.store(msgid, msgstr, options)
      @data.set_comment(msgid, format_comment(@comments))
    end

    clear
  end

  def format_comment(comments)
    return "" if comments.empty?

    comment = comments.join("\n")
    comment << "\n" if comments.last.empty?
    comment
  end

  def on_comment(comment)
    @fuzzy = true if (/fuzzy/ =~ comment)
    if @data.instance_of?(PO)
      if comment == "#"
        @translator_comments << ""
      elsif /\A(#.)\s*(.*)\z/ =~ comment
        mark = $1
        content = $2
        case mark
        when POFormat::TRANSLATOR_COMMENT_MARK
          @translator_comments << content
        when POFormat::EXTRACTED_COMMENT_MARK
          @extracted_comments << content
        when POFormat::REFERENCE_COMMENT_MARK
          @references.concat(parse_references_line(content))
        when POFormat::FLAG_MARK
          @flags.concat(parse_flags_line(content))
        when POFormat::PREVIOUS_COMMENT_MARK
          @previous << content
        else
          @comments << comment
        end
      end
    else
      @comments << comment
    end
  end

  def parse_file(po_file, data)
    args = [ po_file ]
    # In Ruby 1.9, we must detect proper encoding of a PO file.
    if String.instance_methods.include?(:encode)
      encoding = detect_file_encoding(po_file)
      args << "r:#{encoding}"
    end
    @po_file = po_file
    parse(File.open(*args) {|io| io.read }, data)
  end

  private
  def detect_file_encoding(po_file)
    open(po_file, :encoding => "ASCII-8BIT") do |input|
      in_header = false
      input.each_line do |line|
        case line.chomp
        when /\Amsgid\s+"(.*)"\z/
          id = $1
          break unless id.empty?
          in_header = true
        when /\A"Content-Type:.*\scharset=(.*)\\n"\z/
          charset = $1
          next unless in_header
          break if template_charset?(charset)
          return Encoding.find(charset)
        end
      end
    end
    Encoding.default_external
  end

  def template_charset?(charset)
    charset == "CHARSET"
  end

  def detect_entry_type
    if @msgctxt.nil?
      if @msgid_plural.nil?
        :normal
      else
        :plural
      end
    else
      if @msgid_plural.nil?
        :msgctxt
      else
        :msgctxt_plural
      end
    end
  end

  def parse_references_line(line)
    line.split(/\s+/)
  end

  def parse_flags_line(line)
    line.split(/\s+/)
  end

  def clear
    @translator_comments = []
    @extracted_comments = []
    @references = []
    @flags = []
    @previous = []
    @references = []
    @comments = []
    @msgctxt = nil
    @msgid_plural = nil
  end
...end po_parser.ry/module_eval...
##### State transition tables begin ###

racc_action_table = [
     2,    11,    10,     9,     6,    17,    16,    15,    22,    15,
    13,    13,    15,    13,    13,    15,    22,    24,    13,    15 ]

racc_action_check = [
     1,     2,     1,     1,     1,    14,    14,    14,    19,    19,
     6,     9,    12,    16,    17,    18,    20,    22,    24,    25 ]

racc_action_pointer = [
   nil,     0,     1,   nil,   nil,   nil,     3,   nil,   nil,     4,
   nil,   nil,     5,   nil,     0,   nil,     6,     7,     8,     2,
    10,   nil,     9,   nil,    11,    12 ]

racc_action_default = [
    -1,   -16,   -16,    -2,    -3,    -4,   -16,    -6,    -7,   -16,
   -13,    26,    -5,   -15,   -16,   -14,   -16,   -16,    -8,   -16,
    -9,   -11,   -16,   -10,   -16,   -12 ]

racc_goto_table = [
    12,    21,    23,    14,     1,     3,     4,     5,     7,     8,
    18,    19,    20,   nil,   nil,   nil,   nil,   nil,    25 ]

racc_goto_check = [
     5,     9,     9,     5,     1,     2,     3,     4,     6,     7,
     5,     5,     8,   nil,   nil,   nil,   nil,   nil,     5 ]

racc_goto_pointer = [
   nil,     4,     4,     5,     6,    -6,     7,     8,    -7,   -18 ]

racc_goto_default = [
   nil,   nil,   nil,   nil,   nil,   nil,   nil,   nil,   nil,   nil ]

racc_reduce_table = [
  0, 0, :racc_error,
  0, 10, :_reduce_none,
  2, 10, :_reduce_none,
  2, 10, :_reduce_none,
  2, 10, :_reduce_none,
  2, 12, :_reduce_5,
  1, 13, :_reduce_none,
  1, 13, :_reduce_none,
  4, 15, :_reduce_8,
  5, 16, :_reduce_9,
  2, 17, :_reduce_10,
  1, 17, :_reduce_none,
  3, 18, :_reduce_12,
  1, 11, :_reduce_13,
  2, 14, :_reduce_14,
  1, 14, :_reduce_15 ]

racc_reduce_n = 16

racc_shift_n = 26

racc_token_table = {
  false => 0,
  :error => 1,
  :COMMENT => 2,
  :MSGID => 3,
  :MSGCTXT => 4,
  :MSGID_PLURAL => 5,
  :MSGSTR => 6,
  :STRING => 7,
  :PLURAL_NUM => 8 }

racc_nt_base = 9

racc_use_result_var = true

Racc_arg = [
  racc_action_table,
  racc_action_check,
  racc_action_default,
  racc_action_pointer,
  racc_goto_table,
  racc_goto_check,
  racc_goto_default,
  racc_goto_pointer,
  racc_nt_base,
  racc_reduce_table,
  racc_token_table,
  racc_shift_n,
  racc_reduce_n,
  racc_use_result_var ]
Ractor.make_shareable(Racc_arg) if defined?(Ractor)

Racc_token_to_s_table = [
  "$end",
  "error",
  "COMMENT",
  "MSGID",
  "MSGCTXT",
  "MSGID_PLURAL",
  "MSGSTR",
  "STRING",
  "PLURAL_NUM",
  "$start",
  "msgfmt",
  "comment",
  "msgctxt",
  "message",
  "string_list",
  "single_message",
  "plural_message",
  "msgstr_plural",
  "msgstr_plural_line" ]
Ractor.make_shareable(Racc_token_to_s_table) if defined?(Ractor)

Racc_debug_parser = true

##### State transition tables end #####

# reduce 0 omitted

# reduce 1 omitted

# reduce 2 omitted

# reduce 3 omitted

# reduce 4 omitted

module_eval(<<'.,.,', 'po_parser.ry', 26)
  def _reduce_5(val, _values, result)
        @msgctxt = val[1]

    result
  end
.,.,

# reduce 6 omitted

# reduce 7 omitted

module_eval(<<'.,.,', 'po_parser.ry', 38)
  def _reduce_8(val, _values, result)
        msgid = val[1]
    msgstr = val[3]
    use_message_p = true
    if @fuzzy and not msgid.empty?
      use_message_p = (not ignore_fuzzy?)
      if report_warning?
        if ignore_fuzzy?
          $stderr.print _("Warning: fuzzy message was ignored.\n")
        else
          $stderr.print _("Warning: fuzzy message was used.\n")
        end
        $stderr.print "  #{@po_file}: msgid '#{msgid}'\n"
      end
    end
    @fuzzy = false
    if use_message_p
      on_message(msgid, msgstr)
    else
      clear
    end
    result = ""

    result
  end
.,.,

module_eval(<<'.,.,', 'po_parser.ry', 64)
  def _reduce_9(val, _values, result)
        if @fuzzy and ignore_fuzzy?
      if val[1] != ""
        if report_warning?
          $stderr.print _("Warning: fuzzy message was ignored.\n")
          $stderr.print "msgid = '#{val[1]}\n"
        end
      else
        on_message("", unescape(val[3]))
      end
      @fuzzy = false
    else
      @msgid_plural = unescape(val[3])
      on_message(unescape(val[1]), unescape(val[4]))
    end
    result = ""

    result
  end
.,.,

module_eval(<<'.,.,', 'po_parser.ry', 85)
  def _reduce_10(val, _values, result)
        if val[0].size > 0
      result = val[0] + "\000" + val[1]
    else
      result = ""
    end

    result
  end
.,.,

# reduce 11 omitted

module_eval(<<'.,.,', 'po_parser.ry', 97)
  def _reduce_12(val, _values, result)
        result = val[2]

    result
  end
.,.,

module_eval(<<'.,.,', 'po_parser.ry', 104)
  def _reduce_13(val, _values, result)
        on_comment(val[0])

    result
  end
.,.,

module_eval(<<'.,.,', 'po_parser.ry', 112)
  def _reduce_14(val, _values, result)
        result = val.delete_if{|item| item == ""}.join

    result
  end
.,.,

module_eval(<<'.,.,', 'po_parser.ry', 116)
  def _reduce_15(val, _values, result)
        result = val[0]

    result
  end
.,.,

def _reduce_none(val, _values, result)
  val[0]
end

  end   # class POParser
end   # module GetText


