Last active
August 29, 2015 14:05
-
-
Save rummelonp/c9c06ff53822b6f69725 to your computer and use it in GitHub Desktop.
Parslet で漢数字を Int にするやつ
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
require 'parslet' | |
module Kansuji | |
NUMBERS = %w{一 二 三 四 五 六 七 八 九} | |
DIGITS = %w{十 百 千} | |
UNITS = %w{万 億 兆 京 垓 𥝱 穣 溝 澗 正 載 極 恒河沙 阿僧祇 那由他 不可思議 無量大数} | |
def self.parser | |
@parser ||= Parser.new | |
end | |
def self.transform | |
@transform ||= Transform.new | |
end | |
def self.parse(text) | |
transform.apply( | |
parser.parse( | |
text | |
) | |
) | |
end | |
class Parser < Parslet::Parser | |
root(:expressions) | |
rule(:expressions) { | |
( | |
expression >> unit.maybe >> expressions.maybe | | |
expression | |
).as(:expressions) | |
} | |
rule(:expression) { | |
( | |
number.maybe >> digit >> expression.maybe | | |
number | |
).as(:expression) | |
} | |
rule(:number) { | |
alternative_str(NUMBERS).as(:number) | |
} | |
rule(:digit) { | |
alternative_str(DIGITS).as(:digit) | |
} | |
rule(:unit) { | |
alternative_str(UNITS).as(:unit) | |
} | |
def alternative_str(values) | |
values.map { |value| | |
str(value) | |
}.reduce { |alternatives, parslet| | |
alternatives | parslet | |
} | |
end | |
end | |
class Transform < Parslet::Transform | |
rule(expressions: simple(:expressions)) { | |
expressions | |
} | |
rule(expression: simple(:expression)) { | |
expression | |
} | |
rule(number: simple(:number)) { | |
Number.new(number).to_i | |
} | |
rule(digit: simple(:digit)) { | |
Digit.new(digit).to_i | |
} | |
rule(number: simple(:number), digit: simple(:digit)) { | |
Number.new(number).to_i * Digit.new(digit).to_i | |
} | |
rule(digit: simple(:digit), expression: simple(:expression)) { | |
Digit.new(digit).to_i + expression | |
} | |
rule(number: simple(:number), digit: simple(:digit), expression: simple(:expression)) { | |
Number.new(number).to_i * Digit.new(digit).to_i + expression | |
} | |
rule(expression: simple(:expression), unit: simple(:unit), expressions: simple(:expressions)) { | |
expression * Unit.new(unit).to_i + expressions | |
} | |
end | |
class Number < Struct.new(:number) | |
def to_i | |
NUMBERS.index(number) + 1 | |
end | |
end | |
class Digit < Struct.new(:digit) | |
def to_i | |
10 ** (DIGITS.index(digit) + 1) | |
end | |
end | |
class Unit < Struct.new(:unit) | |
def to_i | |
10_000 ** (UNITS.index(unit) + 1) | |
end | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
参考: 漢数字を数値に変換する(rparsec版) - terazzoの日記