regexp_parser 2.2.0 → 2.3.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (107) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +34 -1
  3. data/Gemfile +2 -1
  4. data/LICENSE +1 -1
  5. data/README.md +16 -6
  6. data/Rakefile +1 -59
  7. data/lib/regexp_parser/expression/classes/escape_sequence.rb +12 -7
  8. data/lib/regexp_parser/expression/methods/strfregexp.rb +1 -1
  9. data/lib/regexp_parser/lexer.rb +1 -1
  10. data/lib/regexp_parser/scanner/properties/long.csv +622 -0
  11. data/lib/regexp_parser/scanner/properties/short.csv +246 -0
  12. data/lib/regexp_parser/scanner/scanner.rl +6 -4
  13. data/lib/regexp_parser/scanner.rb +126 -124
  14. data/lib/regexp_parser/syntax/any.rb +2 -5
  15. data/lib/regexp_parser/syntax/base.rb +91 -66
  16. data/lib/regexp_parser/syntax/token/backreference.rb +7 -2
  17. data/lib/regexp_parser/syntax/token/quantifier.rb +4 -4
  18. data/lib/regexp_parser/syntax/token/unicode_property.rb +26 -5
  19. data/lib/regexp_parser/syntax/version_lookup.rb +20 -29
  20. data/lib/regexp_parser/syntax/versions/1.8.6.rb +13 -20
  21. data/lib/regexp_parser/syntax/versions/1.9.1.rb +10 -17
  22. data/lib/regexp_parser/syntax/versions/1.9.3.rb +3 -10
  23. data/lib/regexp_parser/syntax/versions/2.0.0.rb +8 -15
  24. data/lib/regexp_parser/syntax/versions/2.2.0.rb +3 -9
  25. data/lib/regexp_parser/syntax/versions/2.3.0.rb +3 -9
  26. data/lib/regexp_parser/syntax/versions/2.4.0.rb +3 -9
  27. data/lib/regexp_parser/syntax/versions/2.4.1.rb +2 -8
  28. data/lib/regexp_parser/syntax/versions/2.5.0.rb +3 -9
  29. data/lib/regexp_parser/syntax/versions/2.6.0.rb +3 -9
  30. data/lib/regexp_parser/syntax/versions/2.6.2.rb +3 -9
  31. data/lib/regexp_parser/syntax/versions/2.6.3.rb +3 -9
  32. data/lib/regexp_parser/syntax/versions/3.1.0.rb +3 -9
  33. data/lib/regexp_parser/syntax/versions/3.2.0.rb +4 -0
  34. data/lib/regexp_parser/syntax/versions.rb +1 -1
  35. data/lib/regexp_parser/version.rb +1 -1
  36. data/regexp_parser.gemspec +20 -22
  37. metadata +12 -143
  38. data/lib/regexp_parser/scanner/properties/long.yml +0 -607
  39. data/lib/regexp_parser/scanner/properties/short.yml +0 -245
  40. data/spec/expression/base_spec.rb +0 -104
  41. data/spec/expression/clone_spec.rb +0 -152
  42. data/spec/expression/conditional_spec.rb +0 -89
  43. data/spec/expression/free_space_spec.rb +0 -27
  44. data/spec/expression/methods/match_length_spec.rb +0 -161
  45. data/spec/expression/methods/match_spec.rb +0 -25
  46. data/spec/expression/methods/strfregexp_spec.rb +0 -224
  47. data/spec/expression/methods/tests_spec.rb +0 -99
  48. data/spec/expression/methods/traverse_spec.rb +0 -161
  49. data/spec/expression/options_spec.rb +0 -128
  50. data/spec/expression/subexpression_spec.rb +0 -50
  51. data/spec/expression/to_h_spec.rb +0 -26
  52. data/spec/expression/to_s_spec.rb +0 -108
  53. data/spec/lexer/all_spec.rb +0 -22
  54. data/spec/lexer/conditionals_spec.rb +0 -53
  55. data/spec/lexer/delimiters_spec.rb +0 -68
  56. data/spec/lexer/escapes_spec.rb +0 -14
  57. data/spec/lexer/keep_spec.rb +0 -10
  58. data/spec/lexer/literals_spec.rb +0 -64
  59. data/spec/lexer/nesting_spec.rb +0 -99
  60. data/spec/lexer/refcalls_spec.rb +0 -60
  61. data/spec/parser/all_spec.rb +0 -43
  62. data/spec/parser/alternation_spec.rb +0 -88
  63. data/spec/parser/anchors_spec.rb +0 -17
  64. data/spec/parser/conditionals_spec.rb +0 -179
  65. data/spec/parser/errors_spec.rb +0 -30
  66. data/spec/parser/escapes_spec.rb +0 -133
  67. data/spec/parser/free_space_spec.rb +0 -130
  68. data/spec/parser/groups_spec.rb +0 -108
  69. data/spec/parser/keep_spec.rb +0 -6
  70. data/spec/parser/options_spec.rb +0 -28
  71. data/spec/parser/posix_classes_spec.rb +0 -8
  72. data/spec/parser/properties_spec.rb +0 -117
  73. data/spec/parser/quantifiers_spec.rb +0 -68
  74. data/spec/parser/refcalls_spec.rb +0 -117
  75. data/spec/parser/set/intersections_spec.rb +0 -127
  76. data/spec/parser/set/ranges_spec.rb +0 -121
  77. data/spec/parser/sets_spec.rb +0 -178
  78. data/spec/parser/types_spec.rb +0 -18
  79. data/spec/scanner/all_spec.rb +0 -18
  80. data/spec/scanner/anchors_spec.rb +0 -21
  81. data/spec/scanner/conditionals_spec.rb +0 -128
  82. data/spec/scanner/delimiters_spec.rb +0 -52
  83. data/spec/scanner/errors_spec.rb +0 -67
  84. data/spec/scanner/escapes_spec.rb +0 -73
  85. data/spec/scanner/free_space_spec.rb +0 -165
  86. data/spec/scanner/groups_spec.rb +0 -61
  87. data/spec/scanner/keep_spec.rb +0 -10
  88. data/spec/scanner/literals_spec.rb +0 -39
  89. data/spec/scanner/meta_spec.rb +0 -18
  90. data/spec/scanner/options_spec.rb +0 -36
  91. data/spec/scanner/properties_spec.rb +0 -64
  92. data/spec/scanner/quantifiers_spec.rb +0 -25
  93. data/spec/scanner/refcalls_spec.rb +0 -55
  94. data/spec/scanner/sets_spec.rb +0 -151
  95. data/spec/scanner/types_spec.rb +0 -14
  96. data/spec/spec_helper.rb +0 -28
  97. data/spec/support/capturing_stderr.rb +0 -9
  98. data/spec/support/shared_examples.rb +0 -77
  99. data/spec/syntax/syntax_spec.rb +0 -48
  100. data/spec/syntax/syntax_token_map_spec.rb +0 -23
  101. data/spec/syntax/versions/1.8.6_spec.rb +0 -17
  102. data/spec/syntax/versions/1.9.1_spec.rb +0 -10
  103. data/spec/syntax/versions/1.9.3_spec.rb +0 -9
  104. data/spec/syntax/versions/2.0.0_spec.rb +0 -13
  105. data/spec/syntax/versions/2.2.0_spec.rb +0 -9
  106. data/spec/syntax/versions/aliases_spec.rb +0 -38
  107. data/spec/token/token_spec.rb +0 -85
