regexp_parser 2.8.1 → 2.11.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (93) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +6 -4
  3. data/LICENSE +1 -1
  4. data/Rakefile +5 -3
  5. data/lib/regexp_parser/error.rb +2 -0
  6. data/lib/regexp_parser/expression/base.rb +2 -0
  7. data/lib/regexp_parser/expression/classes/alternation.rb +2 -0
  8. data/lib/regexp_parser/expression/classes/anchor.rb +2 -0
  9. data/lib/regexp_parser/expression/classes/backreference.rb +3 -20
  10. data/lib/regexp_parser/expression/classes/character_set/intersection.rb +2 -0
  11. data/lib/regexp_parser/expression/classes/character_set/range.rb +2 -0
  12. data/lib/regexp_parser/expression/classes/character_set.rb +3 -4
  13. data/lib/regexp_parser/expression/classes/character_type.rb +2 -0
  14. data/lib/regexp_parser/expression/classes/conditional.rb +2 -14
  15. data/lib/regexp_parser/expression/classes/escape_sequence.rb +26 -95
  16. data/lib/regexp_parser/expression/classes/free_space.rb +2 -0
  17. data/lib/regexp_parser/expression/classes/group.rb +2 -0
  18. data/lib/regexp_parser/expression/classes/keep.rb +3 -1
  19. data/lib/regexp_parser/expression/classes/literal.rb +2 -0
  20. data/lib/regexp_parser/expression/classes/posix_class.rb +2 -4
  21. data/lib/regexp_parser/expression/classes/root.rb +2 -0
  22. data/lib/regexp_parser/expression/classes/unicode_property.rb +8 -9
  23. data/lib/regexp_parser/expression/methods/construct.rb +2 -0
  24. data/lib/regexp_parser/expression/methods/escape_sequence_char.rb +7 -0
  25. data/lib/regexp_parser/expression/methods/escape_sequence_codepoint.rb +76 -0
  26. data/lib/regexp_parser/expression/methods/human_name.rb +2 -0
  27. data/lib/regexp_parser/expression/methods/match.rb +2 -0
  28. data/lib/regexp_parser/expression/methods/match_length.rb +2 -0
  29. data/lib/regexp_parser/expression/methods/negative.rb +22 -0
  30. data/lib/regexp_parser/expression/methods/options.rb +2 -0
  31. data/lib/regexp_parser/expression/methods/parts.rb +2 -0
  32. data/lib/regexp_parser/expression/methods/printing.rb +2 -0
  33. data/lib/regexp_parser/expression/methods/referenced_expressions.rb +30 -0
  34. data/lib/regexp_parser/expression/methods/strfregexp.rb +2 -0
  35. data/lib/regexp_parser/expression/methods/tests.rb +2 -0
  36. data/lib/regexp_parser/expression/methods/traverse.rb +2 -0
  37. data/lib/regexp_parser/expression/quantifier.rb +3 -1
  38. data/lib/regexp_parser/expression/sequence.rb +2 -0
  39. data/lib/regexp_parser/expression/sequence_operation.rb +2 -0
  40. data/lib/regexp_parser/expression/shared.rb +6 -3
  41. data/lib/regexp_parser/expression/subexpression.rb +2 -0
  42. data/lib/regexp_parser/expression.rb +39 -33
  43. data/lib/regexp_parser/lexer.rb +2 -0
  44. data/lib/regexp_parser/parser.rb +16 -9
  45. data/lib/regexp_parser/scanner/errors/premature_end_error.rb +2 -0
  46. data/lib/regexp_parser/scanner/errors/scanner_error.rb +3 -1
  47. data/lib/regexp_parser/scanner/errors/validation_error.rb +2 -0
  48. data/lib/regexp_parser/scanner/properties/long.csv +37 -0
  49. data/lib/regexp_parser/scanner/properties/short.csv +9 -0
  50. data/lib/regexp_parser/scanner/scanner.rl +62 -18
  51. data/lib/regexp_parser/scanner.rb +1041 -936
  52. data/lib/regexp_parser/syntax/any.rb +2 -0
  53. data/lib/regexp_parser/syntax/base.rb +2 -0
  54. data/lib/regexp_parser/syntax/token/anchor.rb +5 -3
  55. data/lib/regexp_parser/syntax/token/assertion.rb +4 -2
  56. data/lib/regexp_parser/syntax/token/backreference.rb +8 -6
  57. data/lib/regexp_parser/syntax/token/character_set.rb +3 -1
  58. data/lib/regexp_parser/syntax/token/character_type.rb +6 -4
  59. data/lib/regexp_parser/syntax/token/conditional.rb +5 -3
  60. data/lib/regexp_parser/syntax/token/escape.rb +9 -7
  61. data/lib/regexp_parser/syntax/token/group.rb +8 -6
  62. data/lib/regexp_parser/syntax/token/keep.rb +3 -1
  63. data/lib/regexp_parser/syntax/token/meta.rb +4 -2
  64. data/lib/regexp_parser/syntax/token/posix_class.rb +4 -2
  65. data/lib/regexp_parser/syntax/token/quantifier.rb +8 -6
  66. data/lib/regexp_parser/syntax/token/unicode_property.rb +79 -46
  67. data/lib/regexp_parser/syntax/token/virtual.rb +5 -3
  68. data/lib/regexp_parser/syntax/token.rb +18 -16
  69. data/lib/regexp_parser/syntax/version_lookup.rb +4 -2
  70. data/lib/regexp_parser/syntax/versions/1.8.6.rb +2 -0
  71. data/lib/regexp_parser/syntax/versions/1.9.1.rb +2 -0
  72. data/lib/regexp_parser/syntax/versions/1.9.3.rb +2 -0
  73. data/lib/regexp_parser/syntax/versions/2.0.0.rb +2 -0
  74. data/lib/regexp_parser/syntax/versions/2.2.0.rb +2 -0
  75. data/lib/regexp_parser/syntax/versions/2.3.0.rb +2 -0
  76. data/lib/regexp_parser/syntax/versions/2.4.0.rb +2 -0
  77. data/lib/regexp_parser/syntax/versions/2.4.1.rb +2 -0
  78. data/lib/regexp_parser/syntax/versions/2.5.0.rb +2 -0
  79. data/lib/regexp_parser/syntax/versions/2.6.0.rb +2 -0
  80. data/lib/regexp_parser/syntax/versions/2.6.2.rb +2 -0
  81. data/lib/regexp_parser/syntax/versions/2.6.3.rb +2 -0
  82. data/lib/regexp_parser/syntax/versions/3.1.0.rb +2 -0
  83. data/lib/regexp_parser/syntax/versions/3.2.0.rb +2 -0
  84. data/lib/regexp_parser/syntax/versions/3.5.0.rb +4 -0
  85. data/lib/regexp_parser/syntax/versions.rb +3 -1
  86. data/lib/regexp_parser/syntax.rb +3 -1
  87. data/lib/regexp_parser/token.rb +2 -0
  88. data/lib/regexp_parser/version.rb +3 -1
  89. data/lib/regexp_parser.rb +8 -6
  90. data/regexp_parser.gemspec +7 -5
  91. metadata +12 -11
  92. data/CHANGELOG.md +0 -691
  93. data/README.md +0 -506
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: e1426faee272654c45e3da8e262e94cfdbcf134dbad7804aed8cd945334c07be
4
- data.tar.gz: 37eec721839fe2ebfc25c9d614756289b59ee766f5e7e60ecf4839b554bbb93e
3
+ metadata.gz: ba0845a7ebcd158dc60281b731adb0d597b71028a734209a9cf6e850986c03b4
4
+ data.tar.gz: '078369f6bdbf716aff8f435a318e3f1a8e83593951ee7b21c94bbcd597213d54'
5
5
  SHA512:
