regexp_parser 1.4.0 → 1.5.0

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 (133) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +27 -1
  3. data/Gemfile +1 -1
  4. data/README.md +9 -13
  5. data/lib/regexp_parser/expression.rb +33 -21
  6. data/lib/regexp_parser/expression/classes/backref.rb +18 -10
  7. data/lib/regexp_parser/expression/classes/conditional.rb +4 -0
  8. data/lib/regexp_parser/expression/classes/group.rb +4 -2
  9. data/lib/regexp_parser/expression/classes/keep.rb +1 -3
  10. data/lib/regexp_parser/expression/methods/match_length.rb +172 -0
  11. data/lib/regexp_parser/expression/quantifier.rb +2 -2
  12. data/lib/regexp_parser/expression/sequence.rb +0 -4
  13. data/lib/regexp_parser/expression/subexpression.rb +3 -5
  14. data/lib/regexp_parser/lexer.rb +31 -24
  15. data/lib/regexp_parser/parser.rb +25 -3
  16. data/lib/regexp_parser/syntax/tokens.rb +2 -10
  17. data/lib/regexp_parser/version.rb +1 -1
  18. data/regexp_parser.gemspec +2 -2
  19. data/spec/expression/base_spec.rb +80 -0
  20. data/spec/expression/clone_spec.rb +120 -0
  21. data/spec/expression/conditional_spec.rb +89 -0
  22. data/spec/expression/free_space_spec.rb +27 -0
  23. data/spec/expression/methods/match_length_spec.rb +141 -0
  24. data/spec/expression/methods/strfregexp_spec.rb +224 -0
  25. data/spec/expression/methods/tests_spec.rb +97 -0
  26. data/spec/expression/methods/traverse_spec.rb +140 -0
  27. data/spec/expression/subexpression_spec.rb +50 -0
  28. data/spec/expression/to_h_spec.rb +26 -0
  29. data/spec/expression/to_s_spec.rb +100 -0
  30. data/spec/lexer/all_spec.rb +22 -0
  31. data/{test/lexer/test_conditionals.rb → spec/lexer/conditionals_spec.rb} +31 -35
  32. data/spec/lexer/escapes_spec.rb +38 -0
  33. data/spec/lexer/keep_spec.rb +22 -0
  34. data/{test/lexer/test_literals.rb → spec/lexer/literals_spec.rb} +20 -24
  35. data/{test/lexer/test_nesting.rb → spec/lexer/nesting_spec.rb} +11 -13
  36. data/spec/lexer/refcalls_spec.rb +54 -0
  37. data/spec/parser/all_spec.rb +31 -0
  38. data/spec/parser/alternation_spec.rb +88 -0
  39. data/{test/parser/test_anchors.rb → spec/parser/anchors_spec.rb} +7 -10
  40. data/spec/parser/conditionals_spec.rb +179 -0
  41. data/spec/parser/errors_spec.rb +51 -0
  42. data/spec/parser/escapes_spec.rb +132 -0
  43. data/spec/parser/free_space_spec.rb +130 -0
  44. data/spec/parser/groups_spec.rb +267 -0
  45. data/spec/parser/keep_spec.rb +19 -0
  46. data/spec/parser/posix_classes_spec.rb +27 -0
  47. data/spec/parser/properties_spec.rb +127 -0
  48. data/spec/parser/quantifiers_spec.rb +293 -0
  49. data/spec/parser/refcalls_spec.rb +237 -0
  50. data/spec/parser/set/intersections_spec.rb +127 -0
  51. data/spec/parser/set/ranges_spec.rb +111 -0
  52. data/spec/parser/sets_spec.rb +178 -0
  53. data/{test/parser/test_types.rb → spec/parser/types_spec.rb} +13 -20
  54. data/spec/scanner/all_spec.rb +18 -0
  55. data/{test/scanner/test_anchors.rb → spec/scanner/anchors_spec.rb} +8 -10
  56. data/{test/scanner/test_conditionals.rb → spec/scanner/conditionals_spec.rb} +49 -53
  57. data/spec/scanner/errors_spec.rb +90 -0
  58. data/{test/scanner/test_escapes.rb → spec/scanner/escapes_spec.rb} +8 -10
  59. data/{test/scanner/test_free_space.rb → spec/scanner/free_space_spec.rb} +48 -52
  60. data/{test/scanner/test_groups.rb → spec/scanner/groups_spec.rb} +33 -41
  61. data/spec/scanner/keep_spec.rb +33 -0
  62. data/{test/scanner/test_literals.rb → spec/scanner/literals_spec.rb} +8 -12
  63. data/{test/scanner/test_meta.rb → spec/scanner/meta_spec.rb} +8 -10
  64. data/{test/scanner/test_properties.rb → spec/scanner/properties_spec.rb} +14 -19
  65. data/{test/scanner/test_quantifiers.rb → spec/scanner/quantifiers_spec.rb} +7 -9
  66. data/{test/scanner/test_refcalls.rb → spec/scanner/refcalls_spec.rb} +9 -9
  67. data/{test/scanner/test_scripts.rb → spec/scanner/scripts_spec.rb} +8 -12
  68. data/{test/scanner/test_sets.rb → spec/scanner/sets_spec.rb} +14 -17
  69. data/spec/scanner/types_spec.rb +29 -0
  70. data/spec/scanner/unicode_blocks_spec.rb +28 -0
  71. data/spec/spec_helper.rb +14 -0
  72. data/{test → spec}/support/runner.rb +9 -8
  73. data/{test → spec}/support/warning_extractor.rb +5 -7
  74. data/spec/syntax/syntax_spec.rb +44 -0
  75. data/spec/syntax/syntax_token_map_spec.rb +23 -0
  76. data/spec/syntax/versions/1.8.6_spec.rb +38 -0
  77. data/spec/syntax/versions/1.9.1_spec.rb +23 -0
  78. data/spec/syntax/versions/1.9.3_spec.rb +22 -0
  79. data/spec/syntax/versions/2.0.0_spec.rb +28 -0
  80. data/spec/syntax/versions/2.2.0_spec.rb +22 -0
  81. data/spec/syntax/versions/aliases_spec.rb +119 -0
  82. data/spec/token/token_spec.rb +85 -0
  83. metadata +131 -140
  84. data/test/expression/test_all.rb +0 -12
  85. data/test/expression/test_base.rb +0 -90
  86. data/test/expression/test_clone.rb +0 -89
  87. data/test/expression/test_conditionals.rb +0 -113
  88. data/test/expression/test_free_space.rb +0 -35
  89. data/test/expression/test_set.rb +0 -84
  90. data/test/expression/test_strfregexp.rb +0 -230
  91. data/test/expression/test_subexpression.rb +0 -58
  92. data/test/expression/test_tests.rb +0 -99
  93. data/test/expression/test_to_h.rb +0 -59
  94. data/test/expression/test_to_s.rb +0 -104
  95. data/test/expression/test_traverse.rb +0 -161
  96. data/test/helpers.rb +0 -10
  97. data/test/lexer/test_all.rb +0 -41
  98. data/test/lexer/test_keep.rb +0 -24
  99. data/test/lexer/test_refcalls.rb +0 -56
  100. data/test/parser/set/test_intersections.rb +0 -127
  101. data/test/parser/set/test_ranges.rb +0 -111
  102. data/test/parser/test_all.rb +0 -64
  103. data/test/parser/test_alternation.rb +0 -92
  104. data/test/parser/test_conditionals.rb +0 -187
  105. data/test/parser/test_errors.rb +0 -63
  106. data/test/parser/test_escapes.rb +0 -134
  107. data/test/parser/test_free_space.rb +0 -139
  108. data/test/parser/test_groups.rb +0 -289
  109. data/test/parser/test_keep.rb +0 -21
  110. data/test/parser/test_posix_classes.rb +0 -27
  111. data/test/parser/test_properties.rb +0 -134
  112. data/test/parser/test_quantifiers.rb +0 -301
  113. data/test/parser/test_refcalls.rb +0 -186
  114. data/test/parser/test_sets.rb +0 -179
  115. data/test/scanner/test_all.rb +0 -38
  116. data/test/scanner/test_errors.rb +0 -91
  117. data/test/scanner/test_keep.rb +0 -35
  118. data/test/scanner/test_types.rb +0 -35
  119. data/test/scanner/test_unicode_blocks.rb +0 -30
  120. data/test/support/disable_autotest.rb +0 -8
  121. data/test/syntax/test_all.rb +0 -6
  122. data/test/syntax/test_syntax.rb +0 -61
  123. data/test/syntax/test_syntax_token_map.rb +0 -25
  124. data/test/syntax/versions/test_1.8.rb +0 -55
  125. data/test/syntax/versions/test_1.9.1.rb +0 -36
  126. data/test/syntax/versions/test_1.9.3.rb +0 -32
  127. data/test/syntax/versions/test_2.0.0.rb +0 -37
  128. data/test/syntax/versions/test_2.2.0.rb +0 -32
  129. data/test/syntax/versions/test_aliases.rb +0 -129
  130. data/test/syntax/versions/test_all.rb +0 -5
  131. data/test/test_all.rb +0 -5
  132. data/test/token/test_all.rb +0 -2
  133. data/test/token/test_token.rb +0 -107
