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, #base_length, #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.



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

def initialize(token, options = {})
  super

  self.expressions = []
end

Instance Attribute Details

#expressionsObject

Returns the value of attribute expressions.



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

def expressions
  @expressions
end

Instance Method Details

#<<(exp) ⇒ Object



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

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



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

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

#each_expression(include_self = false) ⇒ 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
44
45
# File 'lib/regexp_parser/expression/methods/traverse.rb', line 39

def each_expression(include_self = false)
  return enum_for(__method__, include_self) unless block_given?

  traverse(include_self) do |event, exp, index|
    yield(exp, index) unless event == :exit
  end
end

#flat_map(include_self = false) ⇒ 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.



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

def flat_map(include_self = false)
  result = []

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

  result
end

#initialize_copy(orig) ⇒ Object

Override base method to clone the expressions as well.



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

def initialize_copy(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



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

def te
  ts + to_s.length
end

#to_hObject



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

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

#to_s(format = :full) ⇒ Object



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

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)
  return enum_for(__method__, include_self) 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