module Regexp::Expression::Shared

def self.included(mod)

def self.included(mod)
  mod.class_eval do
    extend Shared::ClassMethods
    attr_accessor :type, :token, :text, :ts, :te,
                  :level, :set_level, :conditional_level,
                  :options, :parent,
                  :custom_to_s_handling, :pre_quantifier_decorations
    attr_reader   :nesting_level, :quantifier
  end
end

def ==(other)

#pretty_print_instance_variables so that it includes all relevant values.
When changing the conditions, please make sure to update

Deep-compare two expressions for equality.
def ==(other)
  self.class   == other.class &&
    text       == other.text &&
    quantifier == other.quantifier &&
    options    == other.options &&
    (terminal? || expressions == other.expressions)
end

def base_length

def base_length
  to_s(:base).length
end

def coded_offset

def coded_offset
  '@%d+%d' % offset
end

def ends_at(include_quantifier = true)

def ends_at(include_quantifier = true)
  ts + (include_quantifier ? full_length : base_length)
end

def full_length

def full_length
  to_s(:original).length
end

def human_name

default implementation, e.g. "atomic group", "hex escape", "word type", ..
def human_name
  [token, type].compact.join(' ').tr('_', ' ')
end

def init_from_token_and_options(token, options = {})

def init_from_token_and_options(token, options = {})
  self.type              = token.type
  self.token             = token.token
  self.text              = token.text
  self.ts                = token.ts
  self.te                = token.te
  self.level             = token.level
  self.set_level         = token.set_level
  self.conditional_level = token.conditional_level
  self.nesting_level     = 0
  self.options           = options || {}
end

def initialize_copy(orig)

def initialize_copy(orig)
  self.text       = orig.text.dup         if orig.text
  self.options    = orig.options.dup      if orig.options
  self.quantifier = orig.quantifier.clone if orig.quantifier
  self.parent     = nil # updated by Subexpression#initialize_copy
  if orig.pre_quantifier_decorations
    self.pre_quantifier_decorations = orig.pre_quantifier_decorations.map(&:dup)
  end
  super
end

def inspect

def inspect
  [
    "#<#{self.class}",
    pretty_print_instance_variables.map { |v| " #{v}=#{instance_variable_get(v).inspect}" },
    ">"
  ].join
end

def intersperse(expressions, separator)

def intersperse(expressions, separator)
  expressions.flat_map { |exp| [exp, separator] }.slice(0...-1)
end

def is?(test_token, test_type = nil)


exp.is? :dot, [:meta, :escape]
# is it a :meta or :escape :dot

exp.is? :dot, :meta
# is it a :meta :dot

exp.is? :character, :set
# is it a :character and a :set

exp.is? :capture
# is it a :capture

exp.is? :* # always returns true
# Any expressions

test_type.
Test if this expression has the given test_token, and optionally a given
def is?(test_token, test_type = nil)
  return true if test_token === :*
  token == test_token and (test_type ? type?(test_type) : true)
end

def negated?

not an alias so as to respect overrides of #negative?
def negated?
  negative?
end

def negative?

def negative?
  false
end

def nesting_level=(lvl)

def nesting_level=(lvl)
  @nesting_level = lvl
  quantifier && quantifier.nesting_level = lvl
  terminal? || each { |subexp| subexp.nesting_level = lvl + 1 }
end

def offset

def offset
  [starts_at, full_length]
end

def one_of?(scope, top = true)


exp.one_of?({meta: [:dot], set: :*})
# meta dots and any set tokens

exp.one_of?(:meta => [:dot, :alternation])
# meta dots and alternations

exp.one_of?(:meta => :*)
# any expression of type meta

exp.one_of?(:group)
# like exp.type?(:group)

exp.one_of?(:*) # always true
# any expression

expression.
from a hash, it will be checked against the token of the
type of the expression. If it's being called for a value
a symbol then it will always be checked against the
the level of the call. If one_of? is called directly with
. A symbol: matches the expression's token or type, depending on

evaluate the key's value.
case, when the scope is a hash, one_of? calls itself to
and the value is either a symbol or an array. In this
. A hash: Where the key is interpreted as the expression type

of the expression's token.
. An array: Interpreted as a set of tokens, tested for inclusion

A scope spec can be one of:

Test if this expression matches an entry in the given scope spec.
def one_of?(scope, top = true)
  case scope
  when Array
    scope.include?(:*) || scope.include?(token)
  when Hash
    if scope.has_key?(:*)
      test_type = scope.has_key?(type) ? type : :*
      one_of?(scope[test_type], false)
    else
      scope.has_key?(type) && one_of?(scope[type], false)
    end
  when Symbol
    scope.equal?(:*) || (top ? type?(scope) : is?(scope))
  else
    raise ArgumentError,
          "Array, Hash, or Symbol expected, #{scope.class.name} given"
  end
end

def optional?

def optional?
  quantified? && quantifier.min == 0
end

def parts

default implementation
def parts
  [text.dup]
end

def pre_quantifier_decoration(expression_format = :original)

def pre_quantifier_decoration(expression_format = :original)
  pre_quantifier_decorations.to_a.join if expression_format == :original
end

def pretty_print(q)

Make pretty-print work despite #inspect implementation.
def pretty_print(q)
  q.pp_object(self)
end

def pretty_print_instance_variables

Called by pretty_print (ruby/pp) and #inspect.
def pretty_print_instance_variables
  [
    (:@text unless text.to_s.empty?),
    (:@quantifier if quantified?),
    (:@options unless options.empty?),
    (:@expressions unless terminal?),
  ].compact
end

def quantified?

def quantified?
  !quantifier.nil?
end

def quantifier=(qtf)

def quantifier=(qtf)
  @quantifier = qtf
  @repetitions = nil # clear memoized value
end

def quantifier_affix(expression_format = :full)

def quantifier_affix(expression_format = :full)
  quantifier.to_s if quantified? && expression_format != :base
end

def starts_at

def starts_at
  ts
end

def to_s(format = :full)


lit.to_s(:original) # => 'a +' # with quantifier AND intermittent decorations
lit.to_s(:base) # => 'a' # without quantifier
lit.to_s(:full) # => 'a+' # default; with quantifier
lit.to_s # => 'a+' # default; with quantifier

lit = Regexp::Parser.parse(/a +/x)[0]

Example:

It takes an optional format argument.

#to_s reproduces the original source, as an unparser would.
def to_s(format = :full)
  base = parts.each_with_object(''.dup) do |part, buff|
    if part.instance_of?(String)
      buff << part
    elsif !part.custom_to_s_handling
      buff << part.to_s(:original)
    end
  end
  "#{base}#{pre_quantifier_decoration(format)}#{quantifier_affix(format)}"
end

def token_class

def token_class
  self.class.token_class
end

def type?(test_type)


exp.type? [:set, :meta]
# is it a :set, or :meta

exp.type? :group
# is it a :group expression

a symbol or an array of symbols to check against the expression's type.
Test if this expression has the given test_type, which can be either
def type?(test_type)
  test_types = Array(test_type).map(&:to_sym)
  test_types.include?(:*) || test_types.include?(type)
end