regexp_parser 1.7.0 → 2.8.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (165) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +8 -2
  3. data/LICENSE +1 -1
  4. data/Rakefile +6 -70
  5. data/lib/regexp_parser/error.rb +4 -0
  6. data/lib/regexp_parser/expression/base.rb +76 -0
  7. data/lib/regexp_parser/expression/classes/alternation.rb +1 -1
  8. data/lib/regexp_parser/expression/classes/anchor.rb +0 -2
  9. data/lib/regexp_parser/expression/classes/{backref.rb → backreference.rb} +22 -2
  10. data/lib/regexp_parser/expression/classes/{set → character_set}/range.rb +4 -8
  11. data/lib/regexp_parser/expression/classes/{set.rb → character_set.rb} +3 -4
  12. data/lib/regexp_parser/expression/classes/{type.rb → character_type.rb} +0 -2
  13. data/lib/regexp_parser/expression/classes/conditional.rb +11 -5
  14. data/lib/regexp_parser/expression/classes/{escape.rb → escape_sequence.rb} +15 -7
  15. data/lib/regexp_parser/expression/classes/free_space.rb +5 -5
  16. data/lib/regexp_parser/expression/classes/group.rb +28 -15
  17. data/lib/regexp_parser/expression/classes/keep.rb +2 -0
  18. data/lib/regexp_parser/expression/classes/literal.rb +1 -5
  19. data/lib/regexp_parser/expression/classes/posix_class.rb +5 -1
  20. data/lib/regexp_parser/expression/classes/root.rb +4 -19
  21. data/lib/regexp_parser/expression/classes/{property.rb → unicode_property.rb} +5 -3
  22. data/lib/regexp_parser/expression/methods/construct.rb +41 -0
  23. data/lib/regexp_parser/expression/methods/human_name.rb +43 -0
  24. data/lib/regexp_parser/expression/methods/match_length.rb +11 -7
  25. data/lib/regexp_parser/expression/methods/parts.rb +23 -0
  26. data/lib/regexp_parser/expression/methods/printing.rb +26 -0
  27. data/lib/regexp_parser/expression/methods/strfregexp.rb +1 -1
  28. data/lib/regexp_parser/expression/methods/tests.rb +47 -1
  29. data/lib/regexp_parser/expression/methods/traverse.rb +34 -18
  30. data/lib/regexp_parser/expression/quantifier.rb +57 -17
  31. data/lib/regexp_parser/expression/sequence.rb +11 -47
  32. data/lib/regexp_parser/expression/sequence_operation.rb +4 -9
  33. data/lib/regexp_parser/expression/shared.rb +111 -0
  34. data/lib/regexp_parser/expression/subexpression.rb +27 -19
  35. data/lib/regexp_parser/expression.rb +14 -141
  36. data/lib/regexp_parser/lexer.rb +83 -41
  37. data/lib/regexp_parser/parser.rb +371 -429
  38. data/lib/regexp_parser/scanner/char_type.rl +11 -11
  39. data/lib/regexp_parser/scanner/errors/premature_end_error.rb +8 -0
  40. data/lib/regexp_parser/scanner/errors/scanner_error.rb +6 -0
  41. data/lib/regexp_parser/scanner/errors/validation_error.rb +63 -0
  42. data/lib/regexp_parser/scanner/properties/long.csv +633 -0
  43. data/lib/regexp_parser/scanner/properties/short.csv +248 -0
  44. data/lib/regexp_parser/scanner/property.rl +4 -4
  45. data/lib/regexp_parser/scanner/scanner.rl +303 -368
  46. data/lib/regexp_parser/scanner.rb +1423 -1674
  47. data/lib/regexp_parser/syntax/any.rb +2 -7
  48. data/lib/regexp_parser/syntax/base.rb +92 -67
  49. data/lib/regexp_parser/syntax/token/anchor.rb +15 -0
  50. data/lib/regexp_parser/syntax/{tokens → token}/assertion.rb +2 -2
  51. data/lib/regexp_parser/syntax/token/backreference.rb +33 -0
  52. data/lib/regexp_parser/syntax/token/character_set.rb +16 -0
  53. data/lib/regexp_parser/syntax/{tokens → token}/character_type.rb +3 -3
  54. data/lib/regexp_parser/syntax/{tokens → token}/conditional.rb +3 -3
  55. data/lib/regexp_parser/syntax/token/escape.rb +33 -0
  56. data/lib/regexp_parser/syntax/{tokens → token}/group.rb +7 -7
  57. data/lib/regexp_parser/syntax/{tokens → token}/keep.rb +1 -1
  58. data/lib/regexp_parser/syntax/token/meta.rb +20 -0
  59. data/lib/regexp_parser/syntax/{tokens → token}/posix_class.rb +3 -3
  60. data/lib/regexp_parser/syntax/token/quantifier.rb +35 -0
  61. data/lib/regexp_parser/syntax/token/unicode_property.rb +733 -0
  62. data/lib/regexp_parser/syntax/token/virtual.rb +11 -0
  63. data/lib/regexp_parser/syntax/token.rb +45 -0
  64. data/lib/regexp_parser/syntax/version_lookup.rb +19 -36
  65. data/lib/regexp_parser/syntax/versions/1.8.6.rb +13 -20
  66. data/lib/regexp_parser/syntax/versions/1.9.1.rb +10 -17
  67. data/lib/regexp_parser/syntax/versions/1.9.3.rb +3 -10
  68. data/lib/regexp_parser/syntax/versions/2.0.0.rb +8 -15
  69. data/lib/regexp_parser/syntax/versions/2.2.0.rb +3 -9
  70. data/lib/regexp_parser/syntax/versions/2.3.0.rb +3 -9
  71. data/lib/regexp_parser/syntax/versions/2.4.0.rb +3 -9
  72. data/lib/regexp_parser/syntax/versions/2.4.1.rb +2 -8
  73. data/lib/regexp_parser/syntax/versions/2.5.0.rb +3 -9
  74. data/lib/regexp_parser/syntax/versions/2.6.0.rb +3 -9
  75. data/lib/regexp_parser/syntax/versions/2.6.2.rb +3 -9
  76. data/lib/regexp_parser/syntax/versions/2.6.3.rb +3 -9
  77. data/lib/regexp_parser/syntax/versions/3.1.0.rb +4 -0
  78. data/lib/regexp_parser/syntax/versions/3.2.0.rb +4 -0
  79. data/lib/regexp_parser/syntax/versions.rb +3 -1
  80. data/lib/regexp_parser/syntax.rb +8 -6
  81. data/lib/regexp_parser/token.rb +9 -20
  82. data/lib/regexp_parser/version.rb +1 -1
  83. data/lib/regexp_parser.rb +0 -2
  84. data/regexp_parser.gemspec +19 -23
  85. metadata +52 -171
  86. data/CHANGELOG.md +0 -349
  87. data/README.md +0 -470
  88. data/lib/regexp_parser/scanner/properties/long.yml +0 -594
  89. data/lib/regexp_parser/scanner/properties/short.yml +0 -237
  90. data/lib/regexp_parser/syntax/tokens/anchor.rb +0 -15
  91. data/lib/regexp_parser/syntax/tokens/backref.rb +0 -24
  92. data/lib/regexp_parser/syntax/tokens/character_set.rb +0 -13
  93. data/lib/regexp_parser/syntax/tokens/escape.rb +0 -30
  94. data/lib/regexp_parser/syntax/tokens/meta.rb +0 -13
  95. data/lib/regexp_parser/syntax/tokens/quantifier.rb +0 -35
  96. data/lib/regexp_parser/syntax/tokens/unicode_property.rb +0 -675
  97. data/lib/regexp_parser/syntax/tokens.rb +0 -45
  98. data/spec/expression/base_spec.rb +0 -94
  99. data/spec/expression/clone_spec.rb +0 -120
  100. data/spec/expression/conditional_spec.rb +0 -89
  101. data/spec/expression/free_space_spec.rb +0 -27
  102. data/spec/expression/methods/match_length_spec.rb +0 -161
  103. data/spec/expression/methods/match_spec.rb +0 -25
  104. data/spec/expression/methods/strfregexp_spec.rb +0 -224
  105. data/spec/expression/methods/tests_spec.rb +0 -99
  106. data/spec/expression/methods/traverse_spec.rb +0 -161
  107. data/spec/expression/options_spec.rb +0 -128
  108. data/spec/expression/root_spec.rb +0 -9
  109. data/spec/expression/sequence_spec.rb +0 -9
  110. data/spec/expression/subexpression_spec.rb +0 -50
  111. data/spec/expression/to_h_spec.rb +0 -26
  112. data/spec/expression/to_s_spec.rb +0 -100
  113. data/spec/lexer/all_spec.rb +0 -22
  114. data/spec/lexer/conditionals_spec.rb +0 -53
  115. data/spec/lexer/escapes_spec.rb +0 -14
  116. data/spec/lexer/keep_spec.rb +0 -10
  117. data/spec/lexer/literals_spec.rb +0 -89
  118. data/spec/lexer/nesting_spec.rb +0 -99
  119. data/spec/lexer/refcalls_spec.rb +0 -55
  120. data/spec/parser/all_spec.rb +0 -43
  121. data/spec/parser/alternation_spec.rb +0 -88
  122. data/spec/parser/anchors_spec.rb +0 -17
  123. data/spec/parser/conditionals_spec.rb +0 -179
  124. data/spec/parser/errors_spec.rb +0 -30
  125. data/spec/parser/escapes_spec.rb +0 -121
  126. data/spec/parser/free_space_spec.rb +0 -130
  127. data/spec/parser/groups_spec.rb +0 -108
  128. data/spec/parser/keep_spec.rb +0 -6
  129. data/spec/parser/posix_classes_spec.rb +0 -8
  130. data/spec/parser/properties_spec.rb +0 -115
  131. data/spec/parser/quantifiers_spec.rb +0 -51
  132. data/spec/parser/refcalls_spec.rb +0 -112
  133. data/spec/parser/set/intersections_spec.rb +0 -127
  134. data/spec/parser/set/ranges_spec.rb +0 -111
  135. data/spec/parser/sets_spec.rb +0 -178
  136. data/spec/parser/types_spec.rb +0 -18
  137. data/spec/scanner/all_spec.rb +0 -18
  138. data/spec/scanner/anchors_spec.rb +0 -21
  139. data/spec/scanner/conditionals_spec.rb +0 -128
  140. data/spec/scanner/errors_spec.rb +0 -68
  141. data/spec/scanner/escapes_spec.rb +0 -53
  142. data/spec/scanner/free_space_spec.rb +0 -133
  143. data/spec/scanner/groups_spec.rb +0 -52
  144. data/spec/scanner/keep_spec.rb +0 -10
  145. data/spec/scanner/literals_spec.rb +0 -49
  146. data/spec/scanner/meta_spec.rb +0 -18
  147. data/spec/scanner/properties_spec.rb +0 -64
  148. data/spec/scanner/quantifiers_spec.rb +0 -20
  149. data/spec/scanner/refcalls_spec.rb +0 -36
  150. data/spec/scanner/sets_spec.rb +0 -102
  151. data/spec/scanner/types_spec.rb +0 -14
  152. data/spec/spec_helper.rb +0 -15
  153. data/spec/support/runner.rb +0 -42
  154. data/spec/support/shared_examples.rb +0 -77
  155. data/spec/support/warning_extractor.rb +0 -60
  156. data/spec/syntax/syntax_spec.rb +0 -48
  157. data/spec/syntax/syntax_token_map_spec.rb +0 -23
  158. data/spec/syntax/versions/1.8.6_spec.rb +0 -17
  159. data/spec/syntax/versions/1.9.1_spec.rb +0 -10
  160. data/spec/syntax/versions/1.9.3_spec.rb +0 -9
  161. data/spec/syntax/versions/2.0.0_spec.rb +0 -13
  162. data/spec/syntax/versions/2.2.0_spec.rb +0 -9
  163. data/spec/syntax/versions/aliases_spec.rb +0 -37
  164. data/spec/token/token_spec.rb +0 -85
  165. /data/lib/regexp_parser/expression/classes/{set → character_set}/intersection.rb +0 -0
