Module: AtCoderFriends::Parser::FormatParser
- Defined in:
- lib/at_coder_friends/parser/format_parser.rb
Overview
parses input data format and generates input definitons
Defined Under Namespace
Classes: Iterator
Constant Summary collapse
- PARSERS =
[ { container: :harray, item: :number, pat: /^(?<v>[a-z]+)[01](\s+\k<v>.)*(\s+\.+)?(\s+\k<v>.)+$/i, names: ->(m) { [m[:v]] }, pat2: ->(_) { nil }, size: ->(f) { [f[-1]] } }, { container: :harray, item: :char, pat: /^(?<v>[a-z]+)[01](\k<v>.)*(\s*\.+\s*)?(\k<v>.)+$/i, names: ->(m) { [m[:v]] }, pat2: ->(_) { nil }, size: ->(f) { [f[-1]] } }, { container: :matrix, item: :number, pat: /^(?<v>[a-z]+)[01][01](\s+\k<v>..)*(\s+\.+)?(\s+\k<v>..)+$/i, names: ->(m) { [m[:v]] }, pat2: ->(v) { /(^#{v}..(\s+#{v}..)*(\s+\.+)?(\s+#{v}..)+|\.+)$/ }, size: ->(f) { f[-2..-1].chars.to_a } }, { container: :matrix, item: :char, pat: /^(?<v>[a-z]+)[01][01](\k<v>..)*(\s*\.+\s*)?(\k<v>..)+$/i, names: ->(m) { [m[:v]] }, pat2: ->(v) { /(^#{v}..(#{v}..)*(\s*\.+\s*)?(#{v}..)+|\.+)$/ }, size: ->(f) { f[-2..-1].chars.to_a } }, { container: :varray, item: :number, pat: /^[a-z]+(?<i>[0-9])(\s+[a-z]+\k<i>)*$/i, names: ->(m) { m[0].split.map { |w| w[0..-2] } }, pat2: lambda { |vs| pat = vs.map { |v| v + '.+' }.join('\s+') /^(#{pat}|\.+)$/ }, size: ->(f) { /(?<sz>\d+)$/ =~ f ? [sz] : [f[-1]] } }, { container: :single, item: :number, pat: /^[a-z]+(\s+[a-z]+)*$/i, names: ->(m) { m[0].split }, pat2: ->(_) { nil }, size: ->(_) { [] } } ].freeze
Class Method Summary collapse
- .match_smp!(inpdefs, smp) ⇒ Object
-
.max_smp(smps) ⇒ Object
rubocop:enable Metrics/MethodLength, Metrics/AbcSize.
- .normalize(fmt) ⇒ Object
- .parse(fmt, smps) ⇒ Object
-
.parse_fmt(lines) ⇒ Object
rubocop:disable Metrics/MethodLength, Metrics/AbcSize.
- .process(pbm) ⇒ Object
Class Method Details
.match_smp!(inpdefs, smp) ⇒ Object
141 142 143 144 145 146 147 148 149 150 151 |
# File 'lib/at_coder_friends/parser/format_parser.rb', line 141 def match_smp!(inpdefs, smp) lines = smp.split("\n") inpdefs.each_with_index do |inpdef, i| break if i >= lines.size next if inpdef.item != :number inpdef.item = :string if lines[i].split[0] =~ /[^\-0-9]/ break if i[varray matrix].include?(inpdef.container) end inpdefs end |
.max_smp(smps) ⇒ Object
rubocop:enable Metrics/MethodLength, Metrics/AbcSize
134 135 136 137 138 139 |
# File 'lib/at_coder_friends/parser/format_parser.rb', line 134 def max_smp(smps) smps .select { |smp| smp.ext == :in } .max_by { |smp| smp.txt.size } &.txt end |
.normalize(fmt) ⇒ Object
94 95 96 97 98 99 100 101 102 103 104 105 |
# File 'lib/at_coder_friends/parser/format_parser.rb', line 94 def normalize(fmt) fmt .gsub(/[+*-]\d+/, '') # N-1, N+1 -> N .gsub(%r{[-/ ]}, ' ') # a-b, a/b -> a b .gsub(/\{.*?\}/) { |w| w.delete(' ') } # {1, 1}->{1,1} shortest match .gsub(/[_,'\\(){}|$]/, '') .gsub(/[・::…‥]+/, '..') .gsub(/[clv]?dots/, '..') .gsub(/^[.\s]+$/, '..') .split("\n") .map(&:strip) end |
.parse(fmt, smps) ⇒ Object
86 87 88 89 90 91 92 |
# File 'lib/at_coder_friends/parser/format_parser.rb', line 86 def parse(fmt, smps) lines = normalize(fmt) defs = parse_fmt(lines) smpx = max_smp(smps) smpx && match_smp!(defs, smpx) defs end |
.parse_fmt(lines) ⇒ Object
rubocop:disable Metrics/MethodLength, Metrics/AbcSize
108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 |
# File 'lib/at_coder_friends/parser/format_parser.rb', line 108 def parse_fmt(lines) it = Iterator.new(lines + ['']) # sentinel prv = nil cur = it.next Enumerator.new do |y| loop do unless (parser = PARSERS.find { |ps| ps[:pat] =~ cur }) puts "unknown format: #{cur}" unless cur.empty? (cur = it.next) ? next : break end container, item = parser.values_at(:container, :item) m = parser[:pat].match(cur) names = parser[:names].call(m) pat2 = parser[:pat2].call(names) loop do prv = cur cur = it.next break unless pat2 && pat2 =~ cur end size = parser[:size].call(prv) y << InputDef.new(container, item, names, size) end end.to_a end |
.process(pbm) ⇒ Object
81 82 83 84 |
# File 'lib/at_coder_friends/parser/format_parser.rb', line 81 def process(pbm) defs = parse(pbm.fmt, pbm.smps) pbm.defs = defs end |