@@ -0,0 +1,178 @@
1
+ require 'spec_helper'
2
+
3
+ RSpec.describe('Set parsing') do
4
+ specify('parse set basic') do
5
+ root = RP.parse('[ab]+')
6
+ exp = root[0]
7
+
8
+ expect(exp).to be_instance_of(CharacterSet)
9
+ expect(exp.count).to eq 2
10
+
11
+ expect(exp[0]).to be_instance_of(Literal)
12
+ expect(exp[0].text).to eq 'a'
13
+ expect(exp[1]).to be_instance_of(Literal)
14
+ expect(exp[1].text).to eq 'b'
15
+
16
+ expect(exp).to be_quantified
17
+ expect(exp.quantifier.min).to eq 1
18
+ expect(exp.quantifier.max).to eq(-1)
19
+ end
20
+
21
+ specify('parse set char type') do
22
+ root = RP.parse('[a\\dc]')
23
+ exp = root[0]
24
+
25
+ expect(exp).to be_instance_of(CharacterSet)
26
+ expect(exp.count).to eq 3
27
+
28
+ expect(exp[1]).to be_instance_of(CharacterType::Digit)
29
+ expect(exp[1].text).to eq '\\d'
30
+ end
31
+
32
+ specify('parse set escape sequence backspace') do
33
+ root = RP.parse('[a\\bc]')
34
+ exp = root[0]
35
+
36
+ expect(exp).to be_instance_of(CharacterSet)
37
+ expect(exp.count).to eq 3
38
+
39
+ expect(exp[1]).to be_instance_of(EscapeSequence::Backspace)
40
+ expect(exp[1].text).to eq '\\b'
41
+
42
+ expect(exp.matches?('a')).to be true
43
+ expect(exp.matches?("\b")).to be true
44
+ expect(exp.matches?('b')).to be false
45
+ expect(exp.matches?('c')).to be true
46
+ end
47
+
48
+ specify('parse set escape sequence hex') do
49
+ root = RP.parse('[a\\x20c]', :any)
50
+ exp = root[0]
51
+
52
+ expect(exp).to be_instance_of(CharacterSet)
53
+ expect(exp.count).to eq 3
54
+
55
+ expect(exp[1]).to be_instance_of(EscapeSequence::Hex)
56
+ expect(exp[1].text).to eq '\\x20'
57
+ end
58
+
59
+ specify('parse set escape sequence codepoint') do
60
+ root = RP.parse('[a\\u0640]')
61
+ exp = root[0]
62
+
63
+ expect(exp).to be_instance_of(CharacterSet)
64
+ expect(exp.count).to eq 2
65
+
66
+ expect(exp[1]).to be_instance_of(EscapeSequence::Codepoint)
67
+ expect(exp[1].text).to eq '\\u0640'
68
+ end
69
+
70
+ specify('parse set escape sequence codepoint list') do
71
+ root = RP.parse('[a\\u{41 1F60D}]')
72
+ exp = root[0]
73
+
74
+ expect(exp).to be_instance_of(CharacterSet)
75
+ expect(exp.count).to eq 2
76
+
77
+ expect(exp[1]).to be_instance_of(EscapeSequence::CodepointList)
78
+ expect(exp[1].text).to eq '\\u{41 1F60D}'
79
+ end
80
+
81
+ specify('parse set posix class') do
82
+ root = RP.parse('[[:digit:][:^lower:]]+')
83
+ exp = root[0]
84
+
85
+ expect(exp).to be_instance_of(CharacterSet)
86
+ expect(exp.count).to eq 2
87
+
88
+ expect(exp[0]).to be_instance_of(PosixClass)
89
+ expect(exp[0].text).to eq '[:digit:]'
90
+ expect(exp[1]).to be_instance_of(PosixClass)
91
+ expect(exp[1].text).to eq '[:^lower:]'
92
+ end
93
+
94
+ specify('parse set nesting') do
95
+ root = RP.parse('[a[b[c]d]e]')
96
+
97
+ exp = root[0]
98
+ expect(exp).to be_instance_of(CharacterSet)
99
+ expect(exp.count).to eq 3
100
+ expect(exp[0]).to be_instance_of(Literal)
101
+ expect(exp[2]).to be_instance_of(Literal)
102
+
103
+ subset1 = exp[1]
104
+ expect(subset1).to be_instance_of(CharacterSet)
105
+ expect(subset1.count).to eq 3
106
+ expect(subset1[0]).to be_instance_of(Literal)
107
+ expect(subset1[2]).to be_instance_of(Literal)
108
+
109
+ subset2 = subset1[1]
110
+ expect(subset2).to be_instance_of(CharacterSet)
111
+ expect(subset2.count).to eq 1
112
+ expect(subset2[0]).to be_instance_of(Literal)
113
+ end
114
+
115
+ specify('parse set nesting negative') do
116
+ root = RP.parse('[a[^b[c]]]')
117
+ exp = root[0]
118
+
119
+ expect(exp).to be_instance_of(CharacterSet)
120
+ expect(exp.count).to eq 2
121
+ expect(exp[0]).to be_instance_of(Literal)
122
+ expect(exp).not_to be_negative
123
+
124
+ subset1 = exp[1]
125
+ expect(subset1).to be_instance_of(CharacterSet)
126
+ expect(subset1.count).to eq 2
127
+ expect(subset1[0]).to be_instance_of(Literal)
128
+ expect(subset1).to be_negative
129
+
130
+ subset2 = subset1[1]
131
+ expect(subset2).to be_instance_of(CharacterSet)
132
+ expect(subset2.count).to eq 1
133
+ expect(subset2[0]).to be_instance_of(Literal)
134
+ expect(subset2).not_to be_negative
135
+ end
136
+
137
+ specify('parse set nesting #to_s') do
138
+ pattern = '[a[b[^c]]]'
139
+ root = RP.parse(pattern)
140
+
141
+ expect(root.to_s).to eq pattern
142
+ end
143
+
144
+ specify('parse set literals are not merged') do
145
+ root = RP.parse("[#{('a' * 10)}]")
146
+ exp = root[0]
147
+
148
+ expect(exp.count).to eq 10
149
+ end
150
+
151
+ specify('parse set whitespace is not merged') do
152
+ root = RP.parse("[#{(' ' * 10)}]")
153
+ exp = root[0]
154
+
155
+ expect(exp.count).to eq 10
156
+ end
157
+
158
+ specify('parse set whitespace is not merged in x mode') do
159
+ root = RP.parse("(?x)[#{(' ' * 10)}]")
160
+ exp = root[1]
161
+
162
+ expect(exp.count).to eq 10
163
+ end
164
+
165
+ specify('parse set collating sequence') do
166
+ root = RP.parse('[a[.span-ll.]h]', :any)
167
+ exp = root[0]
168
+
169
+ expect(exp[1].to_s).to eq '[.span-ll.]'
170
+ end
171
+
172
+ specify('parse set character equivalents') do
173
+ root = RP.parse('[a[=e=]h]', :any)
174
+ exp = root[0]
175
+
176
+ expect(exp[1].to_s).to eq '[=e=]'
177
+ end
178
+ end
@@ -1,7 +1,6 @@
1
- require File.expand_path("../../helpers", __FILE__)
2
-
3
- class TestParserTypes < Test::Unit::TestCase
1
+ require 'spec_helper'
4
2
 
