regexp_parser 1.7.1 → 2.2.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 (139) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +157 -1
  3. data/Gemfile +6 -1
  4. data/LICENSE +1 -1
  5. data/README.md +38 -32
  6. data/Rakefile +18 -27
  7. data/lib/regexp_parser/error.rb +4 -0
  8. data/lib/regexp_parser/expression/base.rb +123 -0
  9. data/lib/regexp_parser/expression/classes/anchor.rb +0 -2
  10. data/lib/regexp_parser/expression/classes/{backref.rb → backreference.rb} +5 -0
  11. data/lib/regexp_parser/expression/classes/{set → character_set}/intersection.rb +0 -0
  12. data/lib/regexp_parser/expression/classes/{set → character_set}/range.rb +2 -1
  13. data/lib/regexp_parser/expression/classes/{set.rb → character_set.rb} +0 -0
  14. data/lib/regexp_parser/expression/classes/conditional.rb +11 -1
  15. data/lib/regexp_parser/expression/classes/{escape.rb → escape_sequence.rb} +13 -7
  16. data/lib/regexp_parser/expression/classes/free_space.rb +2 -4
  17. data/lib/regexp_parser/expression/classes/group.rb +28 -3
  18. data/lib/regexp_parser/expression/classes/literal.rb +1 -5
  19. data/lib/regexp_parser/expression/classes/property.rb +1 -3
  20. data/lib/regexp_parser/expression/classes/root.rb +4 -17
  21. data/lib/regexp_parser/expression/classes/type.rb +0 -2
  22. data/lib/regexp_parser/expression/methods/match_length.rb +2 -2
  23. data/lib/regexp_parser/expression/methods/strfregexp.rb +1 -1
  24. data/lib/regexp_parser/expression/methods/traverse.rb +2 -2
  25. data/lib/regexp_parser/expression/quantifier.rb +11 -2
  26. data/lib/regexp_parser/expression/sequence.rb +3 -20
  27. data/lib/regexp_parser/expression/subexpression.rb +1 -2
  28. data/lib/regexp_parser/expression.rb +7 -139
  29. data/lib/regexp_parser/lexer.rb +13 -11
  30. data/lib/regexp_parser/parser.rb +325 -344
  31. data/lib/regexp_parser/scanner/char_type.rl +11 -11
  32. data/lib/regexp_parser/scanner/properties/long.csv +604 -0
  33. data/lib/regexp_parser/scanner/properties/short.csv +242 -0
  34. data/lib/regexp_parser/scanner/property.rl +2 -2
  35. data/lib/regexp_parser/scanner/scanner.rl +235 -255
  36. data/lib/regexp_parser/scanner.rb +1324 -1387
  37. data/lib/regexp_parser/syntax/any.rb +4 -6
  38. data/lib/regexp_parser/syntax/base.rb +13 -15
  39. data/lib/regexp_parser/syntax/token/anchor.rb +15 -0
  40. data/lib/regexp_parser/syntax/{tokens → token}/assertion.rb +2 -2
  41. data/lib/regexp_parser/syntax/token/backreference.rb +30 -0
  42. data/lib/regexp_parser/syntax/{tokens → token}/character_set.rb +2 -2
  43. data/lib/regexp_parser/syntax/{tokens → token}/character_type.rb +3 -3
  44. data/lib/regexp_parser/syntax/{tokens → token}/conditional.rb +3 -3
  45. data/lib/regexp_parser/syntax/token/escape.rb +31 -0
  46. data/lib/regexp_parser/syntax/{tokens → token}/group.rb +7 -7
  47. data/lib/regexp_parser/syntax/{tokens → token}/keep.rb +1 -1
  48. data/lib/regexp_parser/syntax/{tokens → token}/meta.rb +2 -2
  49. data/lib/regexp_parser/syntax/{tokens → token}/posix_class.rb +3 -3
  50. data/lib/regexp_parser/syntax/token/quantifier.rb +35 -0
  51. data/lib/regexp_parser/syntax/token/unicode_property.rb +696 -0
  52. data/lib/regexp_parser/syntax/token.rb +45 -0
  53. data/lib/regexp_parser/syntax/version_lookup.rb +4 -4
  54. data/lib/regexp_parser/syntax/versions/1.8.6.rb +2 -2
  55. data/lib/regexp_parser/syntax/versions/1.9.1.rb +1 -1
  56. data/lib/regexp_parser/syntax/versions/3.1.0.rb +10 -0
  57. data/lib/regexp_parser/syntax.rb +8 -6
  58. data/lib/regexp_parser/token.rb +9 -20
  59. data/lib/regexp_parser/version.rb +1 -1
  60. data/lib/regexp_parser.rb +0 -2
  61. data/regexp_parser.gemspec +20 -22
  62. metadata +34 -165
  63. data/lib/regexp_parser/scanner/properties/long.yml +0 -594
  64. data/lib/regexp_parser/scanner/properties/short.yml +0 -237
  65. data/lib/regexp_parser/syntax/tokens/anchor.rb +0 -15
  66. data/lib/regexp_parser/syntax/tokens/backref.rb +0 -24
  67. data/lib/regexp_parser/syntax/tokens/escape.rb +0 -30
  68. data/lib/regexp_parser/syntax/tokens/quantifier.rb +0 -35
  69. data/lib/regexp_parser/syntax/tokens/unicode_property.rb +0 -675
  70. data/lib/regexp_parser/syntax/tokens.rb +0 -45
  71. data/spec/expression/base_spec.rb +0 -94
  72. data/spec/expression/clone_spec.rb +0 -120
  73. data/spec/expression/conditional_spec.rb +0 -89
  74. data/spec/expression/free_space_spec.rb +0 -27
  75. data/spec/expression/methods/match_length_spec.rb +0 -161
  76. data/spec/expression/methods/match_spec.rb +0 -25
  77. data/spec/expression/methods/strfregexp_spec.rb +0 -224
  78. data/spec/expression/methods/tests_spec.rb +0 -99
  79. data/spec/expression/methods/traverse_spec.rb +0 -161
  80. data/spec/expression/options_spec.rb +0 -128
  81. data/spec/expression/root_spec.rb +0 -9
  82. data/spec/expression/sequence_spec.rb +0 -9
  83. data/spec/expression/subexpression_spec.rb +0 -50
  84. data/spec/expression/to_h_spec.rb +0 -26
  85. data/spec/expression/to_s_spec.rb +0 -100
  86. data/spec/lexer/all_spec.rb +0 -22
  87. data/spec/lexer/conditionals_spec.rb +0 -53
  88. data/spec/lexer/delimiters_spec.rb +0 -68
  89. data/spec/lexer/escapes_spec.rb +0 -14
  90. data/spec/lexer/keep_spec.rb +0 -10
  91. data/spec/lexer/literals_spec.rb +0 -89
  92. data/spec/lexer/nesting_spec.rb +0 -99
  93. data/spec/lexer/refcalls_spec.rb +0 -55
  94. data/spec/parser/all_spec.rb +0 -43
  95. data/spec/parser/alternation_spec.rb +0 -88
  96. data/spec/parser/anchors_spec.rb +0 -17
  97. data/spec/parser/conditionals_spec.rb +0 -179
  98. data/spec/parser/errors_spec.rb +0 -30
  99. data/spec/parser/escapes_spec.rb +0 -121
  100. data/spec/parser/free_space_spec.rb +0 -130
  101. data/spec/parser/groups_spec.rb +0 -108
  102. data/spec/parser/keep_spec.rb +0 -6
  103. data/spec/parser/posix_classes_spec.rb +0 -8
  104. data/spec/parser/properties_spec.rb +0 -115
  105. data/spec/parser/quantifiers_spec.rb +0 -52
  106. data/spec/parser/refcalls_spec.rb +0 -112
  107. data/spec/parser/set/intersections_spec.rb +0 -127
  108. data/spec/parser/set/ranges_spec.rb +0 -111
  109. data/spec/parser/sets_spec.rb +0 -178
  110. data/spec/parser/types_spec.rb +0 -18
  111. data/spec/scanner/all_spec.rb +0 -18
  112. data/spec/scanner/anchors_spec.rb +0 -21
  113. data/spec/scanner/conditionals_spec.rb +0 -128
  114. data/spec/scanner/delimiters_spec.rb +0 -52
  115. data/spec/scanner/errors_spec.rb +0 -67
  116. data/spec/scanner/escapes_spec.rb +0 -53
  117. data/spec/scanner/free_space_spec.rb +0 -133
  118. data/spec/scanner/groups_spec.rb +0 -52
  119. data/spec/scanner/keep_spec.rb +0 -10
  120. data/spec/scanner/literals_spec.rb +0 -49
  121. data/spec/scanner/meta_spec.rb +0 -18
  122. data/spec/scanner/properties_spec.rb +0 -64
  123. data/spec/scanner/quantifiers_spec.rb +0 -20
  124. data/spec/scanner/refcalls_spec.rb +0 -36
  125. data/spec/scanner/sets_spec.rb +0 -102
  126. data/spec/scanner/types_spec.rb +0 -14
  127. data/spec/spec_helper.rb +0 -15
  128. data/spec/support/runner.rb +0 -42
  129. data/spec/support/shared_examples.rb +0 -77
  130. data/spec/support/warning_extractor.rb +0 -60
  131. data/spec/syntax/syntax_spec.rb +0 -48
  132. data/spec/syntax/syntax_token_map_spec.rb +0 -23
  133. data/spec/syntax/versions/1.8.6_spec.rb +0 -17
  134. data/spec/syntax/versions/1.9.1_spec.rb +0 -10
  135. data/spec/syntax/versions/1.9.3_spec.rb +0 -9
  136. data/spec/syntax/versions/2.0.0_spec.rb +0 -13
  137. data/spec/syntax/versions/2.2.0_spec.rb +0 -9
  138. data/spec/syntax/versions/aliases_spec.rb +0 -37
  139. data/spec/token/token_spec.rb +0 -85