@@ -1,94 +0,0 @@
1
- require 'spec_helper'
2
-
3
- RSpec.describe(Regexp::Expression::Base) do
4
- specify('#to_re') do
5
- re_text = '^a*(b([cde]+))+f?$'
6
-
7
- re = RP.parse(re_text).to_re
8
-
9
- expect(re).to be_a(::Regexp)
10
- expect(re_text).to eq re.source
11
- end
12
-
13
- specify('#level') do
14
- regexp = /^a(b(c(d)))e$/
15
- root = RP.parse(regexp)
16
-
17
- ['^', 'a', '(b(c(d)))', 'e', '$'].each_with_index do |t, i|
18
- expect(root[i].to_s).to eq t
19
- expect(root[i].level).to eq 0
20
- end
21
-
22
- expect(root[2][0].to_s).to eq 'b'
23
- expect(root[2][0].level).to eq 1
24
-
25
- expect(root[2][1][0].to_s).to eq 'c'
26
- expect(root[2][1][0].level).to eq 2
27
-
28
- expect(root[2][1][1][0].to_s).to eq 'd'
29
- expect(root[2][1][1][0].level).to eq 3
30
- end
31
-
32
- specify('#terminal?') do
33
- root = RP.parse('^a([b]+)c$')
34
-
35
- expect(root).not_to be_terminal
36
-
37
- expect(root[0]).to be_terminal
38
- expect(root[1]).to be_terminal
39
- expect(root[2]).not_to be_terminal
40
- expect(root[2][0]).not_to be_terminal
41
- expect(root[2][0][0]).to be_terminal
42
- expect(root[3]).to be_terminal
43
- expect(root[4]).to be_terminal
44
- end
45
-
46
- specify('alt #terminal?') do
47
- root = RP.parse('^(ab|cd)$')
48
-
49
- expect(root).not_to be_terminal
50
-
51
- expect(root[0]).to be_terminal
52
- expect(root[1]).not_to be_terminal
53
- expect(root[1][0]).not_to be_terminal
54
- expect(root[1][0][0]).not_to be_terminal
55
- expect(root[1][0][0][0]).to be_terminal
56
- expect(root[1][0][1]).not_to be_terminal
57
- expect(root[1][0][1][0]).to be_terminal
58
- end
59
-
60
- specify('#coded_offset') do
61
- root = RP.parse('^a*(b+(c?))$')
62
-
63
- expect(root.coded_offset).to eq '@0+12'
64
-
65
- [
66
- ['@0+1', '^'],
67
- ['@1+2', 'a*'],
68
- ['@3+8', '(b+(c?))'],
69
- ['@11+1', '$'],
70
- ].each_with_index do |check, i|
71
- against = [root[i].coded_offset, root[i].to_s]
72
-
73
- expect(against).to eq check
74
- end
75
-
76
- expect([root[2][0].coded_offset, root[2][0].to_s]).to eq ['@4+2', 'b+']
77
- expect([root[2][1].coded_offset, root[2][1].to_s]).to eq ['@6+4', '(c?)']
78
- expect([root[2][1][0].coded_offset, root[2][1][0].to_s]).to eq ['@7+2', 'c?']
79
- end
80
-
81
- specify('#quantity') do
82
- expect(RP.parse(/aa/)[0].quantity).to eq [nil, nil]
83
- expect(RP.parse(/a?/)[0].quantity).to eq [0, 1]
84
- expect(RP.parse(/a*/)[0].quantity).to eq [0, -1]
85
- expect(RP.parse(/a+/)[0].quantity).to eq [1, -1]
86
- end
87
-
88
- specify('#repetitions') do
89
- expect(RP.parse(/aa/)[0].repetitions).to eq 1..1
90
- expect(RP.parse(/a?/)[0].repetitions).to eq 0..1
91
- expect(RP.parse(/a*/)[0].repetitions).to eq 0..(Float::INFINITY)
92
- expect(RP.parse(/a+/)[0].repetitions).to eq 1..(Float::INFINITY)
93
- end
94
- end
@@ -1,120 +0,0 @@
1
- require 'spec_helper'
2
-
3
- RSpec.describe('Expression#clone') do
4
- specify('Base#clone') do
5
- root = RP.parse(/^(?i:a)b+$/i)
6
- copy = root.clone
7
-
8
- expect(copy.to_s).to eq root.to_s
9
-
10
- expect(root.object_id).not_to eq copy.object_id
11
- expect(root.text).to eq copy.text
12
- expect(root.text.object_id).not_to eq copy.text.object_id
13
-
14
- root_1 = root[1]
15
- copy_1 = copy[1]
16
-
17
- expect(root_1.options).to eq copy_1.options
18
- expect(root_1.options.object_id).not_to eq copy_1.options.object_id
19
-
20
- root_2 = root[2]
21
- copy_2 = copy[2]
22
-
23
- expect(root_2).to be_quantified
24
- expect(copy_2).to be_quantified
25
- expect(root_2.quantifier.text).to eq copy_2.quantifier.text
26
- expect(root_2.quantifier.text.object_id).not_to eq copy_2.quantifier.text.object_id
27
- expect(root_2.quantifier.object_id).not_to eq copy_2.quantifier.object_id
28
-
29
- # regression test
30
- expect { root_2.clone }.not_to change { root_2.quantifier.object_id }
31
- expect { root_2.clone }.not_to change { root_2.quantifier.text.object_id }
32
- end
33
-
34
- specify('Subexpression#clone') do
35
- root = RP.parse(/^a(b([cde])f)g$/)
36
- copy = root.clone
37
-
38
- expect(copy.to_s).to eq root.to_s
39
-
40
- expect(root).to respond_to(:expressions)
41
- expect(copy).to respond_to(:expressions)
42
- expect(root.expressions.object_id).not_to eq copy.expressions.object_id
43
- copy.expressions.each_with_index do |exp, index|
44
- expect(root[index].object_id).not_to eq exp.object_id
45
- end
46
- copy[2].each_with_index do |exp, index|
47
- expect(root[2][index].object_id).not_to eq exp.object_id
48
- end
49
-
50
- # regression test
51
- expect { root.clone }.not_to change { root.expressions.object_id }
52
- end
53
-
54
- specify('Group::Named#clone') do
55
- root = RP.parse('^(?<somename>a)+bc$')
56
- copy = root.clone
57
-
58
- expect(copy.to_s).to eq root.to_s
59
-
60
- root_1 = root[1]
61
- copy_1 = copy[1]
62
-
63
- expect(root_1.name).to eq copy_1.name
64
- expect(root_1.name.object_id).not_to eq copy_1.name.object_id
65
- expect(root_1.text).to eq copy_1.text
66
- expect(root_1.expressions.object_id).not_to eq copy_1.expressions.object_id
67
- copy_1.expressions.each_with_index do |exp, index|
68
- expect(root_1[index].object_id).not_to eq exp.object_id
69
- end
70
-
71
- # regression test
72
- expect { root_1.clone }.not_to change { root_1.name.object_id }
73
- end
74
-
75
- specify('Sequence#clone') do
76
- root = RP.parse(/(a|b)/)
77
- copy = root.clone
78
-
79
- # regression test
80
- expect(copy.to_s).to eq root.to_s
81
-
82
- root_seq_op = root[0][0]
83
- copy_seq_op = copy[0][0]
84
- root_seq_1 = root[0][0][0]
85
- copy_seq_1 = copy[0][0][0]
86
-
87
- expect(root_seq_op.object_id).not_to eq copy_seq_op.object_id
88
- expect(root_seq_1.object_id).not_to eq copy_seq_1.object_id
89
- copy_seq_1.expressions.each_with_index do |exp, index|
90
- expect(root_seq_1[index].object_id).not_to eq exp.object_id
91
- end
92
- end
93
-
94
- describe('Base#unquantified_clone') do
95
- it 'produces a clone' do
96
- root = RP.parse(/^a(b([cde])f)g$/)
97
- copy = root.unquantified_clone
98
-
99
- expect(copy.to_s).to eq root.to_s
100
-
101
- expect(copy.object_id).not_to eq root.object_id
102
- end
103
-
104
- it 'does not carry over the callee quantifier' do
105
- expect(RP.parse(/a{3}/)[0]).to be_quantified
106
- expect(RP.parse(/a{3}/)[0].unquantified_clone).not_to be_quantified
107
-
108
- expect(RP.parse(/[a]{3}/)[0]).to be_quantified
109
- expect(RP.parse(/[a]{3}/)[0].unquantified_clone).not_to be_quantified
110
-
111
- expect(RP.parse(/(a|b){3}/)[0]).to be_quantified
112
- expect(RP.parse(/(a|b){3}/)[0].unquantified_clone).not_to be_quantified
113
- end
114
-
115
- it 'keeps quantifiers of callee children' do
116
- expect(RP.parse(/(a{3}){3}/)[0][0]).to be_quantified
117
- expect(RP.parse(/(a{3}){3}/)[0].unquantified_clone[0]).to be_quantified
118
- end
119
- end
120
- end
@@ -1,89 +0,0 @@
1
- require 'spec_helper'
2
-
3
- RSpec.describe(Regexp::Expression::Conditional) do
4
- let(:root) { RP.parse('^(a(b))(b(?(1)c|(?(2)d|(?(3)e|f)))g)$') }
5
- let(:cond_1) { root[2][1] }
6
- let(:cond_2) { root[2][1][2][0] }
7
- let(:cond_3) { root[2][1][2][0][2][0] }
8
-
9
- specify('root level') do
10
- [
11
- '^',
12
- '(a(b))',
13
- '(b(?(1)c|(?(2)d|(?(3)e|f)))g)',
14
- '$'
15
- ].each_with_index do |t, i|
16
- expect(root[i].conditional_level).to eq 0
17
- expect(root[i].to_s).to eq t
18
- end
19
-
20
- expect(root[2][0].to_s).to eq 'b'
21
- expect(root[2][0].conditional_level).to eq 0
22
- end
23
-
24
- specify('level one') do
25
- condition = cond_1.condition
26
- branch_1 = cond_1.branches.first
27
-
28
- expect(condition).to be_a Conditional::Condition
29
- expect(condition.to_s).to eq '(1)'
30
- expect(condition.conditional_level).to eq 1
31
-
32
- expect(branch_1).to be_a Conditional::Branch
33
- expect(branch_1.to_s).to eq 'c'
34
- expect(branch_1.conditional_level).to eq 1
35
-
36
- expect(branch_1.first.to_s).to eq 'c'
37
- expect(branch_1.first.conditional_level).to eq 1
38
- end
39
-
40
- specify('level two') do
41
- condition = cond_2.condition
42
- branch_1 = cond_2.branches.first
43
- branch_2 = cond_2.branches.last
44
-
45
- expect(cond_2.to_s).to start_with '(?'
46
- expect(cond_2.conditional_level).to eq 1
47
-
48
- expect(condition).to be_a Conditional::Condition
49
- expect(condition.to_s).to eq '(2)'
50
- expect(condition.conditional_level).to eq 2
51
-
52
- expect(branch_1).to be_a Conditional::Branch
53
- expect(branch_1.to_s).to eq 'd'
54
- expect(branch_1.conditional_level).to eq 2
55
-
56
- expect(branch_1.first.to_s).to eq 'd'
57
- expect(branch_1.first.conditional_level).to eq 2
58
-
59
- expect(branch_2.first.to_s).to start_with '(?'
60
- expect(branch_2.first.conditional_level).to eq 2
61
- end
62
-
63
- specify('level three') do
64
- condition = cond_3.condition
65
- branch_1 = cond_3.branches.first
66
- branch_2 = cond_3.branches.last
67
-
68
- expect(condition).to be_a Conditional::Condition
69
- expect(condition.to_s).to eq '(3)'
70
- expect(condition.conditional_level).to eq 3
71
-
72
- expect(cond_3.to_s).to eq '(?(3)e|f)'
73
- expect(cond_3.conditional_level).to eq 2
74
-
75
- expect(branch_1).to be_a Conditional::Branch
76
- expect(branch_1.to_s).to eq 'e'
77
- expect(branch_1.conditional_level).to eq 3
78
-
79
- expect(branch_1.first.to_s).to eq 'e'
80
- expect(branch_1.first.conditional_level).to eq 3
81
-
82
- expect(branch_2).to be_a Conditional::Branch
83
- expect(branch_2.to_s).to eq 'f'
84
- expect(branch_2.conditional_level).to eq 3
85
-
86
- expect(branch_2.first.to_s).to eq 'f'
87
- expect(branch_2.first.conditional_level).to eq 3
88
- end
89
- end
@@ -1,27 +0,0 @@
1
- require 'spec_helper'
2
-
3
- RSpec.describe(Regexp::Expression::FreeSpace) do
4
- specify('white space quantify raises error') do
5
- regexp = /
6
- a # Comment
7
- /x
8
-
9
- root = RP.parse(regexp)
10
- space = root[0]
11
-
12
- expect(space).to be_instance_of(FreeSpace::WhiteSpace)
13
- expect { space.quantify(:dummy, '#') }.to raise_error(RuntimeError)
14
- end
15
-
16
- specify('comment quantify raises error') do
17
- regexp = /
18
- a # Comment
19
- /x
20
-
21
- root = RP.parse(regexp)
22
- comment = root[3]
23
-
24
- expect(comment).to be_instance_of(FreeSpace::Comment)
25
- expect { comment.quantify(:dummy, '#') }.to raise_error(RuntimeError)
26
- end
27
- end
@@ -1,161 +0,0 @@
1
- require 'spec_helper'
2
-
3
- RSpec.describe(Regexp::MatchLength) do
4
- ML = described_class
5
-
6
- specify('literal') { expect(ML.of(/a/).minmax).to eq [1, 1] }
7
- specify('literal sequence') { expect(ML.of(/abc/).minmax).to eq [3, 3] }
8
- specify('dot') { expect(ML.of(/./).minmax).to eq [1, 1] }
9
- specify('set') { expect(ML.of(/[abc]/).minmax).to eq [1, 1] }
10
- specify('type') { expect(ML.of(/\d/).minmax).to eq [1, 1] }
11
- specify('escape') { expect(ML.of(/\n/).minmax).to eq [1, 1] }
12
- specify('property') { expect(ML.of(/\p{ascii}/).minmax).to eq [1, 1] }
13
- specify('codepoint list') { expect(ML.of(/\u{61 62 63}/).minmax).to eq [3, 3] }
14
- specify('multi-char literal') { expect(ML.of(/abc/).minmax).to eq [3, 3] }
15
- specify('fixed quantified') { expect(ML.of(/a{5}/).minmax).to eq [5, 5] }
16
- specify('range quantified') { expect(ML.of(/a{5,9}/).minmax).to eq [5, 9] }
17
- specify('nested quantified') { expect(ML.of(/(a{2}){3,4}/).minmax).to eq [6, 8] }
18
- specify('open-end quantified') { expect(ML.of(/a*/).minmax).to eq [0, Float::INFINITY] }
19
- specify('empty subexpression') { expect(ML.of(//).minmax).to eq [0, 0] }
20
- specify('anchor') { expect(ML.of(/^$/).minmax).to eq [0, 0] }
21
- specify('lookaround') { expect(ML.of(/(?=abc)/).minmax).to eq [0, 0] }
22
- specify('free space') { expect(ML.of(/ /x).minmax).to eq [0, 0] }
23
- specify('comment') { expect(ML.of(/(?#comment)/x).minmax).to eq [0, 0] }
24
- specify('backreference') { expect(ML.of(/(abc){2}\1/).minmax).to eq [9, 9] }
25
- specify('subexp call') { expect(ML.of(/(abc){2}\g<-1>/).minmax).to eq [9, 9] }
26
- specify('alternation') { expect(ML.of(/a|bcde/).minmax).to eq [1, 4] }
27
- specify('nested alternation') { expect(ML.of(/a|bc(d|efg)/).minmax).to eq [1, 5] }
28
- specify('quantified alternation') { expect(ML.of(/a|bcde?/).minmax).to eq [1, 4] }
29
- if ruby_version_at_least('2.4.1')
30
- specify('absence group') { expect(ML.of('(?~abc)').minmax).to eq [0, Float::INFINITY] }
31
- end
32
-
33
- specify('raises for missing references') do
34
- exp = RP.parse(/(a)\1/).last
35
- exp.referenced_expression = nil
36
- expect { exp.match_length }.to raise_error(ArgumentError)
37
- end
38
-
39
- describe('::of') do
40
- it('works with Regexps') { expect(ML.of(/foo/).minmax).to eq [3, 3] }
41
- it('works with Strings') { expect(ML.of('foo').minmax).to eq [3, 3] }
42
- it('works with Expressions') { expect(ML.of(RP.parse(/foo/)).minmax).to eq [3, 3] }
43
- end
44
-
45
- describe('Expression#match_length') do
46
- it('returns the MatchLength') { expect(RP.parse(/abc/).match_length.minmax).to eq [3, 3] }
47
- end
48
-
49
- describe('Expression#inner_match_length') do
50
- it 'returns the MatchLength of an expression that does not count towards parent match_length' do
51
- exp = RP.parse(/(?=ab|cdef)/)[0]
52
- expect(exp).to be_a Regexp::Expression::Assertion::Base
53
- expect(exp.match_length.minmax).to eq [0, 0]
54
- expect(exp.inner_match_length.minmax).to eq [2, 4]
55
- end
56
- end
57
-
58
- describe('#include?') do
59
- specify('unquantified') do
60
- expect(ML.of(/a/)).to include 1
61
- expect(ML.of(/a/)).not_to include 0
62
- expect(ML.of(/a/)).not_to include 2
63
- end
64
-
65
- specify('fixed quantified') do
66
- expect(ML.of(/a{5}/)).to include 5
67
- expect(ML.of(/a{5}/)).not_to include 0
68
- expect(ML.of(/a{5}/)).not_to include 4
69
- expect(ML.of(/a{5}/)).not_to include 6
70
- end
71
-
72
- specify('variably quantified') do
73
- expect(ML.of(/a?/)).to include 0
74
- expect(ML.of(/a?/)).to include 1
75
- expect(ML.of(/a?/)).not_to include 2
76
- end
77
-
78
- specify('nested quantified') do
79
- expect(ML.of(/(a{2}){3,4}/)).to include 6
80
- expect(ML.of(/(a{2}){3,4}/)).to include 8
81
- expect(ML.of(/(a{2}){3,4}/)).not_to include 0
82
- expect(ML.of(/(a{2}){3,4}/)).not_to include 5
83
- expect(ML.of(/(a{2}){3,4}/)).not_to include 7
84
- expect(ML.of(/(a{2}){3,4}/)).not_to include 9
85
- end
86
-
87
- specify('branches') do
88
- expect(ML.of(/ab|cdef/)).to include 2
89
- expect(ML.of(/ab|cdef/)).to include 4
90
- expect(ML.of(/ab|cdef/)).not_to include 0
91
- expect(ML.of(/ab|cdef/)).not_to include 3
92
- expect(ML.of(/ab|cdef/)).not_to include 5
93
- end
94
-
95
- specify('called on leaf node') do
96
- expect(ML.of(RP.parse(/a{2}/)[0])).to include 2
97
- expect(ML.of(RP.parse(/a{2}/)[0])).not_to include 0
98
- expect(ML.of(RP.parse(/a{2}/)[0])).not_to include 1
99
- expect(ML.of(RP.parse(/a{2}/)[0])).not_to include 3
100
- end
101
- end
102
-
103
- describe('#fixed?') do
104
- specify('unquantified') { expect(ML.of(/a/)).to be_fixed }
105
- specify('fixed quantified') { expect(ML.of(/a{5}/)).to be_fixed }
106
- specify('variably quantified') { expect(ML.of(/a?/)).not_to be_fixed }
107
- specify('equal branches') { expect(ML.of(/ab|cd/)).to be_fixed }
108
- specify('unequal branches') { expect(ML.of(/ab|cdef/)).not_to be_fixed }
109
- specify('equal quantified branches') { expect(ML.of(/a{2}|cd/)).to be_fixed }
110
- specify('unequal quantified branches') { expect(ML.of(/a{3}|cd/)).not_to be_fixed }
111
- specify('empty') { expect(ML.of(//)).to be_fixed }
112
- end
113
-
114
- describe('#each') do
115
- it 'returns an Enumerator if called without a block' do
116
- result = ML.of(/a?/).each
117
- expect(result).to be_a(Enumerator)
118
- expect(result.next).to eq 0
119
- expect(result.next).to eq 1
120
- expect { result.next }.to raise_error(StopIteration)
121
- end
122
-
123
- it 'is aware of limit option even if called without a block' do
124
- result = ML.of(/a?/).each(limit: 1)
125
- expect(result).to be_a(Enumerator)
126
- expect(result.next).to eq 0
127
- expect { result.next }.to raise_error(StopIteration)
128
- end
129
-
130
- it 'is limited to 1000 iterations in case there are infinite match lengths' do
131
- expect(ML.of(/a*/).first(3000).size).to eq 1000
132
- end
133
-
134
- it 'scaffolds the Enumerable interface' do
135
- expect(ML.of(/abc|defg/).count).to eq 2
136
- expect(ML.of(/(ab)*/).first(5)).to eq [0, 2, 4, 6, 8]
137
- expect(ML.of(/a{,10}/).any? { |len| len > 20 }).to be false
138
- end
139
- end
140
-
141
- describe('#endless_each') do
142
- it 'returns an Enumerator if called without a block' do
143
- result = ML.of(/a?/).endless_each
144
- expect(result).to be_a(Enumerator)
145
- expect(result.next).to eq 0
146
- expect(result.next).to eq 1
147
- expect { result.next }.to raise_error(StopIteration)
148
- end
149
-
150
- it 'never stops iterating for infinite match lengths' do
151
- expect(ML.of(/a*/).endless_each.first(3000).size).to eq 3000
152
- end
153
- end
154
-
155
- describe('#inspect') do
156
- it 'is nice' do
157
- result = RP.parse(/a{2,4}/)[0].match_length
158
- expect(result.inspect).to eq '#<Regexp::MatchLength<Literal> min=2 max=4>'
159
- end
160
- end
161
- end
@@ -1,25 +0,0 @@
1
- require 'spec_helper'
2
-
3
- RSpec.describe('Expression#match') do
4
- it 'returns the #match result of the respective Regexp' do
5
- expect(RP.parse(/a/).match('a')[0]).to eq 'a'
6
- end
7
-
8
- it 'can be given an offset, just like Regexp#match' do
9
- expect(RP.parse(/./).match('ab', 1)[0]).to eq 'b'
10
- end
11
-
12
- it 'works with the #=~ alias' do
13
- expect(RP.parse(/a/) =~ 'a').to be_a MatchData
14
- end
15
- end
16
-
17
- RSpec.describe('Expression#match?') do
18
- it 'returns true if the Respective Regexp matches' do
19
- expect(RP.parse(/a/).match?('a')).to be true
20
- end
21
-
22
- it 'returns false if the Respective Regexp does not match' do
23
- expect(RP.parse(/a/).match?('b')).to be false
24
- end
25
- end