3
+ RSpec.describe('Type parsing') do
5
4
  tests = {
6
5
  /a\dc/ => [1, :type, :digit, CharacterType::Digit],
7
6
  /a\Dc/ => [1, :type, :nondigit, CharacterType::NonDigit],
@@ -17,34 +16,28 @@ class TestParserTypes < Test::Unit::TestCase
17
16
  }
18
17
 
19
18
  tests.each_with_index do |(pattern, (index, type, token, klass)), count|
20
- define_method "test_parse_type_#{token}_#{count}" do
19
+ specify("parse_type_#{token}_#{count}") do
21
20
  root = RP.parse(pattern, 'ruby/1.9')
22
- exp = root.expressions.at(index)
21
+ exp = root.expressions.at(index)
23
22
 
24
- assert exp.is_a?( klass ),
25
- "Expected #{klass}, but got #{exp.class.name}"
23
+ expect(exp).to be_a(klass)
26
24
 
27
- assert_equal type, exp.type
28
- assert_equal token, exp.token
25
+ expect(exp.type).to eq type
26
+ expect(exp.token).to eq token
29
27
  end
30
28
  end
31
29
 
32
- tests_2_0 = {
33
- 'a\Rc' => [1, :type, :linebreak, CharacterType::Linebreak],
34
- 'a\Xc' => [1, :type, :xgrapheme, CharacterType::ExtendedGrapheme],
35
- }
30
+ tests_2_0 = { 'a\\Rc' => [1, :type, :linebreak, CharacterType::Linebreak], 'a\\Xc' => [1, :type, :xgrapheme, CharacterType::ExtendedGrapheme] }
36
31
 
