Class: Kotoshu::Readers::CompoundRule

Inherits:
Object
  • Object
show all
Defined in:
lib/kotoshu/readers/aff_data.rb

Overview

Compound rule pattern.

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(text) ⇒ CompoundRule

Create a new compound rule.

Parameters:

  • text (String)

    The rule text (e.g., "A*B?CD")



226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
# File 'lib/kotoshu/readers/aff_data.rb', line 226

def initialize(text)
  @text = text
  # Parse flags from rule text
  if text.include?('(')
    @flags = text.scan(/\((.+?)\)/).flatten.to_set
    parts = text.scan(/\([^*?]+?\)[*?]?/)
  else
    @flags = text.gsub(/[*?]/, '').chars.to_set
    # Handle ) as a flag character (used in sv dictionaries)
    parts = text.gsub(/(?<=[^*?])\)/, '\\)').gsub(/([^*?])/, '\1')
      .scan(/[^*?][*?]?/)
  end

  # Full-match regex: the entire flag-combination string must match.
  @re = Regexp.new("\\A#{parts.join}\\z")

  # Partial-match regex: any prefix of the rule is accepted. Built
  # by making each trailing part optional, from the end backwards:
  # parts ["A","B","C"] → "A(B(C?)?)?" which matches "A", "AB", "ABC".
  @partial_re = if parts.empty?
                  Regexp.new('\\A\\z')
                else
                  Regexp.new("\\A#{build_partial(parts)}\\z")
                end
end

Instance Attribute Details

#flagsSet<String>

Flags in this rule

Returns:

  • (Set<String>)

    the current value of flags



220
221
222
# File 'lib/kotoshu/readers/aff_data.rb', line 220

def flags
  @flags
end

#partial_reRegexp

Compiled regex for prefix matching

Returns:

  • (Regexp)

    the current value of partial_re



220
221
222
# File 'lib/kotoshu/readers/aff_data.rb', line 220

def partial_re
  @partial_re
end

#reRegexp

Compiled regex for full matching

Returns:

  • (Regexp)

    the current value of re



220
221
222
# File 'lib/kotoshu/readers/aff_data.rb', line 220

def re
  @re
end

#textString

The rule text

Returns:

  • (String)

    the current value of text



220
221
222
# File 'lib/kotoshu/readers/aff_data.rb', line 220

def text
  @text
end

Instance Method Details

#fullmatch(flag_sets) ⇒ Boolean

Check if flag sets fully match this rule.

Parameters:

  • flag_sets (Array<Set<String>>)

    Array of flag sets

Returns:

  • (Boolean)

    True if the entire flag-combination matches



256
257
258
259
260
261
262
263
# File 'lib/kotoshu/readers/aff_data.rb', line 256

def fullmatch(flag_sets)
  relevant_flags = flag_sets.map { |f| @flags.intersection(f).to_a }
  return false if relevant_flags.empty? || relevant_flags.any?(&:empty?)

  relevant_flags[0].product(*relevant_flags[1..]).any? do |fc|
    @re.match?(fc.join)
  end
end

#partial_match(flag_sets) ⇒ Boolean

Check if flag sets form a valid prefix of this rule.

Used during compounds_by_rules recursion to prune branches that can never lead to a full match.

Parameters:

  • flag_sets (Array<Set<String>>)

    Array of flag sets

Returns:

  • (Boolean)

    True if a prefix of the rule matches



272
273
274
275
276
277
278
279
# File 'lib/kotoshu/readers/aff_data.rb', line 272

def partial_match(flag_sets)
  relevant_flags = flag_sets.map { |f| @flags.intersection(f).to_a }
  return false if relevant_flags.empty? || relevant_flags.any?(&:empty?)

  relevant_flags[0].product(*relevant_flags[1..]).any? do |fc|
    @partial_re.match?(fc.join)
  end
end