Class: List::Matcher::Sequence
Instance Attribute Summary
Attributes inherited from Node
#engine, #optional, #root, #symbols
Instance Method Summary collapse
-
#atomy?(s) ⇒ Boolean
infer atomic patterns.
-
#condense(elements) ⇒ Object
iterated repeat condensation.
-
#condense_repeats(elements) ⇒ Object
looks for repeating subsequences, as in ababababab, and condenses them to (?>ab)5 condensation is only done when it results in a more compact regex.
- #convert ⇒ Object
- #flatten ⇒ Object
-
#initialize(engine, *constituents) ⇒ Sequence
constructor
A new instance of Sequence.
Methods inherited from Node
#atomic?, #bound, #children, #finalize, #optional?, #pfx, #qmark, #quote, #root?, #wrap
Constructor Details
#initialize(engine, *constituents) ⇒ Sequence
Returns a new instance of Sequence.
508 509 510 511 |
# File 'lib/list_matcher.rb', line 508 def initialize(engine, *constituents) super(engine, nil) @children = constituents end |
Instance Method Details
#atomy?(s) ⇒ Boolean
infer atomic patterns
568 569 570 |
# File 'lib/list_matcher.rb', line 568 def atomy?(s) s.size == 1 || /\A(?>\\\w|\[(?>[^\[\]\\]|\\.)++\])\z/ === s end |
#condense(elements) ⇒ Object
iterated repeat condensation
573 574 575 576 577 578 579 580 |
# File 'lib/list_matcher.rb', line 573 def condense(elements) while elements.size > 1 condensate = condense_repeats elements break if condensate == elements elements = condensate end elements.join end |
#condense_repeats(elements) ⇒ Object
looks for repeating subsequences, as in ababababab, and condenses them to (?>ab)5 condensation is only done when it results in a more compact regex
531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 |
# File 'lib/list_matcher.rb', line 531 def condense_repeats(elements) (1..(elements.size/2)).each do |l| # length of subsequence considered (0...l).each do |o| # offset from the start of the sequence dup_count = [] (1...(elements.size - o)/l).each do |s| # the sub-sequence number s2 = s * l + o s1 = s2 - l seq1 = elements[s1...s1 + l] seq2 = elements[s2...s2 + l] if seq1 == seq2 s0 = s - 1 counts = dup_count[s] = dup_count[s0] || [ 1, seq1.join, s1, nil ] counts[0] += 1 counts[3] = s2 + l dup_count[s0] = nil end end dup_count.compact! if dup_count.any? copy = elements.dup changed = false dup_count.reverse.each do |repeats, seq, start, finish| a = atomy? seq sl = seq.length if ( a ? 0 : engine.wrap_size ) + 2 + repeats.to_s.length + sl < sl * repeats changed = true copy[start...finish] = ( a ? seq : wrap(seq) ) + "{#{repeats}}" end end return copy if changed end end end elements end |
#convert ⇒ Object
513 514 515 516 |
# File 'lib/list_matcher.rb', line 513 def convert rx = condense children.map(&:convert) finalize rx end |
#flatten ⇒ Object
518 519 520 521 522 523 524 525 526 527 |
# File 'lib/list_matcher.rb', line 518 def flatten super (0...children.size).to_a.reverse.each do |i| c = children[i] if c.is_a?(Sequence) && !c.optional? children.delete_at i children.insert i, *c.children end end end |