regexp_parser 1.7.1 → 2.1.1

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 (58) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +138 -0
  3. data/Gemfile +6 -1
  4. data/README.md +23 -11
  5. data/Rakefile +8 -8
  6. data/lib/regexp_parser/error.rb +4 -0
  7. data/lib/regexp_parser/expression.rb +13 -21
  8. data/lib/regexp_parser/expression/classes/backref.rb +5 -0
  9. data/lib/regexp_parser/expression/classes/conditional.rb +11 -1
  10. data/lib/regexp_parser/expression/classes/free_space.rb +2 -2
  11. data/lib/regexp_parser/expression/classes/group.rb +28 -3
  12. data/lib/regexp_parser/expression/classes/property.rb +1 -1
  13. data/lib/regexp_parser/expression/classes/root.rb +4 -16
  14. data/lib/regexp_parser/expression/classes/set/range.rb +2 -1
  15. data/lib/regexp_parser/expression/methods/match_length.rb +2 -2
  16. data/lib/regexp_parser/expression/methods/traverse.rb +2 -2
  17. data/lib/regexp_parser/expression/quantifier.rb +10 -1
  18. data/lib/regexp_parser/expression/sequence.rb +3 -19
  19. data/lib/regexp_parser/expression/subexpression.rb +1 -1
  20. data/lib/regexp_parser/lexer.rb +6 -6
  21. data/lib/regexp_parser/parser.rb +325 -344
  22. data/lib/regexp_parser/scanner.rb +1320 -1385
  23. data/lib/regexp_parser/scanner/char_type.rl +11 -11
  24. data/lib/regexp_parser/scanner/property.rl +2 -2
  25. data/lib/regexp_parser/scanner/scanner.rl +231 -253
  26. data/lib/regexp_parser/syntax.rb +8 -6
  27. data/lib/regexp_parser/syntax/any.rb +3 -3
  28. data/lib/regexp_parser/syntax/base.rb +1 -1
  29. data/lib/regexp_parser/syntax/version_lookup.rb +4 -4
  30. data/lib/regexp_parser/version.rb +1 -1
  31. data/regexp_parser.gemspec +1 -1
  32. data/spec/expression/base_spec.rb +10 -0
  33. data/spec/expression/clone_spec.rb +36 -4
  34. data/spec/expression/free_space_spec.rb +2 -2
  35. data/spec/expression/methods/match_length_spec.rb +2 -2
  36. data/spec/expression/subexpression_spec.rb +1 -1
  37. data/spec/expression/to_s_spec.rb +39 -31
  38. data/spec/lexer/literals_spec.rb +24 -49
  39. data/spec/lexer/refcalls_spec.rb +5 -0
  40. data/spec/parser/all_spec.rb +2 -2
  41. data/spec/parser/errors_spec.rb +1 -1
  42. data/spec/parser/escapes_spec.rb +1 -1
  43. data/spec/parser/options_spec.rb +28 -0
  44. data/spec/parser/quantifiers_spec.rb +16 -0
  45. data/spec/parser/refcalls_spec.rb +5 -0
  46. data/spec/parser/set/ranges_spec.rb +3 -3
  47. data/spec/scanner/escapes_spec.rb +12 -1
  48. data/spec/scanner/free_space_spec.rb +32 -0
  49. data/spec/scanner/groups_spec.rb +10 -1
  50. data/spec/scanner/literals_spec.rb +28 -38
  51. data/spec/scanner/options_spec.rb +36 -0
  52. data/spec/scanner/quantifiers_spec.rb +18 -13
  53. data/spec/scanner/refcalls_spec.rb +19 -0
  54. data/spec/scanner/sets_spec.rb +65 -16
  55. data/spec/spec_helper.rb +1 -0
  56. metadata +61 -60
  57. data/spec/expression/root_spec.rb +0 -9
  58. data/spec/expression/sequence_spec.rb +0 -9
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: dd872b22bf04a288790ef0f73df9041f14fb88a08c2a03852d9dbbc238b452d6
4
- data.tar.gz: 4641097a24b5fa0f7b0c8e5aacc152587fe8b15d30f3f78bbec8157887b8b897
3
+ metadata.gz: 077b8a0c90d90cf46e44671ec1335a5373eef72c61a0bcf4de43ba5217a188c3
4
+ data.tar.gz: b9aed868af73adcdf40c09720c5d10091b25a53b25a792717ceb5591039a2931
5
5
  SHA512:
