#
#  poparser.ry - ruby version of msgfmt
#
#  Copyright (C) 2002-2005 Masao Mutoh <mutoh@highway.ne.jp>
# 
#  You may redistribute it and/or modify it under the same
#  license terms as Ruby.

class GetText::PoParser 

  token COMMENT MSGID MSGID_PLURAL MSGSTR STRING PLURAL_NUM

  rule

  msgfmt
  : /* empty */
  | msgfmt comment
  | msgfmt message
  ;

  message
  : MSGID string_list MSGSTR string_list
  {
    if @fuzzy and $ignore_fuzzy 
      if val[1] != ""
        $stderr.print _("Warning: fuzzy message was ignored.\n")
        $stderr.print "         msgid '#{val[1]}'\n"
      else
        on_message('', unescape(val[3]))
      end
      @fuzzy = false
    else
      on_message(unescape(val[1]), unescape(val[3]))
    end
    result = ""
  }
  | MSGID string_list MSGID_PLURAL string_list msgstr_plural
  {
    if @fuzzy and $ignore_fuzzy
      if val[1] != ""
        $stderr.print _("Warning: fuzzy message was ignored.\n")
        $stderr.print "msgid = '#{val[1]}\n"
      else
        on_message('', unescape(val[3]))
      end
      @fuzzy = false
    else
      on_message(unescape(val[1]) + "\000" + unescape(val[3]), unescape(val[4]))
    end
    result = ""
  }
  ;

  msgstr_plural
  : msgstr_plural msgstr_plural_line
  {
    result = val[0] + "\000" + val[1]
  }
  | msgstr_plural_line
  ;
  
  msgstr_plural_line
  : MSGSTR PLURAL_NUM string_list
  {
    result = val[2]
  }
  ;

  comment
  : COMMENT 
  {
    on_comment(val[0])
  }
  #| COMMENT
  #;

  string_list
  : string_list STRING
  {
    result = val.delete_if{|item| item == ""}.join
  }
  | STRING
  {
    result = val[0]
  }
  ;
end

---- inner
  include GetText
  GetText.bindtextdomain("rgettext")

  def unescape(orig)
    ret = orig.gsub(/\\n/, "\n")
    ret.gsub!(/\\t/, "\t")
    ret.gsub!(/\\r/, "\r")
    ret.gsub!(/\\"/, "\"")
    ret
  end
  
  def parse(str, data, ignore_fuzzy = true)
    @comments = []
    @data = data
    @fuzzy = false
    $ignore_fuzzy = ignore_fuzzy
    str.strip!
    @q = []
    until str.empty? do
      case str
      when /\A\s+/
	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\#~(.*)/
	$stderr.print _("Warning: obsolete msgid exists.\n")
	$stderr.print "         #{$&}\n"
	@q.push [:COMMENT, $&]
	str = $'
      when /\A\#(.*)/
	@q.push [:COMMENT, $&]
	str = $'      
      when /\A\"(.*)\"/
	@q.push [:STRING, $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)
    @data[msgid] = msgstr
 
    @data.set_comment(msgid, @comments.join("\n"))
    @comments.clear
  end
      
  def on_comment(comment)
    @fuzzy = true if (/fuzzy/ =~ comment)
    @comments << comment
  end 

---- footer