6
- metadata.gz: abed9d7f387634b5e16eb19cbfd5d9aab03288dd4d284b1c52688f958714479783275c5418ee623607ced96b301124ab82dff546e7e4146c7c5ec7feae3e089d
7
- data.tar.gz: 62c0757df1c73df52fcf71ef8de666ab9a51a4a8145e71321424ab0ff8408cb2b707cf154dae64ebbcc5a9c8a12ee377a3eadab7549432a9d0e6ee0e65afddd1
6
+ metadata.gz: e4539f7196c10d233aca76dc0da3fc8ae8df48b11afd3cc8c7548eedf5893a1202ba06f5fa841444b8afc7d4b0178b6cfb2f16db5e4d05401c64ba26fb05d1de
7
+ data.tar.gz: 801716036ad9a094641094077a8f1695d82cda38020369fb7385a9a7c34d7df0fc90c1629865072d22921fdcfa02a11f70c504220be2bd8df699a10d6d787647
data/Gemfile CHANGED
@@ -1,15 +1,17 @@
1
+ # frozen_string_literal: true
2
+
1
3
  source 'https://rubygems.org'
2
4
 
3
5
  gemspec
4
6
 
5
7
  group :development, :test do
6
- gem 'leto', '~> 2.0'
7
- gem 'rake', '~> 13.0'
8
- gem 'regexp_property_values', '~> 1.4'
8
+ gem 'leto', '~> 2.1'
9
+ gem 'rake', '~> 13.1'
10
+ gem 'regexp_property_values', '~> 1.5'
9
11
  gem 'rspec', '~> 3.10'