37
32
  tests_2_0.each_with_index do |(pattern, (index, type, token, klass)), count|
38
- define_method "test_parse_type_#{token}_#{count}" do
33
+ specify("parse_type_#{token}_#{count}") do
39
34
  root = RP.parse(pattern, 'ruby/2.0')
40
- exp = root.expressions.at(index)
35
+ exp = root.expressions.at(index)
41
36
 
42
- assert exp.is_a?( klass ),
43
- "Expected #{klass}, but got #{exp.class.name}"
37
+ expect(exp).to be_a(klass)
44
38
 
45
- assert_equal type, exp.type
46
- assert_equal token, exp.token
39
+ expect(exp.type).to eq type
40
+ expect(exp.token).to eq token
47
41
  end
48
42
  end
49
-
50
43
  end
@@ -0,0 +1,18 @@
1
+ require 'spec_helper'
2
+
3
+ RSpec.describe(Regexp::Scanner) do
4
+ specify('scanner returns an array') do
5
+ expect(RS.scan('abc')).to be_instance_of(Array)
6
+ end
7
+
8
+ specify('scanner returns tokens as arrays') do
9
+ tokens = RS.scan('^abc+[^one]{2,3}\\b\\d\\\\C-C$')
10
+ expect(tokens).to all(be_a Array)
11
+ expect(tokens.map(&:length)).to all(eq 5)
12
+ end
13
+
14
+ specify('scanner token count') do
15
+ re = /^(one|two){2,3}([^d\]efm-qz\,\-]*)(ghi)+$/i
16
+ expect(RS.scan(re).length).to eq 28
17
+ end
18
+ end
@@ -1,7 +1,6 @@
1
- require File.expand_path("../../helpers", __FILE__)
2
-
3
- class ScannerAnchors < Test::Unit::TestCase
1
+ require 'spec_helper'
4
2
 
