regexp-examples 0.0.2 → 0.1.0
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.
- checksums.yaml +8 -8
- data/README.md +3 -4
- data/lib/regexp-examples/backreferences.rb +2 -2
- data/lib/regexp-examples/groups.rb +4 -4
- data/lib/regexp-examples/parser.rb +30 -8
- data/lib/regexp-examples/regexp_extensions.rb +11 -11
- data/lib/regexp-examples/version.rb +1 -1
- data/spec/regexp-examples_spec.rb +15 -0
- metadata +1 -1
checksums.yaml
CHANGED
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
---
|
|
2
2
|
!binary "U0hBMQ==":
|
|
3
3
|
metadata.gz: !binary |-
|
|
4
|
-
|
|
4
|
+
ZmEzZDkwZTIyMTM0MzM1MTQ3YThmY2NhNGJmNGQzZDZmYTdlOTgzZQ==
|
|
5
5
|
data.tar.gz: !binary |-
|
|
6
|
-
|
|
6
|
+
ZTdlYjhjOTg2MTc1MWU5M2NjYTk1ODU2OGNiNWMxYTIxYzlhMjdlMg==
|
|
7
7
|
SHA512:
|
|
8
8
|
metadata.gz: !binary |-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
9
|
+
NTUyY2Q2MzUwNjczMmYwOWQ1YTJkZTk5N2I2YWIzM2Q4NzUxODM0NDg4ZWQ3
|
|
10
|
+
ZDJiYTVkM2RhYzE1NTAzODdjMzY4ZDI4NTM3NjM0ZjJiZWQ1N2U4ZmVmMzIz
|
|
11
|
+
M2YyMDQ1MTAyZDg5NjAwOTY5Y2FlMDIyNzkwZjdhMDJiOTZhNDU=
|
|
12
12
|
data.tar.gz: !binary |-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
13
|
+
ZmQ1NWY5NjRiYzViNjdlNjNhODQ1ODkyZTZmMzk5MTIzZDgxZDFjNDIxODEz
|
|
14
|
+
ODY5ZDcxYzEwODAxYjhmNDE5MGM1ZDk5YzkxYjk5ZTUxYzRkYjY5ZTM2MWNk
|
|
15
|
+
NTNkZmRjYmMzN2ZkNjg4MDQ1MzdlNWNhZjYzOTJlODVkZjQwMTE=
|
data/README.md
CHANGED
|
@@ -29,15 +29,14 @@ or a huge number of possible matches, such as `/.\w/`, then only a subset of the
|
|
|
29
29
|
* Boolean "Or" groups, e.g. `/a|b|c/`
|
|
30
30
|
* Character sets (inluding ranges and negation!), e.g. `/[abc]/`, `/[A-Z0-9]/`, `/[^a-z]/`
|
|
31
31
|
* Escaped characters, e.g. `/\n/`, `/\w/`, `/\D/` (and so on...)
|
|
32
|
-
* Capture groups, and backreferences(!!), e.g. `/(this|that) \1/`
|
|
33
|
-
*
|
|
32
|
+
* Capture groups, including named groups and backreferences(!!), e.g. `/(this|that) \1/` `/(?<name>foo) \k<name>/`
|
|
33
|
+
* Non-capture groups, e.g. `/(?:foo)/`
|
|
34
|
+
* '''Arbitrarily complex combinations of all the above!'''
|
|
34
35
|
|
|
35
36
|
## Not-Yet-Supported syntax
|
|
36
37
|
|
|
37
38
|
I plan to add the following features to the gem (in order of most -> least likely), but have not yet got round to it:
|
|
38
39
|
|
|
39
|
-
* Non-capture groups, e.g. `/(?:foo)/`
|
|
40
|
-
* Named capture groups, e.g. `(?<name>bar)/`
|
|
41
40
|
* Throw exceptions if illegal syntax (see below) is used
|
|
42
41
|
* POSIX bracket expressions, e.g. `/[[:alnum:]]/`, `/[[:space:]]/`
|
|
43
42
|
* Options, e.g. `/pattern/i`, `/foo.*bar/m`
|
|
@@ -23,8 +23,8 @@ module RegexpExamples
|
|
|
23
23
|
[full_example]
|
|
24
24
|
else
|
|
25
25
|
full_example.map! do |partial_example|
|
|
26
|
-
partial_example.gsub(/__(\
|
|
27
|
-
find_backref_for(full_example, $1
|
|
26
|
+
partial_example.gsub(/__(\w+)__/) do |match|
|
|
27
|
+
find_backref_for(full_example, $1)
|
|
28
28
|
end
|
|
29
29
|
end
|
|
30
30
|
end
|
|
@@ -109,13 +109,13 @@ module RegexpExamples
|
|
|
109
109
|
end
|
|
110
110
|
|
|
111
111
|
class BackReferenceGroup
|
|
112
|
-
attr_reader :
|
|
113
|
-
def initialize(
|
|
114
|
-
@
|
|
112
|
+
attr_reader :id
|
|
113
|
+
def initialize(id)
|
|
114
|
+
@id = id
|
|
115
115
|
end
|
|
116
116
|
|
|
117
117
|
def result
|
|
118
|
-
["__#{@
|
|
118
|
+
["__#{@id}__"]
|
|
119
119
|
end
|
|
120
120
|
end
|
|
121
121
|
|
|
@@ -45,8 +45,12 @@ module RegexpExamples
|
|
|
45
45
|
def parse_after_backslash_group
|
|
46
46
|
@current_position += 1
|
|
47
47
|
case
|
|
48
|
-
when
|
|
49
|
-
|
|
48
|
+
when rest_of_string =~ /\A(\d+)/
|
|
49
|
+
@current_position += ($1.length - 1) # In case of 10+ backrefs!
|
|
50
|
+
group = parse_backreference_group($1)
|
|
51
|
+
when rest_of_string =~ /\Ak<([^>]+)>/ # Named capture group
|
|
52
|
+
@current_position += ($1.length + 2)
|
|
53
|
+
group = parse_backreference_group($1)
|
|
50
54
|
when BackslashCharMap.keys.include?(regexp_string[@current_position])
|
|
51
55
|
group = CharGroup.new(
|
|
52
56
|
BackslashCharMap[regexp_string[@current_position]])
|
|
@@ -79,11 +83,25 @@ module RegexpExamples
|
|
|
79
83
|
def parse_multi_group
|
|
80
84
|
@current_position += 1
|
|
81
85
|
@num_groups += 1
|
|
82
|
-
|
|
86
|
+
group_id = nil # init
|
|
87
|
+
rest_of_string.match(/\A(\?)?(:|!|=|<(!|=|[^!=][^>]*))?/) do |match|
|
|
88
|
+
case
|
|
89
|
+
when match[1].nil? # e.g. /(normal)/
|
|
90
|
+
group_id = @num_groups.to_s
|
|
91
|
+
when match[2] == ':' # e.g. /(?:nocapture)/
|
|
92
|
+
@current_position += 2
|
|
93
|
+
group_id = nil
|
|
94
|
+
when %w(! =).include?(match[2]) # e.g. /(?=lookahead)/, /(?!neglookahead)/
|
|
95
|
+
# TODO: Raise exception
|
|
96
|
+
when %w(! =).include?(match[3]) # e.g. /(?<=lookbehind)/, /(?<!neglookbehind)/
|
|
97
|
+
# TODO: Raise exception
|
|
98
|
+
else # e.g. /(?<name>namedgroup)/
|
|
99
|
+
@current_position += (match[3].length + 3)
|
|
100
|
+
group_id = match[3]
|
|
101
|
+
end
|
|
102
|
+
end
|
|
83
103
|
groups = parse
|
|
84
|
-
|
|
85
|
-
# TODO: Named capture groups, i.e. /...(?<name>foo).../
|
|
86
|
-
MultiGroup.new(groups, this_group_num)
|
|
104
|
+
MultiGroup.new(groups, group_id)
|
|
87
105
|
end
|
|
88
106
|
|
|
89
107
|
def parse_multi_end_group
|
|
@@ -127,7 +145,7 @@ module RegexpExamples
|
|
|
127
145
|
end
|
|
128
146
|
|
|
129
147
|
def parse_backreference_group(match)
|
|
130
|
-
BackReferenceGroup.new(match
|
|
148
|
+
BackReferenceGroup.new(match)
|
|
131
149
|
end
|
|
132
150
|
|
|
133
151
|
def parse_star_repeater(group)
|
|
@@ -146,7 +164,7 @@ module RegexpExamples
|
|
|
146
164
|
end
|
|
147
165
|
|
|
148
166
|
def parse_range_repeater(group)
|
|
149
|
-
match =
|
|
167
|
+
match = rest_of_string.match(/\A\{(\d+)(,)?(\d+)?\}/)
|
|
150
168
|
@current_position += match[0].size
|
|
151
169
|
min = match[1].to_i if match[1]
|
|
152
170
|
has_comma = !match[2].nil?
|
|
@@ -157,6 +175,10 @@ module RegexpExamples
|
|
|
157
175
|
def parse_one_time_repeater(group)
|
|
158
176
|
OneTimeRepeater.new(group)
|
|
159
177
|
end
|
|
178
|
+
|
|
179
|
+
def rest_of_string
|
|
180
|
+
regexp_string[@current_position..-1]
|
|
181
|
+
end
|
|
160
182
|
end
|
|
161
183
|
end
|
|
162
184
|
|
|
@@ -1,16 +1,16 @@
|
|
|
1
1
|
class Regexp
|
|
2
|
-
module Examples
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
2
|
+
module Examples
|
|
3
|
+
def examples
|
|
4
|
+
partial_examples =
|
|
5
|
+
RegexpExamples::Parser.new(source)
|
|
6
|
+
.parse
|
|
7
|
+
.map {|repeater| repeater.result}
|
|
8
|
+
full_examples = RegexpExamples::permutations_of_strings(partial_examples.dup, no_join: true)
|
|
9
|
+
full_examples_with_backrefs = \
|
|
10
|
+
RegexpExamples::BackReferenceReplacer.new.substitute_backreferences(full_examples)
|
|
11
|
+
full_examples_with_backrefs.map(&:join)
|
|
12
|
+
end
|
|
12
13
|
end
|
|
13
|
-
end
|
|
14
14
|
include Examples
|
|
15
15
|
end
|
|
16
16
|
|
|
@@ -52,6 +52,21 @@ describe Regexp, "#examples" do
|
|
|
52
52
|
)
|
|
53
53
|
end
|
|
54
54
|
|
|
55
|
+
context "for complex multi groups" do
|
|
56
|
+
examples_exist_and_match(
|
|
57
|
+
/(normal)/,
|
|
58
|
+
/(?:nocapture)/,
|
|
59
|
+
/(?<name>namedgroup)/,
|
|
60
|
+
/(?<name>namedgroup) \k<name>/
|
|
61
|
+
)
|
|
62
|
+
# TODO: These are not yet implemented
|
|
63
|
+
# (expect to raise exception)
|
|
64
|
+
# /(?=lookahead)/,
|
|
65
|
+
# /(?!neglookahead)/,
|
|
66
|
+
# /(?<=lookbehind)/,
|
|
67
|
+
# /(?<!neglookbehind)/,
|
|
68
|
+
end
|
|
69
|
+
|
|
55
70
|
context "for escaped characters" do
|
|
56
71
|
examples_exist_and_match(
|
|
57
72
|
/\w/,
|