@@ -1,224 +0,0 @@
1
- require 'spec_helper'
2
-
3
- RSpec.describe('Expression#strfregexp') do
4
- specify('#strfre alias') do
5
- expect(RP.parse(/a/)).to respond_to(:strfre)
6
- end
7
-
8
- specify('#strfregexp level') do
9
- root = RP.parse(/a(b(c))/)
10
-
11
- expect(root.strfregexp('%l')).to eq 'root'
12
-
13
- a = root.first
14
- expect(a.strfregexp('%%l')).to eq '%0'
15
-
16
- b = root[1].first
17
- expect(b.strfregexp('<%l>')).to eq '<1>'
18
-
19
- c = root[1][1].first
20
- expect(c.strfregexp('[at: %l]')).to eq '[at: 2]'
21
- end
22
-
23
- specify('#strfregexp start end') do
24
- root = RP.parse(/a(b(c))/)
25
-
26
- expect(root.strfregexp('%s')).to eq '0'
27
- expect(root.strfregexp('%e')).to eq '7'
28
-
29
- a = root.first
30
- expect(a.strfregexp('%%s')).to eq '%0'
31
- expect(a.strfregexp('%e')).to eq '1'
32
-
33
- group_1 = root[1]
34
- expect(group_1.strfregexp('GRP:%s')).to eq 'GRP:1'
35
- expect(group_1.strfregexp('%e')).to eq '7'
36
-
37
- b = group_1.first
38
- expect(b.strfregexp('<@%s>')).to eq '<@2>'
39
- expect(b.strfregexp('%e')).to eq '3'
40
-
41
- c = group_1.last.first
42
- expect(c.strfregexp('[at: %s]')).to eq '[at: 4]'
43
- expect(c.strfregexp('%e')).to eq '5'
44
- end
45
-
46
- specify('#strfregexp length') do
47
- root = RP.parse(/a[b]c/)
48
-
49
- expect(root.strfregexp('%S')).to eq '5'
50
-
51
- a = root.first
52
- expect(a.strfregexp('%S')).to eq '1'
53
-
54
- set = root[1]
55
- expect(set.strfregexp('%S')).to eq '3'
56
- end
57
-
58
- specify('#strfregexp coded offset') do
59
- root = RP.parse(/a[b]c/)
60
-
61
- expect(root.strfregexp('%o')).to eq '@0+5'
62
-
63
- a = root.first
64
- expect(a.strfregexp('%o')).to eq '@0+1'
65
-
66
- set = root[1]
67
- expect(set.strfregexp('%o')).to eq '@1+3'
68
- end
69
-
70
- specify('#strfregexp type token') do
71
- root = RP.parse(/a[b](c)/)
72
-
73
- expect(root.strfregexp('%y')).to eq 'expression'
74
- expect(root.strfregexp('%k')).to eq 'root'
75
- expect(root.strfregexp('%i')).to eq 'expression:root'
76
- expect(root.strfregexp('%c')).to eq 'Regexp::Expression::Root'
77
-
78
- a = root.first
79
- expect(a.strfregexp('%y')).to eq 'literal'
80
- expect(a.strfregexp('%k')).to eq 'literal'
81
- expect(a.strfregexp('%i')).to eq 'literal:literal'
82
- expect(a.strfregexp('%c')).to eq 'Regexp::Expression::Literal'
83
-
84
- set = root[1]
85
- expect(set.strfregexp('%y')).to eq 'set'
86
- expect(set.strfregexp('%k')).to eq 'character'
87
- expect(set.strfregexp('%i')).to eq 'set:character'
88
- expect(set.strfregexp('%c')).to eq 'Regexp::Expression::CharacterSet'
89
-
90
- group = root.last
91
- expect(group.strfregexp('%y')).to eq 'group'
92
- expect(group.strfregexp('%k')).to eq 'capture'
93
- expect(group.strfregexp('%i')).to eq 'group:capture'
94
- expect(group.strfregexp('%c')).to eq 'Regexp::Expression::Group::Capture'
95
- end
96
-
97
- specify('#strfregexp quantifier') do
98
- root = RP.parse(/a+[b](c)?d{3,4}/)
99
-
100
- expect(root.strfregexp('%q')).to eq '{1}'
101
- expect(root.strfregexp('%Q')).to eq ''
102
- expect(root.strfregexp('%z, %Z')).to eq '1, 1'
103
-
104
- a = root.first
105
- expect(a.strfregexp('%q')).to eq '{1, or-more}'
106
- expect(a.strfregexp('%Q')).to eq '+'
107
- expect(a.strfregexp('%z, %Z')).to eq '1, -1'
108
-
109
- set = root[1]
110
- expect(set.strfregexp('%q')).to eq '{1}'
111
- expect(set.strfregexp('%Q')).to eq ''
112
- expect(set.strfregexp('%z, %Z')).to eq '1, 1'
113
-
114
- group = root[2]
115
- expect(group.strfregexp('%q')).to eq '{0, 1}'
116
- expect(group.strfregexp('%Q')).to eq '?'
117
- expect(group.strfregexp('%z, %Z')).to eq '0, 1'
118
-
119
- d = root.last
120
- expect(d.strfregexp('%q')).to eq '{3, 4}'
121
- expect(d.strfregexp('%Q')).to eq '{3,4}'
122
- expect(d.strfregexp('%z, %Z')).to eq '3, 4'
123
- end
124
-
125
- specify('#strfregexp text') do
126
- root = RP.parse(/a(b(c))|[d-gk-p]+/)
127
-
128
- expect(root.strfregexp('%t')).to eq 'a(b(c))|[d-gk-p]+'
129
- expect(root.strfregexp('%~t')).to eq 'expression:root'
130
-
131
- alt = root.first
132
- expect(alt.strfregexp('%t')).to eq 'a(b(c))|[d-gk-p]+'
133
- expect(alt.strfregexp('%T')).to eq 'a(b(c))|[d-gk-p]+'
134
- expect(alt.strfregexp('%~t')).to eq 'meta:alternation'
135
-
136
- seq_1 = alt.first
137
- expect(seq_1.strfregexp('%t')).to eq 'a(b(c))'
138
- expect(seq_1.strfregexp('%T')).to eq 'a(b(c))'
139
- expect(seq_1.strfregexp('%~t')).to eq 'expression:sequence'
140
-
141
- group = seq_1[1]
142
- expect(group.strfregexp('%t')).to eq '(b(c))'
143
- expect(group.strfregexp('%T')).to eq '(b(c))'
144
- expect(group.strfregexp('%~t')).to eq 'group:capture'
145
-
146
- seq_2 = alt.last
147
- expect(seq_2.strfregexp('%t')).to eq '[d-gk-p]+'
148
- expect(seq_2.strfregexp('%T')).to eq '[d-gk-p]+'
149
-
150
- set = seq_2.first
151
- expect(set.strfregexp('%t')).to eq '[d-gk-p]'
152
- expect(set.strfregexp('%T')).to eq '[d-gk-p]+'
153
- expect(set.strfregexp('%~t')).to eq 'set:character'
154
- end
155
-
156
- specify('#strfregexp combined') do
157
- root = RP.parse(/a{5}|[b-d]+/)
158
-
159
- expect(root.strfregexp('%b')).to eq '@0+11 expression:root'
160
- expect(root.strfregexp('%b')).to eq root.strfregexp('%o %i')
161
-
162
- expect(root.strfregexp('%m')).to eq '@0+11 expression:root {1}'
163
- expect(root.strfregexp('%m')).to eq root.strfregexp('%b %q')
164
-
165
- expect(root.strfregexp('%a')).to eq '@0+11 expression:root {1} a{5}|[b-d]+'
166
- expect(root.strfregexp('%a')).to eq root.strfregexp('%m %t')
167
- end
168
-
169
- specify('#strfregexp conditional') do
170
- root = RP.parse('(?<A>a)(?(<A>)b|c)', 'ruby/2.0')
171
-
172
- expect { root.strfregexp }.not_to(raise_error)
173
- end
174
-
175
- specify('#strfregexp_tree') do
176
- root = RP.parse(/a[b-d]*(e(f+))?/)
177
-
178
- expect(root.strfregexp_tree('%>%o %~t')).to eq(
179
- "@0+15 expression:root\n" +
180
- " @0+1 a\n" +
181
- " @1+6 set:character\n" +
182
- " @2+3 set:range\n" +
183
- " @2+1 b\n" +
184
- " @4+1 d\n" +
185
- " @7+8 group:capture\n" +
186
- " @8+1 e\n" +
187
- " @9+4 group:capture\n" +
188
- " @10+2 f+"
189
- )
190
- end
191
-
192
- specify('#strfregexp_tree separator') do
193
- root = RP.parse(/a[b-d]*(e(f+))?/)
194
-
195
- expect(root.strfregexp_tree('%>%o %~t', true, '-SEP-')).to eq(
196
- "@0+15 expression:root-SEP-" +
197
- " @0+1 a-SEP-" +
198
- " @1+6 set:character-SEP-" +
199
- " @2+3 set:range-SEP-" +
200
- " @2+1 b-SEP-" +
201
- " @4+1 d-SEP-" +
202
- " @7+8 group:capture-SEP-" +
203
- " @8+1 e-SEP-" +
204
- " @9+4 group:capture-SEP-" +
205
- " @10+2 f+"
206
- )
207
- end
208
-
209
- specify('#strfregexp_tree excluding self') do
210
- root = RP.parse(/a[b-d]*(e(f+))?/)
211
-
212
- expect(root.strfregexp_tree('%>%o %~t', false)).to eq(
213
- "@0+1 a\n" +
214
- "@1+6 set:character\n" +
215
- " @2+3 set:range\n" +
216
- " @2+1 b\n" +
217
- " @4+1 d\n" +
218
- "@7+8 group:capture\n" +
219
- " @8+1 e\n" +
220
- " @9+4 group:capture\n" +
221
- " @10+2 f+"
222
- )
223
- end
224
- end
@@ -1,99 +0,0 @@
1
- require 'spec_helper'
2
-
3
- RSpec.describe('ExpressionTests') do
4
- specify('#type?') do
5
- root = RP.parse(/abcd|(ghij)|[klmn]/)
6
-
7
- alt = root.first
8
-
9
- expect(alt.type?(:meta)).to be true
10
- expect(alt.type?(:escape)).to be false
11
- expect(alt.type?(%i[meta escape])).to be true
12
- expect(alt.type?(%i[literal escape])).to be false
13
- expect(alt.type?(:*)).to be true
14
- expect(alt.type?([:*])).to be true
15
- expect(alt.type?(%i[literal escape *])).to be true
16
-
17
- seq_1 = alt[0]
18
- expect(seq_1.type?(:expression)).to be true
19
- expect(seq_1.first.type?(:literal)).to be true
20
-
21
- seq_2 = alt[1]
22
- expect(seq_2.type?(:*)).to be true
23
- expect(seq_2.first.type?(:group)).to be true
24
-
25
- seq_3 = alt[2]
26
- expect(seq_3.first.type?(:set)).to be true
27
- end
28
-
29
- specify('#is?') do
30
- root = RP.parse(/.+|\.?/)
31
-
32
- expect(root.is?(:*)).to be true
33
-
34
- alt = root.first
35
- expect(alt.is?(:*)).to be true
36
- expect(alt.is?(:alternation)).to be true
37
- expect(alt.is?(:alternation, :meta)).to be true
38
-
39
- seq_1 = alt[0]
40
- expect(seq_1.is?(:sequence)).to be true
41
- expect(seq_1.is?(:sequence, :expression)).to be true
42
-
43
- expect(seq_1.first.is?(:dot)).to be true
44
- expect(seq_1.first.is?(:dot, :escape)).to be false
45
- expect(seq_1.first.is?(:dot, :meta)).to be true
46
- expect(seq_1.first.is?(:dot, %i[escape meta])).to be true
47
-
48
- seq_2 = alt[1]
49
- expect(seq_2.first.is?(:dot)).to be true
50
- expect(seq_2.first.is?(:dot, :escape)).to be true
51
- expect(seq_2.first.is?(:dot, :meta)).to be false
52
- expect(seq_2.first.is?(:dot, %i[meta escape])).to be true
53
- end
54
-
55
- specify('#one_of?') do
56
- root = RP.parse(/\Aab(c[\w])d|e.\z/)
57
-
58
- expect(root.one_of?(:*)).to be true
59
- expect(root.one_of?(:* => :*)).to be true
60
- expect(root.one_of?(:* => [:*])).to be true
61
-
62
- alt = root.first
63
- expect(alt.one_of?(:*)).to be true
64
- expect(alt.one_of?(:meta)).to be true
65
- expect(alt.one_of?(:meta, :alternation)).to be true
66
- expect(alt.one_of?(meta: %i[dot bogus])).to be false
67
- expect(alt.one_of?(meta: %i[dot alternation])).to be true
68
-
69
- seq_1 = alt[0]
70
- expect(seq_1.one_of?(:expression)).to be true
71
- expect(seq_1.one_of?(expression: :sequence)).to be true
72
-
73
- expect(seq_1.first.one_of?(:anchor)).to be true
74
- expect(seq_1.first.one_of?(anchor: :bos)).to be true
75
- expect(seq_1.first.one_of?(anchor: :eos)).to be false
76
- expect(seq_1.first.one_of?(anchor: %i[escape meta bos])).to be true
77
- expect(seq_1.first.one_of?(anchor: %i[escape meta eos])).to be false
78
-
79
- seq_2 = alt[1]
80
- expect(seq_2.first.one_of?(:literal)).to be true
81
-
82
- expect(seq_2[1].one_of?(:meta)).to be true
83
- expect(seq_2[1].one_of?(meta: :dot)).to be true
84
- expect(seq_2[1].one_of?(meta: :alternation)).to be false
85
- expect(seq_2[1].one_of?(meta: [:dot])).to be true
86
-
87
- expect(seq_2.last.one_of?(:group)).to be false
88
- expect(seq_2.last.one_of?(group: [:*])).to be false
89
- expect(seq_2.last.one_of?(group: [:*], meta: :*)).to be false
90
-
91
- expect(seq_2.last.one_of?(:meta => [:*], :* => :*)).to be true
92
- expect(seq_2.last.one_of?(meta: [:*], anchor: :*)).to be true
93
- expect(seq_2.last.one_of?(meta: [:*], anchor: :eos)).to be true
94
- expect(seq_2.last.one_of?(meta: [:*], anchor: [:bos])).to be false
95
- expect(seq_2.last.one_of?(meta: [:*], anchor: %i[bos eos])).to be true
96
-
97
- expect { root.one_of?(Object.new) }.to raise_error(ArgumentError)
98
- end
99
- end
@@ -1,161 +0,0 @@
1
- require 'spec_helper'
2
-
3
- RSpec.describe('Subexpression#traverse') do
4
- specify('Subexpression#traverse') do
5
- root = RP.parse(/a(b(c(d)))|g[h-i]j|klmn/)
6
-
7
- enters = 0
8
- visits = 0
9
- exits = 0
10
-
11
- root.traverse do |event, _exp, _index|
12
- enters = (enters + 1) if event == :enter
13
- visits = (visits + 1) if event == :visit
14
- exits = (exits + 1) if event == :exit
15
- end
16
-
17
- expect(enters).to eq 9
18
- expect(enters).to eq exits
19
-
20
- expect(visits).to eq 9
21
- end
22
-
23
- specify('Subexpression#traverse including self') do
24
- root = RP.parse(/a(b(c(d)))|g[h-i]j|klmn/)
25
-
26
- enters = 0
27
- visits = 0
28
- exits = 0
29
-
30
- root.traverse(true) do |event, _exp, _index|
31
- enters = (enters + 1) if event == :enter
32
- visits = (visits + 1) if event == :visit
33
- exits = (exits + 1) if event == :exit
34
- end
35
-
36
- expect(enters).to eq 10
37
- expect(enters).to eq exits
38
-
39
- expect(visits).to eq 9
40
- end
41
-
42
- specify('Subexpression#traverse without a block') do
43
- root = RP.parse(/abc/)
44
- enum = root.traverse
45
-
46
- expect(enum).to be_a(Enumerator)
47
- event, expr, idx = enum.next
48
- expect(event).to eq(:visit)
49
- expect(expr).to be_a(Regexp::Expression::Literal)
50
- expect(idx).to eq(0)
51
- end
52
-
53
- specify('Subexpression#walk alias') do
54
- root = RP.parse(/abc/)
55
-
56
- expect(root).to respond_to(:walk)
57
- end
58
-
59
- specify('Subexpression#each_expression') do
60
- root = RP.parse(/a(?x:b(c))|g[h-k]/)
61
-
62
- count = 0
63
- root.each_expression { count += 1 }
64
-
65
- expect(count).to eq 13
66
- end
67
-
68
- specify('Subexpression#each_expression including self') do
69
- root = RP.parse(/a(?x:b(c))|g[h-k]/)
70
-
71
- count = 0
72
- root.each_expression(true) { count += 1 }
73
-
74
- expect(count).to eq 14
75
- end
76
-
77
- specify('Subexpression#each_expression indices') do
78
- root = RP.parse(/a(b)c/)
79
-
80
- indices = []
81
- root.each_expression { |_exp, index| (indices << index) }
82
-
83
- expect(indices).to eq [0, 1, 0, 2]
84
- end
85
-
86
- specify('Subexpression#each_expression indices including self') do
87
- root = RP.parse(/a(b)c/)
88
-
89
- indices = []
90
- root.each_expression(true) { |_exp, index| (indices << index) }
91
-
92
- expect(indices).to eq [0, 0, 1, 0, 2]
93
- end
94
-
95
- specify('Subexpression#each_expression without a block') do
96
- root = RP.parse(/abc/)
97
- enum = root.each_expression
98
-
99
- expect(enum).to be_a(Enumerator)
100
- expr, idx = enum.next
101
- expect(expr).to be_a(Regexp::Expression::Literal)
102
- expect(idx).to eq(0)
103
- end
104
-
105
- specify('Subexpression#flat_map without block') do
106
- root = RP.parse(/a(b([c-e]+))?/)
107
-
108
- array = root.flat_map
109
-
110
- expect(array).to be_instance_of(Array)
111
- expect(array.length).to eq 8
112
-
113
- array.each do |item|
114
- expect(item).to be_instance_of(Array)
115
- expect(item.length).to eq 2
116
- expect(item.first).to be_a(Regexp::Expression::Base)
117
- expect(item.last).to be_a(Integer)
118
- end
119
- end
120
-
121
- specify('Subexpression#flat_map without block including self') do
122
- root = RP.parse(/a(b([c-e]+))?/)
123
-
124
- array = root.flat_map(true)
125
-
126
- expect(array).to be_instance_of(Array)
127
- expect(array.length).to eq 9
128
- end
129
-
130
- specify('Subexpression#flat_map indices') do
131
- root = RP.parse(/a(b([c-e]+))?f*g/)
132
-
133
- indices = root.flat_map { |_exp, index| index }
134
-
135
- expect(indices).to eq [0, 1, 0, 1, 0, 0, 0, 1, 2, 3]
136
- end
137
-
138
- specify('Subexpression#flat_map indices including self') do
139
- root = RP.parse(/a(b([c-e]+))?f*g/)
140
-
141
- indices = root.flat_map(true) { |_exp, index| index }
142
-
143
- expect(indices).to eq [0, 0, 1, 0, 1, 0, 0, 0, 1, 2, 3]
144
- end
145
-
146
- specify('Subexpression#flat_map expressions') do
147
- root = RP.parse(/a(b(c(d)))/)
148
-
149
- levels = root.flat_map { |exp, _index| [exp.level, exp.text] if exp.terminal? }.compact
150
-
151
- expect(levels).to eq [[0, 'a'], [1, 'b'], [2, 'c'], [3, 'd']]
152
- end
153
-
154
- specify('Subexpression#flat_map expressions including self') do
155
- root = RP.parse(/a(b(c(d)))/)
156
-
157
- levels = root.flat_map(true) { |exp, _index| [exp.level, exp.to_s] }.compact
158
-
159
- expect(levels).to eq [[nil, 'a(b(c(d)))'], [0, 'a'], [0, '(b(c(d)))'], [1, 'b'], [1, '(c(d))'], [2, 'c'], [2, '(d)'], [3, 'd']]
160
- end
161
- end
@@ -1,128 +0,0 @@
1
- require 'spec_helper'
2
-
3
- RSpec.describe('Expression#options') do
4
- it 'returns a hash of options/flags that affect the expression' do
5
- exp = RP.parse(/a/ix)[0]
6
- expect(exp).to be_a Literal
7
- expect(exp.options).to eq(i: true, x: true)
8
- end
9
-
10
- it 'includes options that are locally enabled via special groups' do
11
- exp = RP.parse(/(?x)(?m:a)/i)[1][0]
12
- expect(exp).to be_a Literal
13
- expect(exp.options).to eq(i: true, m: true, x: true)
14
- end
15
-
16
- it 'excludes locally disabled options' do
17
- exp = RP.parse(/(?x)(?-im:a)/i)[1][0]
18
- expect(exp).to be_a Literal
19
- expect(exp.options).to eq(x: true)
20
- end
21
-
22
- it 'gives correct precedence to negative options' do
23
- # Negative options have precedence. E.g. /(?i-i)a/ is case-sensitive.
24
- regexp = /(?i-i:a)/
25
- expect(regexp).to match 'a'
26
- expect(regexp).not_to match 'A'
27
-
28
- exp = RP.parse(regexp)[0][0]
29
- expect(exp).to be_a Literal
30
- expect(exp.options).to eq({})
31
- end
32
-
33
- it 'correctly handles multiple negative option parts' do
34
- regexp = /(?--m--mx--) . /mx
35
- expect(regexp).to match ' . '
36
- expect(regexp).not_to match '.'
37
- expect(regexp).not_to match "\n"
38
-
39
- exp = RP.parse(regexp)[2]
40
- expect(exp.options).to eq({})
41
- end
42
-
43
- it 'gives correct precedence when encountering multiple encoding flags' do
44
- # Any encoding flag overrides all previous encoding flags. If there are
45
- # multiple encoding flags in an options string, the last one wins.
46
- # E.g. /(?dau)\w/ matches UTF8 chars but /(?dua)\w/ only ASCII chars.
47
- regexp1 = /(?dau)\w/
48
- regexp2 = /(?dua)\w/
49
- expect(regexp1).to match 'ü'
50
- expect(regexp2).not_to match 'ü'
51
-
52
- exp1 = RP.parse(regexp1)[1]
53
- exp2 = RP.parse(regexp2)[1]
54
- expect(exp1.options).to eq(u: true)
55
- expect(exp2.options).to eq(a: true)
56
- end
57
-
58
- it 'is accessible via shortcuts' do
59
- exp = Root.build
60
-
61
- expect { exp.options[:i] = true }
62
- .to change { exp.i? }.from(false).to(true)
63
- .and change { exp.ignore_case? }.from(false).to(true)
64
- .and change { exp.case_insensitive? }.from(false).to(true)
65
-
66
- expect { exp.options[:m] = true }
67
- .to change { exp.m? }.from(false).to(true)
68
- .and change { exp.multiline? }.from(false).to(true)
69
-
70
- expect { exp.options[:x] = true }
71
- .to change { exp.x? }.from(false).to(true)
72
- .and change { exp.extended? }.from(false).to(true)
73
- .and change { exp.free_spacing? }.from(false).to(true)
74
-
75
- expect { exp.options[:a] = true }
76
- .to change { exp.a? }.from(false).to(true)
77
- .and change { exp.ascii_classes? }.from(false).to(true)
78
-
79
- expect { exp.options[:d] = true }
80
- .to change { exp.d? }.from(false).to(true)
81
- .and change { exp.default_classes? }.from(false).to(true)
82
-
83
- expect { exp.options[:u] = true }
84
- .to change { exp.u? }.from(false).to(true)
85
- .and change { exp.unicode_classes? }.from(false).to(true)
86
- end
87
-
88
- RSpec.shared_examples '#options' do |regexp, path, klass|
89
- it "works for expression class #{klass}" do
90
- exp = RP.parse(/#{regexp.source}/i).dig(*path)
91
- expect(exp).to be_a(klass)
92
- expect(exp).to be_i
93
- expect(exp).not_to be_x
94
- end
95
- end
96
-
97
- include_examples '#options', //, [], Root
98
- include_examples '#options', /a/, [0], Literal
99
- include_examples '#options', /\A/, [0], Anchor::Base
100
- include_examples '#options', /\d/, [0], CharacterType::Base
101
- include_examples '#options', /\n/, [0], EscapeSequence::Base
102
- include_examples '#options', /\K/, [0], Keep::Mark
103
- include_examples '#options', /./, [0], CharacterType::Any
104
- include_examples '#options', /(a)/, [0], Group::Base
105
- include_examples '#options', /(a)/, [0, 0], Literal
106
- include_examples '#options', /(?=a)/, [0], Assertion::Base
107
- include_examples '#options', /(?=a)/, [0, 0], Literal
108
- include_examples '#options', /(a|b)/, [0], Group::Base
109
- include_examples '#options', /(a|b)/, [0, 0], Alternation
110
- include_examples '#options', /(a|b)/, [0, 0, 0], Alternative
111
- include_examples '#options', /(a|b)/, [0, 0, 0, 0], Literal
112
- include_examples '#options', /(a)\1/, [1], Backreference::Base
113
- include_examples '#options', /(a)\k<1>/, [1], Backreference::Number
114
- include_examples '#options', /(a)\g<1>/, [1], Backreference::NumberCall
115
- include_examples '#options', /[a]/, [0], CharacterSet
116
- include_examples '#options', /[a]/, [0, 0], Literal
117
- include_examples '#options', /[a-z]/, [0, 0], CharacterSet::Range
118
- include_examples '#options', /[a-z]/, [0, 0, 0], Literal
119
- include_examples '#options', /[a&&z]/, [0, 0], CharacterSet::Intersection
120
- include_examples '#options', /[a&&z]/, [0, 0, 0], CharacterSet::IntersectedSequence
121
- include_examples '#options', /[a&&z]/, [0, 0, 0, 0], Literal
122
- include_examples '#options', /[[:ascii:]]/, [0, 0], PosixClass
123
- include_examples '#options', /\p{word}/, [0], UnicodeProperty::Base
124
- include_examples '#options', /(a)(?(1)b|c)/, [1], Conditional::Expression
125
- include_examples '#options', /(a)(?(1)b|c)/, [1, 0], Conditional::Condition
126
- include_examples '#options', /(a)(?(1)b|c)/, [1, 1], Conditional::Branch
127
- include_examples '#options', /(a)(?(1)b|c)/, [1, 1, 0], Literal
128
- end
@@ -1,9 +0,0 @@
1
- require 'spec_helper'
2
-
3
- RSpec.describe(Regexp::Expression::Root) do
4
- describe('#initialize') do
5
- it 'supports the old, nonstandard arity for backwards compatibility' do
6
- expect { Root.new }.to output.to_stderr
7
- end
8
- end
9
- end
@@ -1,9 +0,0 @@
1
- require 'spec_helper'
2
-
3
- RSpec.describe(Regexp::Expression::Sequence) do
4
- describe('#initialize') do
5
- it 'supports the old, nonstandard arity for backwards compatibility' do
6
- expect { Sequence.new(0, 0, 0) }.to output.to_stderr
7
- end
8
- end
9
- end
@@ -1,50 +0,0 @@
1
- require 'spec_helper'
2
-
3
- RSpec.describe(Regexp::Expression::Subexpression) do
4
- specify('#ts, #te') do
5
- regx = /abcd|ghij|klmn|pqur/
6
- root = RP.parse(regx)
7
-
8
- alt = root.first
9
-
10
- { 0 => [0, 4], 1 => [5, 9], 2 => [10, 14], 3 => [15, 19] }.each do |index, span|
11
- sequence = alt[index]
12
-
13
- expect(sequence.ts).to eq span[0]
14
- expect(sequence.te).to eq span[1]
15
- end
16
- end
17
-
18
- specify('#nesting_level') do
19
- root = RP.parse(/a(b(\d|[ef-g[h]]))/)
20
-
21
- tests = {
22
- 'a' => 1,
23
- 'b' => 2,
24
- '\d|[ef-g[h]]' => 3, # alternation
25
- '\d' => 4, # first alternative
26
- '[ef-g[h]]' => 4, # second alternative
27
- 'e' => 5,
28
- 'f-g' => 5,
29
- 'f' => 6,
30
- 'g' => 6,
31
- 'h' => 6,
32
- }
33
-
34
- root.each_expression do |exp|
35
- next unless expected_nesting_level = tests.delete(exp.to_s)
36
- expect(expected_nesting_level).to eq exp.nesting_level
37
- end
38
-
39
- expect(tests).to be_empty
40
- end
41
-
42
- specify('#dig') do
43
- root = RP.parse(/(((a)))/)
44
-
45
- expect(root.dig(0).to_s).to eq '(((a)))'
46
- expect(root.dig(0, 0, 0, 0).to_s).to eq 'a'
47
- expect(root.dig(0, 0, 0, 0, 0)).to be_nil
48
- expect(root.dig(3, 7)).to be_nil
49
- end
50
- end