Skip to content

Commit dd50d5e

Browse files
committed
Backreferences for NAMED capture groups (v0.1.0)
e.g. /(?<name>foo) \k<name>/.examples Bumped the version to 0.1.0 as this is a big feature update!
1 parent dc538cc commit dd50d5e

File tree

7 files changed

+29
-25
lines changed

7 files changed

+29
-25
lines changed

README.md

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -29,10 +29,9 @@ or a huge number of possible matches, such as `/.\w/`, then only a subset of the
2929
* Boolean "Or" groups, e.g. `/a|b|c/`
3030
* Character sets (inluding ranges and negation!), e.g. `/[abc]/`, `/[A-Z0-9]/`, `/[^a-z]/`
3131
* Escaped characters, e.g. `/\n/`, `/\w/`, `/\D/` (and so on...)
32-
* Capture groups, and backreferences(!!), e.g. `/(this|that) \1/`
33-
* Named capture groups, e.g. `(?<name>bar)/`(Warning: Named capture group backreferences not yet implemented!)
32+
* Capture groups, including named groups and backreferences(!!), e.g. `/(this|that) \1/` `/(?<name>foo) \k<name>/`
3433
* Non-capture groups, e.g. `/(?:foo)/`
35-
* Arbitrarily complex combinations of all the above!
34+
* '''Arbitrarily complex combinations of all the above!'''
3635

3736
## Not-Yet-Supported syntax
3837

lib/regexp-examples/backreferences.rb

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,8 @@ def substitute_backreferences(full_examples)
2323
[full_example]
2424
else
2525
full_example.map! do |partial_example|
26-
partial_example.gsub(/__(\d+)__/) do |match|
27-
find_backref_for(full_example, $1.to_i)
26+
partial_example.gsub(/__(\w+)__/) do |match|
27+
find_backref_for(full_example, $1)
2828
end
2929
end
3030
end

lib/regexp-examples/groups.rb

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -109,13 +109,13 @@ def result
109109
end
110110

111111
class BackReferenceGroup
112-
attr_reader :num
113-
def initialize(num)
114-
@num = num
112+
attr_reader :id
113+
def initialize(id)
114+
@id = id
115115
end
116116

117117
def result
118-
["__#{@num}__"]
118+
["__#{@id}__"]
119119
end
120120
end
121121

lib/regexp-examples/parser.rb

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,11 @@ def parse_after_backslash_group
4646
@current_position += 1
4747
case
4848
when rest_of_string =~ /\A(\d+)/
49-
group = parse_backreference_group($&)
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)
5054
when BackslashCharMap.keys.include?(regexp_string[@current_position])
5155
group = CharGroup.new(
5256
BackslashCharMap[regexp_string[@current_position]])
@@ -83,7 +87,7 @@ def parse_multi_group
8387
rest_of_string.match(/\A(\?)?(:|!|=|<(!|=|[^!=][^>]*))?/) do |match|
8488
case
8589
when match[1].nil? # e.g. /(normal)/
86-
group_id = @num_groups
90+
group_id = @num_groups.to_s
8791
when match[2] == ':' # e.g. /(?:nocapture)/
8892
@current_position += 2
8993
group_id = nil
@@ -141,7 +145,7 @@ def parse_single_char_group(char)
141145
end
142146

143147
def parse_backreference_group(match)
144-
BackReferenceGroup.new(match.to_i)
148+
BackReferenceGroup.new(match)
145149
end
146150

147151
def parse_star_repeater(group)
Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,16 @@
11
class Regexp
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)
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
1213
end
13-
end
1414
include Examples
1515
end
1616

lib/regexp-examples/version.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
module RegexpExamples
2-
VERSION = '0.0.2'
2+
VERSION = '0.1.0'
33
end

spec/regexp-examples_spec.rb

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,8 @@ def self.examples_exist_and_match(*regexps)
5656
examples_exist_and_match(
5757
/(normal)/,
5858
/(?:nocapture)/,
59-
/(?<name>namedgroup)/
59+
/(?<name>namedgroup)/,
60+
/(?<name>namedgroup) \k<name>/
6061
)
6162
# TODO: These are not yet implemented
6263
# (expect to raise exception)

0 commit comments

Comments
 (0)