Skip to content

Commit

Permalink
Backreferences for NAMED capture groups (v0.1.0)
Browse files Browse the repository at this point in the history
e.g. /(?<name>foo) \k<name>/.examples
Bumped the version to 0.1.0 as this is a big feature update!
  • Loading branch information
tom-lord committed Jan 11, 2015
1 parent dc538cc commit dd50d5e
Show file tree
Hide file tree
Showing 7 changed files with 29 additions and 25 deletions.
5 changes: 2 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,10 +29,9 @@ or a huge number of possible matches, such as `/.\w/`, then only a subset of the
* Boolean "Or" groups, e.g. `/a|b|c/`
* Character sets (inluding ranges and negation!), e.g. `/[abc]/`, `/[A-Z0-9]/`, `/[^a-z]/`
* Escaped characters, e.g. `/\n/`, `/\w/`, `/\D/` (and so on...)
* Capture groups, and backreferences(!!), e.g. `/(this|that) \1/`
* Named capture groups, e.g. `(?<name>bar)/`(Warning: Named capture group backreferences not yet implemented!)
* Capture groups, including named groups and backreferences(!!), e.g. `/(this|that) \1/` `/(?<name>foo) \k<name>/`
* Non-capture groups, e.g. `/(?:foo)/`
* Arbitrarily complex combinations of all the above!
* '''Arbitrarily complex combinations of all the above!'''

## Not-Yet-Supported syntax

Expand Down
4 changes: 2 additions & 2 deletions lib/regexp-examples/backreferences.rb
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,8 @@ def substitute_backreferences(full_examples)
[full_example]
else
full_example.map! do |partial_example|
partial_example.gsub(/__(\d+)__/) do |match|
find_backref_for(full_example, $1.to_i)
partial_example.gsub(/__(\w+)__/) do |match|
find_backref_for(full_example, $1)
end
end
end
Expand Down
8 changes: 4 additions & 4 deletions lib/regexp-examples/groups.rb
Original file line number Diff line number Diff line change
Expand Up @@ -109,13 +109,13 @@ def result
end

class BackReferenceGroup
attr_reader :num
def initialize(num)
@num = num
attr_reader :id
def initialize(id)
@id = id
end

def result
["__#{@num}__"]
["__#{@id}__"]
end
end

Expand Down
10 changes: 7 additions & 3 deletions lib/regexp-examples/parser.rb
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,11 @@ def parse_after_backslash_group
@current_position += 1
case
when rest_of_string =~ /\A(\d+)/
group = parse_backreference_group($&)
@current_position += ($1.length - 1) # In case of 10+ backrefs!
group = parse_backreference_group($1)
when rest_of_string =~ /\Ak<([^>]+)>/ # Named capture group
@current_position += ($1.length + 2)
group = parse_backreference_group($1)
when BackslashCharMap.keys.include?(regexp_string[@current_position])
group = CharGroup.new(
BackslashCharMap[regexp_string[@current_position]])
Expand Down Expand Up @@ -83,7 +87,7 @@ def parse_multi_group
rest_of_string.match(/\A(\?)?(:|!|=|<(!|=|[^!=][^>]*))?/) do |match|
case
when match[1].nil? # e.g. /(normal)/
group_id = @num_groups
group_id = @num_groups.to_s
when match[2] == ':' # e.g. /(?:nocapture)/
@current_position += 2
group_id = nil
Expand Down Expand Up @@ -141,7 +145,7 @@ def parse_single_char_group(char)
end

def parse_backreference_group(match)
BackReferenceGroup.new(match.to_i)
BackReferenceGroup.new(match)
end

def parse_star_repeater(group)
Expand Down
22 changes: 11 additions & 11 deletions lib/regexp-examples/regexp_extensions.rb
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
class Regexp
module Examples
def examples
partial_examples =
RegexpExamples::Parser.new(source)
.parse
.map {|repeater| repeater.result}
full_examples = RegexpExamples::permutations_of_strings(partial_examples.dup, no_join: true)
full_examples_with_backrefs = \
RegexpExamples::BackReferenceReplacer.new.substitute_backreferences(full_examples)
full_examples_with_backrefs.map(&:join)
module Examples
def examples
partial_examples =
RegexpExamples::Parser.new(source)
.parse
.map {|repeater| repeater.result}
full_examples = RegexpExamples::permutations_of_strings(partial_examples.dup, no_join: true)
full_examples_with_backrefs = \
RegexpExamples::BackReferenceReplacer.new.substitute_backreferences(full_examples)
full_examples_with_backrefs.map(&:join)
end
end
end
include Examples
end

2 changes: 1 addition & 1 deletion lib/regexp-examples/version.rb
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
module RegexpExamples
VERSION = '0.0.2'
VERSION = '0.1.0'
end
3 changes: 2 additions & 1 deletion spec/regexp-examples_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,8 @@ def self.examples_exist_and_match(*regexps)
examples_exist_and_match(
/(normal)/,
/(?:nocapture)/,
/(?<name>namedgroup)/
/(?<name>namedgroup)/,
/(?<name>namedgroup) \k<name>/
)
# TODO: These are not yet implemented
# (expect to raise exception)
Expand Down

0 comments on commit dd50d5e

Please sign in to comment.