regexp_parser 1.3.0 → 1.7.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (172) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +72 -1
  3. data/Gemfile +3 -3
  4. data/README.md +12 -19
  5. data/Rakefile +3 -4
  6. data/lib/regexp_parser/expression.rb +28 -53
  7. data/lib/regexp_parser/expression/classes/backref.rb +18 -10
  8. data/lib/regexp_parser/expression/classes/conditional.rb +7 -2
  9. data/lib/regexp_parser/expression/classes/escape.rb +0 -4
  10. data/lib/regexp_parser/expression/classes/group.rb +4 -2
  11. data/lib/regexp_parser/expression/classes/keep.rb +1 -3
  12. data/lib/regexp_parser/expression/methods/match.rb +13 -0
  13. data/lib/regexp_parser/expression/methods/match_length.rb +172 -0
  14. data/lib/regexp_parser/expression/methods/options.rb +35 -0
  15. data/lib/regexp_parser/expression/methods/strfregexp.rb +0 -1
  16. data/lib/regexp_parser/expression/methods/tests.rb +6 -15
  17. data/lib/regexp_parser/expression/methods/traverse.rb +3 -1
  18. data/lib/regexp_parser/expression/quantifier.rb +2 -2
  19. data/lib/regexp_parser/expression/sequence.rb +3 -6
  20. data/lib/regexp_parser/expression/sequence_operation.rb +2 -6
  21. data/lib/regexp_parser/expression/subexpression.rb +3 -5
  22. data/lib/regexp_parser/lexer.rb +30 -44
  23. data/lib/regexp_parser/parser.rb +47 -24
  24. data/lib/regexp_parser/scanner.rb +1228 -1367
  25. data/lib/regexp_parser/scanner/char_type.rl +0 -3
  26. data/lib/regexp_parser/scanner/properties/long.yml +34 -1
  27. data/lib/regexp_parser/scanner/properties/short.yml +12 -0
  28. data/lib/regexp_parser/scanner/scanner.rl +101 -194
  29. data/lib/regexp_parser/syntax/tokens.rb +2 -10
  30. data/lib/regexp_parser/syntax/tokens/unicode_property.rb +72 -21
  31. data/lib/regexp_parser/syntax/versions/2.6.0.rb +10 -0
  32. data/lib/regexp_parser/syntax/versions/2.6.2.rb +10 -0
  33. data/lib/regexp_parser/syntax/versions/2.6.3.rb +10 -0
  34. data/lib/regexp_parser/version.rb +1 -1
  35. data/regexp_parser.gemspec +3 -3
  36. data/spec/expression/base_spec.rb +94 -0
  37. data/spec/expression/clone_spec.rb +120 -0
  38. data/spec/expression/conditional_spec.rb +89 -0
  39. data/spec/expression/free_space_spec.rb +27 -0
  40. data/spec/expression/methods/match_length_spec.rb +161 -0
  41. data/spec/expression/methods/match_spec.rb +25 -0
  42. data/spec/expression/methods/strfregexp_spec.rb +224 -0
  43. data/spec/expression/methods/tests_spec.rb +99 -0
  44. data/spec/expression/methods/traverse_spec.rb +161 -0
  45. data/spec/expression/options_spec.rb +128 -0
  46. data/spec/expression/root_spec.rb +9 -0
  47. data/spec/expression/sequence_spec.rb +9 -0
  48. data/spec/expression/subexpression_spec.rb +50 -0
  49. data/spec/expression/to_h_spec.rb +26 -0
  50. data/spec/expression/to_s_spec.rb +100 -0
  51. data/spec/lexer/all_spec.rb +22 -0
  52. data/spec/lexer/conditionals_spec.rb +53 -0
  53. data/spec/lexer/delimiters_spec.rb +68 -0
  54. data/spec/lexer/escapes_spec.rb +14 -0
  55. data/spec/lexer/keep_spec.rb +10 -0
  56. data/spec/lexer/literals_spec.rb +89 -0
  57. data/spec/lexer/nesting_spec.rb +99 -0
  58. data/spec/lexer/refcalls_spec.rb +55 -0
  59. data/spec/parser/all_spec.rb +43 -0
  60. data/spec/parser/alternation_spec.rb +88 -0
  61. data/spec/parser/anchors_spec.rb +17 -0
  62. data/spec/parser/conditionals_spec.rb +179 -0
  63. data/spec/parser/errors_spec.rb +30 -0
  64. data/spec/parser/escapes_spec.rb +121 -0
  65. data/spec/parser/free_space_spec.rb +130 -0
  66. data/spec/parser/groups_spec.rb +108 -0
  67. data/spec/parser/keep_spec.rb +6 -0
  68. data/spec/parser/posix_classes_spec.rb +8 -0
  69. data/spec/parser/properties_spec.rb +115 -0
  70. data/spec/parser/quantifiers_spec.rb +52 -0
  71. data/spec/parser/refcalls_spec.rb +112 -0
  72. data/spec/parser/set/intersections_spec.rb +127 -0
  73. data/spec/parser/set/ranges_spec.rb +111 -0
  74. data/spec/parser/sets_spec.rb +178 -0
  75. data/spec/parser/types_spec.rb +18 -0
  76. data/spec/scanner/all_spec.rb +18 -0
  77. data/spec/scanner/anchors_spec.rb +21 -0
  78. data/spec/scanner/conditionals_spec.rb +128 -0
  79. data/spec/scanner/delimiters_spec.rb +52 -0
  80. data/spec/scanner/errors_spec.rb +67 -0
  81. data/spec/scanner/escapes_spec.rb +53 -0
  82. data/spec/scanner/free_space_spec.rb +133 -0
  83. data/spec/scanner/groups_spec.rb +52 -0
  84. data/spec/scanner/keep_spec.rb +10 -0
  85. data/spec/scanner/literals_spec.rb +49 -0
  86. data/spec/scanner/meta_spec.rb +18 -0
  87. data/spec/scanner/properties_spec.rb +64 -0
  88. data/spec/scanner/quantifiers_spec.rb +20 -0
  89. data/spec/scanner/refcalls_spec.rb +36 -0
  90. data/spec/scanner/sets_spec.rb +102 -0
  91. data/spec/scanner/types_spec.rb +14 -0
  92. data/spec/spec_helper.rb +15 -0
  93. data/{test → spec}/support/runner.rb +9 -8
  94. data/spec/support/shared_examples.rb +77 -0
  95. data/{test → spec}/support/warning_extractor.rb +5 -7
  96. data/spec/syntax/syntax_spec.rb +48 -0
  97. data/spec/syntax/syntax_token_map_spec.rb +23 -0
  98. data/spec/syntax/versions/1.8.6_spec.rb +17 -0
  99. data/spec/syntax/versions/1.9.1_spec.rb +10 -0
  100. data/spec/syntax/versions/1.9.3_spec.rb +9 -0
  101. data/spec/syntax/versions/2.0.0_spec.rb +13 -0
  102. data/spec/syntax/versions/2.2.0_spec.rb +9 -0
  103. data/spec/syntax/versions/aliases_spec.rb +37 -0
  104. data/spec/token/token_spec.rb +85 -0
  105. metadata +151 -146
  106. data/test/expression/test_all.rb +0 -12
  107. data/test/expression/test_base.rb +0 -90
  108. data/test/expression/test_clone.rb +0 -89
  109. data/test/expression/test_conditionals.rb +0 -113
  110. data/test/expression/test_free_space.rb +0 -35
  111. data/test/expression/test_set.rb +0 -84
  112. data/test/expression/test_strfregexp.rb +0 -230
  113. data/test/expression/test_subexpression.rb +0 -58
  114. data/test/expression/test_tests.rb +0 -99
  115. data/test/expression/test_to_h.rb +0 -59
  116. data/test/expression/test_to_s.rb +0 -104
  117. data/test/expression/test_traverse.rb +0 -161
  118. data/test/helpers.rb +0 -10
  119. data/test/lexer/test_all.rb +0 -41
  120. data/test/lexer/test_conditionals.rb +0 -127
  121. data/test/lexer/test_keep.rb +0 -24
  122. data/test/lexer/test_literals.rb +0 -130
  123. data/test/lexer/test_nesting.rb +0 -132
  124. data/test/lexer/test_refcalls.rb +0 -56
  125. data/test/parser/set/test_intersections.rb +0 -127
  126. data/test/parser/set/test_ranges.rb +0 -111
  127. data/test/parser/test_all.rb +0 -64
  128. data/test/parser/test_alternation.rb +0 -92
  129. data/test/parser/test_anchors.rb +0 -34
  130. data/test/parser/test_conditionals.rb +0 -187
  131. data/test/parser/test_errors.rb +0 -63
  132. data/test/parser/test_escapes.rb +0 -134
  133. data/test/parser/test_free_space.rb +0 -139
  134. data/test/parser/test_groups.rb +0 -289
  135. data/test/parser/test_keep.rb +0 -21
  136. data/test/parser/test_posix_classes.rb +0 -27
  137. data/test/parser/test_properties.rb +0 -133
  138. data/test/parser/test_quantifiers.rb +0 -301
  139. data/test/parser/test_refcalls.rb +0 -186
  140. data/test/parser/test_sets.rb +0 -179
  141. data/test/parser/test_types.rb +0 -50
  142. data/test/scanner/test_all.rb +0 -38
  143. data/test/scanner/test_anchors.rb +0 -38
  144. data/test/scanner/test_conditionals.rb +0 -184
  145. data/test/scanner/test_errors.rb +0 -91
  146. data/test/scanner/test_escapes.rb +0 -56
  147. data/test/scanner/test_free_space.rb +0 -200
  148. data/test/scanner/test_groups.rb +0 -79
  149. data/test/scanner/test_keep.rb +0 -35
  150. data/test/scanner/test_literals.rb +0 -89
  151. data/test/scanner/test_meta.rb +0 -40
  152. data/test/scanner/test_properties.rb +0 -312
  153. data/test/scanner/test_quantifiers.rb +0 -37
  154. data/test/scanner/test_refcalls.rb +0 -52
  155. data/test/scanner/test_scripts.rb +0 -53
  156. data/test/scanner/test_sets.rb +0 -119
  157. data/test/scanner/test_types.rb +0 -35
  158. data/test/scanner/test_unicode_blocks.rb +0 -30
  159. data/test/support/disable_autotest.rb +0 -8
  160. data/test/syntax/test_all.rb +0 -6
  161. data/test/syntax/test_syntax.rb +0 -61
  162. data/test/syntax/test_syntax_token_map.rb +0 -25
  163. data/test/syntax/versions/test_1.8.rb +0 -55
  164. data/test/syntax/versions/test_1.9.1.rb +0 -36
  165. data/test/syntax/versions/test_1.9.3.rb +0 -32
  166. data/test/syntax/versions/test_2.0.0.rb +0 -37
  167. data/test/syntax/versions/test_2.2.0.rb +0 -32
  168. data/test/syntax/versions/test_aliases.rb +0 -129
  169. data/test/syntax/versions/test_all.rb +0 -5
  170. data/test/test_all.rb +0 -5
  171. data/test/token/test_all.rb +0 -2
  172. data/test/token/test_token.rb +0 -107
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 9af74355b57139b93d0207bfbf6fc6fbb43c1eb6aa531bd11710e39168af107a
4
- data.tar.gz: 8d63533aa2206b121fd59959a43cad2b64e3b3c6d0f8617953d2c401033c86d5
3
+ metadata.gz: dd872b22bf04a288790ef0f73df9041f14fb88a08c2a03852d9dbbc238b452d6
4
+ data.tar.gz: 4641097a24b5fa0f7b0c8e5aacc152587fe8b15d30f3f78bbec8157887b8b897
5
5
  SHA512:
