Class: Regexp::Expression::Subexpression

Inherits:
Base
  • Object
show all
Includes:
Enumerable
Defined in:
lib/regexp_parser/expression/subexpression.rb,
lib/regexp_parser/expression/methods/traverse.rb,
lib/regexp_parser/expression/methods/strfregexp.rb,
lib/regexp_parser/expression/methods/match_length.rb

Instance Attribute Summary collapse

Attributes inherited from Base

#conditional_level, #level, #nesting_level, #options, #quantifier, #set_level, #text, #token, #ts, #type

Instance Method Summary collapse

Methods inherited from Base

#ascii_classes?, #attributes, #case_insensitive?, #coded_offset, #default_classes?, #free_spacing?, #full_length, #greedy?, #is?, #match, #match?, #multiline?, #offset, #one_of?, #possessive?, #quantified?, #quantifier_affix, #quantify, #quantity, #reluctant?, #repetitions, #strfregexp, #terminal?, #to_re, #type?, #unicode_classes?, #unquantified_clone

Constructor Details

#initialize(token, options = {}) ⇒ Subexpression

Returns a new instance of Subexpression.



8
9
10
11
12
# File 'lib/regexp_parser/expression/subexpression.rb', line 8

def initialize(token, options = {})
  super

  self.expressions = []
end

Instance Attribute Details

#expressionsObject

Returns the value of attribute expressions.



6
7
8
# File 'lib/regexp_parser/expression/subexpression.rb', line 6

def expressions
  @expressions
end

Instance Method Details

#<<(exp) ⇒ Object



20
21
22
23
24
25
26
27
# File 'lib/regexp_parser/expression/subexpression.rb', line 20

def <<(exp)
  if exp.is_a?(WhiteSpace) && last && last.is_a?(WhiteSpace)
    last.merge(exp)
  else
    exp.nesting_level = nesting_level + 1
    expressions << exp
  end
end

#dig(*indices) ⇒ Object



37
38
39
40
41
# File 'lib/regexp_parser/expression/subexpression.rb', line 37

def dig(*indices)
  exp = self
  indices.each { |idx| exp = exp.nil? || exp.terminal? ? nil : exp[idx] }
  exp
end

#each_expression(include_self = false, &block) ⇒ Object

Iterates over the expressions of this expression as an array, passing the expression and its index within its parent to the given block.



39
40
41
42
43
# File 'lib/regexp_parser/expression/methods/traverse.rb', line 39

def each_expression(include_self = false, &block)
  traverse(include_self) do |event, exp, index|
    yield(exp, index) unless event == :exit
  end
end

#flat_map(include_self = false, &block) ⇒ Object

Returns a new array with the results of calling the given block once for every expression. If a block is not given, returns an array with each expression and its level index as an array.



48
49
50
51
52
53
54
55
56
57
58
59
60
# File 'lib/regexp_parser/expression/methods/traverse.rb', line 48

def flat_map(include_self = false, &block)
  result = []

  each_expression(include_self) do |exp, index|
    if block_given?
      result << yield(exp, index)
    else
      result << [exp, index]
    end
  end

  result
end

#initialize_clone(orig) ⇒ Object

Override base method to clone the expressions as well.



15
16
17
18
# File 'lib/regexp_parser/expression/subexpression.rb', line 15

def initialize_clone(orig)
  self.expressions = orig.expressions.map(&:clone)
  super
end

#inner_match_lengthObject



114
115
116
117
118
119
# File 'lib/regexp_parser/expression/methods/match_length.rb', line 114

def inner_match_length
  dummy = Regexp::Expression::Root.build
  dummy.expressions = expressions.map(&:clone)
  dummy.quantifier = quantifier && quantifier.clone
  dummy.match_length
end

#match_lengthObject



107
108
109
110
111
112
# File 'lib/regexp_parser/expression/methods/match_length.rb', line 107

def match_length
  MatchLength.new(self,
                   base_min: map { |exp| exp.match_length.min }.inject(0, :+),
                   base_max: map { |exp| exp.match_length.max }.inject(0, :+),
                   reify: ->{ map { |exp| exp.match_length.to_re }.join })
end

#strfregexp_tree(format = '%a', include_self = true, separator = "\n") ⇒ Object Also known as: strfre_tree



102
103
104
105
106
107
108
109
110
# File 'lib/regexp_parser/expression/methods/strfregexp.rb', line 102

def strfregexp_tree(format = '%a', include_self = true, separator = "\n")
  output = include_self ? [self.strfregexp(format)] : []

  output += flat_map do |exp, index|
    exp.strfregexp(format, (include_self ? 1 : 0), index)
  end

  output.join(separator)
end

#teObject



43
44
45
# File 'lib/regexp_parser/expression/subexpression.rb', line 43

def te
  ts + to_s.length
end

#to_hObject



52
53
54
55
56
57
# File 'lib/regexp_parser/expression/subexpression.rb', line 52

def to_h
  attributes.merge({
    text:        to_s(:base),
    expressions: expressions.map(&:to_h)
  })
end

#to_s(format = :full) ⇒ Object



47
48
49
50
# File 'lib/regexp_parser/expression/subexpression.rb', line 47

def to_s(format = :full)
  # Note: the format does not get passed down to subexpressions.
  "#{expressions.join}#{quantifier_affix(format)}"
end

#traverse(include_self = false, &block) ⇒ Object Also known as: walk

Traverses the subexpression (depth-first, pre-order) and calls the given block for each expression with three arguments; the traversal event, the expression, and the index of the expression within its parent.

The event argument is passed as follows:

  • For subexpressions, :enter upon entering the subexpression, and :exit upon exiting it.

  • For terminal expressions, :visit is called once.

Returns self.



16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
# File 'lib/regexp_parser/expression/methods/traverse.rb', line 16

def traverse(include_self = false, &block)
  raise 'traverse requires a block' unless block_given?

  block.call(:enter, self, 0) if include_self

  each_with_index do |exp, index|
    if exp.terminal?
      block.call(:visit, exp, index)
    else
      block.call(:enter, exp, index)
      exp.traverse(&block)
      block.call(:exit, exp, index)
    end
  end

  block.call(:exit, self, 0) if include_self

  self
end