@@ -1,108 +0,0 @@
1
- require 'spec_helper'
2
-
3
- RSpec.describe('Group parsing') do
4
- include_examples 'parse', /(?=abc)(?!def)/,
5
- 0 => [:assertion, :lookahead, Assertion::Lookahead],
6
- 1 => [:assertion, :nlookahead, Assertion::NegativeLookahead]
7
-
8
- include_examples 'parse', /(?<=abc)(?<!def)/,
9
- 0 => [:assertion, :lookbehind, Assertion::Lookbehind],
10
- 1 => [:assertion, :nlookbehind, Assertion::NegativeLookbehind]
11
-
12
- include_examples 'parse', /a(?# is for apple)b(?# for boy)c(?# cat)/,
13
- 1 => [:group, :comment, Group::Comment],
14
- 3 => [:group, :comment, Group::Comment],
15
- 5 => [:group, :comment, Group::Comment]
16
-
17
- if ruby_version_at_least('2.4.1')
18
- include_examples 'parse', 'a(?~b)c(?~d)e',
19
- 1 => [:group, :absence, Group::Absence],
20
- 3 => [:group, :absence, Group::Absence]
21
- end
22
-
23
- include_examples 'parse', /(?m:a)/,
24
- 0 => [:group, :options, Group::Options, options: { m: true }, option_changes: { m: true }]
25
-
26
- # self-defeating group option
27
- include_examples 'parse', /(?m-m:a)/,
28
- 0 => [:group, :options, Group::Options, options: {}, option_changes: { m: false }]
29
-
30
- # activate one option in nested group
31
- include_examples 'parse', /(?x-mi:a(?m:b))/,
32
- 0 => [:group, :options, Group::Options, options: { x: true }, option_changes: { i: false, m: false, x: true }],
33
- [0, 1] => [:group, :options, Group::Options, options: { m: true, x: true }, option_changes: { m: true }]
34
-
35
- # deactivate one option in nested group
36
- include_examples 'parse', /(?ix-m:a(?-i:b))/,
37
- 0 => [:group, :options, Group::Options, options: { i: true, x: true }, option_changes: { i: true, m: false, x: true }],
38
- [0, 1] => [:group, :options, Group::Options, options: { x: true }, option_changes: { i: false }]
39
-
40
- # invert all options in nested group
41
- include_examples 'parse', /(?xi-m:a(?m-ix:b))/,
42
- 0 => [:group, :options, Group::Options, options: { i: true, x: true }, option_changes: { i: true, m: false, x: true }],
43
- [0, 1] => [:group, :options, Group::Options, options: { m: true }, option_changes: { i: false, m: true, x: false }]
44
-
45
- # nested options affect literal subexpressions
46
- include_examples 'parse', /(?x-mi:a(?m:b))/,
47
- [0, 0] => [:literal, :literal, Literal, text: 'a', options: { x: true }],
48
- [0, 1, 0] => [:literal, :literal, Literal, text: 'b', options: { m: true, x: true }]
49
-
50
- # option switching group
51
- include_examples 'parse', /a(?i-m)b/m,
52
- 0 => [:literal, :literal, Literal, text: 'a', options: { m: true }],
53
- 1 => [:group, :options_switch, Group::Options, options: { i: true }, option_changes: { i: true, m: false }],
54
- 2 => [:literal, :literal, Literal, text: 'b', options: { i: true }]
55
-
56
- # option switch in group
57
- include_examples 'parse', /(a(?i-m)b)c/m,
58
- 0 => [:group, :capture, Group::Capture, options: { m: true }],
59
- [0, 0] => [:literal, :literal, Literal, text: 'a', options: { m: true }],
60
- [0, 1] => [:group, :options_switch, Group::Options, options: { i: true }, option_changes: { i: true, m: false }],
61
- [0, 2] => [:literal, :literal, Literal, text: 'b', options: { i: true }],
62
- 1 => [:literal, :literal, Literal, text: 'c', options: { m: true }]
63
-
64
- # nested option switch in group
65
- include_examples 'parse', /((?i-m)(a(?-i)b))/m,
66
- [0, 1] => [:group, :capture, Group::Capture, options: { i: true }],
67
- [0, 1, 0] => [:literal, :literal, Literal, text: 'a', options: { i: true }],
68
- [0, 1, 1] => [:group, :options_switch, Group::Options, options: {}, option_changes: { i: false }],
69
- [0, 1, 2] => [:literal, :literal, Literal, text: 'b', options: {}]
70
-
71
- # options dau
72
- include_examples 'parse', /(?dua:abc)/,
73
- 0 => [:group, :options, Group::Options, options: { a: true }, option_changes: { a: true }]
74
-
75
- # nested options dau
76
- include_examples 'parse', /(?u:a(?d:b))/,
77
- 0 => [:group, :options, Group::Options, options: { u: true }, option_changes: { u: true }],
78
- [0, 1] => [:group, :options, Group::Options, options: { d: true }, option_changes: { d: true, u: false }],
79
- [0, 1, 0] => [:literal, :literal, Literal, text: 'b', options: { d: true }]
80
-
81
- # nested options da
82
- include_examples 'parse', /(?di-xm:a(?da-x:b))/,
83
- 0 => [:group, :options, Group::Options, options: { d: true, i:true }],
84
- [0, 1] => [:group, :options, Group::Options, options: { a: true, i: true }, option_changes: { a: true, d: false, x: false}],
85
- [0, 1, 0] => [:literal, :literal, Literal, text: 'b', options: { a: true, i: true }]
86
-
87
- specify('parse group number') do
88
- root = RP.parse(/(a)(?=b)((?:c)(d|(e)))/)
89
-
90
- expect(root[0].number).to eq 1
91
- expect(root[1]).not_to respond_to(:number)
92
- expect(root[2].number).to eq 2
93
- expect(root[2][0]).not_to respond_to(:number)
94
- expect(root[2][1].number).to eq 3
95
- expect(root[2][1][0][1][0].number).to eq 4
96
- end
97
-
98
- specify('parse group number at level') do
99
- root = RP.parse(/(a)(?=b)((?:c)(d|(e)))/)
100
-
101
- expect(root[0].number_at_level).to eq 1
102
- expect(root[1]).not_to respond_to(:number_at_level)
103
- expect(root[2].number_at_level).to eq 2
104
- expect(root[2][0]).not_to respond_to(:number_at_level)
105
- expect(root[2][1].number_at_level).to eq 1
106
- expect(root[2][1][0][1][0].number_at_level).to eq 1
107
- end
108
- end
@@ -1,6 +0,0 @@
1
- require 'spec_helper'
2
-
3
- RSpec.describe('Keep parsing') do
4
- include_examples 'parse', /ab\Kcd/, 1 => [:keep, :mark, Keep::Mark, text: '\K']
5
- include_examples 'parse', /(a\K)/, [0, 1] => [:keep, :mark, Keep::Mark, text: '\K']
6
- end
@@ -1,28 +0,0 @@
1
- require 'spec_helper'
2
-
3
- RSpec.describe('passing options to parse') do
4
- it 'raises if if parsing from a Regexp and options are passed' do
5
- expect { RP.parse(/a+/, options: ::Regexp::EXTENDED) }.to raise_error(
6
- ArgumentError,
7
- 'options cannot be supplied unless parsing a String'
8
- )
9
- end
10
-
11
- it 'sets options if parsing from a String' do
12
- root = RP.parse('a+', options: ::Regexp::MULTILINE | ::Regexp::EXTENDED)
13
-
14
- expect(root.options).to eq(m: true, x: true)
15
- end
16
-
17
- it 'allows options to not be supplied when parsing from a Regexp' do
18
- root = RP.parse(/a+/ix)
19
-
20
- expect(root.options).to eq(i: true, x: true)
21
- end
22
-
23
- it 'has an empty option-hash when parsing from a String and passing no options' do
24
- root = RP.parse('a+')
25
-
26
- expect(root.options).to be_empty
27
- end
28
- end
@@ -1,8 +0,0 @@
1
- require 'spec_helper'
2
-
3
- RSpec.describe('PosixClass parsing') do
4
- include_examples 'parse', /[[:word:]]/, [0, 0] => [:posixclass, :word, PosixClass,
5
- name: 'word', text: '[:word:]', negative?: false]
6
- include_examples 'parse', /[[:^word:]]/, [0, 0] => [:nonposixclass, :word, PosixClass,
7
- name: 'word', text: '[:^word:]', negative?: true]
8
- end
@@ -1,117 +0,0 @@
1
- require 'spec_helper'
2
-
3
- RSpec.describe('Property parsing') do
4
- example_props = [
5
- 'Alnum',
6
- 'Any',
7
- 'Age=1.1',
8
- 'Dash',
9
- 'di',
10
- 'Default_Ignorable_Code_Point',
11
- 'Math',
12
- 'Noncharacter-Code_Point', # test dash
13
- 'sd',
14
- 'Soft Dotted', # test whitespace
15
- 'sterm',
16
- 'xidc',
17
- 'XID_Continue',
18
- 'Emoji',
19
- 'InChessSymbols'
20
- ]
21
-
22
- example_props.each do |name|
23
- it("parses property #{name}") do
24
- exp = RP.parse("ab\\p{#{name}}", '*').last
25
-
26
- expect(exp).to be_a(UnicodeProperty::Base)
27
- expect(exp.type).to eq :property
28
- expect(exp.name).to eq name
29
- end
30
-
31
- it("parses nonproperty #{name}") do
32
- exp = RP.parse("ab\\P{#{name}}", '*').last
33
-
34
- expect(exp).to be_a(UnicodeProperty::Base)
35
- expect(exp.type).to eq :nonproperty
36
- expect(exp.name).to eq name
37
- end
38
- end
39
-
40
- if ruby_version_at_least('2.7.0')
41
- specify('parse all properties of current ruby') do
42
- unsupported = RegexpPropertyValues.all_for_current_ruby.reject do |prop|
43
- RP.parse("\\p{#{prop}}") rescue false
44
- end
45
- expect(unsupported).to be_empty
46
- end
47
- end
48
-
49
- specify('parse property negative') do
50
- root = RP.parse('ab\p{L}cd', 'ruby/1.9')
51
- expect(root[1]).not_to be_negative
52
- end
53
-
54
- specify('parse nonproperty negative') do
55
- root = RP.parse('ab\P{L}cd', 'ruby/1.9')
56
- expect(root[1]).to be_negative
57
- end
58
-
59
- specify('parse caret nonproperty negative') do
60
- root = RP.parse('ab\p{^L}cd', 'ruby/1.9')
61
- expect(root[1]).to be_negative
62
- end
63
-
64
- specify('parse double negated property negative') do
65
- root = RP.parse('ab\P{^L}cd', 'ruby/1.9')
66
- expect(root[1]).not_to be_negative
67
- end
68
-
69
- specify('parse property shortcut') do
70
- expect(RP.parse('\p{lowercase_letter}')[0].shortcut).to eq 'll'
71
- expect(RP.parse('\p{sc}')[0].shortcut).to eq 'sc'
72
- expect(RP.parse('\p{in_bengali}')[0].shortcut).to be_nil
73
- end
74
-
75
- specify('parse property age') do
76
- root = RP.parse('ab\p{age=5.2}cd', 'ruby/1.9')
77
- expect(root[1]).to be_a(UnicodeProperty::Age)
78
- end
79
-
80
- specify('parse property derived') do
81
- root = RP.parse('ab\p{Math}cd', 'ruby/1.9')
82
- expect(root[1]).to be_a(UnicodeProperty::Derived)
83
- end
84
-
85
- specify('parse property script') do
86
- root = RP.parse('ab\p{Hiragana}cd', 'ruby/1.9')
87
- expect(root[1]).to be_a(UnicodeProperty::Script)
88
- end
89
-
90
- specify('parse property script V1 9 3') do
91
- root = RP.parse('ab\p{Brahmi}cd', 'ruby/1.9.3')
92
- expect(root[1]).to be_a(UnicodeProperty::Script)
93
- end
94
-
95
- specify('parse property script V2 2 0') do
96
- root = RP.parse('ab\p{Caucasian_Albanian}cd', 'ruby/2.2')
97
- expect(root[1]).to be_a(UnicodeProperty::Script)
98
- end
99
-
100
- specify('parse property block') do
101
- root = RP.parse('ab\p{InArmenian}cd', 'ruby/1.9')
102
- expect(root[1]).to be_a(UnicodeProperty::Block)
103
- end
104
-
105
- specify('parse property following literal') do
106
- root = RP.parse('ab\p{Lu}cd', 'ruby/1.9')
107
- expect(root[2]).to be_a(Literal)
108
- end
109
-
110
- specify('parse abandoned newline property') do
111
- root = RP.parse('\p{newline}', 'ruby/1.9')
112
- expect(root.expressions.last).to be_a(UnicodeProperty::Base)
113
-
114
- expect { RP.parse('\p{newline}', 'ruby/2.0') }
115
- .to raise_error(Regexp::Syntax::NotImplementedError)
116
- end
117
- end
@@ -1,68 +0,0 @@
1
- require 'spec_helper'
2
-
3
- RSpec.describe('Quantifier parsing') do
4
- RSpec.shared_examples 'quantifier' do |pattern, text, mode, token, min, max|
5
- it "parses the quantifier in #{pattern} as #{mode} #{token}" do
6
- root = RP.parse(pattern, '*')
7
- exp = root[0]
8
-
9
- expect(exp).to be_quantified
10
- expect(exp.quantifier.token).to eq token
11
- expect(exp.quantifier.min).to eq min
12
- expect(exp.quantifier.max).to eq max
13
- expect(exp.quantifier.mode).to eq mode
14
- expect(exp.quantifier.text).to eq text
15
- end
16
- end
17
-
18
- include_examples 'quantifier', /a?b/, '?', :greedy, :zero_or_one, 0, 1
19
- include_examples 'quantifier', /a??b/, '??', :reluctant, :zero_or_one, 0, 1
20
- include_examples 'quantifier', /a?+b/, '?+', :possessive, :zero_or_one, 0, 1
21
- include_examples 'quantifier', /a*b/, '*', :greedy, :zero_or_more, 0, -1
22
- include_examples 'quantifier', /a*?b/, '*?', :reluctant, :zero_or_more, 0, -1
23
- include_examples 'quantifier', /a*+b/, '*+', :possessive, :zero_or_more, 0, -1
24
- include_examples 'quantifier', /a+b/, '+', :greedy, :one_or_more, 1, -1
25
- include_examples 'quantifier', /a+?b/, '+?', :reluctant, :one_or_more, 1, -1
26
- include_examples 'quantifier', /a++b/, '++', :possessive, :one_or_more, 1, -1
27
- include_examples 'quantifier', /a{2,4}b/, '{2,4}', :greedy, :interval, 2, 4
28
- include_examples 'quantifier', /a{2,4}?b/, '{2,4}?', :reluctant, :interval, 2, 4
29
- include_examples 'quantifier', /a{2,4}+b/, '{2,4}+', :possessive, :interval, 2, 4
30
- include_examples 'quantifier', /a{2,}b/, '{2,}', :greedy, :interval, 2, -1
31
- include_examples 'quantifier', /a{2,}?b/, '{2,}?', :reluctant, :interval, 2, -1
32
- include_examples 'quantifier', /a{2,}+b/, '{2,}+', :possessive, :interval, 2, -1
33
- include_examples 'quantifier', /a{,3}b/, '{,3}', :greedy, :interval, 0, 3
34
- include_examples 'quantifier', /a{,3}?b/, '{,3}?', :reluctant, :interval, 0, 3
35
- include_examples 'quantifier', /a{,3}+b/, '{,3}+', :possessive, :interval, 0, 3
36
- include_examples 'quantifier', /a{4}b/, '{4}', :greedy, :interval, 4, 4
37
- include_examples 'quantifier', /a{4}?b/, '{4}?', :reluctant, :interval, 4, 4
38
- include_examples 'quantifier', /a{4}+b/, '{4}+', :possessive, :interval, 4, 4
39
- include_examples 'quantifier', /a{004}+b/, '{004}+', :possessive, :interval, 4, 4
40
-
41
- # special case: exps with chained quantifiers are wrapped in implicit passive groups
42
- include_examples 'parse', /a+{2}{3}/,
43
- 0 => [
44
- :group, :passive, Group::Passive, implicit?: true, level: 0,
45
- quantifier: Quantifier.new(:interval, '{3}', 3, 3, :greedy)
46
- ],
47
- [0, 0] => [
48
- :group, :passive, Group::Passive, implicit?: true, level: 1,
49
- quantifier: Quantifier.new(:interval, '{2}', 2, 2, :greedy)
50
- ],
51
- [0, 0, 0] => [
52
- :literal, :literal, Literal, text: 'a', level: 2,
53
- quantifier: Quantifier.new(:one_or_more, '+', 1, -1, :greedy)
54
- ]
55
-
56
- specify('mode-checking methods') do
57
- exp = RP.parse(/a??/).first
58
-
59
- expect(exp).to be_reluctant
60
- expect(exp).to be_lazy
61
- expect(exp).not_to be_greedy
62
- expect(exp).not_to be_possessive
63
- expect(exp.quantifier).to be_reluctant
64
- expect(exp.quantifier).to be_lazy
65
- expect(exp.quantifier).not_to be_greedy
66
- expect(exp.quantifier).not_to be_possessive
67
- end
68
- end
@@ -1,117 +0,0 @@
1
- require 'spec_helper'
2
-
3
- RSpec.describe('Refcall parsing') do
4
- include_examples 'parse', /(abc)\1/,
5
- 1 => [:backref, :number, Backreference::Number, number: 1]
6
-
7
- include_examples 'parse', /(?<X>abc)\k<X>/,
8
- 1 => [:backref, :name_ref, Backreference::Name, name: 'X']
9
- include_examples 'parse', /(?<X>abc)\k'X'/,
10
- 1 => [:backref, :name_ref, Backreference::Name, name: 'X']
11
-
12
- include_examples 'parse', /(abc)\k<1>/,
13
- 1 => [:backref, :number_ref, Backreference::Number, number: 1]
14
- include_examples 'parse', /(abc)\k'1'/,
15
- 1 => [:backref, :number_ref, Backreference::Number, number: 1]
16
-
17
- include_examples 'parse', /(abc)\k<-1>/,
18
- 1 => [:backref, :number_rel_ref, Backreference::NumberRelative, number: -1]
19
- include_examples 'parse', /(abc)\k'-1'/,
20
- 1 => [:backref, :number_rel_ref, Backreference::NumberRelative, number: -1]
21
-
22
- include_examples 'parse', /(?<X>abc)\g<X>/,
23
- 1 => [:backref, :name_call, Backreference::NameCall, name: 'X']
24
- include_examples 'parse', /(?<X>abc)\g'X'/,
25
- 1 => [:backref, :name_call, Backreference::NameCall, name: 'X']
26
-
27
- include_examples 'parse', /(abc)\g<1>/,
28
- 1 => [:backref, :number_call, Backreference::NumberCall, number: 1]
29
- include_examples 'parse', /(abc)\g'1'/,
30
- 1 => [:backref, :number_call, Backreference::NumberCall, number: 1]
31
-
32
- include_examples 'parse', '\g<0>',
33
- 0 => [:backref, :number_call, Backreference::NumberCall, number: 0]
34
- include_examples 'parse', "\\g'0'",
35
- 0 => [:backref, :number_call, Backreference::NumberCall, number: 0]
36
-
37
- include_examples 'parse', /(abc)\g<-1>/,
38
- 1 => [:backref, :number_rel_call, Backreference::NumberCallRelative, number: -1]
39
- include_examples 'parse', /(abc)\g'-1'/,
40
- 1 => [:backref, :number_rel_call, Backreference::NumberCallRelative, number: -1]
41
-
42
- include_examples 'parse', /\g<+1>(abc)/,
43
- 0 => [:backref, :number_rel_call, Backreference::NumberCallRelative, number: 1]
44
- include_examples 'parse', /\g'+1'(abc)/,
45
- 0 => [:backref, :number_rel_call, Backreference::NumberCallRelative, number: 1]
46
-
47
- include_examples 'parse', /(?<X>abc)\k<X-0>/,
48
- 1 => [:backref, :name_recursion_ref, Backreference::NameRecursionLevel,
49
- name: 'X', recursion_level: 0]
50
- include_examples 'parse', /(?<X>abc)\k'X-0'/,
51
- 1 => [:backref, :name_recursion_ref, Backreference::NameRecursionLevel,
52
- name: 'X', recursion_level: 0]
53
-
54
- include_examples 'parse', /(abc)\k<1-0>/,
55
- 1 => [:backref, :number_recursion_ref, Backreference::NumberRecursionLevel,
56
- number: 1, recursion_level: 0]
57
- include_examples 'parse', /(abc)\k'1-0'/,
58
- 1 => [:backref, :number_recursion_ref, Backreference::NumberRecursionLevel,
59
- number: 1, recursion_level: 0]
60
- include_examples 'parse', /(abc)\k'-1+0'/,
61
- 1 => [:backref, :number_recursion_ref, Backreference::NumberRecursionLevel,
62
- number: -1, recursion_level: 0]
63
- include_examples 'parse', /(abc)\k'1+1'/,
64
- 1 => [:backref, :number_recursion_ref, Backreference::NumberRecursionLevel,
65
- number: 1, recursion_level: 1]
66
- include_examples 'parse', /(abc)\k'1-1'/,
67
- 1 => [:backref, :number_recursion_ref, Backreference::NumberRecursionLevel,
68
- number: 1, recursion_level: -1]
69
-
70
- specify('parse backref effective_number') do
71
- root = RP.parse('(abc)(def)\\k<-1>(ghi)\\k<-3>\\k<-1>', 'ruby/1.9')
72
- exp1 = root[2]
73
- exp2 = root[4]
74
- exp3 = root[5]
75
-
76
- expect([exp1, exp2, exp3]).to all be_instance_of(Backreference::NumberRelative)
77
- expect(exp1.effective_number).to eq 2
78
- expect(exp2.effective_number).to eq 1
79
- expect(exp3.effective_number).to eq 3
80
- end
81
-
82
- specify('parse backref referenced_expression') do
83
- root = RP.parse('(abc)(def)\\k<-1>(ghi)\\k<-3>\\k<-1>', 'ruby/1.9')
84
- exp1 = root[2]
85
- exp2 = root[4]
86
- exp3 = root[5]
87
-
88
- expect([exp1, exp2, exp3]).to all be_instance_of(Backreference::NumberRelative)
89
- expect(exp1.referenced_expression.to_s).to eq '(def)'
90
- expect(exp2.referenced_expression.to_s).to eq '(abc)'
91
- expect(exp3.referenced_expression.to_s).to eq '(ghi)'
92
- end
93
-
94
- specify('parse backref call effective_number') do
95
- root = RP.parse('\\g<+1>(abc)\\g<+2>(def)(ghi)\\g<-2>', 'ruby/1.9')
96
- exp1 = root[0]
97
- exp2 = root[2]
98
- exp3 = root[5]
99
-
100
- expect([exp1, exp2, exp3]).to all be_instance_of(Backreference::NumberCallRelative)
101
- expect(exp1.effective_number).to eq 1
102
- expect(exp2.effective_number).to eq 3
103
- expect(exp3.effective_number).to eq 2
104
- end
105
-
106
- specify('parse backref call referenced_expression') do
107
- root = RP.parse('\\g<+1>(abc)\\g<+2>(def)(ghi)\\g<-2>', 'ruby/1.9')
108
- exp1 = root[0]
109
- exp2 = root[2]
110
- exp3 = root[5]
111
-
112
- expect([exp1, exp2, exp3]).to all be_instance_of(Backreference::NumberCallRelative)
113
- expect(exp1.referenced_expression.to_s).to eq '(abc)'
114
- expect(exp2.referenced_expression.to_s).to eq '(ghi)'
115
- expect(exp3.referenced_expression.to_s).to eq '(def)'
116
- end
117
- end
@@ -1,127 +0,0 @@
1
- require 'spec_helper'
2
-
3
- # edge cases with `...-&&...` and `...&&-...` are checked in test_ranges.rb
4
-
5
- RSpec.describe('CharacterSet::Intersection parsing') do
6
- specify('parse set intersection') do
7
- root = RP.parse('[a&&z]')
8
- set = root[0]
9
- ints = set[0]
10
-
11
- expect(set.count).to eq 1
12
- expect(ints).to be_instance_of(CharacterSet::Intersection)
13
- expect(ints.count).to eq 2
14
-
15
- seq1, seq2 = ints.expressions
16
- expect(seq1).to be_instance_of(CharacterSet::IntersectedSequence)
17
- expect(seq1.count).to eq 1
18
- expect(seq1.first.to_s).to eq 'a'
19
- expect(seq1.first).to be_instance_of(Literal)
20
- expect(seq2).to be_instance_of(CharacterSet::IntersectedSequence)
21
- expect(seq2.count).to eq 1
22
- expect(seq2.first.to_s).to eq 'z'
23
- expect(seq2.first).to be_instance_of(Literal)
24
-
25
- expect(set).not_to match 'a'
26
- expect(set).not_to match '&'
27
- expect(set).not_to match 'z'
28
- end
29
-
30
- specify('parse set intersection range and subset') do
31
- root = RP.parse('[a-z&&[^a]]')
32
- set = root[0]
33
- ints = set[0]
34
-
35
- expect(set.count).to eq 1
36
- expect(ints).to be_instance_of(CharacterSet::Intersection)
37
- expect(ints.count).to eq 2
38
-
39
- seq1, seq2 = ints.expressions
40
- expect(seq1).to be_instance_of(CharacterSet::IntersectedSequence)
41
- expect(seq1.count).to eq 1
42
- expect(seq1.first.to_s).to eq 'a-z'
43
- expect(seq1.first).to be_instance_of(CharacterSet::Range)
44
- expect(seq2).to be_instance_of(CharacterSet::IntersectedSequence)
45
- expect(seq2.count).to eq 1
46
- expect(seq2.first.to_s).to eq '[^a]'
47
- expect(seq2.first).to be_instance_of(CharacterSet)
48
-
49
- expect(set).not_to match 'a'
50
- expect(set).not_to match '&'
51
- expect(set).to match 'b'
52
- end
53
-
54
- specify('parse set intersection trailing range') do
55
- root = RP.parse('[a&&a-z]')
56
- set = root[0]
57
- ints = set[0]
58
-
59
- expect(set.count).to eq 1
60
- expect(ints).to be_instance_of(CharacterSet::Intersection)
61
- expect(ints.count).to eq 2
62
-
63
- seq1, seq2 = ints.expressions
64
- expect(seq1).to be_instance_of(CharacterSet::IntersectedSequence)
65
- expect(seq1.count).to eq 1
66
- expect(seq1.first.to_s).to eq 'a'
67
- expect(seq1.first).to be_instance_of(Literal)
68
- expect(seq2).to be_instance_of(CharacterSet::IntersectedSequence)
69
- expect(seq2.count).to eq 1
70
- expect(seq2.first.to_s).to eq 'a-z'
71
- expect(seq2.first).to be_instance_of(CharacterSet::Range)
72
-
73
- expect(set).to match 'a'
74
- expect(set).not_to match '&'
75
- expect(set).not_to match 'b'
76
- end
77
-
78
- specify('parse set intersection type') do
79
- root = RP.parse('[a&&\\w]')
80
- set = root[0]
81
- ints = set[0]
82
-
83
- expect(set.count).to eq 1
84
- expect(ints).to be_instance_of(CharacterSet::Intersection)
85
- expect(ints.count).to eq 2
86
-
87
- seq1, seq2 = ints.expressions
88
- expect(seq1).to be_instance_of(CharacterSet::IntersectedSequence)
89
- expect(seq1.count).to eq 1
90
- expect(seq1.first.to_s).to eq 'a'
91
- expect(seq1.first).to be_instance_of(Literal)
92
- expect(seq2).to be_instance_of(CharacterSet::IntersectedSequence)
93
- expect(seq2.count).to eq 1
94
- expect(seq2.first.to_s).to eq '\\w'
95
- expect(seq2.first).to be_instance_of(CharacterType::Word)
96
-
97
- expect(set).to match 'a'
98
- expect(set).not_to match '&'
99
- expect(set).not_to match 'b'
100
- end
101
-
102
- specify('parse set intersection multipart') do
103
- root = RP.parse('[\\h&&\\w&&efg]')
104
- set = root[0]
105
- ints = set[0]
106
-
107
- expect(set.count).to eq 1
108
- expect(ints).to be_instance_of(CharacterSet::Intersection)
109
- expect(ints.count).to eq 3
110
-
111
- seq1, seq2, seq3 = ints.expressions
112
- expect(seq1).to be_instance_of(CharacterSet::IntersectedSequence)
113
- expect(seq1.count).to eq 1
114
- expect(seq1.first.to_s).to eq '\\h'
115
- expect(seq2).to be_instance_of(CharacterSet::IntersectedSequence)
116
- expect(seq2.count).to eq 1
117
- expect(seq2.first.to_s).to eq '\\w'
118
- expect(seq3).to be_instance_of(CharacterSet::IntersectedSequence)
119
- expect(seq3.count).to eq 3
120
- expect(seq3.to_s).to eq 'efg'
121
-
122
- expect(set).to match 'e'
123
- expect(set).to match 'f'
124
- expect(set).not_to match 'a'
125
- expect(set).not_to match 'g'
126
- end
127
- end