6
- metadata.gz: de6afb1888075eaa8d220192882494eb67c54aaba5fa84b991adf753dbb06949b8b0ea6d44054d32c3cba1e8cb6ee04d8f8f2f8643e4663188ddca3b7ec7e07a
7
- data.tar.gz: f9e7d91a317bb153b645380a6447faca2656b87fa164afae9dc1cf9bc63463c11a87388258d18a49ed3df7afc3a7b25cd0a2113db412c2e7f504cee9aec8c255
6
+ metadata.gz: 858570df4a7047a2d8b09555b56de28a66ca4f8022e596c249900f5312f8e7fb9376384ca816bc3c08f3e324930702ad410a28b5be680adea6867e1f8075441e
7
+ data.tar.gz: 0d70e7b4f18739826bb334fb305e335e44a354ae302214ca3c1884f66ace8680e48a9e4c64b890b220b82056da761084413c8b9b8c5e363382f5cf165b3d3448
@@ -1,5 +1,76 @@
1
1
  ## [Unreleased]
2
2
 
3
+ ### [1.7.1] - 2020-06-07 - [Ammar Ali](mailto:ammarabuali@gmail.com)
4
+
5
+ ### Fixed
6
+
7
+ - Support for literals that include the unescaped delimiters `{`, `}`, and `]`. These
8
+ delimiters are informally supported by various regexp engines.
9
+
10
+ ### [1.7.0] - 2020-02-23 - [Janosch Müller](mailto:janosch84@gmail.com)
11
+
12
+ ### Added
13
+
14
+ - `Expression#each_expression` and `#traverse` can now be called without a block
15
+ * this returns an `Enumerator` and allows chaining, e.g. `each_expression.select`
16
+ * thanks to [Masataka Kuwabara](https://github.com/pocke)
17
+
18
+ ### Fixed
19
+
20
+ - `MatchLength#each` no longer ignores the given `limit:` when called without a block
21
+
22
+ ### [1.6.0] - 2019-06-16 - [Janosch Müller](mailto:janosch84@gmail.com)
23
+
24
+ ### Added
25
+
26
+ - Added support for 16 new unicode properties introduced in Ruby 2.6.2 and 2.6.3
27
+
28
+ ### [1.5.1] - 2019-05-23 - [Janosch Müller](mailto:janosch84@gmail.com)
29
+
30
+ ### Fixed
31
+
32
+ - Fixed `#options` (and thus `#i?`, `#u?` etc.) not being set for some expressions:
33
+ * this affected posix classes as well as alternation, conditional, and intersection branches
34
+ * `#options` was already correct for all child expressions of such branches
35
+ * this only made an operational difference for posix classes as they respect encoding flags
36
+ - Fixed `#options` not respecting all negative options in weird cases like '(?u-m-x)'
37
+ - Fixed `Group#option_changes` not accounting for indirectly disabled (overridden) encoding flags
38
+ - Fixed `Scanner` allowing negative encoding options if there were no positive options, e.g. '(?-u)'
39
+ - Fixed `ScannerError` for some valid meta/control sequences such as '\\C-\\\\'
40
+ - Fixed `Expression#match` and `#=~` not working with a single argument
41
+
42
+ ### [1.5.0] - 2019-05-14 - [Janosch Müller](mailto:janosch84@gmail.com)
43
+
44
+ ### Added
45
+
46
+ - Added `#referenced_expression` for backrefs, subexp calls and conditionals
47
+ * returns the `Group` expression that is being referenced via name or number
48
+ - Added `Expression#repetitions`
49
+ * returns a `Range` of allowed repetitions (`1..1` if there is no quantifier)
50
+ * like `#quantity` but with a more uniform interface
51
+ - Added `Expression#match_length`
52
+ * allows to inspect and iterate over String lengths matched by the Expression
53
+
54
+ ### Fixed
55
+
56
+ - Fixed `Expression#clone` "direction"
57
+ * it used to dup ivars onto the callee, leaving only the clone referencing the original objects
58
+ * this will affect you if you call `#eql?`/`#equal?` on expressions or use them as Hash keys
59
+ - Fixed `#clone` results for `Sequences`, e.g. alternations and conditionals
60
+ * the inner `#text` was cloned onto the `Sequence` and thus duplicated
61
+ * e.g. `Regexp::Parser.parse(/(a|bc)/).clone.to_s # => (aa|bcbc)`
62
+ - Fixed inconsistent `#to_s` output for `Sequences`
63
+ * it used to return only the "specific" text, e.g. "|" for an alternation
64
+ * now it includes nested expressions as it does for all other `Subexpressions`
65
+ - Fixed quantification of codepoint lists with more than one entry (`\u{62 63 64}+`)
66
+ * quantifiers apply only to the last entry, so this token is now split up if quantified
67
+
68
+ ### [1.4.0] - 2019-04-02 - [Janosch Müller](mailto:janosch84@gmail.com)
69
+
70
+ ### Added
71
+
72
+ - Added support for 19 new unicode properties introduced in Ruby 2.6.0
73
+
3
74
  ### [1.3.0] - 2018-11-14 - [Janosch Müller](mailto:janosch84@gmail.com)
4
75
 
5
76
  ### Added
@@ -69,7 +140,7 @@ This release includes several breaking changes, mostly to character sets, #map a
69
140
  - Changed `(?m)` and the likes to emit as `:options_switch` token (@4ade4d1)
70
141
  * allows differentiating from group-local `:options`, e.g. `(?m:.)`
71
142
  - Changed name of `Backreference::..NestLevel` to `..RecursionLevel` (@4184339)
72
- - Changed B`ackreference::Number#number` from `String` to `Integer` (@40a2231)
143
+ - Changed `Backreference::Number#number` from `String` to `Integer` (@40a2231)
73
144
 
74
145
  ### Added
75
146
 
data/Gemfile CHANGED
@@ -3,7 +3,7 @@ source 'https://rubygems.org'
3
3
  gemspec
4
4
 
5
5
  group :development, :test do
6
- gem 'rake'
7
- gem 'regexp_property_values'
8
- gem 'test-unit'
6
+ gem 'rake', '~> 13.0'
7
+ gem 'regexp_property_values', '~> 1.0'
8
+ gem 'rspec', '~> 3.8'
9
9
  end
data/README.md CHANGED
@@ -136,11 +136,8 @@ Regexp::Scanner.scan( /(cat?([bhm]at)){3,5}/ ).map {|token| token[2]}
136
136
  to the lexer.
137
137
 
138
138
  * The MRI implementation may accept expressions that either conflict with
139
- the documentation or are undocumented. The scanner does not support such
140
- implementation quirks.
141
- _(See issues [#3](https://github.com/ammar/regexp_parser/issues/3) and
142
- [#15](https://github.com/ammar/regexp_parser/issues/15) for examples)_
143
-
139
+ the documentation or are undocumented, like `{}` and `]` _(unescaped)_.
140
+ The scanner will try to support as many of these cases as possible.
144
141
 
145
142
  ---
146
143
  ### Syntax
@@ -357,7 +354,7 @@ _Note that not all of these are available in all versions of Ruby_
357
354
  |   _**Meta**_ | `\M-c`, `\M-\C-C`, `\M-\cC`, `\C-\M-C`, `\c\M-C` | ✓ |
358
355
  |   _**Octal**_ | `\0`, `\01`, `\012` | ✓ |
359
356
  |   _**Unicode**_ | `\uHHHH`, `\u{H+ H+}` | ✓ |
360
- | **Unicode Properties** | _<sub>([Unicode 10.0.0](http://www.unicode.org/versions/Unicode10.0.0/))</sub>_ | &#x22f1; |
357
+ | **Unicode Properties** | _<sub>([Unicode 11.0.0](http://www.unicode.org/versions/Unicode11.0.0/))</sub>_ | &#x22f1; |
361
358
  | &emsp;&nbsp;_**Age**_ | `\p{Age=5.2}`, `\P{age=7.0}`, `\p{^age=8.0}` | &#x2713; |
362
359
  | &emsp;&nbsp;_**Blocks**_ | `\p{InArmenian}`, `\P{InKhmer}`, `\p{^InThai}` | &#x2713; |
363
360
  | &emsp;&nbsp;_**Classes**_ | `\p{Alpha}`, `\P{Space}`, `\p{^Alnum}` | &#x2713; |
@@ -391,28 +388,22 @@ To run the tests simply run rake from the root directory, as 'test' is the defau
391
388
 
392
389
  It generates the scanner's code from the Ragel source files and runs all the tests, thus it requires Ragel to be installed.
393
390
 
394
- The tests use Ruby's test/unit. They can also be run with:
391
+ The tests use RSpec. They can also be run with the test runner that whitelists some warnings:
395
392
 
396
393
  ```
397
394
  bin/test
398
395
  ```
399
396
 
400
- The test runner accepts all arguments accepted by test/unit. You can run a specific test like so:
401
-
402
- ```
403
- bin/test test/scanner/test_properties.rb
404
- ```
405
-
406
- It is sometimes helpful during development to focus on a specific test case, for example:
397
+ You can run a specific test like so:
407
398
 
408
399
  ```
409
- bin/test test/expression/test_base.rb -n test_expression_to_re
400
+ bin/test spec/scanner/properties_spec.rb
410
401
  ```
411
402
 
412
- Note that changes to Ragel files will not be reflected when using `bin/test`, so you might want to run:
403
+ Note that changes to Ragel files will not be reflected when running `rspec` or `bin/test`, so you might want to run:
413
404
 
414
405
  ```
415
- rake ragel:rb && bin/test test/scanner/test_properties.rb
406
+ rake ragel:rb && bin/test spec/scanner/properties_spec.rb
416
407
  ```
417
408
 
418
409
  ## Building
@@ -440,7 +431,9 @@ Projects using regexp_parser.
440
431
 
441
432
  - [meta_re](https://github.com/ammar/meta_re) is a regular expression preprocessor with alias support.
442
433
 
443
- - [mutant](https://github.com/mbj/mutant) manipulates your regular expressions (amongst others) to see if your tests cover their behavior.
434
+ - [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
+
436
+ - [twitter-cldr-rb](https://github.com/twitter/twitter-cldr-rb) uses regexp_parser to generate examples of postal codes.
444
437
 
445
438
  - [js_regex](https://github.com/janosch-x/js_regex) converts Ruby regular expressions to JavaScript-compatible regular expressions.
446
439
 
@@ -471,4 +464,4 @@ Documentation and books used while working on this project.
471
464
 
472
465
  ---
473
466
  ##### Copyright
474
- _Copyright (c) 2010-2016 Ammar Ali. See LICENSE file for details._
467
+ _Copyright (c) 2010-2019 Ammar Ali. See LICENSE file for details._
data/Rakefile CHANGED
@@ -74,14 +74,13 @@ namespace :props do
74
74
  puts "Wrote #{hash.count} aliases to `#{path}`"
75
75
  end
76
76
 
77
- _, long_names = RegexpPropertyValues.short_and_long_names
78
- long_names_to_tokens = long_names.map do |name|
79
- [name.downcase.gsub(/[^0-9a-z=.]/, ''), name.downcase]
77
+ long_names_to_tokens = RegexpPropertyValues.all.map do |val|
78
+ [val.identifier, val.full_name.downcase]
80
79
  end
81
80
  write_hash_to_file.call(long_names_to_tokens, "#{dir}/long.yml")
82
81
 
83
82
  short_names_to_tokens = RegexpPropertyValues.alias_hash.map do |k, v|
84
- [k.downcase.gsub(/[^0-9a-z=.]/, ''), v.downcase]
83
+ [k.identifier, v.full_name.downcase]
85
84
  end
86
85
  write_hash_to_file.call(short_names_to_tokens, "#{dir}/short.yml")
87
86
  end
@@ -21,10 +21,10 @@ module Regexp::Expression
21
21
  self.options = options
22
22
  end
23
23
 
24
- def initialize_clone(other)
25
- other.text = (text ? text.dup : nil)
26
- other.options = (options ? options.dup : nil)
27
- other.quantifier = (quantifier ? quantifier.clone : nil)
24
+ def initialize_clone(orig)
25
+ self.text = (orig.text ? orig.text.dup : nil)
26
+ self.options = (orig.options ? orig.options.dup : nil)
27
+ self.quantifier = (orig.quantifier ? orig.quantifier.clone : nil)
28
28
  super
29
29
  end
30
30
 
@@ -62,15 +62,28 @@ module Regexp::Expression
62
62
  self.quantifier = Quantifier.new(token, text, min, max, mode)
63
63
  end
64
64
 
65
+ def unquantified_clone
66
+ clone.tap { |exp| exp.quantifier = nil }
67
+ end
68
+
65
69
  def quantified?
66
70
  !quantifier.nil?
67
71
  end
68
72
 
73
+ # Deprecated. Prefer `#repetitions` which has a more uniform interface.
69
74
  def quantity
70
75
  return [nil,nil] unless quantified?
71
76
  [quantifier.min, quantifier.max]
72
77
  end
73
78
 
79
+ def repetitions
80
+ return 1..1 unless quantified?
81
+ min = quantifier.min
82
+ 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] } }
85
+ end
86
+
74
87
  def greedy?
75
88
  quantified? and quantifier.greedy?
76
89
  end
@@ -84,49 +97,6 @@ module Regexp::Expression
84
97
  quantified? and quantifier.possessive?
85
98
  end
86
99
 
87
- def multiline?
88
- options[:m] == true
89
- end
90
- alias :m? :multiline?
91
-
92
- def case_insensitive?
93
- options[:i] == true
94
- end
95
- alias :i? :case_insensitive?
96
- alias :ignore_case? :case_insensitive?
97
-
98
- def free_spacing?
99
- options[:x] == true
100
- end
101
- alias :x? :free_spacing?
102
- alias :extended? :free_spacing?
103
-
104
- if RUBY_VERSION >= '2.0'
105
- def default_classes?
106
- options[:d] == true
107
- end
108
- alias :d? :default_classes?
109
-
110
- def ascii_classes?
111
- options[:a] == true
112
- end
113
- alias :a? :ascii_classes?
114
-
115
- def unicode_classes?
116
- options[:u] == true
117
- end
118
- alias :u? :unicode_classes?
119
- end
120
-
121
- def matches?(string)
122
- Regexp.new(to_s) =~ string ? true : false
123
- end
124
-
125
- def match(string, offset)
126
- Regexp.new(to_s).match(string, offset)
127
- end
128
- alias :=~ :match
129
-
130
100
  def attributes
131
101
  {
132
102
  type: type,
@@ -145,12 +115,14 @@ module Regexp::Expression
145
115
  end
146
116
 
147
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.')
148
120
  case exp
149
121
  when String
150
122
  Regexp::Parser.parse(exp)
151
123
  when Regexp
152
- Regexp::Parser.parse(exp.source)
153
- when Regexp::Expression
124
+ Regexp::Parser.parse(exp.source) # <- causes loss of root options
125
+ when Regexp::Expression # <- never triggers
154
126
  exp
155
127
  else
156
128
  raise ArgumentError, 'Expression.parsed accepts a String, Regexp, or '\
@@ -161,10 +133,6 @@ module Regexp::Expression
161
133
 
162
134
  end # module Regexp::Expression
163
135
 
164
- require 'regexp_parser/expression/methods/tests'
165
- require 'regexp_parser/expression/methods/traverse'
166
- require 'regexp_parser/expression/methods/strfregexp'
167
-
168
136
  require 'regexp_parser/expression/quantifier'
169
137
  require 'regexp_parser/expression/subexpression'
170
138
  require 'regexp_parser/expression/sequence'
@@ -186,3 +154,10 @@ require 'regexp_parser/expression/classes/set'
186
154
  require 'regexp_parser/expression/classes/set/intersection'
187
155
  require 'regexp_parser/expression/classes/set/range'
188
156
  require 'regexp_parser/expression/classes/type'
157
+
158
+ require 'regexp_parser/expression/methods/match'
159
+ require 'regexp_parser/expression/methods/match_length'
160
+ require 'regexp_parser/expression/methods/options'
161
+ require 'regexp_parser/expression/methods/strfregexp'
162
+ require 'regexp_parser/expression/methods/tests'
163
+ require 'regexp_parser/expression/methods/traverse'
@@ -1,9 +1,12 @@
1
1
  module Regexp::Expression
2
2
  module Backreference
3
- class Base < Regexp::Expression::Base; end
3
+ class Base < Regexp::Expression::Base
4
+ attr_accessor :referenced_expression
5
+ end
4
6
 
5
7
  class Number < Backreference::Base
6
8
  attr_reader :number
9
+ alias reference number
7
10
 
8
11
  def initialize(token, options = {})
9
12
  @number = token.text[token.token.equal?(:number) ? 1..-1 : 3..-2].to_i
@@ -13,6 +16,7 @@ module Regexp::Expression
13
16
 
14
17
  class Name < Backreference::Base
15
18
  attr_reader :name
19
+ alias reference name
16
20
 
17
21
  def initialize(token, options = {})
18
22
  @name = token.text[3..-2]
@@ -20,27 +24,31 @@ module Regexp::Expression
20
24
  end
21
25
  end
22
26
 
27
+ class NumberRelative < Backreference::Number
28
+ attr_accessor :effective_number
29
+ alias reference effective_number
30
+ end
31
+
23
32
  class NumberCall < Backreference::Number; end
24
- class NumberRelative < Backreference::Number; end
25
- class NumberCallRelative < Backreference::Number; end
26
- class NameCall < Backreference::Name; end
33
+ class NameCall < Backreference::Name; end
34
+ class NumberCallRelative < Backreference::NumberRelative; end
27
35
 
28
- class NumberRecursionLevel < Backreference::Base
29
- attr_reader :number, :recursion_level
36
+ class NumberRecursionLevel < Backreference::Number
37
+ attr_reader :recursion_level
30
38
 
31
39
  def initialize(token, options = {})
32
- @number, @recursion_level = token.text[3..-2].split(/(?=[+-])/).map(&:to_i)
33
40
  super
41
+ @number, @recursion_level = token.text[3..-2].split(/(?=[+-])/).map(&:to_i)
34
42
  end
35
43
  end
36
44
 
37
- class NameRecursionLevel < Backreference::Base
38
- attr_reader :name, :recursion_level
45
+ class NameRecursionLevel < Backreference::Name
46
+ attr_reader :recursion_level
39
47
 
40
48
  def initialize(token, options = {})
49
+ super
41
50
  @name, recursion_level = token.text[3..-2].split(/(?=[+-])/)
42
51
  @recursion_level = recursion_level.to_i
43
- super
44
52
  end
45
53
  end
46
54
  end
@@ -7,6 +7,8 @@ module Regexp::Expression
7
7
  end
8
8
 
9
9
  class Condition < Regexp::Expression::Base
10
+ attr_accessor :referenced_expression
11
+
10
12
  # Name or number of the referenced capturing group that determines state.
11
13
  # Returns a String if reference is by name, Integer if by number.
12
14
  def reference
@@ -18,13 +20,16 @@ module Regexp::Expression
18
20
  class Branch < Regexp::Expression::Sequence; end
19
21
 
20
22
  class Expression < Regexp::Expression::Subexpression
23
+ attr_accessor :referenced_expression
24
+
21
25
  def <<(exp)
22
26
  expressions.last << exp
23
27
  end
24
28
 
25
- def add_sequence
29
+ def add_sequence(active_opts = {})
26
30
  raise TooManyBranches.new if branches.length == 2
27
- Branch.add_to(self, { conditional_level: conditional_level + 1 })
31
+ params = { conditional_level: conditional_level + 1 }
32
+ Branch.add_to(self, params, active_opts)
28
33
  end
29
34
  alias :branch :add_sequence
30
35
 
@@ -60,10 +60,6 @@ module Regexp::Expression
60
60
  codepoint.chr('utf-8')
61
61
  end
62
62
 
63
- def codepoint
64
- raise NotImplementedError, 'implement in subclass'
65
- end
66
-
67
63
  private
68
64
 
69
65
  def control_sequence_to_s(control_sequence)
@@ -19,20 +19,22 @@ module Regexp::Expression
19
19
 
20
20
  class Capture < Group::Base
21
21
  attr_accessor :number, :number_at_level
22
+ alias identifier number
22
23
 
23
24
  def capturing?; true end
24
25
  end
25
26
 
26
27
  class Named < Group::Capture
27
28
  attr_reader :name
29
+ alias identifier name
28
30
 
29
31
  def initialize(token, options = {})
30
32
  @name = token.text[3..-2]
31
33
  super
32
34
  end
33
35
 
34
- def initialize_clone(other)
35
- other.instance_variable_set(:@name, name.dup)
36
+ def initialize_clone(orig)
37
+ @name = orig.name.dup
36
38
  super
37
39
  end
38
40
  end