regexp_parser 2.2.0 → 2.2.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 (88) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +14 -2
  3. data/LICENSE +1 -1
  4. data/README.md +2 -2
  5. data/Rakefile +5 -8
  6. data/lib/regexp_parser/expression/classes/escape_sequence.rb +12 -7
  7. data/lib/regexp_parser/expression/methods/strfregexp.rb +1 -1
  8. data/lib/regexp_parser/scanner/properties/long.csv +604 -0
  9. data/lib/regexp_parser/scanner/properties/short.csv +242 -0
  10. data/lib/regexp_parser/scanner/scanner.rl +6 -4
  11. data/lib/regexp_parser/scanner.rb +126 -124
  12. data/lib/regexp_parser/syntax/base.rb +3 -5
  13. data/lib/regexp_parser/syntax/token/backreference.rb +7 -2
  14. data/lib/regexp_parser/syntax/versions/1.8.6.rb +2 -2
  15. data/lib/regexp_parser/syntax/versions/1.9.1.rb +1 -1
  16. data/lib/regexp_parser/version.rb +1 -1
  17. data/regexp_parser.gemspec +20 -22
  18. metadata +11 -143
  19. data/lib/regexp_parser/scanner/properties/long.yml +0 -607
  20. data/lib/regexp_parser/scanner/properties/short.yml +0 -245
  21. data/spec/expression/base_spec.rb +0 -104
  22. data/spec/expression/clone_spec.rb +0 -152
  23. data/spec/expression/conditional_spec.rb +0 -89
  24. data/spec/expression/free_space_spec.rb +0 -27
  25. data/spec/expression/methods/match_length_spec.rb +0 -161
  26. data/spec/expression/methods/match_spec.rb +0 -25
  27. data/spec/expression/methods/strfregexp_spec.rb +0 -224
  28. data/spec/expression/methods/tests_spec.rb +0 -99
  29. data/spec/expression/methods/traverse_spec.rb +0 -161
  30. data/spec/expression/options_spec.rb +0 -128
  31. data/spec/expression/subexpression_spec.rb +0 -50
  32. data/spec/expression/to_h_spec.rb +0 -26
  33. data/spec/expression/to_s_spec.rb +0 -108
  34. data/spec/lexer/all_spec.rb +0 -22
  35. data/spec/lexer/conditionals_spec.rb +0 -53
  36. data/spec/lexer/delimiters_spec.rb +0 -68
  37. data/spec/lexer/escapes_spec.rb +0 -14
  38. data/spec/lexer/keep_spec.rb +0 -10
  39. data/spec/lexer/literals_spec.rb +0 -64
  40. data/spec/lexer/nesting_spec.rb +0 -99
  41. data/spec/lexer/refcalls_spec.rb +0 -60
  42. data/spec/parser/all_spec.rb +0 -43
  43. data/spec/parser/alternation_spec.rb +0 -88
  44. data/spec/parser/anchors_spec.rb +0 -17
  45. data/spec/parser/conditionals_spec.rb +0 -179
  46. data/spec/parser/errors_spec.rb +0 -30
  47. data/spec/parser/escapes_spec.rb +0 -133
  48. data/spec/parser/free_space_spec.rb +0 -130
  49. data/spec/parser/groups_spec.rb +0 -108
  50. data/spec/parser/keep_spec.rb +0 -6
  51. data/spec/parser/options_spec.rb +0 -28
  52. data/spec/parser/posix_classes_spec.rb +0 -8
  53. data/spec/parser/properties_spec.rb +0 -117
  54. data/spec/parser/quantifiers_spec.rb +0 -68
  55. data/spec/parser/refcalls_spec.rb +0 -117
  56. data/spec/parser/set/intersections_spec.rb +0 -127
  57. data/spec/parser/set/ranges_spec.rb +0 -121
  58. data/spec/parser/sets_spec.rb +0 -178
  59. data/spec/parser/types_spec.rb +0 -18
  60. data/spec/scanner/all_spec.rb +0 -18
  61. data/spec/scanner/anchors_spec.rb +0 -21
  62. data/spec/scanner/conditionals_spec.rb +0 -128
  63. data/spec/scanner/delimiters_spec.rb +0 -52
  64. data/spec/scanner/errors_spec.rb +0 -67
  65. data/spec/scanner/escapes_spec.rb +0 -73
  66. data/spec/scanner/free_space_spec.rb +0 -165
  67. data/spec/scanner/groups_spec.rb +0 -61
  68. data/spec/scanner/keep_spec.rb +0 -10
  69. data/spec/scanner/literals_spec.rb +0 -39
  70. data/spec/scanner/meta_spec.rb +0 -18
  71. data/spec/scanner/options_spec.rb +0 -36
  72. data/spec/scanner/properties_spec.rb +0 -64
  73. data/spec/scanner/quantifiers_spec.rb +0 -25
  74. data/spec/scanner/refcalls_spec.rb +0 -55
  75. data/spec/scanner/sets_spec.rb +0 -151
  76. data/spec/scanner/types_spec.rb +0 -14
  77. data/spec/spec_helper.rb +0 -28
  78. data/spec/support/capturing_stderr.rb +0 -9
  79. data/spec/support/shared_examples.rb +0 -77
  80. data/spec/syntax/syntax_spec.rb +0 -48
  81. data/spec/syntax/syntax_token_map_spec.rb +0 -23
  82. data/spec/syntax/versions/1.8.6_spec.rb +0 -17
  83. data/spec/syntax/versions/1.9.1_spec.rb +0 -10
  84. data/spec/syntax/versions/1.9.3_spec.rb +0 -9
  85. data/spec/syntax/versions/2.0.0_spec.rb +0 -13
  86. data/spec/syntax/versions/2.2.0_spec.rb +0 -9
  87. data/spec/syntax/versions/aliases_spec.rb +0 -38
  88. 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