3
+ RSpec.describe('Anchor scanning') do
5
4
  tests = {
6
5
  '^abc' => [0, :anchor, :bol, '^', 0, 1],
7
6
  'abc$' => [1, :anchor, :eol, '$', 3, 4],
@@ -23,16 +22,15 @@ class ScannerAnchors < Test::Unit::TestCase
23
22
  }
24
23
 
25
24
  tests.each_with_index do |(pattern, (index, type, token, text, ts, te)), count|
26
- define_method "test_scanner_#{type}_#{token}_#{count}" do
25
+ specify("scanner_#{type}_#{token}_#{count}") do
27
26
  tokens = RS.scan(pattern)
28
27
  result = tokens[index]
29
28
 
30
- assert_equal type, result[0]
31
- assert_equal token, result[1]
32
- assert_equal text, result[2]
33
- assert_equal ts, result[3]
34
- assert_equal te, result[4]
29
+ expect(result[0]).to eq type
30
+ expect(result[1]).to eq token
31
+ expect(result[2]).to eq text
32
+ expect(result[3]).to eq ts
33
+ expect(result[4]).to eq te
35
34
  end
36
35
  end
37
-
38
36
  end
@@ -1,45 +1,41 @@
1
- require File.expand_path("../../helpers", __FILE__)
1
+ require 'spec_helper'
2
2
 