10
12
  if RUBY_VERSION.to_f >= 2.7
11
13
  gem 'benchmark-ips', '~> 2.1'
12
14
  gem 'gouteur', '~> 1.1'
13
- gem 'rubocop', '~> 1.7'
15
+ gem 'rubocop', '>= 1.80.2'
14
16
  end
15
17
  end
data/LICENSE CHANGED
@@ -1,4 +1,4 @@
1
- Copyright (c) 2010, 2012-2023, Ammar Ali
1
+ Copyright (c) 2010, 2012-2025, Ammar Ali
2
2
 
3
3
  Permission is hereby granted, free of charge, to any person
4
4
  obtaining a copy of this software and associated documentation
data/Rakefile CHANGED
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'bundler'
2
4
  require 'rubygems'
3
5
  require 'rubygems/package_task'
@@ -14,10 +16,10 @@ RSpec::Core::RakeTask.new(:spec)
14
16
  task :default => [:'test:full']
15
17
 
16
18
  namespace :test do
17
- task full: [:'ragel:rb', :spec]
19
+ task full: [:ragel, :spec]
18
20
  end
19
21
 
20
22
  # Add ragel task as a prerequisite for building the gem to ensure that the
21
23
  # latest scanner code is generated and included in the build.
22
- desc "Runs ragel:rb before building the gem"
23
- task :build => ['ragel:rb']
24
+ desc "Runs ragel before building the gem"
25
+ task build: :ragel
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  class Regexp::Parser
2
4
  # base class for all gem-specific errors
3
5
  class Error < StandardError; end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Regexp::Expression
2
4
  class Base
3
5
  include Regexp::Expression::Shared
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Regexp::Expression
2
4
  # A sequence of expressions, used by Alternation as one of its alternatives.
3
5
  class Alternative < Regexp::Expression::Sequence; end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Regexp::Expression
2
4
  module Anchor
3
5
  class Base < Regexp::Expression::Base; end
@@ -1,25 +1,8 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Regexp::Expression
2
4
  module Backreference
3
- class Base < Regexp::Expression::Base
4
- attr_accessor :referenced_expression
5
-
6
- def initialize_copy(orig)
7
- exp_id = [self.class, self.starts_at]
8
-
9
- # prevent infinite recursion for recursive subexp calls
10
- copied = @@copied ||= {}
11
- self.referenced_expression =
12
- if copied[exp_id]
13
- orig.referenced_expression
14
- else
15
- copied[exp_id] = true
16
- orig.referenced_expression.dup
17
- end
18
- copied.clear
19
-
20
- super
21
- end
22
- end
5
+ class Base < Regexp::Expression::Base; end
23
6
 
