regexp_parser 2.2.0 → 2.2.1

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