3
- class ScannerConditionals < Test::Unit::TestCase
4
-
5
- # Basic conditional scan token tests
3
+ RSpec.describe('Conditional scanning') do
6
4
  tests = {
7
- /(a)(?(1)T|F)1/ => [3, :conditional, :open, '(?', 3, 5],
8
- /(a)(?(1)T|F)2/ => [4, :conditional, :condition_open, '(', 5, 6],
9
- /(a)(?(1)T|F)3/ => [5, :conditional, :condition, '1', 6, 7],
10
- /(a)(?(1)T|F)4/ => [6, :conditional, :condition_close, ')', 7, 8],
11
- /(a)(?(1)T|F)5/ => [7, :literal, :literal, 'T', 8, 9],
12
- /(a)(?(1)T|F)6/ => [8, :conditional, :separator, '|', 9, 10],
13
- /(a)(?(1)T|F)7/ => [9, :literal, :literal, 'F', 10, 11],
14
- /(a)(?(1)T|F)8/ => [10, :conditional, :close, ')', 11, 12],
15
-
16
- /(a)(?(1)TRUE)9/ => [8, :conditional, :close, ')', 12, 13],
17
-
18
- /(a)(?(1)TRUE|)10/ => [8, :conditional, :separator, '|', 12, 13],
19
- /(a)(?(1)TRUE|)11/ => [9, :conditional, :close, ')', 13, 14],
20
-
21
- /(?<N>A)(?(<N>)T|F)1/ => [5, :conditional, :condition, '<N>', 10, 13],
22
- /(?'N'A)(?('N')T|F)2/ => [5, :conditional, :condition, "'N'", 10, 13],
5
+ '(a)(?(1)T|F)1' => [3, :conditional, :open, '(?', 3, 5],
6
+ '(a)(?(1)T|F)2' => [4, :conditional, :condition_open, '(', 5, 6],
7
+ '(a)(?(1)T|F)3' => [5, :conditional, :condition, '1', 6, 7],
8
+ '(a)(?(1)T|F)4' => [6, :conditional, :condition_close, ')', 7, 8],
9
+ '(a)(?(1)T|F)5' => [7, :literal, :literal, 'T', 8, 9],
10
+ '(a)(?(1)T|F)6' => [8, :conditional, :separator, '|', 9, 10],
11
+ '(a)(?(1)T|F)7' => [9, :literal, :literal, 'F', 10, 11],
12
+ '(a)(?(1)T|F)8' => [10, :conditional, :close, ')', 11, 12],
13
+ '(a)(?(1)TRUE)9' => [8, :conditional, :close, ')', 12, 13],
14
+ '(a)(?(1)TRUE|)10' => [8, :conditional, :separator, '|', 12, 13],
15
+ '(a)(?(1)TRUE|)11' => [9, :conditional, :close, ')', 13, 14],
16
+ '(?<N>A)(?(<N>)T|F)1' => [5, :conditional, :condition, '<N>', 10, 13],
17
+ "(?'N'A)(?('N')T|F)2" => [5, :conditional, :condition, "'N'", 10, 13]
23
18
  }
24
19
 
25
20
  tests.each_with_index do |(pattern, (index, type, token, text, ts, te)), count|
26
- define_method "test_scanner_#{type}_#{token}_#{count}" do
21
+ specify("scanner_#{type}_#{token}_#{count}") do
27
22
  tokens = RS.scan(pattern)
28
23
  result = tokens[index]
29
24
 
30
- assert_equal type, result[0]
31
- assert_equal token, result[1]
32
- assert_equal text, result[2]
33
- assert_equal ts, result[3]
34
- assert_equal te, result[4]
25
+ expect(result[0]).to eq type
26
+ expect(result[1]).to eq token
27
+ expect(result[2]).to eq text
28
+ expect(result[3]).to eq ts
29
+ expect(result[4]).to eq te
35
30
  end
36
31
  end
37
32
 
38
- def test_scan_conditional_nested
39
- regexp = /(a(b(c)))(?(1)(?(2)d|(?(3)e|f))|(?(2)(?(1)g|h)))/
33
+ specify('scan conditional nested') do
34
+ regexp = '(a(b(c)))(?(1)(?(2)d|(?(3)e|f))|(?(2)(?(1)g|h)))'
40
35
  tokens = RS.scan(regexp)
41
36
 
