module Regexp::Expression::Shared
Public Class Methods
# 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
Public Instance Methods
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.
# 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
# File lib/regexp_parser/expression/shared.rb, line 51 def base_length to_s(:base).length end
# File lib/regexp_parser/expression/shared.rb, line 96 def coded_offset '@%d+%d' % offset end
# File lib/regexp_parser/expression/shared.rb, line 47 def ends_at(include_quantifier = true) ts + (include_quantifier ? full_length : base_length) end
# File lib/regexp_parser/expression/shared.rb, line 55 def full_length to_s(:original).length end
default implementation, e.g. “atomic group”, “hex escape”, “word type”, ..
# File lib/regexp_parser/expression/methods/human_name.rb, line 4 def human_name [token, type].compact.join(' ').tr('_', ' ') end
# 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
# 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
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]
# 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
not an alias so as to respect overrides of negative?
# File lib/regexp_parser/expression/methods/negative.rb, line 8 def negated? negative? end
# File lib/regexp_parser/expression/methods/negative.rb, line 3 def negative? false end
# 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
# File lib/regexp_parser/expression/shared.rb, line 92 def offset [starts_at, full_length] end
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: :*})
# 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
# File lib/regexp_parser/expression/methods/tests.rb, line 111 def optional? quantified? && quantifier.min == 0 end
default implementation
# File lib/regexp_parser/expression/methods/parts.rb, line 4 def parts [text.dup] end
# 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
Make pretty-print work despite inspect
implementation.
# File lib/regexp_parser/expression/methods/printing.rb, line 12 def pretty_print(q) q.pp_object(self) end
Called by pretty_print
(ruby/pp) and inspect
.
# 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
# File lib/regexp_parser/expression/methods/tests.rb, line 115 def quantified? !quantifier.nil? end
# File lib/regexp_parser/expression/shared.rb, line 106 def quantifier=(qtf) @quantifier = qtf @repetitions = nil # clear memoized value end
# File lib/regexp_parser/expression/shared.rb, line 88 def quantifier_affix(expression_format = :full) quantifier.to_s if quantified? && expression_format != :base end
# File lib/regexp_parser/expression/shared.rb, line 43 def starts_at ts end
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
# 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
# File lib/regexp_parser/expression/methods/construct.rb, line 37 def token_class self.class.token_class end
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]
# 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
Private Instance Methods
# File lib/regexp_parser/expression/shared.rb, line 18 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
# File lib/regexp_parser/expression/methods/parts.rb, line 10 def intersperse(expressions, separator) expressions.flat_map { |exp| [exp, separator] }.slice(0...-1) end