regexp-examples 0.0.2 → 0.1.0

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