class ChineseNumber::Parser

Constants

ARABIC_NUMBER
DIGIT_MAP
DIGIT_TOKEN
MULTIPERS
MULTIPER_TOKEN
TOKEN

Attributes

parts[R]

Public Class Methods

generate_base_map() click to toggle source
# File lib/chinese_number/parser.rb, line 9
def self.generate_base_map
  chinese_numbers = "一两二三四五六七八九〇零".chars
  digits          = "122345678900".chars.map(&:to_i)
  Hash.new.tap do |map|
    chinese_numbers.each_with_index do |w, i|
      d      = digits[i]
      map[w] = map[d.to_s] = d
    end
  end
end
generate_multipers_map() click to toggle source
# File lib/chinese_number/parser.rb, line 20
def self.generate_multipers_map
  {
    '十' => 10,
    '百' => 100,
    '千' => 1000,
    '万' => 10000,

    # “兆” 在各处有不同的意义
    # 可能是 “百万”、“万亿”或“万万亿”
    # see:
    # http://zh.wikipedia.org/wiki/%E5%85%86
    #
    # 你可以通过这样的方式修改成需要的含义:
    #
    #   ChineseNumber::Parser::MULTIPERS['兆'] = 10000_0000_0000
    '兆' => 100_0000,

    '亿' => 10000_0000
  }
end

Public Instance Methods

parse(word) click to toggle source
# File lib/chinese_number/parser.rb, line 48
def parse word
  
  raise InvalidWord unless word =~ /\A#{TOKEN}\Z/

  # 类似“二零一二” 这种短语,可以直接拼数字返回
  unless word =~ MULTIPER_TOKEN
    return word.gsub(/\S/) {|w| DIGIT_MAP[w]}.to_i
  end

  @scanner = StringScanner.new( word )
  @parts   = []

  while w = @scanner.scan( /\S/ )
    case w
    when ARABIC_NUMBER
      if @scanner.check(ARABIC_NUMBER)
        w << @scanner.scan( /\d+/ )
        handle_digit w.to_i
      else
        handle_digit DIGIT_MAP[w]
      end
    when DIGIT_TOKEN
      handle_digit DIGIT_MAP[w]
    when MULTIPER_TOKEN
      handle_multiper MULTIPERS[w]
    else
      raise UnexpectToken.new(w)
    end
  end

  parts.reduce(0) do |sum, part|
    sum + part.to_i
  end
end

Private Instance Methods

handle_digit(num) click to toggle source
# File lib/chinese_number/parser.rb, line 85
def handle_digit num
  # 此处处理省略倍数的情况,例如
  # "一万五"、"八万八"
  if @scanner.eos? && parts.last && parts.last.factor >= 10
    parts << MultipedNum.new( num, parts.last.factor / 10 )
  else
    parts << MultipedNum.new( num, 1 )
  end
end
handle_multiper(multiper) click to toggle source
# File lib/chinese_number/parser.rb, line 95
def handle_multiper multiper
  if parts.empty?
    parts << MultipedNum.new( 1, 1 )
  end

  if parts.last.factor <= multiper
    parts.each do |part|
      if part.factor <= multiper
        part.factor *= multiper
      end
    end
  else
    parts << MultipedNum.new( 1, multiper )
  end
end