42
- [ [ 0, :group, :capture, '(', 0, 1],
37
+ [
38
+ [ 0, :group, :capture, '(', 0, 1],
43
39
  [ 1, :literal, :literal, 'a', 1, 2],
44
40
  [ 2, :group, :capture, '(', 2, 3],
45
41
  [ 3, :literal, :literal, 'b', 3, 4],
@@ -85,19 +81,20 @@ class ScannerConditionals < Test::Unit::TestCase
85
81
  ].each do |index, type, token, text, ts, te|
86
82
  result = tokens[index]
87
83
 
88
- assert_equal type, result[0]
89
- assert_equal token, result[1]
90
- assert_equal text, result[2]
91
- assert_equal ts, result[3]
92
- assert_equal te, result[4]
84
+ expect(result[0]).to eq type
85
+ expect(result[1]).to eq token
86
+ expect(result[2]).to eq text
87
+ expect(result[3]).to eq ts
88
+ expect(result[4]).to eq te
93
89
  end
94
90
  end
95
91
 
96
- def test_scan_conditional_nested_groups
97
- regexp = /((a)|(b)|((?(2)(c(d|e)+)?|(?(3)f|(?(4)(g|(h)(i)))))))/
92
+ specify('scan conditional nested groups') do
93
+ regexp = '((a)|(b)|((?(2)(c(d|e)+)?|(?(3)f|(?(4)(g|(h)(i)))))))'
98
94
  tokens = RS.scan(regexp)
99
95
 
100
- [ [ 0, :group, :capture, '(', 0, 1],
96
+ [
97
+ [ 0, :group, :capture, '(', 0, 1],
101
98
  [ 1, :group, :capture, '(', 1, 2],
102
99
  [ 2, :literal, :literal, 'a', 2, 3],
103
100
  [ 3, :group, :close, ')', 3, 4],
@@ -150,35 +147,34 @@ class ScannerConditionals < Test::Unit::TestCase
150
147
  ].each do |index, type, token, text, ts, te|
151
148
  result = tokens[index]
152
149
 
153
- assert_equal type, result[0]
154
- assert_equal token, result[1]
155
- assert_equal text, result[2]
156
- assert_equal ts, result[3]
157
- assert_equal te, result[4]
150
+ expect(result[0]).to eq type
151
+ expect(result[1]).to eq token
152
+ expect(result[2]).to eq text
153
+ expect(result[3]).to eq ts
154
+ expect(result[4]).to eq te
158
155
  end
159
156
  end
160
157
 
161
- def test_scan_conditional_nested_alternation
162
- regexp = /(a)(?(1)(b|c|d)|(e|f|g))(h)(?(2)(i|j|k)|(l|m|n))|o|p/
158
+ specify('scan conditional nested alternation') do
159
+ regexp = '(a)(?(1)(b|c|d)|(e|f|g))(h)(?(2)(i|j|k)|(l|m|n))|o|p'
163
160
  tokens = RS.scan(regexp)
164
161
 
165
162
  [9, 11, 17, 19, 32, 34, 40, 42, 46, 48].each do |index|
166
163
  result = tokens[index]
167
164
 
168
- assert_equal :meta, result[0]
169
- assert_equal :alternation, result[1]
170
- assert_equal '|', result[2]
171
- assert_equal 1, result[4] - result[3]
165
+ expect(result[0]).to eq :meta
166
+ expect(result[1]).to eq :alternation
167
+ expect(result[2]).to eq '|'
168
+ expect((result[4] - result[3])).to eq 1
172
169
  end
173
170
 
174
171
  [14, 37].each do |index|
175
172
  result = tokens[index]
176
173
 
177
- assert_equal :conditional, result[0]
178
- assert_equal :separator, result[1]
179
- assert_equal '|', result[2]
180
- assert_equal 1, result[4] - result[3]
174
+ expect(result[0]).to eq :conditional
175
+ expect(result[1]).to eq :separator
176
+ expect(result[2]).to eq '|'
177
+ expect((result[4] - result[3])).to eq 1
181
178
  end
182
179
  end
183
-
184
180
  end
@@ -0,0 +1,90 @@
1
+ require 'spec_helper'
2
+
3
+ RSpec.describe('Scanning errors') do
4
+ specify('scanner unbalanced set') do
5
+ expect { RS.scan('[[:alpha:]') }.to raise_error(RS::PrematureEndError)
6
+ end
7
+
8
+ specify('scanner unbalanced group') do
9
+ expect { RS.scan('(abc') }.to raise_error(RS::PrematureEndError)
10
+ end
11
+
12
+ specify('scanner unbalanced interval') do
13
+ expect { RS.scan('a{1,2') }.to raise_error(RS::PrematureEndError)
14
+ end
15
+
16
+ specify('scanner eof in property') do
17
+ expect { RS.scan('\\p{asci') }.to raise_error(RS::PrematureEndError)
18
+ end
19
+
20
+ specify('scanner incomplete property') do
21
+ expect { RS.scan('\\p{ascii abc') }.to raise_error(RS::PrematureEndError)
22
+ end
23
+
24
+ specify('scanner unknown property') do
25
+ expect { RS.scan('\\p{foobar}') }.to raise_error(RS::UnknownUnicodePropertyError)
26
+ end
27
+
28
+ specify('scanner incomplete options') do
29
+ expect { RS.scan('(?mix abc)') }.to raise_error(RS::ScannerError)
30
+ end
31
+
32
+ specify('scanner eof options') do
33
+ expect { RS.scan('(?mix') }.to raise_error(RS::PrematureEndError)
34
+ end
35
+
36
+ specify('scanner incorrect options') do
37
+ expect { RS.scan('(?mix^bc') }.to raise_error(RS::ScannerError)
38
+ end
39
+
40
+ specify('scanner eof escape') do
41
+ expect { RS.scan('\\') }.to raise_error(RS::PrematureEndError)
42
+ end
43
+
44
+ specify('scanner eof in hex escape') do
45
+ expect { RS.scan('\\x') }.to raise_error(RS::PrematureEndError)
46
+ end
47
+
48
+ specify('scanner eof in codepoint escape') do
49
+ expect { RS.scan('\\u') }.to raise_error(RS::PrematureEndError)
50
+ expect { RS.scan('\\u0') }.to raise_error(RS::PrematureEndError)
51
+ expect { RS.scan('\\u00') }.to raise_error(RS::PrematureEndError)
52
+ expect { RS.scan('\\u000') }.to raise_error(RS::PrematureEndError)
53
+ expect { RS.scan('\\u{') }.to raise_error(RS::PrematureEndError)
54
+ expect { RS.scan('\\u{00') }.to raise_error(RS::PrematureEndError)
55
+ expect { RS.scan('\\u{0000') }.to raise_error(RS::PrematureEndError)
56
+ expect { RS.scan('\\u{0000 ') }.to raise_error(RS::PrematureEndError)
57
+ expect { RS.scan('\\u{0000 0000') }.to raise_error(RS::PrematureEndError)
58
+ end
59
+
60
+ specify('scanner eof in control sequence') do
61
+ expect { RS.scan('\\c') }.to raise_error(RS::PrematureEndError)
62
+ expect { RS.scan('\\c\\M') }.to raise_error(RS::PrematureEndError)
63
+ expect { RS.scan('\\c\\M-') }.to raise_error(RS::PrematureEndError)
64
+ expect { RS.scan('\\C') }.to raise_error(RS::PrematureEndError)
65
+ expect { RS.scan('\\C-') }.to raise_error(RS::PrematureEndError)
66
+ expect { RS.scan('\\C-\\M') }.to raise_error(RS::PrematureEndError)
67
+ expect { RS.scan('\\C-\\M-') }.to raise_error(RS::PrematureEndError)
68
+ end
69
+
70
+ specify('scanner eof in meta sequence') do
71
+ expect { RS.scan('\\M') }.to raise_error(RS::PrematureEndError)
72
+ expect { RS.scan('\\M-') }.to raise_error(RS::PrematureEndError)
73
+ expect { RS.scan('\\M-\\') }.to raise_error(RS::PrematureEndError)
74
+ expect { RS.scan('\\M-\\c') }.to raise_error(RS::PrematureEndError)
75
+ expect { RS.scan('\\M-\\C') }.to raise_error(RS::PrematureEndError)
76
+ expect { RS.scan('\\M-\\C-') }.to raise_error(RS::PrematureEndError)
77
+ end
78
+
79
+ specify('scanner invalid hex escape') do
80
+ expect { RS.scan('\\xZ') }.to raise_error(RS::InvalidSequenceError)
81
+ expect { RS.scan('\\xZ0') }.to raise_error(RS::InvalidSequenceError)
82
+ end
83
+
84
+ specify('scanner invalid named group') do
85
+ expect { RS.scan("(?'')") }.to raise_error(RS::InvalidGroupError)
86
+ expect { RS.scan("(?''empty-name)") }.to raise_error(RS::InvalidGroupError)
87
+ expect { RS.scan('(?<>)') }.to raise_error(RS::InvalidGroupError)
88
+ expect { RS.scan('(?<>empty-name)') }.to raise_error(RS::InvalidGroupError)
89
+ end
90
+ end