class Diachronr::Rule
rule for applying a single sound change
Attributes
condition[RW]
from[RW]
to[RW]
Public Class Methods
new(rule)
click to toggle source
# File lib/diachronr/rule.rb, line 10 def initialize(rule) @from, @to, @condition = rule.split '/' end
Public Instance Methods
apply(target, options = {})
click to toggle source
# File lib/diachronr/rule.rb, line 84 def apply(target, options = {}) categories = options[:categories] || [] return apply_categories target, categories if category? categories # construct regex from condition from_condition = @condition.gsub '_', @from to_condition = @condition.gsub '_', @to # change word boundaries to regex from_condition = Regexp.new from_condition.gsub('#', '\b') to_condition.delete! '#' # split on from_condition and join with to_condition # if you need a limit higher than 10.... nope split_target = target.split from_condition, 10 split_target.join to_condition end
apply_categories(target, categories)
click to toggle source
# File lib/diachronr/rule.rb, line 73 def apply_categories(target, categories) # parse categories, apply each exploded rule to the original target # merge the changes together rules = category_rules(categories) + condition_rules(categories) matches = rules.map { |r| r.apply target, categories: categories } matches.uniq! matches.delete target matches.count == 1 ? matches.first : merge_matches(target, matches) end
categories?(value, categories)
click to toggle source
# File lib/diachronr/rule.rb, line 22 def categories?(value, categories) !get_categories(value, categories).empty? end
category?(categories)
click to toggle source
# File lib/diachronr/rule.rb, line 18 def category?(categories) categories?(from, categories) || categories?(condition, categories) end
category_rules(categories)
click to toggle source
# File lib/diachronr/rule.rb, line 40 def category_rules(categories) rules = [] get_categories(from, categories).each_with_index do |cat, i| cat.contents.each_char.with_index do |f, fi| rules << Rule.new( "#{new_from(cat, f)}/#{new_to(categories, i, fi)}/#{condition}" ) end end rules end
condition_rules(categories)
click to toggle source
# File lib/diachronr/rule.rb, line 52 def condition_rules(categories) rules = [] get_categories(condition, categories).each do |cat| cat.contents.each_char do |c| new_condition = condition.gsub cat.sign, c rules << Rule.new("#{from}/#{to}/#{new_condition}") end end rules end
get_categories(value, categories)
click to toggle source
# File lib/diachronr/rule.rb, line 26 def get_categories(value, categories) categories.select { |c| value.include? c.sign } end
merge_matches(target, matches)
click to toggle source
# File lib/diachronr/rule.rb, line 63 def merge_matches(target, matches) new_target = target.dup matches.each do |match| match.each_char.with_index do |m, i| new_target[i] = m if target[i] != m end end new_target end
new_from(category, char)
click to toggle source
# File lib/diachronr/rule.rb, line 36 def new_from(category, char) from.gsub category.sign, char end
new_to(categories, category_index, index)
click to toggle source
# File lib/diachronr/rule.rb, line 30 def new_to(categories, category_index, index) t = get_categories(to, categories)[category_index] return to if t.nil? t.contents[index] end
to_s()
click to toggle source
# File lib/diachronr/rule.rb, line 14 def to_s "'#{@from}' > '#{@to}' / '#{@condition}'" end