24
7
  class Number < Backreference::Base
25
8
  attr_reader :number
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Regexp::Expression
2
4
  class CharacterSet < Regexp::Expression::Subexpression
3
5
  class IntersectedSequence < Regexp::Expression::Sequence; end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Regexp::Expression
2
4
  class CharacterSet < Regexp::Expression::Subexpression
3
5
  class Range < Regexp::Expression::Subexpression
@@ -1,10 +1,9 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Regexp::Expression
2
4
  class CharacterSet < Regexp::Expression::Subexpression
3
5
  attr_accessor :closed, :negative
4
-
5
- alias :negative? :negative
6
- alias :negated? :negative
7
- alias :closed? :closed
6
+ alias :closed? :closed
8
7
 
9
8
  def initialize(token, options = {})
10
9
  self.negative = false
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Regexp::Expression
2
4
  module CharacterType
3
5
  class Base < Regexp::Expression::Base; end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Regexp::Expression
2
4
  module Conditional
3
5
  class TooManyBranches < Regexp::Parser::Error
@@ -7,26 +9,17 @@ module Regexp::Expression
7
9
  end
8
10
 
9
11
  class Condition < Regexp::Expression::Base
10
- attr_accessor :referenced_expression
11
-
12
12
  # Name or number of the referenced capturing group that determines state.
13
13
  # Returns a String if reference is by name, Integer if by number.
14
14
  def reference
15
15
  ref = text.tr("'<>()", "")
16
16
  ref =~ /\D/ ? ref : Integer(ref)
17
17
  end
18
-
19
- def initialize_copy(orig)
20
- self.referenced_expression = orig.referenced_expression.dup
21
- super
22
- end
23
18
  end
24
19
 
25
20
  class Branch < Regexp::Expression::Sequence; end
26
21
 
27
22
  class Expression < Regexp::Expression::Subexpression
28
- attr_accessor :referenced_expression
29
-
30
23
  def <<(exp)
31
24
  expressions.last << exp
32
25
  end
@@ -54,11 +47,6 @@ module Regexp::Expression
54
47
  def reference
55
48
  condition.reference
56
49
  end
57
-
58
- def initialize_copy(orig)
59
- self.referenced_expression = orig.referenced_expression.dup
60
- super
61
- end
62
50
  end
63
51
  end
64
52
  end
@@ -1,100 +1,31 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Regexp::Expression
2
4
  module EscapeSequence