6
- metadata.gz: 858570df4a7047a2d8b09555b56de28a66ca4f8022e596c249900f5312f8e7fb9376384ca816bc3c08f3e324930702ad410a28b5be680adea6867e1f8075441e
7
- data.tar.gz: 0d70e7b4f18739826bb334fb305e335e44a354ae302214ca3c1884f66ace8680e48a9e4c64b890b220b82056da761084413c8b9b8c5e363382f5cf165b3d3448
6
+ metadata.gz: 9c04d9a6434c6e3f322e97e8e2a1c86b3ddda88bd8821368a37b92f5836e4c3df1dc27a79165303420c3e8d5eea31bda1483824da01a40ce30961b645ba65ddd
7
+ data.tar.gz: 01e5c261e9dca0c4df7c696128dbc0520ca40aa6b9393cc8d6c3bdb8386470aeb773566000b811f98c1407038216c8d2c0b444c7955ea5a881ac759796f8a440
data/CHANGELOG.md CHANGED
@@ -1,5 +1,143 @@
1
1
  ## [Unreleased]
2
2
 
3
+ ## [2.1.1] - 2021-02-23 - [Janosch Müller](mailto:janosch84@gmail.com)
4
+
5
+ ### Fixed
6
+
7
+ - fixed `NameError` when requiring only `'regexp_parser/scanner'` in v2.1.0
8
+ * thanks to [Jared White and Sam Ruby](https://github.com/ruby2js/ruby2js) for the report
9
+
10
+ ## [2.1.0] - 2021-02-22 - [Janosch Müller](mailto:janosch84@gmail.com)
11
+
12
+ ### Added
13
+
14
+ - common ancestor for all scanning/parsing/lexing errors
15
+ * `Regexp::Parser::Error` can now be rescued as a catch-all
16
+ * the following errors (and their many descendants) now inherit from it:
17
+ - `Regexp::Expression::Conditional::TooManyBranches`
18
+ - `Regexp::Parser::ParserError`
19
+ - `Regexp::Scanner::ScannerError`
20
+ - `Regexp::Scanner::ValidationError`
21
+ - `Regexp::Syntax::SyntaxError`
22
+ * it replaces `ArgumentError` in some rare cases (`Regexp::Parser.parse('?')`)
23
+ * thanks to [sandstrom](https://github.com/sandstrom) for the cue
24
+
25
+ ### Fixed
26
+
27
+ - fixed scanning of whole-pattern recursion calls `\g<0>` and `\g'0'`
28
+ * a regression in v2.0.1 had caused them to be scanned as literals
29
+ - fixed scanning of some backreference and subexpression call edge cases
30
+ * e.g. `\k<+1>`, `\g<x-1>`
31
+ - fixed tokenization of some escapes in character sets
32
+ * `.`, `|`, `{`, `}`, `(`, `)`, `^`, `$`, `?`, `+`, `*`
33
+ * all of these correctly emitted `#type` `:literal` and `#token` `:literal` if *not* escaped
34
+ * if escaped, they emitted e.g. `#type` `:escape` and `#token` `:group_open` for `[\(]`
35
+ * the escaped versions now correctly emit `#type` `:escape` and `#token` `:literal`
36
+ - fixed handling of control/metacontrol escapes in character sets
37
+ * e.g. `[\cX]`, `[\M-\C-X]`
38
+ * they were misread as bunch of individual literals, escapes, and ranges
39
+ - fixed some cases where calling `#dup`/`#clone` on expressions led to shared state
40
+
41
+ ## [2.0.3] - 2020-12-28 - [Janosch Müller](mailto:janosch84@gmail.com)
42
+
43
+ ### Fixed
44
+
45
+ - fixed error when scanning some unlikely and redundant but valid charset patterns
46
+ * e.g. `/[[.a-b.]]/`, `/[[=e=]]/`,
47
+ - fixed ancestry of some error classes related to syntax version lookup
48
+ * `NotImplementedError`, `InvalidVersionNameError`, `UnknownSyntaxNameError`
49
+ * they now correctly inherit from `Regexp::Syntax::SyntaxError` instead of Rubys `::SyntaxError`
50
+
51
+ ## [2.0.2] - 2020-12-25 - [Janosch Müller](mailto:janosch84@gmail.com)
52
+
53
+ ### Fixed
54
+
55
+ - fixed `FrozenError` when calling `#to_s` on a frozen `Group::Passive`
56
+ * thanks to [Daniel Gollahon](https://github.com/dgollahon)
57
+
58
+ ## [2.0.1] - 2020-12-20 - [Janosch Müller](mailto:janosch84@gmail.com)
59
+
60
+ ### Fixed
61
+
62
+ - fixed error when scanning some group names
63
+ * this affected names containing hyphens, digits or multibyte chars, e.g. `/(?<a1>a)/`
64
+ * thanks to [Daniel Gollahon](https://github.com/dgollahon) for the report
65
+ - fixed error when scanning hex escapes with just one hex digit
66
+ * e.g. `/\x0A/` was scanned correctly, but the equivalent `/\xA/` was not
67
+ * thanks to [Daniel Gollahon](https://github.com/dgollahon) for the report
68
+
69
+ ## [2.0.0] - 2020-11-25 - [Janosch Müller](mailto:janosch84@gmail.com)
70
+
71
+ ### Changed
72
+
73
+ - some methods that used to return byte-based indices now return char-based indices
74
+ * the returned values have only changed for Regexps that contain multibyte chars
75
+ * this is only a breaking change if you used such methods directly AND relied on them pointing to bytes
76
+ * affected methods:
77
+ * `Regexp::Token` `#length`, `#offset`, `#te`, `#ts`
78
+ * `Regexp::Expression::Base` `#full_length`, `#offset`, `#starts_at`, `#te`, `#ts`
79
+ * thanks to [Akinori MUSHA](https://github.com/knu) for the report
80
+ - removed some deprecated methods/signatures
81
+ * these are rarely used and have been showing deprecation warnings for a long time
82
+ * `Regexp::Expression::Subexpression.new` with 3 arguments
83
+ * `Regexp::Expression::Root.new` without a token argument
84
+ * `Regexp::Expression.parsed`
85
+
86
+ ### Added
87
+
88
+ - `Regexp::Expression::Base#base_length`
89
+ * returns the character count of an expression body, ignoring any quantifier
90
+ - pragmatic, experimental support for chained quantifiers
91
+ * e.g.: `/^a{10}{4,6}$/` matches exactly 40, 50 or 60 `a`s
92
+ * successive quantifiers used to be silently dropped by the parser
93
+ * they are now wrapped with passive groups as if they were written `(?:a{10}){4,6}`
94
+ * thanks to [calfeld](https://github.com/calfeld) for reporting this a while back
95
+
96
+ ### Fixed
97
+
98
+ - incorrect encoding output for non-ascii comments
99
+ * this led to a crash when calling `#to_s` on parse results containing such comments
100
+ * thanks to [Michael Glass](https://github.com/michaelglass) for the report
101
+ - some crashes when scanning contrived patterns such as `'\😋'`
102
+
103
+ ### [1.8.2] - 2020-10-11 - [Janosch Müller](mailto:janosch84@gmail.com)
104
+
105
+ ### Fixed
106
+
107
+ - fix `FrozenError` in `Expression::Base#repetitions` on Ruby 3.0
108
+ * thanks to [Thomas Walpole](https://github.com/twalpole)
109
+ - removed "unknown future version" warning on Ruby 3.0
110
+
111
+ ### [1.8.1] - 2020-09-28 - [Janosch Müller](mailto:janosch84@gmail.com)
112
+
113
+ ### Fixed
114
+
115
+ - fixed scanning of comment-like text in normal mode
116
+ * this was an old bug, but had become more prevalent in v1.8.0
117
+ * thanks to [Tietew](https://github.com/Tietew) for the report
118
+ - specified correct minimum Ruby version in gemspec
119
+ * it said 1.9 but really required 2.0 as of v1.8.0
120
+
121
+ ### [1.8.0] - 2020-09-20 - [Janosch Müller](mailto:janosch84@gmail.com)
122
+
123
+ ### Changed
124
+
125
+ - dropped support for running on Ruby 1.9.x
126
+
127
+ ### Added
128
+
129
+ - regexp flags can now be passed when parsing a `String` as regexp body
130
+ * see the [README](/README.md#usage) for details
131
+ * thanks to [Owen Stephens](https://github.com/owst)
132
+ - bare occurrences of `\g` and `\k` are now allowed and scanned as literal escapes
133
+ * matches Onigmo behavior
134
+ * thanks for the report to [Marc-André Lafortune](https://github.com/marcandre)
135
+
136
+ ### Fixed
137
+
138
+ - fixed parsing comments without preceding space or trailing newline in x-mode
139
+ * thanks to [Owen Stephens](https://github.com/owst)
140
+
3
141
  ### [1.7.1] - 2020-06-07 - [Ammar Ali](mailto:ammarabuali@gmail.com)
4
142
 
5
143
  ### Fixed
data/Gemfile CHANGED
@@ -3,7 +3,12 @@ source 'https://rubygems.org'
3
3
  gemspec
4
4
 
5
5
  group :development, :test do
6
+ gem 'ice_nine', '~> 0.11.2'
6
7
  gem 'rake', '~> 13.0'
7
8
  gem 'regexp_property_values', '~> 1.0'
8
- gem 'rspec', '~> 3.8'
9
+ gem 'rspec', '~> 3.10'
10
+ if RUBY_VERSION.to_f >= 2.7
11
+ gem 'gouteur'
12
+ gem 'rubocop', '~> 1.7'
13
+ end
9
14
  end
data/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # Regexp::Parser
2
2
 
3
- [![Gem Version](https://badge.fury.io/rb/regexp_parser.svg)](http://badge.fury.io/rb/regexp_parser) [![Build Status](https://secure.travis-ci.org/ammar/regexp_parser.svg?branch=master)](http://travis-ci.org/ammar/regexp_parser) [![Code Climate](https://codeclimate.com/github/ammar/regexp_parser.svg)](https://codeclimate.com/github/ammar/regexp_parser/badges)
3
+ [![Gem Version](https://badge.fury.io/rb/regexp_parser.svg)](http://badge.fury.io/rb/regexp_parser) [![Build Status](https://github.com/ammar/regexp_parser/workflows/tests/badge.svg)](https://github.com/ammar/regexp_parser/actions) [![Build Status](https://github.com/ammar/regexp_parser/workflows/gouteur/badge.svg)](https://github.com/ammar/regexp_parser/actions) [![Code Climate](https://codeclimate.com/github/ammar/regexp_parser.svg)](https://codeclimate.com/github/ammar/regexp_parser/badges)
4
4
 
5
5
  A Ruby gem for tokenizing, parsing, and transforming regular expressions.
6
6
 
@@ -8,8 +8,8 @@ A Ruby gem for tokenizing, parsing, and transforming regular expressions.
8
8
  * A scanner/tokenizer based on [Ragel](http://www.colm.net/open-source/ragel/)
9
9
  * A lexer that produces a "stream" of token objects.
10
10
  * A parser that produces a "tree" of Expression objects (OO API)
11
- * Runs on Ruby 1.9, 2.x, and JRuby (1.9 mode) runtimes.
12
- * Recognizes Ruby 1.8, 1.9, and 2.x regular expressions [See Supported Syntax](#supported-syntax)
11
+ * Runs on Ruby 2.x, 3.x and JRuby runtimes
12
+ * Recognizes Ruby 1.8, 1.9, 2.x and 3.x regular expressions [See Supported Syntax](#supported-syntax)
13
13
 
14
14
 
15
15
  _For examples of regexp_parser in use, see [Example Projects](#example-projects)._
@@ -18,13 +18,10 @@ _For examples of regexp_parser in use, see [Example Projects](#example-projects)
18
18
  ---
19
19
  ## Requirements
20
20
 
21
- * Ruby >= 1.9
21
+ * Ruby >= 2.0
22
22
  * Ragel >= 6.0, but only if you want to build the gem or work on the scanner.
23
23
 
24
24
 
25
- _Note: See the .travis.yml file for covered versions._
26
-
27
-
28
25
  ---
29
26
  ## Install
30
27
 
@@ -72,6 +69,17 @@ called with the results as follows:
72
69
  * **Parser**: after completion, the block gets passed the root expression.
73
70
  _The result of the block is returned._
74
71
 
72
+ All three methods accept either a `Regexp` or `String` (containing the pattern)
73
+ - if a String is passed, `options` can be supplied:
74
+
75
+ ```ruby
76
+ require 'regexp_parser'
77
+
78
+ Regexp::Parser.parse(
79
+ "a+ # Recognises a and A...",
80
+ options: ::Regexp::EXTENDED | ::Regexp::IGNORECASE
81
+ )
82
+ ```
75
83
 
76
84
  ---
77
85
  ## Components
@@ -306,7 +314,7 @@ Expression class. See the next section for details._
306
314
 
307
315
  ## Supported Syntax
308
316
  The three modules support all the regular expression syntax features of Ruby 1.8,
309
- 1.9, and 2.x:
317
+ 1.9, 2.x and 3.x:
310
318
 
311
319
  _Note that not all of these are available in all versions of Ruby_
312
320
 
@@ -429,13 +437,17 @@ rake install
429
437
  ## Example Projects
430
438
  Projects using regexp_parser.
431
439
 
440
+ - [capybara](https://github.com/teamcapybara/capybara) is an integration testing tool that uses regexp_parser to convert Regexps to css/xpath selectors.
441
+
442
+ - [js_regex](https://github.com/janosch-x/js_regex) converts Ruby regular expressions to JavaScript-compatible regular expressions.
443
+
432
444
  - [meta_re](https://github.com/ammar/meta_re) is a regular expression preprocessor with alias support.
433
445
 
434
446
  - [mutant](https://github.com/mbj/mutant) (before v0.9.0) manipulates your regular expressions (amongst others) to see if your tests cover their behavior.
435
447
 
436
- - [twitter-cldr-rb](https://github.com/twitter/twitter-cldr-rb) uses regexp_parser to generate examples of postal codes.
448
+ - [rubocop](https://github.com/rubocop-hq/rubocop) is a linter for Ruby that uses regexp_parser to lint Regexps.
437
449
 
438
- - [js_regex](https://github.com/janosch-x/js_regex) converts Ruby regular expressions to JavaScript-compatible regular expressions.
450
+ - [twitter-cldr-rb](https://github.com/twitter/twitter-cldr-rb) is a localization helper that uses regexp_parser to generate examples of postal codes.
439
451
 
440
452
 
441
453
  ## References
@@ -464,4 +476,4 @@ Documentation and books used while working on this project.
464
476
 
465
477
  ---
466
478
  ##### Copyright
467
- _Copyright (c) 2010-2019 Ammar Ali. See LICENSE file for details._
479
+ _Copyright (c) 2010-2020 Ammar Ali. See LICENSE file for details._
data/Rakefile CHANGED
@@ -7,8 +7,8 @@ require 'bundler'
7
7
  require 'rubygems/package_task'
8
8
 
9
9
 
10
- RAGEL_SOURCE_DIR = File.expand_path '../lib/regexp_parser/scanner', __FILE__
11
- RAGEL_OUTPUT_DIR = File.expand_path '../lib/regexp_parser', __FILE__
10
+ RAGEL_SOURCE_DIR = File.join(__dir__, 'lib/regexp_parser/scanner')
11
+ RAGEL_OUTPUT_DIR = File.join(__dir__, 'lib/regexp_parser')
12
12
  RAGEL_SOURCE_FILES = %w{scanner} # scanner.rl includes property.rl
13
13
 
14
14
 
@@ -25,11 +25,11 @@ end
25
25
 
26
26
  namespace :ragel do
27
27
  desc "Process the ragel source files and output ruby code"
28
- task :rb do |t|
29
- RAGEL_SOURCE_FILES.each do |file|
30
- output_file = "#{RAGEL_OUTPUT_DIR}/#{file}.rb"
28
+ task :rb do
29
+ RAGEL_SOURCE_FILES.each do |source_file|
30
+ output_file = "#{RAGEL_OUTPUT_DIR}/#{source_file}.rb"
31
31
  # using faster flat table driven FSM, about 25% larger code, but about 30% faster
32
- sh "ragel -F1 -R #{RAGEL_SOURCE_DIR}/#{file}.rl -o #{output_file}"
32
+ sh "ragel -F1 -R #{RAGEL_SOURCE_DIR}/#{source_file}.rl -o #{output_file}"
33
33
 
34
34
  contents = File.read(output_file)
35
35
 
@@ -42,7 +42,7 @@ namespace :ragel do
42
42
  end
43
43
 
44
44
  desc "Delete the ragel generated source file(s)"
45
- task :clean do |t|
45
+ task :clean do
46
46
  RAGEL_SOURCE_FILES.each do |file|
47
47
  sh "rm -f #{RAGEL_OUTPUT_DIR}/#{file}.rb"
48
48
  end
@@ -61,7 +61,7 @@ namespace :props do
61
61
  task :update do
62
62
  require 'regexp_property_values'
63
63
  RegexpPropertyValues.update
64
- dir = File.expand_path('../lib/regexp_parser/scanner/properties', __FILE__)
64
+ dir = File.join(__dir__, 'lib/regexp_parser/scanner/properties')
65
65
 
66
66
  require 'psych'
67
67
  write_hash_to_file = ->(hash, path) do
@@ -0,0 +1,4 @@
1
+ class Regexp::Parser
2
+ # base class for all gem-specific errors (inherited but never raised itself)
3
+ class Error < StandardError; end
4
+ end
@@ -1,5 +1,6 @@
1
- module Regexp::Expression
1
+ require 'regexp_parser/error'
2
2
 
3
+ module Regexp::Expression
3
4
  class Base
4
5
  attr_accessor :type, :token
5
6
  attr_accessor :text, :ts
@@ -21,7 +22,7 @@ module Regexp::Expression
21
22
  self.options = options
22
23
  end
23
24
 
24
- def initialize_clone(orig)
25
+ def initialize_copy(orig)
25
26
  self.text = (orig.text ? orig.text.dup : nil)
26
27
  self.options = (orig.options ? orig.options.dup : nil)
27
28
  self.quantifier = (orig.quantifier ? orig.quantifier.clone : nil)
@@ -34,6 +35,10 @@ module Regexp::Expression
34
35
 
35
36
  alias :starts_at :ts
36
37
 
38
+ def base_length
39
+ to_s(:base).length
40
+ end
41
+
37
42
  def full_length
38
43
  to_s.length
39
44
  end
@@ -80,8 +85,12 @@ module Regexp::Expression
80
85
  return 1..1 unless quantified?
81
86
  min = quantifier.min
82
87
  max = quantifier.max < 0 ? Float::INFINITY : quantifier.max
83
- # fix Range#minmax - https://bugs.ruby-lang.org/issues/15807
84
- (min..max).tap { |r| r.define_singleton_method(:minmax) { [min, max] } }
88
+ range = min..max
89
+ # fix Range#minmax on old Rubies - https://bugs.ruby-lang.org/issues/15807
90
+ if RUBY_VERSION.to_f < 2.7
91
+ range.define_singleton_method(:minmax) { [min, max] }
92
+ end
93
+ range
85
94
  end
86
95
 
87
96
  def greedy?
@@ -114,23 +123,6 @@ module Regexp::Expression
114
123
  alias :to_h :attributes
115
124
  end
116
125
 
117
- def self.parsed(exp)
118
- warn('WARNING: Regexp::Expression::Base.parsed is buggy and '\
119
- 'will be removed in 2.0.0. Use Regexp::Parser.parse instead.')
120
- case exp
121
- when String
122
- Regexp::Parser.parse(exp)
123
- when Regexp
124
- Regexp::Parser.parse(exp.source) # <- causes loss of root options
125
- when Regexp::Expression # <- never triggers
126
- exp
127
- else
128
- raise ArgumentError, 'Expression.parsed accepts a String, Regexp, or '\
129
- 'a Regexp::Expression as a value for exp, but it '\
130
- "was given #{exp.class.name}."
131
- end
132
- end
133
-
134
126
  end # module Regexp::Expression
135
127
 
136
128
  require 'regexp_parser/expression/quantifier'
@@ -2,6 +2,11 @@ module Regexp::Expression
2
2
  module Backreference
3
3
  class Base < Regexp::Expression::Base
4
4
  attr_accessor :referenced_expression
5
+
6
+ def initialize_copy(orig)
7
+ self.referenced_expression = orig.referenced_expression.dup
8
+ super
9
+ end
5
10
  end
6
11
 
7
12
  class Number < Backreference::Base
@@ -1,6 +1,6 @@
1
1
  module Regexp::Expression
2
2
  module Conditional
3
- class TooManyBranches < StandardError
3
+ class TooManyBranches < Regexp::Parser::Error
4
4
  def initialize
5
5
  super('The conditional expression has more than 2 branches')
6
6
  end
@@ -15,6 +15,11 @@ module Regexp::Expression
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
18
23
  end
19
24
 
20
25
  class Branch < Regexp::Expression::Sequence; end
@@ -53,6 +58,11 @@ module Regexp::Expression
53
58
  def to_s(format = :full)
54
59
  "#{text}#{condition}#{branches.join('|')})#{quantifier_affix(format)}"
55
60
  end
61
+
62
+ def initialize_copy(orig)
63
+ self.referenced_expression = orig.referenced_expression.dup
64
+ super
65
+ end
56
66
  end
57
67
  end
58
68
  end
@@ -1,8 +1,8 @@
1
1
  module Regexp::Expression
2
2
 
3
3
  class FreeSpace < Regexp::Expression::Base
4
- def quantify(token, text, min = nil, max = nil, mode = :greedy)
5
- raise "Can not quantify a free space object"
4
+ def quantify(_token, _text, _min = nil, _max = nil, _mode = :greedy)
5
+ raise Regexp::Parser::Error, 'Can not quantify a free space object'
6
6
  end
7
7
  end
8
8
 
@@ -10,11 +10,36 @@ module Regexp::Expression
10
10
  def comment?; false end
11
11
  end
12
12
 
13
- class Atomic < Group::Base; end
14
- class Passive < Group::Base; end
13
+ class Passive < Group::Base
14
+ attr_writer :implicit
15
+
16
+ def initialize(*)
17
+ @implicit = false
18
+ super
19
+ end
20
+
21
+ def to_s(format = :full)
22
+ if implicit?
23
+ "#{expressions.join}#{quantifier_affix(format)}"
24
+ else
25
+ super
26
+ end
27
+ end
28
+
29
+ def implicit?
30
+ @implicit
31
+ end
32
+ end
33
+
15
34
  class Absence < Group::Base; end
35
+ class Atomic < Group::Base; end
16
36
  class Options < Group::Base
17
37
  attr_accessor :option_changes
38
+
39
+ def initialize_copy(orig)
40
+ self.option_changes = orig.option_changes.dup
41
+ super
42
+ end
18
43
  end
19
44
 
20
45
  class Capture < Group::Base
@@ -33,7 +58,7 @@ module Regexp::Expression
33
58
  super
34
59
  end
35
60
 
36
- def initialize_clone(orig)
61
+ def initialize_copy(orig)
37
62
  @name = orig.name.dup
38
63
  super
39
64
  end