regexp_parser 0.1.6 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/ChangeLog +57 -0
- data/Gemfile +8 -0
- data/LICENSE +1 -1
- data/README.md +225 -206
- data/Rakefile +9 -3
- data/lib/regexp_parser.rb +7 -11
- data/lib/regexp_parser/expression.rb +72 -14
- data/lib/regexp_parser/expression/classes/alternation.rb +3 -16
- data/lib/regexp_parser/expression/classes/conditional.rb +57 -0
- data/lib/regexp_parser/expression/classes/free_space.rb +17 -0
- data/lib/regexp_parser/expression/classes/keep.rb +7 -0
- data/lib/regexp_parser/expression/classes/set.rb +28 -7
- data/lib/regexp_parser/expression/methods/strfregexp.rb +113 -0
- data/lib/regexp_parser/expression/methods/tests.rb +116 -0
- data/lib/regexp_parser/expression/methods/traverse.rb +63 -0
- data/lib/regexp_parser/expression/quantifier.rb +10 -0
- data/lib/regexp_parser/expression/sequence.rb +45 -0
- data/lib/regexp_parser/expression/subexpression.rb +29 -1
- data/lib/regexp_parser/lexer.rb +31 -8
- data/lib/regexp_parser/parser.rb +118 -45
- data/lib/regexp_parser/scanner.rb +1745 -1404
- data/lib/regexp_parser/scanner/property.rl +57 -3
- data/lib/regexp_parser/scanner/scanner.rl +161 -34
- data/lib/regexp_parser/syntax.rb +12 -2
- data/lib/regexp_parser/syntax/ruby/1.9.1.rb +3 -3
- data/lib/regexp_parser/syntax/ruby/1.9.3.rb +2 -7
- data/lib/regexp_parser/syntax/ruby/2.0.0.rb +4 -1
- data/lib/regexp_parser/syntax/ruby/2.1.4.rb +13 -0
- data/lib/regexp_parser/syntax/ruby/2.1.5.rb +13 -0
- data/lib/regexp_parser/syntax/ruby/2.1.rb +2 -2
- data/lib/regexp_parser/syntax/ruby/2.2.0.rb +16 -0
- data/lib/regexp_parser/syntax/ruby/2.2.rb +8 -0
- data/lib/regexp_parser/syntax/tokens.rb +19 -2
- data/lib/regexp_parser/syntax/tokens/conditional.rb +22 -0
- data/lib/regexp_parser/syntax/tokens/keep.rb +14 -0
- data/lib/regexp_parser/syntax/tokens/unicode_property.rb +45 -4
- data/lib/regexp_parser/token.rb +23 -8
- data/lib/regexp_parser/version.rb +5 -0
- data/regexp_parser.gemspec +35 -0
- data/test/expression/test_all.rb +6 -1
- data/test/expression/test_base.rb +19 -0
- data/test/expression/test_conditionals.rb +114 -0
- data/test/expression/test_free_space.rb +33 -0
- data/test/expression/test_set.rb +61 -0
- data/test/expression/test_strfregexp.rb +214 -0
- data/test/expression/test_subexpression.rb +24 -0
- data/test/expression/test_tests.rb +99 -0
- data/test/expression/test_to_h.rb +48 -0
- data/test/expression/test_to_s.rb +46 -0
- data/test/expression/test_traverse.rb +164 -0
- data/test/lexer/test_all.rb +16 -3
- data/test/lexer/test_conditionals.rb +101 -0
- data/test/lexer/test_keep.rb +24 -0
- data/test/lexer/test_literals.rb +51 -51
- data/test/lexer/test_nesting.rb +62 -62
- data/test/lexer/test_refcalls.rb +18 -20
- data/test/parser/test_all.rb +18 -3
- data/test/parser/test_alternation.rb +11 -14
- data/test/parser/test_conditionals.rb +148 -0
- data/test/parser/test_escapes.rb +29 -5
- data/test/parser/test_free_space.rb +139 -0
- data/test/parser/test_groups.rb +40 -0
- data/test/parser/test_keep.rb +21 -0
- data/test/scanner/test_all.rb +8 -2
- data/test/scanner/test_conditionals.rb +166 -0
- data/test/scanner/test_escapes.rb +8 -5
- data/test/scanner/test_free_space.rb +133 -0
- data/test/scanner/test_groups.rb +28 -0
- data/test/scanner/test_keep.rb +33 -0
- data/test/scanner/test_properties.rb +4 -0
- data/test/scanner/test_scripts.rb +71 -1
- data/test/syntax/ruby/test_1.9.3.rb +2 -2
- data/test/syntax/ruby/test_2.0.0.rb +38 -0
- data/test/syntax/ruby/test_2.2.0.rb +38 -0
- data/test/syntax/ruby/test_all.rb +1 -8
- data/test/syntax/ruby/test_files.rb +104 -0
- data/test/test_all.rb +2 -1
- data/test/token/test_all.rb +2 -0
- data/test/token/test_token.rb +109 -0
- metadata +75 -21
- data/VERSION.yml +0 -5
- data/lib/regexp_parser/ctype.rb +0 -48
- data/test/syntax/ruby/test_2.x.rb +0 -46
data/test/parser/test_escapes.rb
CHANGED
@@ -2,10 +2,6 @@ require File.expand_path("../../helpers", __FILE__)
|
|
2
2
|
|
3
3
|
class TestParserEscapes < Test::Unit::TestCase
|
4
4
|
|
5
|
-
def test_parse_control_sequence_short
|
6
|
-
#root = RP.parse(/\b\d\\\c2\C-C\M-\C-2/)
|
7
|
-
end
|
8
|
-
|
9
5
|
tests = {
|
10
6
|
/a\ac/ => [1, :escape, :bell, EscapeSequence::Bell],
|
11
7
|
/a\ec/ => [1, :escape, :escape, EscapeSequence::AsciiEscape],
|
@@ -33,7 +29,7 @@ class TestParserEscapes < Test::Unit::TestCase
|
|
33
29
|
|
34
30
|
count = 0
|
35
31
|
tests.each do |pattern, test|
|
36
|
-
define_method "
|
32
|
+
define_method "test_parse_escape_#{test[2]}_#{count+=1}" do
|
37
33
|
root = RP.parse(pattern, 'ruby/1.9')
|
38
34
|
exp = root.expressions[test[0]]
|
39
35
|
|
@@ -45,4 +41,32 @@ class TestParserEscapes < Test::Unit::TestCase
|
|
45
41
|
end
|
46
42
|
end
|
47
43
|
|
44
|
+
def test_parse_escape_control_sequence_lower
|
45
|
+
root = RP.parse(/a\\\c2b/)
|
46
|
+
|
47
|
+
assert_equal( EscapeSequence::Control, root[2].class )
|
48
|
+
assert_equal( '\\c2', root[2].text )
|
49
|
+
end
|
50
|
+
|
51
|
+
def test_parse_escape_control_sequence_upper
|
52
|
+
root = RP.parse(/\d\\\C-C\w/)
|
53
|
+
|
54
|
+
assert_equal( EscapeSequence::Control, root[2].class )
|
55
|
+
assert_equal( '\\C-C', root[2].text )
|
56
|
+
end
|
57
|
+
|
58
|
+
def test_parse_escape_meta_sequence
|
59
|
+
root = RP.parse(/\Z\\\M-Z/n)
|
60
|
+
|
61
|
+
assert_equal( EscapeSequence::Meta, root[2].class )
|
62
|
+
assert_equal( '\\M-Z', root[2].text )
|
63
|
+
end
|
64
|
+
|
65
|
+
def test_parse_escape_meta_control_sequence
|
66
|
+
root = RP.parse(/\A\\\M-\C-X/n)
|
67
|
+
|
68
|
+
assert_equal( EscapeSequence::MetaControl, root[2].class )
|
69
|
+
assert_equal( '\\M-\\C-X', root[2].text )
|
70
|
+
end
|
71
|
+
|
48
72
|
end
|
@@ -0,0 +1,139 @@
|
|
1
|
+
require File.expand_path("../../helpers", __FILE__)
|
2
|
+
|
3
|
+
class ParserFreeSpace < Test::Unit::TestCase
|
4
|
+
|
5
|
+
def test_parse_free_space_spaces
|
6
|
+
regexp = /a ? b * c + d{2,4}/x
|
7
|
+
root = RP.parse(regexp)
|
8
|
+
|
9
|
+
0.upto(6) do |i|
|
10
|
+
if i%2 == 1
|
11
|
+
# Consecutive spaces get merged by the parser, thus the two spaces.
|
12
|
+
assert_equal( WhiteSpace, root[i].class )
|
13
|
+
assert_equal( ' ', root[i].text )
|
14
|
+
else
|
15
|
+
assert_equal( Literal, root[i].class )
|
16
|
+
assert_equal( true, root[i].quantified? )
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
def test_parse_non_free_space_literals
|
22
|
+
regexp = /a b c d/
|
23
|
+
root = RP.parse(regexp)
|
24
|
+
|
25
|
+
assert_equal( Literal, root.first.class )
|
26
|
+
assert_equal( 'a b c d', root.first.text )
|
27
|
+
end
|
28
|
+
|
29
|
+
def test_parse_free_space_comments
|
30
|
+
regexp = %r{
|
31
|
+
a ? # One letter
|
32
|
+
b {2,5} # Another one
|
33
|
+
[c-g] + # A set
|
34
|
+
(h|i|j) | # A group
|
35
|
+
klm *
|
36
|
+
nop +
|
37
|
+
}x
|
38
|
+
|
39
|
+
root = RP.parse(regexp)
|
40
|
+
|
41
|
+
alt = root.first
|
42
|
+
assert_equal( Alternation, alt.class )
|
43
|
+
|
44
|
+
alt_1 = alt.alternatives.first
|
45
|
+
assert_equal( Alternative, alt_1.class )
|
46
|
+
assert_equal( 15, alt_1.length )
|
47
|
+
|
48
|
+
[0, 2, 4, 6, 8, 12, 14].each do |i|
|
49
|
+
assert_equal( WhiteSpace, alt_1[i].class )
|
50
|
+
end
|
51
|
+
|
52
|
+
[3, 7, 11].each do |i|
|
53
|
+
assert_equal( Comment, alt_1[i].class )
|
54
|
+
end
|
55
|
+
|
56
|
+
alt_2 = alt.alternatives.last
|
57
|
+
assert_equal( Alternative, alt_2.class )
|
58
|
+
assert_equal( 7, alt_2.length )
|
59
|
+
|
60
|
+
[0, 2, 4, 6].each do |i|
|
61
|
+
assert_equal( WhiteSpace, alt_2[i].class )
|
62
|
+
end
|
63
|
+
|
64
|
+
assert_equal( Comment, alt_2[1].class )
|
65
|
+
end
|
66
|
+
|
67
|
+
def test_parse_free_space_nested_comments
|
68
|
+
# Tests depend on spacing and indentation, obviously.
|
69
|
+
regexp = %r{
|
70
|
+
# Group one
|
71
|
+
(
|
72
|
+
abc # Comment one
|
73
|
+
\d? # Optional \d
|
74
|
+
)+
|
75
|
+
|
76
|
+
# Group two
|
77
|
+
(
|
78
|
+
def # Comment two
|
79
|
+
\s? # Optional \s
|
80
|
+
)?
|
81
|
+
}x
|
82
|
+
|
83
|
+
root = RP.parse(regexp)
|
84
|
+
|
85
|
+
top_comment_1 = root[1]
|
86
|
+
assert_equal( Comment, top_comment_1.class )
|
87
|
+
assert_equal( "# Group one\n", top_comment_1.text )
|
88
|
+
assert_equal( 7, top_comment_1.starts_at )
|
89
|
+
|
90
|
+
top_comment_2 = root[5]
|
91
|
+
assert_equal( Comment, top_comment_2.class )
|
92
|
+
assert_equal( "# Group two\n", top_comment_2.text )
|
93
|
+
assert_equal( 95, top_comment_2.starts_at )
|
94
|
+
|
95
|
+
# Nested comments
|
96
|
+
[3, 7].each_with_index do |g, i|
|
97
|
+
group = root[g]
|
98
|
+
|
99
|
+
[3, 7].each do |c|
|
100
|
+
comment = group[c]
|
101
|
+
assert_equal( Comment, comment.class )
|
102
|
+
assert_equal( 14, comment.text.length )
|
103
|
+
end
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
def test_parse_free_space_quantifiers
|
108
|
+
regexp = %r{
|
109
|
+
a
|
110
|
+
# comment 1
|
111
|
+
?
|
112
|
+
(
|
113
|
+
b # comment 2
|
114
|
+
# comment 3
|
115
|
+
+
|
116
|
+
)
|
117
|
+
# comment 4
|
118
|
+
*
|
119
|
+
}x
|
120
|
+
|
121
|
+
root = RP.parse(regexp)
|
122
|
+
|
123
|
+
literal_1 = root[1]
|
124
|
+
assert_equal( Literal, literal_1.class )
|
125
|
+
assert_equal( true, literal_1.quantified? )
|
126
|
+
assert_equal( :zero_or_one, literal_1.quantifier.token )
|
127
|
+
|
128
|
+
group = root[5]
|
129
|
+
assert_equal( Group::Capture, group.class )
|
130
|
+
assert_equal( true, group.quantified? )
|
131
|
+
assert_equal( :zero_or_more, group.quantifier.token )
|
132
|
+
|
133
|
+
literal_2 = group[1]
|
134
|
+
assert_equal( Literal, literal_2.class )
|
135
|
+
assert_equal( true, literal_2.quantified? )
|
136
|
+
assert_equal( :one_or_more, literal_2.quantifier.token )
|
137
|
+
end
|
138
|
+
|
139
|
+
end
|
data/test/parser/test_groups.rb
CHANGED
@@ -34,6 +34,46 @@ class TestParserGroups < Test::Unit::TestCase
|
|
34
34
|
assert_equal( false, t.expressions[0].expressions[1].x? )
|
35
35
|
end
|
36
36
|
|
37
|
+
if RUBY_VERSION >= '2.0'
|
38
|
+
def test_parse_options_dau
|
39
|
+
t = RP.parse('(?dua:abc)')
|
40
|
+
|
41
|
+
assert_equal( true, t.expressions[0].d? )
|
42
|
+
assert_equal( true, t.expressions[0].a? )
|
43
|
+
assert_equal( true, t.expressions[0].u? )
|
44
|
+
end
|
45
|
+
|
46
|
+
def test_parse_nested_options_dau
|
47
|
+
t = RP.parse('(?u:a(?d:b))')
|
48
|
+
|
49
|
+
assert_equal( true, t.expressions[0].u? )
|
50
|
+
assert_equal( false, t.expressions[0].d? )
|
51
|
+
assert_equal( false, t.expressions[0].a? )
|
52
|
+
|
53
|
+
assert_equal( true, t.expressions[0].expressions[1].d? )
|
54
|
+
assert_equal( false, t.expressions[0].expressions[1].a? )
|
55
|
+
assert_equal( false, t.expressions[0].expressions[1].u? )
|
56
|
+
end
|
57
|
+
|
58
|
+
def test_parse_nested_options_da
|
59
|
+
t = RP.parse('(?di-xm:a(?da-x:b))')
|
60
|
+
|
61
|
+
assert_equal( true, t.expressions[0].d? )
|
62
|
+
assert_equal( true, t.expressions[0].i? )
|
63
|
+
assert_equal( false, t.expressions[0].m? )
|
64
|
+
assert_equal( false, t.expressions[0].x? )
|
65
|
+
assert_equal( false, t.expressions[0].a? )
|
66
|
+
assert_equal( false, t.expressions[0].u? )
|
67
|
+
|
68
|
+
assert_equal( true, t.expressions[0].expressions[1].d? )
|
69
|
+
assert_equal( true, t.expressions[0].expressions[1].a? )
|
70
|
+
assert_equal( false, t.expressions[0].expressions[1].u? )
|
71
|
+
assert_equal( false, t.expressions[0].expressions[1].x? )
|
72
|
+
assert_equal( false, t.expressions[0].expressions[1].m? )
|
73
|
+
assert_equal( false, t.expressions[0].expressions[1].i? )
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
37
77
|
def test_parse_lookahead
|
38
78
|
t = RP.parse('(?=abc)(?!def)', 'ruby/1.8')
|
39
79
|
|
@@ -0,0 +1,21 @@
|
|
1
|
+
require File.expand_path("../../helpers", __FILE__)
|
2
|
+
|
3
|
+
class ParserKeep < Test::Unit::TestCase
|
4
|
+
|
5
|
+
def test_parse_keep
|
6
|
+
regexp = /ab\Kcd/
|
7
|
+
root = RP.parse(regexp)
|
8
|
+
|
9
|
+
assert_equal( Keep::Mark, root[1].class )
|
10
|
+
assert_equal( '\\K', root[1].text )
|
11
|
+
end
|
12
|
+
|
13
|
+
def test_parse_keep_nested
|
14
|
+
regexp = /(a\\\Kb)/
|
15
|
+
root = RP.parse(regexp)
|
16
|
+
|
17
|
+
assert_equal( Keep::Mark, root[0][2].class )
|
18
|
+
assert_equal( '\\K', root[0][2].text )
|
19
|
+
end
|
20
|
+
|
21
|
+
end
|
data/test/scanner/test_all.rb
CHANGED
@@ -1,12 +1,18 @@
|
|
1
1
|
require File.expand_path("../../helpers", __FILE__)
|
2
2
|
|
3
3
|
%w{
|
4
|
-
anchors errors escapes groups literals
|
5
|
-
quantifiers scripts sets types
|
4
|
+
anchors errors escapes free_space groups literals
|
5
|
+
meta properties quantifiers scripts sets types
|
6
6
|
}.each do|tc|
|
7
7
|
require File.expand_path("../test_#{tc}", __FILE__)
|
8
8
|
end
|
9
9
|
|
10
|
+
if RUBY_VERSION >= '2.0.0'
|
11
|
+
%w{conditionals keep}.each do|tc|
|
12
|
+
require File.expand_path("../test_#{tc}", __FILE__)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
10
16
|
class TestRegexpScanner < Test::Unit::TestCase
|
11
17
|
|
12
18
|
def test_scanner_returns_an_array
|
@@ -0,0 +1,166 @@
|
|
1
|
+
require File.expand_path("../../helpers", __FILE__)
|
2
|
+
|
3
|
+
class ScannerConditionals < Test::Unit::TestCase
|
4
|
+
|
5
|
+
# Basic conditional scan token tests
|
6
|
+
tests = {
|
7
|
+
/(?(1)T|F)/ => [0, :conditional, :open, '(?', 0, 2],
|
8
|
+
/(?(2)T|F)/ => [1, :conditional, :condition_open, '(', 2, 3],
|
9
|
+
/(?(3)T|F)/ => [2, :conditional, :condition, '3', 3, 4],
|
10
|
+
/(?(4)T|F)/ => [3, :conditional, :condition_close, ')', 4, 5],
|
11
|
+
/(?(5)T|F)/ => [4, :literal, :literal, 'T', 5, 6],
|
12
|
+
/(?(6)T|F)/ => [5, :conditional, :separator, '|', 6, 7],
|
13
|
+
/(?(7)T|F)/ => [6, :literal, :literal, 'F', 7, 8],
|
14
|
+
/(?(8)T|F)/ => [7, :conditional, :close, ')', 8, 9],
|
15
|
+
|
16
|
+
/(?(1)TRUE)/ => [5, :conditional, :close, ')', 9, 10],
|
17
|
+
|
18
|
+
/(?(1)TRUE|)/ => [5, :conditional, :separator, '|', 9, 10],
|
19
|
+
/(?(2)TRUE|)/ => [6, :conditional, :close, ')', 10, 11],
|
20
|
+
|
21
|
+
/(?<N>A)(?(<N>)T|F)/ => [5, :conditional, :condition, '<N>', 10, 13],
|
22
|
+
/(?'N'A)(?('N')T|F)/ => [5, :conditional, :condition, "'N'", 10, 13],
|
23
|
+
}
|
24
|
+
|
25
|
+
count = 0
|
26
|
+
tests.each do |pattern, test|
|
27
|
+
define_method "test_scan_#{test[1]}_#{test[2]}_#{count+=1}" do
|
28
|
+
|
29
|
+
tokens = RS.scan(pattern)
|
30
|
+
token = tokens[test[0]]
|
31
|
+
assert_equal( test[1,5], token )
|
32
|
+
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
def test_scan_conditional_nested
|
37
|
+
regexp = /(a(b(c)))(?(1)(?(2)d|(?(3)e|f))|(?(2)(?(1)g|h)))/
|
38
|
+
tokens = RS.scan(regexp)
|
39
|
+
|
40
|
+
[ [ 0, :group, :capture, '(', 0, 1],
|
41
|
+
[ 1, :literal, :literal, 'a', 1, 2],
|
42
|
+
[ 2, :group, :capture, '(', 2, 3],
|
43
|
+
[ 3, :literal, :literal, 'b', 3, 4],
|
44
|
+
[ 4, :group, :capture, '(', 4, 5],
|
45
|
+
[ 5, :literal, :literal, 'c', 5, 6],
|
46
|
+
[ 6, :group, :close, ')', 6, 7],
|
47
|
+
[ 7, :group, :close, ')', 7, 8],
|
48
|
+
[ 8, :group, :close, ')', 8, 9],
|
49
|
+
[ 9, :conditional, :open, '(?', 9, 11],
|
50
|
+
[10, :conditional, :condition_open, '(', 11, 12],
|
51
|
+
[11, :conditional, :condition, '1', 12, 13],
|
52
|
+
[12, :conditional, :condition_close, ')', 13, 14],
|
53
|
+
[13, :conditional, :open, '(?', 14, 16],
|
54
|
+
[14, :conditional, :condition_open, '(', 16, 17],
|
55
|
+
[15, :conditional, :condition, '2', 17, 18],
|
56
|
+
[16, :conditional, :condition_close, ')', 18, 19],
|
57
|
+
[17, :literal, :literal, 'd', 19, 20],
|
58
|
+
[18, :conditional, :separator, '|', 20, 21],
|
59
|
+
[19, :conditional, :open, '(?', 21, 23],
|
60
|
+
[20, :conditional, :condition_open, '(', 23, 24],
|
61
|
+
[21, :conditional, :condition, '3', 24, 25],
|
62
|
+
[22, :conditional, :condition_close, ')', 25, 26],
|
63
|
+
[23, :literal, :literal, 'e', 26, 27],
|
64
|
+
[24, :conditional, :separator, '|', 27, 28],
|
65
|
+
[25, :literal, :literal, 'f', 28, 29],
|
66
|
+
[26, :conditional, :close, ')', 29, 30],
|
67
|
+
[27, :conditional, :close, ')', 30, 31],
|
68
|
+
[28, :conditional, :separator, '|', 31, 32],
|
69
|
+
[29, :conditional, :open, '(?', 32, 34],
|
70
|
+
[30, :conditional, :condition_open, '(', 34, 35],
|
71
|
+
[31, :conditional, :condition, '2', 35, 36],
|
72
|
+
[32, :conditional, :condition_close, ')', 36, 37],
|
73
|
+
[33, :conditional, :open, '(?', 37, 39],
|
74
|
+
[34, :conditional, :condition_open, '(', 39, 40],
|
75
|
+
[35, :conditional, :condition, '1', 40, 41],
|
76
|
+
[36, :conditional, :condition_close, ')', 41, 42],
|
77
|
+
[37, :literal, :literal, 'g', 42, 43],
|
78
|
+
[38, :conditional, :separator, '|', 43, 44],
|
79
|
+
[39, :literal, :literal, 'h', 44, 45],
|
80
|
+
[40, :conditional, :close, ')', 45, 46],
|
81
|
+
[41, :conditional, :close, ')', 46, 47],
|
82
|
+
[42, :conditional, :close, ')', 47, 48]
|
83
|
+
].each do |test|
|
84
|
+
assert_equal( test[1,5], tokens[test[0]] )
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
def test_scan_conditional_nested_groups
|
89
|
+
regexp = /((a)|(b)|((?(2)(c(d|e)+)?|(?(3)f|(?(4)(g|(h)(i)))))))/
|
90
|
+
tokens = RS.scan(regexp)
|
91
|
+
|
92
|
+
[ [ 0, :group, :capture, '(', 0, 1],
|
93
|
+
[ 1, :group, :capture, '(', 1, 2],
|
94
|
+
[ 2, :literal, :literal, 'a', 2, 3],
|
95
|
+
[ 3, :group, :close, ')', 3, 4],
|
96
|
+
[ 4, :meta, :alternation, '|', 4, 5],
|
97
|
+
[ 5, :group, :capture, '(', 5, 6],
|
98
|
+
[ 6, :literal, :literal, 'b', 6, 7],
|
99
|
+
[ 7, :group, :close, ')', 7, 8],
|
100
|
+
[ 8, :meta, :alternation, '|', 8, 9],
|
101
|
+
[ 9, :group, :capture, '(', 9, 10],
|
102
|
+
[10, :conditional, :open, '(?', 10, 12],
|
103
|
+
[11, :conditional, :condition_open, '(', 12, 13],
|
104
|
+
[12, :conditional, :condition, '2', 13, 14],
|
105
|
+
[13, :conditional, :condition_close, ')', 14, 15],
|
106
|
+
[14, :group, :capture, '(', 15, 16],
|
107
|
+
[15, :literal, :literal, 'c', 16, 17],
|
108
|
+
[16, :group, :capture, '(', 17, 18],
|
109
|
+
[17, :literal, :literal, 'd', 18, 19],
|
110
|
+
[18, :meta, :alternation, '|', 19, 20],
|
111
|
+
[19, :literal, :literal, 'e', 20, 21],
|
112
|
+
[20, :group, :close, ')', 21, 22],
|
113
|
+
[21, :quantifier, :one_or_more, '+', 22, 23],
|
114
|
+
[22, :group, :close, ')', 23, 24],
|
115
|
+
[23, :quantifier, :zero_or_one, '?', 24, 25],
|
116
|
+
[24, :conditional, :separator, '|', 25, 26],
|
117
|
+
[25, :conditional, :open, '(?', 26, 28],
|
118
|
+
[26, :conditional, :condition_open, '(', 28, 29],
|
119
|
+
[27, :conditional, :condition, '3', 29, 30],
|
120
|
+
[28, :conditional, :condition_close, ')', 30, 31],
|
121
|
+
[29, :literal, :literal, 'f', 31, 32],
|
122
|
+
[30, :conditional, :separator, '|', 32, 33],
|
123
|
+
[31, :conditional, :open, '(?', 33, 35],
|
124
|
+
[32, :conditional, :condition_open, '(', 35, 36],
|
125
|
+
[33, :conditional, :condition, '4', 36, 37],
|
126
|
+
[34, :conditional, :condition_close, ')', 37, 38],
|
127
|
+
[35, :group, :capture, '(', 38, 39],
|
128
|
+
[36, :literal, :literal, 'g', 39, 40],
|
129
|
+
[37, :meta, :alternation, '|', 40, 41],
|
130
|
+
[38, :group, :capture, '(', 41, 42],
|
131
|
+
[39, :literal, :literal, 'h', 42, 43],
|
132
|
+
[40, :group, :close, ')', 43, 44],
|
133
|
+
[41, :group, :capture, '(', 44, 45],
|
134
|
+
[42, :literal, :literal, 'i', 45, 46],
|
135
|
+
[43, :group, :close, ')', 46, 47],
|
136
|
+
[44, :group, :close, ')', 47, 48],
|
137
|
+
[45, :conditional, :close, ')', 48, 49],
|
138
|
+
[46, :conditional, :close, ')', 49, 50],
|
139
|
+
[47, :conditional, :close, ')', 50, 51],
|
140
|
+
[48, :group, :close, ')', 51, 52],
|
141
|
+
[49, :group, :close, ')', 52, 53]
|
142
|
+
].each do |test|
|
143
|
+
assert_equal( test[1,5], tokens[test[0]] )
|
144
|
+
end
|
145
|
+
end
|
146
|
+
|
147
|
+
def test_scan_conditional_nested_alternation
|
148
|
+
regexp = /(a)(?(1)(b|c|d)|(e|f|g))(h)(?(2)(i|j|k)|(l|m|n))|o|p/
|
149
|
+
tokens = RS.scan(regexp)
|
150
|
+
|
151
|
+
[9, 11, 17, 19, 32, 34, 40, 42, 46, 48].each do |token|
|
152
|
+
assert_equal(:meta, tokens[token][0])
|
153
|
+
assert_equal(:alternation, tokens[token][1])
|
154
|
+
assert_equal('|', tokens[token][2])
|
155
|
+
assert_equal(1, tokens[token][4] - tokens[token][3])
|
156
|
+
end
|
157
|
+
|
158
|
+
[14, 37].each do |token|
|
159
|
+
assert_equal(:conditional, tokens[token][0])
|
160
|
+
assert_equal(:separator, tokens[token][1])
|
161
|
+
assert_equal('|', tokens[token][2])
|
162
|
+
assert_equal(1, tokens[token][4] - tokens[token][3])
|
163
|
+
end
|
164
|
+
end
|
165
|
+
|
166
|
+
end
|