3
- class Base < Regexp::Expression::Base
4
- def codepoint
5
- char.ord
6
- end
7
-
8
- if ''.respond_to?(:undump)
9
- def char
10
- %("#{text}").undump
11
- end
12
- else
13
- # poor man's unescape without using eval
14
- require 'yaml'
15
- def char
16
- YAML.load(%Q(---\n"#{text}"\n))
17
- end
18
- end
19
- end
20
-
21
- class Literal < EscapeSequence::Base
22
- def char
23
- text[1..-1]
24
- end
25
- end
26
-
27
- class AsciiEscape < EscapeSequence::Base; end
28
- class Backspace < EscapeSequence::Base; end
29
- class Bell < EscapeSequence::Base; end
30
- class FormFeed < EscapeSequence::Base; end
31
- class Newline < EscapeSequence::Base; end
32
- class Return < EscapeSequence::Base; end
33
- class Tab < EscapeSequence::Base; end
34
- class VerticalTab < EscapeSequence::Base; end
35
-
36
- class Hex < EscapeSequence::Base; end
37
- class Codepoint < EscapeSequence::Base; end
38
-
39
- class CodepointList < EscapeSequence::Base
40
- def char
41
- raise NoMethodError, 'CodepointList responds only to #chars'
42
- end
43
-
44
- def codepoint
45
- raise NoMethodError, 'CodepointList responds only to #codepoints'
46
- end
47
-
48
- def chars
49
- codepoints.map { |cp| cp.chr('utf-8') }
50
- end
51
-
52
- def codepoints
53
- text.scan(/\h+/).map(&:hex)
54
- end
55
- end
56
-
57
- class Octal < EscapeSequence::Base
58
- def char
59
- text[1..-1].to_i(8).chr('utf-8')
60
- end
61
- end
62
-
63
- class AbstractMetaControlSequence < EscapeSequence::Base
64
- def char
65
- codepoint.chr('utf-8')
66
- end
67
-
68
- private
69
-
70
- def control_sequence_to_s(control_sequence)
71
- five_lsb = control_sequence.unpack('B*').first[-5..-1]
72
- ["000#{five_lsb}"].pack('B*')
73
- end
74
-
75
- def meta_char_to_codepoint(meta_char)
76
- byte_value = meta_char.ord
77
- byte_value < 128 ? byte_value + 128 : byte_value
78
- end
79
- end
80
-
81
- class Control < AbstractMetaControlSequence
82
- def codepoint
83
- control_sequence_to_s(text).ord
84
- end
85
- end
86
-
87
- class Meta < AbstractMetaControlSequence
88
- def codepoint
89
- meta_char_to_codepoint(text[-1])
90
- end
91
- end
92
-
93
- class MetaControl < AbstractMetaControlSequence
94
- def codepoint
95
- meta_char_to_codepoint(control_sequence_to_s(text))
96
- end
97
- end
5
+ Base = Class.new(Regexp::Expression::Base)
6
+
7
+ AsciiEscape = Class.new(Base) # \e
8
+ Backspace = Class.new(Base) # \b
9
+ Bell = Class.new(Base) # \a
10
+ FormFeed = Class.new(Base) # \f
11
+ Newline = Class.new(Base) # \n
12
+ Return = Class.new(Base) # \r
13
+ Tab = Class.new(Base) # \t
14
+ VerticalTab = Class.new(Base) # \v
15
+
16
+ Literal = Class.new(Base) # e.g. \j, \@, \😀 (ineffectual escapes)
17
+
18
+ Octal = Class.new(Base) # e.g. \012
19
+ Hex = Class.new(Base) # e.g. \x0A
20
+ Codepoint = Class.new(Base) # e.g. \u000A
21
+
22
+ CodepointList = Class.new(Base) # e.g. \u{A B}
23
+ UTF8Hex = Class.new(Base) # e.g. \xE2\x82\xAC
24
+
25
+ AbstractMetaControlSequence = Class.new(Base)
26
+ Control = Class.new(AbstractMetaControlSequence) # e.g. \cB
27
+ Meta = Class.new(AbstractMetaControlSequence) # e.g. \M-Z
28
+ MetaControl = Class.new(AbstractMetaControlSequence) # e.g. \M-\cX
98
29
  end
99
30
 
100
31
  # alias for symmetry between Token::* and Expression::*
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Regexp::Expression
2
4
  class FreeSpace < Regexp::Expression::Base
3
5
  def quantify(*_args)
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Regexp::Expression
2
4
  module Group
3
5
  class Base < Regexp::Expression::Subexpression
@@ -1,6 +1,8 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Regexp::Expression
2
4
  module Keep
3
- # TOOD: in regexp_parser v3.0.0 this should possibly be a Subexpression
5
+ # TODO: in regexp_parser v3.0.0 this should possibly be a Subexpression
4
6
  # that contains all expressions to its left.
5
7
  class Mark < Regexp::Expression::Base; end
6
8
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Regexp::Expression
2
4
  class Literal < Regexp::Expression::Base; end
3
5
  end
@@ -1,9 +1,7 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Regexp::Expression
2
4
  class PosixClass < Regexp::Expression::Base
3
- def negative?
4
- type == :nonposixclass
5
- end
6
-
7
5
  def name
