Module: Regexp::Expression::Shared

Included in:
Base, Quantifier
Defined in:
lib/regexp_parser/expression/shared.rb,
lib/regexp_parser/expression/methods/parts.rb,
lib/regexp_parser/expression/methods/tests.rb,
lib/regexp_parser/expression/methods/negative.rb,
lib/regexp_parser/expression/methods/printing.rb,
lib/regexp_parser/expression/methods/construct.rb,
lib/regexp_parser/expression/methods/human_name.rb

Defined Under Namespace

Modules: ClassMethods

Class Method Summary collapse

Instance Method Summary collapse

Class Method Details

.included(mod) ⇒ Object



5
6
7
8
9
10
11
12
13
14
15
16
# File 'lib/regexp_parser/expression/shared.rb', line 5

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

Instance Method Details

#==(other) ⇒ Object Also known as: ===, eql?

Deep-compare two expressions for equality.

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



101
102
103
104
105
106
107
# File 'lib/regexp_parser/expression/methods/tests.rb', line 101

def ==(other)
  self.class   == other.class &&
    text       == other.text &&
    quantifier == other.quantifier &&
    options    == other.options &&
    (terminal? || expressions == other.expressions)
end

#base_lengthObject



51
52
53
# File 'lib/regexp_parser/expression/shared.rb', line 51

def base_length
  to_s(:base).length
end

#coded_offsetObject



96
97
98
# File 'lib/regexp_parser/expression/shared.rb', line 96

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

#ends_at(include_quantifier = true) ⇒ Object



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

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

#full_lengthObject



55
56
57
# File 'lib/regexp_parser/expression/shared.rb', line 55

def full_length
  to_s(:original).length
end

#human_nameObject

default implementation, e.g. “atomic group”, “hex escape”, “word type”, ..



4
5
6
# File 'lib/regexp_parser/expression/methods/human_name.rb', line 4

def human_name
  [token, type].compact.join(' ').tr('_', ' ')
end

#initialize_copy(orig) ⇒ Object



32
33
34
35
36
37
38
39
40
41
# File 'lib/regexp_parser/expression/shared.rb', line 32

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

#inspectObject



3
4
5
6
7
8
9
# File 'lib/regexp_parser/expression/methods/printing.rb', line 3

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

#is?(test_token, test_type = nil) ⇒ Boolean

Test if this expression has the given test_token, and optionally a given test_type.

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

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

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

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

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

Returns:

  • (Boolean)


36
37
38
39
# File 'lib/regexp_parser/expression/methods/tests.rb', line 36

def is?(test_token, test_type = nil)
  return true if test_token === :*
  token == test_token and (test_type ? type?(test_type) : true)
end

#negated?Boolean

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

Returns:

  • (Boolean)


8
9
10
# File 'lib/regexp_parser/expression/methods/negative.rb', line 8

def negated?
  negative?
end

#negative?Boolean

Returns:

  • (Boolean)


3
4
5
# File 'lib/regexp_parser/expression/methods/negative.rb', line 3

def negative?
  false
end

#nesting_level=(lvl) ⇒ Object



100
101
102
103
104
# File 'lib/regexp_parser/expression/shared.rb', line 100

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

#offsetObject



92
93
94
# File 'lib/regexp_parser/expression/shared.rb', line 92

def offset
  [starts_at, full_length]
end

#one_of?(scope, top = true) ⇒ Boolean

Test if this expression matches an entry in the given scope spec.

A scope spec can be one of:

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

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

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

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

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

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

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

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

Returns:

  • (Boolean)


75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
# File 'lib/regexp_parser/expression/methods/tests.rb', line 75

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

#optional?Boolean

Returns:

  • (Boolean)


111
112
113
# File 'lib/regexp_parser/expression/methods/tests.rb', line 111

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

#partsObject

default implementation



4
5
6
# File 'lib/regexp_parser/expression/methods/parts.rb', line 4

def parts
  [text.dup]
end

#pre_quantifier_decoration(expression_format = :original) ⇒ Object



84
85
86
# File 'lib/regexp_parser/expression/shared.rb', line 84

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

#pretty_print(q) ⇒ Object

Make pretty-print work despite #inspect implementation.



12
13
14
# File 'lib/regexp_parser/expression/methods/printing.rb', line 12

def pretty_print(q)
  q.pp_object(self)
end

#pretty_print_instance_variablesObject

Called by pretty_print (ruby/pp) and #inspect.



17
18
19
20
21
22
23
24
# File 'lib/regexp_parser/expression/methods/printing.rb', line 17

def pretty_print_instance_variables
  [
    (:@text unless text.to_s.empty?),
    (:@quantifier if quantified?),
    (:@options unless options.empty?),
    (:@expressions unless terminal?),
  ].compact
end

#quantified?Boolean

Returns:

  • (Boolean)


115
116
117
# File 'lib/regexp_parser/expression/methods/tests.rb', line 115

def quantified?
  !quantifier.nil?
end

#quantifier=(qtf) ⇒ Object



106
107
108
109
# File 'lib/regexp_parser/expression/shared.rb', line 106

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

#quantifier_affix(expression_format = :full) ⇒ Object



88
89
90
# File 'lib/regexp_parser/expression/shared.rb', line 88

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

#starts_atObject



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

def starts_at
  ts
end

#to_s(format = :full) ⇒ Object Also known as: to_str

#to_s reproduces the original source, as an unparser would.

It takes an optional format argument.

Example:

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

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



72
73
74
75
76
77
78
79
80
81
# File 'lib/regexp_parser/expression/shared.rb', line 72

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

#token_classObject



37
38
39
# File 'lib/regexp_parser/expression/methods/construct.rb', line 37

def token_class
  self.class.token_class
end

#type?(test_type) ⇒ Boolean

Test if this expression has the given test_type, which can be either a symbol or an array of symbols to check against the expression’s type.

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

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

Returns:

  • (Boolean)


13
14
15
16
# File 'lib/regexp_parser/expression/methods/tests.rb', line 13

def type?(test_type)
  test_types = Array(test_type).map(&:to_sym)
  test_types.include?(:*) || test_types.include?(type)
end