class Regexp::Expression::Subexpression

def <<(exp)

def <<(exp)
  exp.parent = self
  expressions << exp
end

def dig(*indices)

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

def each_expression(include_self = false, &block)

their parents are also passed to it.
If the block takes two arguments, the indices of the children within
given block.
Traverses the expression, passing each recursive child to the
def each_expression(include_self = false, &block)
  return enum_for(__method__, include_self) unless block
  if block.arity == 1
    block.call(self) if include_self
    each_expression_without_index(&block)
  else
    block.call(self, 0) if include_self
    each_expression_with_index(&block)
  end
end

def each_expression_with_index(&block)

def each_expression_with_index(&block)
  each_with_index do |exp, index|
    block.call(exp, index)
    exp.each_expression_with_index(&block) unless exp.terminal?
  end
end

def each_expression_without_index(&block)

def each_expression_without_index(&block)
  each do |exp|
    block.call(exp)
    exp.each_expression_without_index(&block) unless exp.terminal?
  end
end

def extract_quantifier_target(quantifier_description)

def extract_quantifier_target(quantifier_description)
  pre_quantifier_decorations = []
  target = expressions.reverse.find do |exp|
    if exp.decorative?
      exp.custom_to_s_handling = true
      pre_quantifier_decorations << exp.text
      next
    end
    exp
  end
  target or raise Regexp::Parser::ParserError,
    "No valid target found for '#{quantifier_description}' quantifier"
  target.pre_quantifier_decorations = pre_quantifier_decorations
  target
end

def flat_map(include_self = false, &block)

each expression and its level index as an array.
for every expression. If a block is not given, returns an array with
Returns a new array with the results of calling the given block once
def flat_map(include_self = false, &block)
  case block && block.arity
  when nil then each_expression(include_self).to_a
  when 2   then each_expression(include_self).map(&block)
  else          each_expression(include_self).map { |exp| block.call(exp) }
  end
end

def initialize(token, options = {})

def initialize(token, options = {})
  self.expressions = []
  super
end

def initialize_copy(orig)

Override base method to clone the expressions as well.
def initialize_copy(orig)
  self.expressions = orig.expressions.map do |exp|
    exp.clone.tap { |copy| copy.parent = self }
  end
  super
end

def inner_match_length

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

def match_length

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

def strfregexp_tree(format = '%a', include_self = true, separator = "\n")

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

def te

def te
  ts + base_length
end

def to_h

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

def traverse(include_self = false, &block)

Returns self.

- For terminal expressions, :visit is called once.

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

The event argument is passed as follows:

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