8
6
  text[/\w+/]
9
7
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Regexp::Expression
2
4
  class Root < Regexp::Expression::Subexpression
3
5
  def self.build(options = {})
@@ -1,10 +1,8 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Regexp::Expression
2
4
  module UnicodeProperty
3
5
  class Base < Regexp::Expression::Base
4
- def negative?
5
- type == :nonproperty
6
- end
7
-
8
6
  def name
9
7
  text[/\A\\[pP]\{([^}]+)\}\z/, 1]
10
8
  end
@@ -109,11 +107,12 @@ module Regexp::Expression
109
107
  class Unassigned < Codepoint::Base; end
110
108
  end
111
109
 
112
- class Age < UnicodeProperty::Base; end
113
- class Derived < UnicodeProperty::Base; end
114
- class Emoji < UnicodeProperty::Base; end
115
- class Script < UnicodeProperty::Base; end
116
- class Block < UnicodeProperty::Base; end
110
+ class Age < UnicodeProperty::Base; end
111
+ class Block < UnicodeProperty::Base; end
112
+ class Derived < UnicodeProperty::Base; end
113
+ class Emoji < UnicodeProperty::Base; end
114
+ class Enumerated < UnicodeProperty::Base; end
115
+ class Script < UnicodeProperty::Base; end
117
116
  end
118
117
 
119
118
  # alias for symmetry between token symbol and Expression class name
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Regexp::Expression
2
4
  module Shared
3
5
  module ClassMethods
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ Regexp::Expression::EscapeSequence::Base.class_eval do
4
+ def char
5
+ codepoint.chr('utf-8')
6
+ end
7
+ end
@@ -0,0 +1,76 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Regexp::Expression::EscapeSequence
4
+ AsciiEscape.class_eval { def codepoint; 0x1B end }
5
+ Backspace.class_eval { def codepoint; 0x8 end }
6
+ Bell.class_eval { def codepoint; 0x7 end }
7
+ FormFeed.class_eval { def codepoint; 0xC end }
8
+ Newline.class_eval { def codepoint; 0xA end }
9
+ Return.class_eval { def codepoint; 0xD end }
10
+ Tab.class_eval { def codepoint; 0x9 end }
11
+ VerticalTab.class_eval { def codepoint; 0xB end }
12
+
13
+ Literal.class_eval { def codepoint; text[1].ord end }
14
+
15
+ Octal.class_eval { def codepoint; text[/\d+/].to_i(8) end }
16
+
17
+ Hex.class_eval { def codepoint; text[/\h+/].hex end }
18
+ Codepoint.class_eval { def codepoint; text[/\h+/].hex end }
19
+
20
+ UTF8Hex.class_eval do
21
+ def codepoint
22
+ text.scan(/\h+/).map(&:hex).pack('C*').force_encoding('utf-8').ord
23
+ end
24
+ end
25
+
26
+ CodepointList.class_eval do
27
+ # Maybe this should be a unique top-level expression class?
28
+ def char
29
+ raise NoMethodError, 'CodepointList responds only to #chars'
30
+ end
31
+
32
+ def codepoint
33
+ raise NoMethodError, 'CodepointList responds only to #codepoints'
34
+ end
35
+
36
+ def chars
37
+ codepoints.map { |cp| cp.chr('utf-8') }
38
+ end
39
+
40
+ def codepoints
41
+ text.scan(/\h+/).map(&:hex)
42
+ end
43
+ end
44
+
45
+ AbstractMetaControlSequence.class_eval do
46
+ private
47
+
48
+ def control_sequence_to_s(control_sequence)
49
+ five_lsb = control_sequence.unpack('B*').first[-5..-1]
50
+ ["000#{five_lsb}"].pack('B*')
51
+ end
52
+
53
+ def meta_char_to_codepoint(meta_char)
54
+ byte_value = meta_char.ord
55
+ byte_value < 128 ? byte_value + 128 : byte_value
56
+ end
57
+ end
58
+
59
+ Control.class_eval do
60
+ def codepoint
61
+ control_sequence_to_s(text).ord
62
+ end
63
+ end
64
+
65
+ Meta.class_eval do
66
+ def codepoint
67
+ meta_char_to_codepoint(text[-1])
68
+ end
69
+ end
70
+
71
+ MetaControl.class_eval do
72
+ def codepoint
73
+ meta_char_to_codepoint(control_sequence_to_s(text))
74
+ end
75
+ end
76
+ end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Regexp::Expression
2
4
  module Shared
