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 CHANGED
@@ -1,15 +1,15 @@
1
1
  ---
2
2
  !binary "U0hBMQ==":
3
3
  metadata.gz: !binary |-
4
- M2JjOGMxOWExYWQxMzdhMjdkN2Y4YjQzMDlhMmU3Mzc2MjA3NmRhZQ==
4
+ ZmEzZDkwZTIyMTM0MzM1MTQ3YThmY2NhNGJmNGQzZDZmYTdlOTgzZQ==
5
5
  data.tar.gz: !binary |-
6
- NDkxOTNhYmMyZjU1YTgwMzQ5Njk5MWJmOGZjZGM1YWVhMzIxOGE3Mw==
6
+ ZTdlYjhjOTg2MTc1MWU5M2NjYTk1ODU2OGNiNWMxYTIxYzlhMjdlMg==
7
7
  SHA512:
8
8
  metadata.gz: !binary |-
9
- MGVhODk0ZTI5YjU1MmIwMmVkNjdjNTZhZDIxNDU4N2MzYTA2MWM2MDJlYTBj
10
- NDU1MGIxZmNhNGI0MTNkZjMyZjc1MDdlZGY1YThlYTg3NzUwZGNhNjcyZjg3
11
- MjY3YWQ2Yjk2ODY0YjZmZTEyZjc2NWE0ZTY5ZWIwZmYxYWM4ZjQ=
9
+ NTUyY2Q2MzUwNjczMmYwOWQ1YTJkZTk5N2I2YWIzM2Q4NzUxODM0NDg4ZWQ3
10
+ ZDJiYTVkM2RhYzE1NTAzODdjMzY4ZDI4NTM3NjM0ZjJiZWQ1N2U4ZmVmMzIz
11
+ M2YyMDQ1MTAyZDg5NjAwOTY5Y2FlMDIyNzkwZjdhMDJiOTZhNDU=
12
12
  data.tar.gz: !binary |-
13
- NjkwYWYwM2Q1MDM3ZjEzNjc0MDU0YTU1NWRmYWQyMTljYjJhZDEzZTU0N2Jj
14
- ODU5YmNhNTJhY2NjMWRmODJkZGE2NmM1ZjQzY2UyODU2Y2JmZDc1MGE0NTVk
15
- NTMzYWM4NGJiNTMxMWVmZTA0MGZkZjc1NjM3ZWMxNzM5MGRiZTE=
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
- * Arbitrarily complex combinations of all the above!
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(/__(\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)
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 :num
113
- def initialize(num)
114
- @num = num
112
+ attr_reader :id
113
+ def initialize(id)
114
+ @id = id
115
115
  end
116
116
 
117
117
  def result
118
- ["__#{@num}__"]
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 regexp_string[@current_position..-1] =~ /^(\d+)/
49
- group = parse_backreference_group($&)
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
- this_group_num = @num_groups
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
- # TODO: Non-capture groups, i.e. /...(?:foo).../
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.to_i)
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 = regexp_string[@current_position..-1].match(/^\{(\d+)(,)?(\d+)?\}/)
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
- 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
12
13
  end
13
- end
14
14
  include Examples
15
15
  end
16
16
 
@@ -1,3 +1,3 @@
1
1
  module RegexpExamples
2
- VERSION = '0.0.2'
2
+ VERSION = '0.1.0'
3
3
  end
@@ -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/,
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: regexp-examples
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.2
4
+ version: 0.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Tom Lord