Module: Kotodama
- Defined in:
- lib/rule.rb,
lib/type.rb,
lib/change.rb,
lib/kotodama.rb,
lib/language.rb,
lib/kotodama_grammar.rb
Defined Under Namespace
Classes: Change, Language, Rule, Type
Constant Summary collapse
- VERSION =
'1.2.5'
- GRAMMAR =
Kaiseki::Grammar.new do starting :document skipping :WS | :COMMENT rule :document do parses proc { @language = Language.new } & :options_block.optional & :content_block.zero_or_more & :EOF.skip filter { @language } end rule :options_block do parses 'options'.skip & '{'.skip & :option.zero_or_more & '}'.skip end rule :option do parses :LITERAL & '=>'.skip & (:ATOM | :INT) & ';'.skip node [:key, :value] action do @language.[@key] = @value end end rule :content_block do parses :type_block | :rule_block | :change_block | :spelling_rule | :zipf_block end rule :type_block do parses 'type'.skip & :ATOM.set(:id) & :get_type & '{'.skip & :symbol_declaration.zero_or_more & '}'.skip end action :get_type do if @language.types.key? @id @type = @language.types[@id] else @type = @language.types[@id] = Type.new(@language) end end rule :symbol_declaration do parses :LIST & :WEIGHT.optional & ';'.skip node [:symbols, :weight] action do @symbols.each {|n| @type.add n, @weight } end end rule :rule_block do parses 'rule'.skip & :ATOM.set(:id) & :get_rule & '{'.skip & (:exclude_expression | :rule_expression).zero_or_more & '}'.skip end action :get_rule do if @language.rules.key? @id @rule = @language.rules[@id] else @rule = @language.rules[@id] = Rule.new(@language) end end rule :exclude_expression do parses 'exclude'.skip & :ID.one_or_more & ';'.skip action { @rule.excludes << @result.join } end rule :rule_expression do parses :ATOM.one_or_more & :WEIGHT.optional & ';'.skip node [:expression, :weight] action { @rule.add @expression, @weight } end rule :change_block do parses 'change'.skip & :ATOM.set(:id) & :get_change & '{'.skip & (:ATOM.set(:id).action { @change.add [:load, @id, nil] } | :sound_change).zero_or_more & '}'.skip end action :get_change do if @language.changes.key? @id @change = @language.changes[@id] else @change = @language.changes[@id] = Change.new(@language) end end rule :sound_change do parses (:insert_change | :delete_change | :convert_change) & :change_env.optional & ';'.skip node [:type, :env] action do @type[2] = @env @change.add @type end end rule :insert_change do parses 'insert'.skip & :ATOM.one_or_more filter { [:insert, (@result.is_a?(Array) ? @result : [@result]), nil] } end rule :delete_change do parses 'delete'.skip & :ATOM.one_or_more filter { [:delete, (@result.is_a?(Array) ? @result : [@result]), nil] } end rule :convert_change do parses :ATOM.one_or_more & '>'.skip & :ATOM.one_or_more node [:from, :to] filter { [:convert, [@from, @to], nil] } end rule :change_env do parses '/'.skip & '#'.optional & :ATOM.zero_or_more & '_'.skip & :ATOM.zero_or_more & '#'.optional end rule :spelling_rule do parses 'spell'.skip & :ID & 'as'.skip & :LITERAL & ';'.skip node [:symbol, :spelling] action do @language.spellings[@symbol] = @spelling[1..-1] end end rule :zipf_block do parses 'zipf'.skip & :FLOAT.set(:float) & '{'.skip & (:LIST & ';'.skip).one_or_more.set(:lists) & '}'.skip action do zipf_list = [] @lists.each {|list1| list1.each {|n| zipf_list << n } } zipf_list.length.times do |i| value = 1.0 / (i + 1) ** @float value = (value * 100).to_i @language.zipf[zipf_list[i]] = value end end end rule :ID do parses /[a-zA-Z][0-9]?/ filter do if @result.length == 1 @result + '0' else @result end end end rule :LIST do parses (:ATOM & (','.skip & :ATOM).zero_or_more).merge end rule :LITERAL do parses /\"([^"]*)\"/ | /\'([^']*)\'/ simplify false filter do '$' + @result.captures[0] end end rule :ATOM do parses :ID | :LITERAL end rule :WEIGHT do parses '('.skip & :INT & ')'.skip end rule :INT do parses /\d+/ cast Integer end rule :FLOAT do parses /\d+\.\d+/ cast Float end rule :WS do parses /\s+/ end rule :COMMENT do parses /%[^\n]*\n/ end end