regexp_parser 1.4.0 → 1.5.0

Sign up to get free protection for your applications and to get access to all the features.
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