3
5
  # default implementation, e.g. "atomic group", "hex escape", "word type", ..
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Regexp::Expression
2
4
  class Base
3
5
  def match?(string)
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  class Regexp::MatchLength
2
4
  include Enumerable
3
5
 
@@ -0,0 +1,22 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Regexp::Expression
4
+ module Shared
5
+ def negative?
6
+ false
7
+ end
8
+
9
+ # not an alias so as to respect overrides of #negative?
10
+ def negated?
11
+ negative?
12
+ end
13
+ end
14
+
15
+ Anchor::NonWordBoundary.class_eval { def negative?; true end }
16
+ Assertion::NegativeLookahead.class_eval { def negative?; true end }
17
+ Assertion::NegativeLookbehind.class_eval { def negative?; true end }
18
+ CharacterSet.class_eval { def negative?; negative end }
19
+ CharacterType::Base.class_eval { def negative?; token.to_s.start_with?('non') end }
20
+ PosixClass.class_eval { def negative?; type == :nonposixclass end }
21
+ UnicodeProperty::Base.class_eval { def negative?; type == :nonproperty end }
22
+ end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Regexp::Expression
2
4
  class Base
3
5
  def multiline?
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Regexp::Expression
2
4
  module Shared
3
5
  # default implementation
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Regexp::Expression
2
4
  module Shared
3
5
  def inspect
@@ -0,0 +1,30 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Regexp::Expression
4
+ module ReferencedExpressions
5
+ attr_accessor :referenced_expressions
6
+
7
+ def referenced_expression
8
+ referenced_expressions && referenced_expressions.first
9
+ end
10
+
11
+ def initialize_copy(orig)
12
+ exp_id = [self.class, self.starts_at]
13
+
14
+ # prevent infinite recursion for recursive subexp calls
15
+ copied = self.class.instance_eval { @copied_ref_exps ||= {} }
16
+ self.referenced_expressions =
17
+ if copied[exp_id]
18
+ orig.referenced_expressions
19
+ else
20
+ copied[exp_id] = true
21
+ orig.referenced_expressions && orig.referenced_expressions.map(&:dup)
22
+ end
23
+ copied.clear
24
+
25
+ super
26
+ end
27
+ end
28
+
29
+ Base.include ReferencedExpressions
30
+ end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Regexp::Expression
2
4
  class Base
3
5
 
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Regexp::Expression
2
4
  module Shared
3
5
 
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Regexp::Expression
2
4
  class Subexpression < Regexp::Expression::Base
3
5
 
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Regexp::Expression
2
4
  # TODO: in v3.0.0, maybe put Shared back into Base, and inherit from Base and
3
5
  # call super in #initialize, but raise in #quantifier= and #quantify,
@@ -6,7 +8,7 @@ module Regexp::Expression
6
8
  class Quantifier
7
9
  include Regexp::Expression::Shared
8
10
 
9
- MODES = %i[greedy possessive reluctant]
11
+ MODES = %i[greedy possessive reluctant].freeze
10
12
 
11
13
  def initialize(*args)
12
14
  deprecated_old_init(*args) and return if args.count == 4 || args.count == 5
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Regexp::Expression
2
4
  # A sequence of expressions. Differs from a Subexpressions by how it handles
3
5
  # quantifiers, as it applies them to its last element instead of itself as
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Regexp::Expression
2
4
  # abstract class
3
5
  class SequenceOperation < Regexp::Expression::Subexpression