regexador 0.4.5 → 0.4.6

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,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: b16d02292d2ae9d888a09c04d2e3330c72be9836
4
- data.tar.gz: d4b472b343ece2a984b30ceecae7968fefdb6c93
2
+ SHA256:
3
+ metadata.gz: ef781dea6cb100272e9885a401b5710d8721eddd9280a262b34c15ba444a35a0
4
+ data.tar.gz: bab1c2a5a233e23a701be3a852340092cff4710de52580692a5a184e5bee71ec
5
5
  SHA512:
6
- metadata.gz: 1f12498dd028fb55dcef7f927d81a1057af6441824c56d2c6fb8dfe9ee9c99e3c6fb7caa9c94069e848489b737e5d025196a9bf74f4fa844014a61509d361adb
7
- data.tar.gz: 896ba315badba2f4bdfce8d731c3a3802111ce712ac1bbb768bb4fa8c0f54d1306eabbba896214ccd97fef74c9439f66abcd66a5c9612eb494959dc67d2f256f
6
+ metadata.gz: b01ba0354deb1aab96a3d1aa95447ec5af4764511bdd9f4a6ec73586eb22db619aedee35c05977d40fc18b9e6f9d73638f332efca5cd3967c1fee6fe50dc78d3
7
+ data.tar.gz: '0980bc439ced111c2ae822dcd9416bd290e8cf8f3d17ec00b70e24bb65961c458a3fcd5844fcbbfb620f2463f128861c6b2698ce4d8705c30adb2fd33d233182'
data/README.md CHANGED
@@ -19,21 +19,25 @@ as [the wiki](http://github.com/Hal9000/regexador/wiki).
19
19
 
20
20
  ### The Basic Concept
21
21
 
22
- Many people are intimidated or confused by regular expressions.
23
- A large part of this is the confusing syntax.
22
+ Many people are intimidated or confused by regular expressions. A large part of
23
+ this is the complex syntax.
24
24
 
25
- Regexador is a mini-language purely for building regular expressions.
26
- It's purely a Ruby project for now, though in theory it could be
27
- implemented in/for other languages.
25
+ Regexador is a mini-language purely for building regular expressions. It's purely
26
+ a Ruby project at the moment, although there are tentative plans for ports to
27
+ Elixir and Python.
28
28
 
29
- For an analogy, think of how we sometimes manipulate databases by
30
- constructing SQL queries and passing them into the appropriate
29
+ A traditional (or internal) Ruby DSL consists of creative use of methods and
30
+ operators to "fake" a language inside Ruby code. The internal DSL is itself
31
+ Ruby code that must obeu Ruby syntax.
32
+
33
+ But what is an external DSL? For an analogy, think of how we sometimes manipulate
34
+ databases by constructing SQL queries and passing them into the appropriate
31
35
  methods. Regexador works much the same way.
32
36
 
33
37
  ### A Short Example
34
38
 
35
- Suppose we want to match a string consisting of a single IP address.
36
- (Remember that the numbers can only range as high as 255.)
39
+ Suppose we want to match a string consisting of a single IP address. (Remember that
40
+ the numbers can only range as high as 255.)
37
41
 
38
42
  Here is traditional regular expression notation:
39
43
 
@@ -45,11 +49,10 @@ And here is Regexador notation:
45
49
  num = "25" D5 | `2 D4 D | maybe D1 1,2*D
46
50
  match BOS num dot num dot num dot num EOS end
47
51
 
48
- In your Ruby code, you can create a Regexador "script" or "program"
49
- (probably by means of a here-document) that you can then pass into
50
- the Regexador class. At minimum, you can convert this into a "real"
51
- Ruby regular expression; there are a few other features and functions,
52
- and more may be added.
52
+ In your Ruby code, you can create a Regexador "script" or "program" (probably
53
+ by means of a here-document) that you can then pass into the Regexador class.
54
+ At minimum, you can convert this into a "real" Ruby regular expression; there
55
+ are a few other features and functions, and more are being added.
53
56
 
54
57
  So here is a complete Ruby program:
55
58
 
@@ -75,9 +78,7 @@ So here is a complete Ruby program:
75
78
  end
76
79
 
77
80
 
78
-
79
81
  **Traditional Syntax: Things I Personally Dislike**
80
-
81
82
  - There are no keywords -- only punctuation.
82
83
  These symbols all have special meanings: ^$.\[]()+\*? (and others)
83
84
  - ^ has at least three different meanings
@@ -93,42 +94,39 @@ So here is a complete Ruby program:
93
94
 
94
95
  ### Regexador at a Glance
95
96
 
96
- I'm attracted to old-fashioned line-oriented syntax; but I don't want
97
- to lock myself into that completely.
97
+ I'm attracted to old-fashioned line-oriented syntax; but I don't want to lock
98
+ myself into that completely.
98
99
 
99
- In general, useful definitions (variables) will come first. Many things
100
- are predefined already, such as all the usual anchors and the POSIX
101
- character classes. These are in all caps and are considered constants.
100
+ In general, useful definitions (variables) will come first. Many things are
101
+ predefined already, such as all the usual anchors and the POSIX character
102
+ classes. These are in all caps and are considered constants.
102
103
 
103
- At the end, a *match* clause drives the actual building of the final
104
- regular expression. Within this clause, names may be assigned to the
105
- individual sub-matches (using variables that start with "@"). These will
106
- naturally be available externally as named captures.
104
+ At the end, a *match* clause drives the actual building of the final regular
105
+ expression. Within this clause, names may be assigned to the individual
106
+ sub-matches (using variables that start with "@"). These will naturally be
107
+ available externally as named captures.
107
108
 
108
- Because this is really just a "builder," and because we don't have "hooks"
109
- into the regular expression engine itself, a Regexador script will not
110
- look or act much like a "real program." There will be no arithmetic, no
111
- function calls, no looping or branching. Also there can be no printing
112
- of debug information "at matching time"; in principle, printing could be
113
- done during parsing/compilation, but I don't see any value in this.
109
+ Because this is really just a "builder," and because we don't have "hooks" into
110
+ the regular expression engine itself, a Regexador script will not look or act
111
+ much like a "real program." There will be no arithmetic, no function calls, no
112
+ looping or branching. Also there can be no printing of debug information "at
113
+ matching time"; in principle, printing could be done during parsing/compilation,
114
+ but I don't see any value in this.
114
115
 
115
- Of course, syntax errors in Regexador will be found and made available
116
- to the caller.
116
+ Of course, syntax errors in Regexador will be found and made available to the
117
+ caller.
117
118
 
118
119
 
119
120
  **Beginning at the Beginning**
120
121
 
121
- I've tried to "think ahead" so as not to paint myself into a corner
122
- too much.
122
+ I've tried to "think ahead" so as not to paint myself into a corner too much.
123
123
 
124
- However, probably not all of this can be implemented in the first
125
- version. The current "working version" (0.2.7) has been implemented
126
- over a period of nine weeks.
124
+ However, probably not all of this can be implemented in the earliest versions.
125
+ The original "working version" (0.2.7) was implemented over a period of nine
126
+ weeks.
127
127
 
128
- Therefore some of the syntax described in the following will not be
129
- available right away.
130
-
131
- Features still postponed:
128
+ Therefore some of the functionality described here is not yet fully implemented.
129
+ Features still postponed include:
132
130
  - intra-line comments: #{...}
133
131
  - case/end
134
132
  - unsure about upto, thru
@@ -251,11 +249,13 @@ But data type matters, of course:
251
249
  n = "foo"
252
250
  m,n * "def" # Syntax error!
253
251
 
254
- The "match clause" uses all previous definitions to finally build the regular expression. It starts with "match" and ends with "end":
252
+ The "match clause" uses all previous definitions to finally build the regular
253
+ expression. It starts with "match" and ends with "end":
255
254
 
256
255
  match "abc" | "def" | many `x end
257
256
 
258
- Named matches are only used inside the match clause; anywhere a pattern may be used, "@var = pattern" may also be used.
257
+ Named matches are only used inside the match clause; anywhere a pattern may be
258
+ used, "@var = pattern" may also be used.
259
259
 
260
260
  match @first = (many %alpha) SPACES @last = (many %alpha) end
261
261
 
@@ -267,7 +267,7 @@ Multiple lines are fine (and more readable):
267
267
  @last = many %alpha
268
268
  end
269
269
 
270
- A "case" may be used for more complex alternatives (needed??):
270
+ Planned: A "case" may be used for more complex alternatives. (Is this needed?)
271
271
 
272
272
  case
273
273
  when "abc" ...
@@ -275,7 +275,8 @@ Multiple lines are fine (and more readable):
275
275
  when "xyz" ...
276
276
  end
277
277
 
278
- Multiple "programs" can be concatenated, assuming the initial ones are all definitions and there is only one match clause at the end.
278
+ Multiple "programs" can be concatenated, assuming the initial ones are all
279
+ definitions and there is only one match clause at the end.
279
280
 
280
281
  # Ruby code
281
282
  defs = "..."
@@ -373,6 +374,13 @@ Determine whether a credit card number is valid Regex: /^(?:4[0-9]{12}(?:[0-9
373
374
 
374
375
  This history has been maintained only since version 0.4.2
375
376
 
377
+ *0.4.6*
378
+ - Moving from rspec to minitest
379
+ - Verifying compatibility with Ruby 2.6, 2.7
380
+ - improving gemspec
381
+ - improving README
382
+ - working on railroad diagrams
383
+
376
384
  *0.4.3*
377
385
  - Experimenting with lookarounds (pos/neg lookahead/behind)
378
386
  - Rearranged tests
@@ -1,6 +1,7 @@
1
1
  abort "Require out of order" if ! defined? Regexador
2
2
 
3
3
  class Regexador::Parser
4
+ rule(:cSPACE) { str(" ") }
4
5
  rule(:cSQUOTE) { str("'") }
5
6
  rule(:cQUOTE) { str('"') }
6
7
  rule(:cAMPERSAND) { str('&') }
@@ -3,19 +3,21 @@ abort "Require out of order" if ! defined? Regexador
3
3
 
4
4
  class Regexador::Parser
5
5
 
6
- rule(:kANY) { str("any") }
7
- rule(:kMANY) { str("many") }
8
- rule(:kMAYBE) { str("maybe") }
9
- rule(:kMATCH) { str("match") }
10
- rule(:kEND) { str("end") }
11
- rule(:kNOCASE) { str("nocase") }
6
+ rule(:non_alphanum) { lower.absent? >> upper.absent? >> cUNDERSCORE.absent? >> digit.absent? }
12
7
 
13
- rule(:kWITH) { str("with") }
14
- rule(:kWITHOUT) { str("without") }
15
- rule(:kFIND) { str("find") }
8
+ rule(:kANY) { str("any") >> non_alphanum }
9
+ rule(:kMANY) { str("many") >> non_alphanum }
10
+ rule(:kMAYBE) { str("maybe") >> non_alphanum }
11
+ rule(:kMATCH) { str("match") >> non_alphanum }
12
+ rule(:kEND) { str("end") >> non_alphanum }
13
+ rule(:kNOCASE) { str("nocase") >> non_alphanum }
16
14
 
17
- rule(:kWITHIN) { str("within") }
18
- rule(:kESCAPING) { str("escaping") }
15
+ rule(:kWITH) { str("with") >> non_alphanum }
16
+ rule(:kWITHOUT) { str("without") >> non_alphanum }
17
+ rule(:kFIND) { str("find") >> non_alphanum }
18
+
19
+ rule(:kWITHIN) { str("within") >> non_alphanum }
20
+ rule(:kESCAPING) { str("escaping") >> non_alphanum }
19
21
 
20
22
  rule(:keyword) { kANY | kMANY | kMAYBE | kMATCH | kEND | kNOCASE |
21
23
  kWITH | kWITHOUT | kFIND | kWITHIN | kESCAPING }
@@ -18,8 +18,9 @@ class Regexador::Parser
18
18
  rule(:lower) { match('[a-z]') }
19
19
  rule(:upper) { match('[A-Z]') }
20
20
 
21
- rule(:comment) { cHASH >> space >> (cNEWLINE.absent? >> any).repeat(0) }
21
+ rule(:comment) { space? >> cHASH >> space >> (cNEWLINE.absent? >> any).repeat(0) >> cNEWLINE }
22
22
  rule(:endofline) { space? >> comment.maybe >> cNEWLINE }
23
+ rule(:statement) { (assignment | comment) }
23
24
 
24
25
  rule(:digit) { match('[0-9]') }
25
26
  rule(:digits) { digit.repeat(1) }
@@ -95,7 +96,7 @@ class Regexador::Parser
95
96
 
96
97
  rule(:assignment) { space? >> name.as(:var) >> space? >> cEQUAL >> space? >> rvalue.as(:rvalue) }
97
98
 
98
- rule(:definitions) { (endofline | assignment >> endofline).repeat(0) }
99
+ rule(:definitions) { (statement >> endofline).repeat(0).maybe }
99
100
 
100
101
  rule(:oneline_clause) { space? >> kMATCH >> space? >> pattern >> kEND >> endofline.maybe }
101
102
 
@@ -0,0 +1,3347 @@
1
+ require_relative '../lib/regexador'
2
+ require 'pp'
3
+
4
+ require 'parslet/convenience'
5
+ require 'parslet/rig/rspec'
6
+
7
+ describe Regexador do
8
+
9
+ before(:all) do
10
+ @parser = Regexador::Parser.new
11
+ @pattern = @parser.pattern
12
+ end
13
+
14
+ class Program
15
+ attr_accessor :description, :program, :regex, :good, :bad, :examples
16
+
17
+ def initialize(code)
18
+ @code = code
19
+ @parser = Regexador::Parser.new
20
+ end
21
+
22
+ def parseable?
23
+ result = @parser.parse(@code) rescue nil # != nil
24
+ !! result
25
+ end
26
+
27
+ def parse_pattern # FIXME no longer used?
28
+ tree = @parser.pattern.parse(@code)
29
+ tree = tree[:alternation] if tree.size == 1 && tree.keys.first == :alternation
30
+ tree = tree[:sequence].first if tree.size == 1 && tree.keys.first == :sequence
31
+ tree
32
+ end
33
+
34
+ def parse
35
+ tree = @parser.parse(@code)
36
+ end
37
+
38
+ def debug_bad_program_parse
39
+ @parser.parse(@code)
40
+ atree = nil
41
+ rescue Parslet::ParseFailed => error
42
+ atree = error.cause.ascii_tree.split("
43
+ ")
44
+ lchar = /at line (d+) char (d+).$/
45
+ fname = rand(10**5).to_s + ".tree"
46
+ File.open(fname, "w") {|f| f.puts @code + "
47
+ " + atree.join("
48
+ ") }
49
+ puts "See file: " + fname
50
+ return
51
+ # FIXME bad logic below
52
+ begin
53
+ atree.map! do |line|
54
+ line.gsub!(/`- ||- || /, " ")
55
+ _, ln, cn = line.match(lchar).to_a
56
+ line.sub!(lchar, "")
57
+ line.sub!(/ /, " ")
58
+ line = '%-5s' % (ln+':'+cn) + line
59
+ end
60
+ rescue
61
+ end
62
+ puts atree
63
+ end
64
+
65
+ def regexp
66
+ Regexador.new(@code).to_regex
67
+ end
68
+ end
69
+
70
+
71
+ def self.program &block
72
+ let(:code, &block)
73
+ let(:program) { Program.new(code) }
74
+ let(:regexp) { program.regexp }
75
+
76
+ subject { program }
77
+ end
78
+
79
+ ### Test 1: Single char
80
+
81
+ describe "A correct program (Single char)" do
82
+ prog = <<-'END'
83
+ match `x end
84
+ END
85
+
86
+ good = ["abcx", "xyzb", "x"]
87
+ bad = ["yz", "", "ABC"]
88
+ wanted = /x/
89
+
90
+ myprog = Program.new(prog)
91
+ parsed = nil
92
+
93
+ it "should parse correctly" do
94
+ parsed = myprog.parseable?
95
+ myprog.debug_bad_program_parse unless parsed
96
+ parsed.should == true
97
+ end
98
+
99
+ rx = nil
100
+ it "can be converted to a regex" do
101
+ rx = myprog.regexp
102
+ rx.class.should == Regexp
103
+ end
104
+
105
+ # Check sanity: Is test valid?
106
+ good.each {|str| it('has expected regex matching ' + str.inspect) { wanted.should =~ str } }
107
+ bad.each {|str| it('has expected regex NOT matching ' + str.inspect) { wanted.should_not =~ str } }
108
+
109
+ # Is compiled result valid?
110
+ good.each {|str| it('should match ' + str.inspect) { rx.should =~ str } }
111
+ bad.each {|str| it('should NOT match ' + str.inspect) { rx.should_not =~ str } }
112
+
113
+
114
+ end
115
+
116
+
117
+ ### Test 2: Unicode codepoint
118
+
119
+ describe "A correct program (Unicode codepoint)" do
120
+ prog = <<-'END'
121
+ match &20ac end
122
+ END
123
+
124
+ good = ["€", "xyz€", "x€yz"]
125
+ bad = ["yz", "", "ABC"]
126
+ wanted = /€/
127
+
128
+ myprog = Program.new(prog)
129
+ parsed = nil
130
+
131
+ it "should parse correctly" do
132
+ parsed = myprog.parseable?
133
+ myprog.debug_bad_program_parse unless parsed
134
+ parsed.should == true
135
+ end
136
+
137
+ rx = nil
138
+ it "can be converted to a regex" do
139
+ rx = myprog.regexp
140
+ rx.class.should == Regexp
141
+ end
142
+
143
+ # Check sanity: Is test valid?
144
+ good.each {|str| it('has expected regex matching ' + str.inspect) { wanted.should =~ str } }
145
+ bad.each {|str| it('has expected regex NOT matching ' + str.inspect) { wanted.should_not =~ str } }
146
+
147
+ # Is compiled result valid?
148
+ good.each {|str| it('should match ' + str.inspect) { rx.should =~ str } }
149
+ bad.each {|str| it('should NOT match ' + str.inspect) { rx.should_not =~ str } }
150
+
151
+
152
+ end
153
+
154
+
155
+ ### Test 3: Manual international characters
156
+
157
+ describe "A correct program (Manual international characters)" do
158
+ prog = <<-'END'
159
+ match "ö" end
160
+ END
161
+
162
+ good = ["öffnen", "xyzö", "xöyz"]
163
+ bad = ["offnen", "yz", "", "ABC"]
164
+ wanted = /ö/
165
+
166
+ myprog = Program.new(prog)
167
+ parsed = nil
168
+
169
+ it "should parse correctly" do
170
+ parsed = myprog.parseable?
171
+ myprog.debug_bad_program_parse unless parsed
172
+ parsed.should == true
173
+ end
174
+
175
+ rx = nil
176
+ it "can be converted to a regex" do
177
+ rx = myprog.regexp
178
+ rx.class.should == Regexp
179
+ end
180
+
181
+ # Check sanity: Is test valid?
182
+ good.each {|str| it('has expected regex matching ' + str.inspect) { wanted.should =~ str } }
183
+ bad.each {|str| it('has expected regex NOT matching ' + str.inspect) { wanted.should_not =~ str } }
184
+
185
+ # Is compiled result valid?
186
+ good.each {|str| it('should match ' + str.inspect) { rx.should =~ str } }
187
+ bad.each {|str| it('should NOT match ' + str.inspect) { rx.should_not =~ str } }
188
+
189
+
190
+ end
191
+
192
+
193
+ ### Test 4: Simple range
194
+
195
+ describe "A correct program (Simple range)" do
196
+ prog = <<-'END'
197
+ match `a-`f end
198
+ END
199
+
200
+ good = ["alpha", "xyzb", "c"]
201
+ bad = ["xyz", "", "ABC"]
202
+ wanted = /[a-f]/
203
+
204
+ myprog = Program.new(prog)
205
+ parsed = nil
206
+
207
+ it "should parse correctly" do
208
+ parsed = myprog.parseable?
209
+ myprog.debug_bad_program_parse unless parsed
210
+ parsed.should == true
211
+ end
212
+
213
+ rx = nil
214
+ it "can be converted to a regex" do
215
+ rx = myprog.regexp
216
+ rx.class.should == Regexp
217
+ end
218
+
219
+ # Check sanity: Is test valid?
220
+ good.each {|str| it('has expected regex matching ' + str.inspect) { wanted.should =~ str } }
221
+ bad.each {|str| it('has expected regex NOT matching ' + str.inspect) { wanted.should_not =~ str } }
222
+
223
+ # Is compiled result valid?
224
+ good.each {|str| it('should match ' + str.inspect) { rx.should =~ str } }
225
+ bad.each {|str| it('should NOT match ' + str.inspect) { rx.should_not =~ str } }
226
+
227
+
228
+ end
229
+
230
+
231
+ ### Test 5: Negated range
232
+
233
+ describe "A correct program (Negated range)" do
234
+ prog = <<-'END'
235
+ match `c~`p end
236
+ END
237
+
238
+ good = ["ab", "rst"]
239
+ bad = ["def", "mno", ""]
240
+ wanted = /[^c-p]/
241
+
242
+ myprog = Program.new(prog)
243
+ parsed = nil
244
+
245
+ it "should parse correctly" do
246
+ parsed = myprog.parseable?
247
+ myprog.debug_bad_program_parse unless parsed
248
+ parsed.should == true
249
+ end
250
+
251
+ rx = nil
252
+ it "can be converted to a regex" do
253
+ rx = myprog.regexp
254
+ rx.class.should == Regexp
255
+ end
256
+
257
+ # Check sanity: Is test valid?
258
+ good.each {|str| it('has expected regex matching ' + str.inspect) { wanted.should =~ str } }
259
+ bad.each {|str| it('has expected regex NOT matching ' + str.inspect) { wanted.should_not =~ str } }
260
+
261
+ # Is compiled result valid?
262
+ good.each {|str| it('should match ' + str.inspect) { rx.should =~ str } }
263
+ bad.each {|str| it('should NOT match ' + str.inspect) { rx.should_not =~ str } }
264
+
265
+
266
+ end
267
+
268
+
269
+ ### Test 6: Negated char
270
+
271
+ describe "A correct program (Negated char)" do
272
+ prog = <<-'END'
273
+ match ~`d end
274
+ END
275
+
276
+ good = ["xyz", "123"]
277
+ bad = ["d", "dd"]
278
+ wanted = /[^d]/
279
+
280
+ myprog = Program.new(prog)
281
+ parsed = nil
282
+
283
+ it "should parse correctly" do
284
+ parsed = myprog.parseable?
285
+ myprog.debug_bad_program_parse unless parsed
286
+ parsed.should == true
287
+ end
288
+
289
+ rx = nil
290
+ it "can be converted to a regex" do
291
+ rx = myprog.regexp
292
+ rx.class.should == Regexp
293
+ end
294
+
295
+ # Check sanity: Is test valid?
296
+ good.each {|str| it('has expected regex matching ' + str.inspect) { wanted.should =~ str } }
297
+ bad.each {|str| it('has expected regex NOT matching ' + str.inspect) { wanted.should_not =~ str } }
298
+
299
+ # Is compiled result valid?
300
+ good.each {|str| it('should match ' + str.inspect) { rx.should =~ str } }
301
+ bad.each {|str| it('should NOT match ' + str.inspect) { rx.should_not =~ str } }
302
+
303
+
304
+ end
305
+
306
+
307
+ ### Test 7: POSIX class
308
+
309
+ describe "A correct program (POSIX class)" do
310
+ prog = <<-'END'
311
+ match %alnum end
312
+ END
313
+
314
+ good = ["abc365", "237", "xyz"]
315
+ bad = ["---", ":,.-"]
316
+ wanted = /[[:alnum:]]/
317
+
318
+ myprog = Program.new(prog)
319
+ parsed = nil
320
+
321
+ it "should parse correctly" do
322
+ parsed = myprog.parseable?
323
+ myprog.debug_bad_program_parse unless parsed
324
+ parsed.should == true
325
+ end
326
+
327
+ rx = nil
328
+ it "can be converted to a regex" do
329
+ rx = myprog.regexp
330
+ rx.class.should == Regexp
331
+ end
332
+
333
+ # Check sanity: Is test valid?
334
+ good.each {|str| it('has expected regex matching ' + str.inspect) { wanted.should =~ str } }
335
+ bad.each {|str| it('has expected regex NOT matching ' + str.inspect) { wanted.should_not =~ str } }
336
+
337
+ # Is compiled result valid?
338
+ good.each {|str| it('should match ' + str.inspect) { rx.should =~ str } }
339
+ bad.each {|str| it('should NOT match ' + str.inspect) { rx.should_not =~ str } }
340
+
341
+
342
+ end
343
+
344
+
345
+ ### Test 8: Simple char class
346
+
347
+ describe "A correct program (Simple char class)" do
348
+ prog = <<-'END'
349
+ match 'prstu' end
350
+ END
351
+
352
+ good = ["du", "ppp", "sr"]
353
+ bad = ["abc", "xyz"]
354
+ wanted = /[prstu]/
355
+
356
+ myprog = Program.new(prog)
357
+ parsed = nil
358
+
359
+ it "should parse correctly" do
360
+ parsed = myprog.parseable?
361
+ myprog.debug_bad_program_parse unless parsed
362
+ parsed.should == true
363
+ end
364
+
365
+ rx = nil
366
+ it "can be converted to a regex" do
367
+ rx = myprog.regexp
368
+ rx.class.should == Regexp
369
+ end
370
+
371
+ # Check sanity: Is test valid?
372
+ good.each {|str| it('has expected regex matching ' + str.inspect) { wanted.should =~ str } }
373
+ bad.each {|str| it('has expected regex NOT matching ' + str.inspect) { wanted.should_not =~ str } }
374
+
375
+ # Is compiled result valid?
376
+ good.each {|str| it('should match ' + str.inspect) { rx.should =~ str } }
377
+ bad.each {|str| it('should NOT match ' + str.inspect) { rx.should_not =~ str } }
378
+
379
+
380
+ end
381
+
382
+
383
+ ### Test 9: Negated char class
384
+
385
+ describe "A correct program (Negated char class)" do
386
+ prog = <<-'END'
387
+ match ~'ilmnop' end
388
+ END
389
+
390
+ good = ["abacus", "peccata", "hydrogen"]
391
+ bad = ["oil", "pill"]
392
+ wanted = /[^ilmnop]/
393
+
394
+ myprog = Program.new(prog)
395
+ parsed = nil
396
+
397
+ it "should parse correctly" do
398
+ parsed = myprog.parseable?
399
+ myprog.debug_bad_program_parse unless parsed
400
+ parsed.should == true
401
+ end
402
+
403
+ rx = nil
404
+ it "can be converted to a regex" do
405
+ rx = myprog.regexp
406
+ rx.class.should == Regexp
407
+ end
408
+
409
+ # Check sanity: Is test valid?
410
+ good.each {|str| it('has expected regex matching ' + str.inspect) { wanted.should =~ str } }
411
+ bad.each {|str| it('has expected regex NOT matching ' + str.inspect) { wanted.should_not =~ str } }
412
+
413
+ # Is compiled result valid?
414
+ good.each {|str| it('should match ' + str.inspect) { rx.should =~ str } }
415
+ bad.each {|str| it('should NOT match ' + str.inspect) { rx.should_not =~ str } }
416
+
417
+
418
+ end
419
+
420
+
421
+ ### Test 10: Predef Beginning of string
422
+
423
+ describe "A correct program (Predef Beginning of string)" do
424
+ prog = <<-'END'
425
+ match BOS end
426
+ END
427
+
428
+ good = [""]
429
+ bad = []
430
+ wanted = /^/
431
+
432
+ myprog = Program.new(prog)
433
+ parsed = nil
434
+
435
+ it "should parse correctly" do
436
+ parsed = myprog.parseable?
437
+ myprog.debug_bad_program_parse unless parsed
438
+ parsed.should == true
439
+ end
440
+
441
+ rx = nil
442
+ it "can be converted to a regex" do
443
+ rx = myprog.regexp
444
+ rx.class.should == Regexp
445
+ end
446
+
447
+ # Check sanity: Is test valid?
448
+ good.each {|str| it('has expected regex matching ' + str.inspect) { wanted.should =~ str } }
449
+ bad.each {|str| it('has expected regex NOT matching ' + str.inspect) { wanted.should_not =~ str } }
450
+
451
+ # Is compiled result valid?
452
+ good.each {|str| it('should match ' + str.inspect) { rx.should =~ str } }
453
+ bad.each {|str| it('should NOT match ' + str.inspect) { rx.should_not =~ str } }
454
+
455
+
456
+ end
457
+
458
+
459
+ ### Test 11: Predef End of string
460
+
461
+ describe "A correct program (Predef End of string)" do
462
+ prog = <<-'END'
463
+ match EOS end
464
+ END
465
+
466
+ good = [""]
467
+ bad = []
468
+ wanted = /$/
469
+
470
+ myprog = Program.new(prog)
471
+ parsed = nil
472
+
473
+ it "should parse correctly" do
474
+ parsed = myprog.parseable?
475
+ myprog.debug_bad_program_parse unless parsed
476
+ parsed.should == true
477
+ end
478
+
479
+ rx = nil
480
+ it "can be converted to a regex" do
481
+ rx = myprog.regexp
482
+ rx.class.should == Regexp
483
+ end
484
+
485
+ # Check sanity: Is test valid?
486
+ good.each {|str| it('has expected regex matching ' + str.inspect) { wanted.should =~ str } }
487
+ bad.each {|str| it('has expected regex NOT matching ' + str.inspect) { wanted.should_not =~ str } }
488
+
489
+ # Is compiled result valid?
490
+ good.each {|str| it('should match ' + str.inspect) { rx.should =~ str } }
491
+ bad.each {|str| it('should NOT match ' + str.inspect) { rx.should_not =~ str } }
492
+
493
+
494
+ end
495
+
496
+
497
+ ### Test 12: Predef Word boundary
498
+
499
+ describe "A correct program (Predef Word boundary)" do
500
+ prog = <<-'END'
501
+ match WB end
502
+ END
503
+
504
+ good = ["xyz"]
505
+ bad = ["", "---"]
506
+ wanted = /\b/
507
+
508
+ myprog = Program.new(prog)
509
+ parsed = nil
510
+
511
+ it "should parse correctly" do
512
+ parsed = myprog.parseable?
513
+ myprog.debug_bad_program_parse unless parsed
514
+ parsed.should == true
515
+ end
516
+
517
+ rx = nil
518
+ it "can be converted to a regex" do
519
+ rx = myprog.regexp
520
+ rx.class.should == Regexp
521
+ end
522
+
523
+ # Check sanity: Is test valid?
524
+ good.each {|str| it('has expected regex matching ' + str.inspect) { wanted.should =~ str } }
525
+ bad.each {|str| it('has expected regex NOT matching ' + str.inspect) { wanted.should_not =~ str } }
526
+
527
+ # Is compiled result valid?
528
+ good.each {|str| it('should match ' + str.inspect) { rx.should =~ str } }
529
+ bad.each {|str| it('should NOT match ' + str.inspect) { rx.should_not =~ str } }
530
+
531
+
532
+ end
533
+
534
+
535
+ ### Test 13: Simple string
536
+
537
+ describe "A correct program (Simple string)" do
538
+ prog = <<-'END'
539
+ match "xyz" end
540
+ END
541
+
542
+ good = ["xyz", "abcxyzdef"]
543
+ bad = ["abc", "xydefz"]
544
+ wanted = /xyz/
545
+
546
+ myprog = Program.new(prog)
547
+ parsed = nil
548
+
549
+ it "should parse correctly" do
550
+ parsed = myprog.parseable?
551
+ myprog.debug_bad_program_parse unless parsed
552
+ parsed.should == true
553
+ end
554
+
555
+ rx = nil
556
+ it "can be converted to a regex" do
557
+ rx = myprog.regexp
558
+ rx.class.should == Regexp
559
+ end
560
+
561
+ # Check sanity: Is test valid?
562
+ good.each {|str| it('has expected regex matching ' + str.inspect) { wanted.should =~ str } }
563
+ bad.each {|str| it('has expected regex NOT matching ' + str.inspect) { wanted.should_not =~ str } }
564
+
565
+ # Is compiled result valid?
566
+ good.each {|str| it('should match ' + str.inspect) { rx.should =~ str } }
567
+ bad.each {|str| it('should NOT match ' + str.inspect) { rx.should_not =~ str } }
568
+
569
+
570
+ end
571
+
572
+
573
+ ### Test 14: Single-bounded repetition
574
+
575
+ describe "A correct program (Single-bounded repetition)" do
576
+ prog = <<-'END'
577
+ match 5 * "xyz" end
578
+ END
579
+
580
+ good = ["xyzxyzxyzxyzxyz"]
581
+ bad = ["xyzxyzxyzxyz"]
582
+ wanted = /(xyz){5}/
583
+
584
+ myprog = Program.new(prog)
585
+ parsed = nil
586
+
587
+ it "should parse correctly" do
588
+ parsed = myprog.parseable?
589
+ myprog.debug_bad_program_parse unless parsed
590
+ parsed.should == true
591
+ end
592
+
593
+ rx = nil
594
+ it "can be converted to a regex" do
595
+ rx = myprog.regexp
596
+ rx.class.should == Regexp
597
+ end
598
+
599
+ # Check sanity: Is test valid?
600
+ good.each {|str| it('has expected regex matching ' + str.inspect) { wanted.should =~ str } }
601
+ bad.each {|str| it('has expected regex NOT matching ' + str.inspect) { wanted.should_not =~ str } }
602
+
603
+ # Is compiled result valid?
604
+ good.each {|str| it('should match ' + str.inspect) { rx.should =~ str } }
605
+ bad.each {|str| it('should NOT match ' + str.inspect) { rx.should_not =~ str } }
606
+
607
+
608
+ end
609
+
610
+
611
+ ### Test 15: Double-bounded repetition
612
+
613
+ describe "A correct program (Double-bounded repetition)" do
614
+ prog = <<-'END'
615
+ match 3,4 * %alpha end
616
+ END
617
+
618
+ good = ["abc", "abcd"]
619
+ bad = ["ab", "x"]
620
+ wanted = /([[:alpha:]]){3,4}/
621
+
622
+ myprog = Program.new(prog)
623
+ parsed = nil
624
+
625
+ it "should parse correctly" do
626
+ parsed = myprog.parseable?
627
+ myprog.debug_bad_program_parse unless parsed
628
+ parsed.should == true
629
+ end
630
+
631
+ rx = nil
632
+ it "can be converted to a regex" do
633
+ rx = myprog.regexp
634
+ rx.class.should == Regexp
635
+ end
636
+
637
+ # Check sanity: Is test valid?
638
+ good.each {|str| it('has expected regex matching ' + str.inspect) { wanted.should =~ str } }
639
+ bad.each {|str| it('has expected regex NOT matching ' + str.inspect) { wanted.should_not =~ str } }
640
+
641
+ # Is compiled result valid?
642
+ good.each {|str| it('should match ' + str.inspect) { rx.should =~ str } }
643
+ bad.each {|str| it('should NOT match ' + str.inspect) { rx.should_not =~ str } }
644
+
645
+
646
+ end
647
+
648
+
649
+ ### Test 16: any-qualifier
650
+
651
+ describe "A correct program (any-qualifier)" do
652
+ prog = <<-'END'
653
+ match any "abc" end
654
+ END
655
+
656
+ good = ["", "abc", "abcabc", "xyz"]
657
+ bad = []
658
+ wanted = /(abc)*/
659
+
660
+ myprog = Program.new(prog)
661
+ parsed = nil
662
+
663
+ it "should parse correctly" do
664
+ parsed = myprog.parseable?
665
+ myprog.debug_bad_program_parse unless parsed
666
+ parsed.should == true
667
+ end
668
+
669
+ rx = nil
670
+ it "can be converted to a regex" do
671
+ rx = myprog.regexp
672
+ rx.class.should == Regexp
673
+ end
674
+
675
+ # Check sanity: Is test valid?
676
+ good.each {|str| it('has expected regex matching ' + str.inspect) { wanted.should =~ str } }
677
+ bad.each {|str| it('has expected regex NOT matching ' + str.inspect) { wanted.should_not =~ str } }
678
+
679
+ # Is compiled result valid?
680
+ good.each {|str| it('should match ' + str.inspect) { rx.should =~ str } }
681
+ bad.each {|str| it('should NOT match ' + str.inspect) { rx.should_not =~ str } }
682
+
683
+
684
+ end
685
+
686
+
687
+ ### Test 17: many-qualifier
688
+
689
+ describe "A correct program (many-qualifier)" do
690
+ prog = <<-'END'
691
+ match many "def" end
692
+ END
693
+
694
+ good = ["def", "defdef", "defdefdef"]
695
+ bad = ["", "de", "xyz"]
696
+ wanted = /(def)+/
697
+
698
+ myprog = Program.new(prog)
699
+ parsed = nil
700
+
701
+ it "should parse correctly" do
702
+ parsed = myprog.parseable?
703
+ myprog.debug_bad_program_parse unless parsed
704
+ parsed.should == true
705
+ end
706
+
707
+ rx = nil
708
+ it "can be converted to a regex" do
709
+ rx = myprog.regexp
710
+ rx.class.should == Regexp
711
+ end
712
+
713
+ # Check sanity: Is test valid?
714
+ good.each {|str| it('has expected regex matching ' + str.inspect) { wanted.should =~ str } }
715
+ bad.each {|str| it('has expected regex NOT matching ' + str.inspect) { wanted.should_not =~ str } }
716
+
717
+ # Is compiled result valid?
718
+ good.each {|str| it('should match ' + str.inspect) { rx.should =~ str } }
719
+ bad.each {|str| it('should NOT match ' + str.inspect) { rx.should_not =~ str } }
720
+
721
+
722
+ end
723
+
724
+
725
+ ### Test 18: nocase-qualifier
726
+
727
+ describe "A correct program (nocase-qualifier)" do
728
+ prog = <<-'END'
729
+ match nocase "ghi" end
730
+ END
731
+
732
+ good = ["ghi", "GHI", "abGhicd"]
733
+ bad = ["", "gh", "abc"]
734
+ wanted = /((?i)ghi)/
735
+
736
+ myprog = Program.new(prog)
737
+ parsed = nil
738
+
739
+ it "should parse correctly" do
740
+ parsed = myprog.parseable?
741
+ myprog.debug_bad_program_parse unless parsed
742
+ parsed.should == true
743
+ end
744
+
745
+ rx = nil
746
+ it "can be converted to a regex" do
747
+ rx = myprog.regexp
748
+ rx.class.should == Regexp
749
+ end
750
+
751
+ # Check sanity: Is test valid?
752
+ good.each {|str| it('has expected regex matching ' + str.inspect) { wanted.should =~ str } }
753
+ bad.each {|str| it('has expected regex NOT matching ' + str.inspect) { wanted.should_not =~ str } }
754
+
755
+ # Is compiled result valid?
756
+ good.each {|str| it('should match ' + str.inspect) { rx.should =~ str } }
757
+ bad.each {|str| it('should NOT match ' + str.inspect) { rx.should_not =~ str } }
758
+
759
+
760
+ end
761
+
762
+
763
+ ### Test 19: maybe-qualifier
764
+
765
+ describe "A correct program (maybe-qualifier)" do
766
+ prog = <<-'END'
767
+ match maybe "ghi" end
768
+ END
769
+
770
+ good = ["", "ghi", "abghicd", "gh"]
771
+ bad = []
772
+ wanted = /(ghi)?/
773
+
774
+ myprog = Program.new(prog)
775
+ parsed = nil
776
+
777
+ it "should parse correctly" do
778
+ parsed = myprog.parseable?
779
+ myprog.debug_bad_program_parse unless parsed
780
+ parsed.should == true
781
+ end
782
+
783
+ rx = nil
784
+ it "can be converted to a regex" do
785
+ rx = myprog.regexp
786
+ rx.class.should == Regexp
787
+ end
788
+
789
+ # Check sanity: Is test valid?
790
+ good.each {|str| it('has expected regex matching ' + str.inspect) { wanted.should =~ str } }
791
+ bad.each {|str| it('has expected regex NOT matching ' + str.inspect) { wanted.should_not =~ str } }
792
+
793
+ # Is compiled result valid?
794
+ good.each {|str| it('should match ' + str.inspect) { rx.should =~ str } }
795
+ bad.each {|str| it('should NOT match ' + str.inspect) { rx.should_not =~ str } }
796
+
797
+
798
+ end
799
+
800
+
801
+ ### Test 20: Simple concatenation of two strings
802
+
803
+ describe "A correct program (Simple concatenation of two strings)" do
804
+ prog = <<-'END'
805
+ match "abc" "def" end
806
+ END
807
+
808
+ good = ["abcdefghi", "xyzabcdef"]
809
+ bad = ["", "abcxyzdef"]
810
+ wanted = /abcdef/
811
+
812
+ myprog = Program.new(prog)
813
+ parsed = nil
814
+
815
+ it "should parse correctly" do
816
+ parsed = myprog.parseable?
817
+ myprog.debug_bad_program_parse unless parsed
818
+ parsed.should == true
819
+ end
820
+
821
+ rx = nil
822
+ it "can be converted to a regex" do
823
+ rx = myprog.regexp
824
+ rx.class.should == Regexp
825
+ end
826
+
827
+ # Check sanity: Is test valid?
828
+ good.each {|str| it('has expected regex matching ' + str.inspect) { wanted.should =~ str } }
829
+ bad.each {|str| it('has expected regex NOT matching ' + str.inspect) { wanted.should_not =~ str } }
830
+
831
+ # Is compiled result valid?
832
+ good.each {|str| it('should match ' + str.inspect) { rx.should =~ str } }
833
+ bad.each {|str| it('should NOT match ' + str.inspect) { rx.should_not =~ str } }
834
+
835
+
836
+ end
837
+
838
+
839
+ ### Test 21: Concat of string and char class
840
+
841
+ describe "A correct program (Concat of string and char class)" do
842
+ prog = <<-'END'
843
+ match "abc"'def' end
844
+ END
845
+
846
+ good = ["abcd", "abce"]
847
+ bad = ["", "abcx"]
848
+ wanted = /abc[def]/
849
+
850
+ myprog = Program.new(prog)
851
+ parsed = nil
852
+
853
+ it "should parse correctly" do
854
+ parsed = myprog.parseable?
855
+ myprog.debug_bad_program_parse unless parsed
856
+ parsed.should == true
857
+ end
858
+
859
+ rx = nil
860
+ it "can be converted to a regex" do
861
+ rx = myprog.regexp
862
+ rx.class.should == Regexp
863
+ end
864
+
865
+ # Check sanity: Is test valid?
866
+ good.each {|str| it('has expected regex matching ' + str.inspect) { wanted.should =~ str } }
867
+ bad.each {|str| it('has expected regex NOT matching ' + str.inspect) { wanted.should_not =~ str } }
868
+
869
+ # Is compiled result valid?
870
+ good.each {|str| it('should match ' + str.inspect) { rx.should =~ str } }
871
+ bad.each {|str| it('should NOT match ' + str.inspect) { rx.should_not =~ str } }
872
+
873
+
874
+ end
875
+
876
+
877
+ ### Test 22: Simple alternation
878
+
879
+ describe "A correct program (Simple alternation)" do
880
+ prog = <<-'END'
881
+ match "abc" | "def" end
882
+ END
883
+
884
+ good = ["abc", "xyzabc123", "xdefy"]
885
+ bad = ["", "abde", "ab c d ef"]
886
+ wanted = /(abc|def)/
887
+
888
+ myprog = Program.new(prog)
889
+ parsed = nil
890
+
891
+ it "should parse correctly" do
892
+ parsed = myprog.parseable?
893
+ myprog.debug_bad_program_parse unless parsed
894
+ parsed.should == true
895
+ end
896
+
897
+ rx = nil
898
+ it "can be converted to a regex" do
899
+ rx = myprog.regexp
900
+ rx.class.should == Regexp
901
+ end
902
+
903
+ # Check sanity: Is test valid?
904
+ good.each {|str| it('has expected regex matching ' + str.inspect) { wanted.should =~ str } }
905
+ bad.each {|str| it('has expected regex NOT matching ' + str.inspect) { wanted.should_not =~ str } }
906
+
907
+ # Is compiled result valid?
908
+ good.each {|str| it('should match ' + str.inspect) { rx.should =~ str } }
909
+ bad.each {|str| it('should NOT match ' + str.inspect) { rx.should_not =~ str } }
910
+
911
+
912
+ end
913
+
914
+
915
+ ### Test 23: Alternation of concatenations
916
+
917
+ describe "A correct program (Alternation of concatenations)" do
918
+ prog = <<-'END'
919
+ match "ab" "c" | "d" "ef" end
920
+ END
921
+
922
+ good = ["abc", "xyzabc123", "xdefy"]
923
+ bad = ["", "abde", "ab c d ef"]
924
+ wanted = /(abc|def)/
925
+
926
+ myprog = Program.new(prog)
927
+ parsed = nil
928
+
929
+ it "should parse correctly" do
930
+ parsed = myprog.parseable?
931
+ myprog.debug_bad_program_parse unless parsed
932
+ parsed.should == true
933
+ end
934
+
935
+ rx = nil
936
+ it "can be converted to a regex" do
937
+ rx = myprog.regexp
938
+ rx.class.should == Regexp
939
+ end
940
+
941
+ # Check sanity: Is test valid?
942
+ good.each {|str| it('has expected regex matching ' + str.inspect) { wanted.should =~ str } }
943
+ bad.each {|str| it('has expected regex NOT matching ' + str.inspect) { wanted.should_not =~ str } }
944
+
945
+ # Is compiled result valid?
946
+ good.each {|str| it('should match ' + str.inspect) { rx.should =~ str } }
947
+ bad.each {|str| it('should NOT match ' + str.inspect) { rx.should_not =~ str } }
948
+
949
+
950
+ end
951
+
952
+
953
+ ### Test 24: Precedence of concatenation over alternation
954
+
955
+ describe "A correct program (Precedence of concatenation over alternation)" do
956
+ prog = <<-'END'
957
+ match "a" "b" | "c" end
958
+ END
959
+
960
+ good = ["ab", "c"]
961
+ bad = ["b", "a", "d"]
962
+ wanted = /(ab|c)/
963
+
964
+ myprog = Program.new(prog)
965
+ parsed = nil
966
+
967
+ it "should parse correctly" do
968
+ parsed = myprog.parseable?
969
+ myprog.debug_bad_program_parse unless parsed
970
+ parsed.should == true
971
+ end
972
+
973
+ rx = nil
974
+ it "can be converted to a regex" do
975
+ rx = myprog.regexp
976
+ rx.class.should == Regexp
977
+ end
978
+
979
+ # Check sanity: Is test valid?
980
+ good.each {|str| it('has expected regex matching ' + str.inspect) { wanted.should =~ str } }
981
+ bad.each {|str| it('has expected regex NOT matching ' + str.inspect) { wanted.should_not =~ str } }
982
+
983
+ # Is compiled result valid?
984
+ good.each {|str| it('should match ' + str.inspect) { rx.should =~ str } }
985
+ bad.each {|str| it('should NOT match ' + str.inspect) { rx.should_not =~ str } }
986
+
987
+
988
+ end
989
+
990
+
991
+ ### Test 25: Precedence of parens over concatenation
992
+
993
+ describe "A correct program (Precedence of parens over concatenation)" do
994
+ prog = <<-'END'
995
+ match "a" ("b" | "c") end
996
+ END
997
+
998
+ good = ["ab", "ac"]
999
+ bad = ["a", "b", "c"]
1000
+ wanted = /a(b|c)/
1001
+
1002
+ myprog = Program.new(prog)
1003
+ parsed = nil
1004
+
1005
+ it "should parse correctly" do
1006
+ parsed = myprog.parseable?
1007
+ myprog.debug_bad_program_parse unless parsed
1008
+ parsed.should == true
1009
+ end
1010
+
1011
+ rx = nil
1012
+ it "can be converted to a regex" do
1013
+ rx = myprog.regexp
1014
+ rx.class.should == Regexp
1015
+ end
1016
+
1017
+ # Check sanity: Is test valid?
1018
+ good.each {|str| it('has expected regex matching ' + str.inspect) { wanted.should =~ str } }
1019
+ bad.each {|str| it('has expected regex NOT matching ' + str.inspect) { wanted.should_not =~ str } }
1020
+
1021
+ # Is compiled result valid?
1022
+ good.each {|str| it('should match ' + str.inspect) { rx.should =~ str } }
1023
+ bad.each {|str| it('should NOT match ' + str.inspect) { rx.should_not =~ str } }
1024
+
1025
+
1026
+ end
1027
+
1028
+
1029
+ ### Test 26: Anchors and alternation
1030
+
1031
+ describe "A correct program (Anchors and alternation)" do
1032
+ prog = <<-'END'
1033
+ match BOS "x" | "y" EOS end
1034
+ END
1035
+
1036
+ good = ["xabc", "abcy"]
1037
+ bad = ["abc", "abcx", "yabc", "axb", "ayb", "axyb"]
1038
+ wanted = /(^x|y$)/
1039
+
1040
+ myprog = Program.new(prog)
1041
+ parsed = nil
1042
+
1043
+ it "should parse correctly" do
1044
+ parsed = myprog.parseable?
1045
+ myprog.debug_bad_program_parse unless parsed
1046
+ parsed.should == true
1047
+ end
1048
+
1049
+ rx = nil
1050
+ it "can be converted to a regex" do
1051
+ rx = myprog.regexp
1052
+ rx.class.should == Regexp
1053
+ end
1054
+
1055
+ # Check sanity: Is test valid?
1056
+ good.each {|str| it('has expected regex matching ' + str.inspect) { wanted.should =~ str } }
1057
+ bad.each {|str| it('has expected regex NOT matching ' + str.inspect) { wanted.should_not =~ str } }
1058
+
1059
+ # Is compiled result valid?
1060
+ good.each {|str| it('should match ' + str.inspect) { rx.should =~ str } }
1061
+ bad.each {|str| it('should NOT match ' + str.inspect) { rx.should_not =~ str } }
1062
+
1063
+
1064
+ end
1065
+
1066
+
1067
+ ### Test 27: Anchors, alternation, parens
1068
+
1069
+ describe "A correct program (Anchors, alternation, parens)" do
1070
+ prog = <<-'END'
1071
+ match BOS ("x" | "y") EOS end
1072
+ END
1073
+
1074
+ good = ["x", "y"]
1075
+ bad = ["abc", "abcx", "yabc", "xabc", "abcy"]
1076
+ wanted = /^(x|y)$/
1077
+
1078
+ myprog = Program.new(prog)
1079
+ parsed = nil
1080
+
1081
+ it "should parse correctly" do
1082
+ parsed = myprog.parseable?
1083
+ myprog.debug_bad_program_parse unless parsed
1084
+ parsed.should == true
1085
+ end
1086
+
1087
+ rx = nil
1088
+ it "can be converted to a regex" do
1089
+ rx = myprog.regexp
1090
+ rx.class.should == Regexp
1091
+ end
1092
+
1093
+ # Check sanity: Is test valid?
1094
+ good.each {|str| it('has expected regex matching ' + str.inspect) { wanted.should =~ str } }
1095
+ bad.each {|str| it('has expected regex NOT matching ' + str.inspect) { wanted.should_not =~ str } }
1096
+
1097
+ # Is compiled result valid?
1098
+ good.each {|str| it('should match ' + str.inspect) { rx.should =~ str } }
1099
+ bad.each {|str| it('should NOT match ' + str.inspect) { rx.should_not =~ str } }
1100
+
1101
+
1102
+ end
1103
+
1104
+
1105
+ ### Test 28: Parens, concatenation, alternation
1106
+
1107
+ describe "A correct program (Parens, concatenation, alternation)" do
1108
+ prog = <<-'END'
1109
+ match BOS ((maybe `0) `1-`9 | `1 D2) EOS end
1110
+ END
1111
+
1112
+ good = ["01", "09", "12"]
1113
+ bad = ["0", "00", "13"]
1114
+ wanted = /^((0)?[1-9]|1[0-2])$/
1115
+
1116
+ myprog = Program.new(prog)
1117
+ parsed = nil
1118
+
1119
+ it "should parse correctly" do
1120
+ parsed = myprog.parseable?
1121
+ myprog.debug_bad_program_parse unless parsed
1122
+ parsed.should == true
1123
+ end
1124
+
1125
+ rx = nil
1126
+ it "can be converted to a regex" do
1127
+ rx = myprog.regexp
1128
+ rx.class.should == Regexp
1129
+ end
1130
+
1131
+ # Check sanity: Is test valid?
1132
+ good.each {|str| it('has expected regex matching ' + str.inspect) { wanted.should =~ str } }
1133
+ bad.each {|str| it('has expected regex NOT matching ' + str.inspect) { wanted.should_not =~ str } }
1134
+
1135
+ # Is compiled result valid?
1136
+ good.each {|str| it('should match ' + str.inspect) { rx.should =~ str } }
1137
+ bad.each {|str| it('should NOT match ' + str.inspect) { rx.should_not =~ str } }
1138
+
1139
+
1140
+ end
1141
+
1142
+
1143
+ ### Test 29: Single backtick char
1144
+
1145
+ describe "A correct program (Single backtick char)" do
1146
+ prog = <<-'END'
1147
+ match `` end
1148
+ END
1149
+
1150
+ good = ["`", "this is a tick: `", "tock ` tock"]
1151
+ bad = ["", "abc"]
1152
+ wanted = /`/
1153
+
1154
+ myprog = Program.new(prog)
1155
+ parsed = nil
1156
+
1157
+ it "should parse correctly" do
1158
+ parsed = myprog.parseable?
1159
+ myprog.debug_bad_program_parse unless parsed
1160
+ parsed.should == true
1161
+ end
1162
+
1163
+ rx = nil
1164
+ it "can be converted to a regex" do
1165
+ rx = myprog.regexp
1166
+ rx.class.should == Regexp
1167
+ end
1168
+
1169
+ # Check sanity: Is test valid?
1170
+ good.each {|str| it('has expected regex matching ' + str.inspect) { wanted.should =~ str } }
1171
+ bad.each {|str| it('has expected regex NOT matching ' + str.inspect) { wanted.should_not =~ str } }
1172
+
1173
+ # Is compiled result valid?
1174
+ good.each {|str| it('should match ' + str.inspect) { rx.should =~ str } }
1175
+ bad.each {|str| it('should NOT match ' + str.inspect) { rx.should_not =~ str } }
1176
+
1177
+
1178
+ end
1179
+
1180
+
1181
+ ### Test 30: Single backslash char
1182
+
1183
+ describe "A correct program (Single backslash char)" do
1184
+ prog = <<-'END'
1185
+ match `\ end
1186
+ END
1187
+
1188
+ good = ["\\", "trying \\n", "and \\b also"]
1189
+ bad = ["\n", "\b", "neither \r nor \t"]
1190
+ wanted = /\\/
1191
+
1192
+ myprog = Program.new(prog)
1193
+ parsed = nil
1194
+
1195
+ it "should parse correctly" do
1196
+ parsed = myprog.parseable?
1197
+ myprog.debug_bad_program_parse unless parsed
1198
+ parsed.should == true
1199
+ end
1200
+
1201
+ rx = nil
1202
+ it "can be converted to a regex" do
1203
+ rx = myprog.regexp
1204
+ rx.class.should == Regexp
1205
+ end
1206
+
1207
+ # Check sanity: Is test valid?
1208
+ good.each {|str| it('has expected regex matching ' + str.inspect) { wanted.should =~ str } }
1209
+ bad.each {|str| it('has expected regex NOT matching ' + str.inspect) { wanted.should_not =~ str } }
1210
+
1211
+ # Is compiled result valid?
1212
+ good.each {|str| it('should match ' + str.inspect) { rx.should =~ str } }
1213
+ bad.each {|str| it('should NOT match ' + str.inspect) { rx.should_not =~ str } }
1214
+
1215
+
1216
+ end
1217
+
1218
+
1219
+ ### Test 31: Empty string
1220
+
1221
+ describe "A correct program (Empty string)" do
1222
+ prog = <<-'END'
1223
+ match "" end
1224
+ END
1225
+
1226
+ good = ["", "abc"]
1227
+ bad = []
1228
+ wanted = //
1229
+
1230
+ myprog = Program.new(prog)
1231
+ parsed = nil
1232
+
1233
+ it "should parse correctly" do
1234
+ parsed = myprog.parseable?
1235
+ myprog.debug_bad_program_parse unless parsed
1236
+ parsed.should == true
1237
+ end
1238
+
1239
+ rx = nil
1240
+ it "can be converted to a regex" do
1241
+ rx = myprog.regexp
1242
+ rx.class.should == Regexp
1243
+ end
1244
+
1245
+ # Check sanity: Is test valid?
1246
+ good.each {|str| it('has expected regex matching ' + str.inspect) { wanted.should =~ str } }
1247
+ bad.each {|str| it('has expected regex NOT matching ' + str.inspect) { wanted.should_not =~ str } }
1248
+
1249
+ # Is compiled result valid?
1250
+ good.each {|str| it('should match ' + str.inspect) { rx.should =~ str } }
1251
+ bad.each {|str| it('should NOT match ' + str.inspect) { rx.should_not =~ str } }
1252
+
1253
+
1254
+ end
1255
+
1256
+
1257
+ ### Test 32: Simple char class
1258
+
1259
+ describe "A correct program (Simple char class)" do
1260
+ prog = <<-'END'
1261
+ match 'abcdef' end
1262
+ END
1263
+
1264
+ good = ["there's a cat here", "item c"]
1265
+ bad = ["", "proton"]
1266
+ wanted = /[abcdef]/
1267
+
1268
+ myprog = Program.new(prog)
1269
+ parsed = nil
1270
+
1271
+ it "should parse correctly" do
1272
+ parsed = myprog.parseable?
1273
+ myprog.debug_bad_program_parse unless parsed
1274
+ parsed.should == true
1275
+ end
1276
+
1277
+ rx = nil
1278
+ it "can be converted to a regex" do
1279
+ rx = myprog.regexp
1280
+ rx.class.should == Regexp
1281
+ end
1282
+
1283
+ # Check sanity: Is test valid?
1284
+ good.each {|str| it('has expected regex matching ' + str.inspect) { wanted.should =~ str } }
1285
+ bad.each {|str| it('has expected regex NOT matching ' + str.inspect) { wanted.should_not =~ str } }
1286
+
1287
+ # Is compiled result valid?
1288
+ good.each {|str| it('should match ' + str.inspect) { rx.should =~ str } }
1289
+ bad.each {|str| it('should NOT match ' + str.inspect) { rx.should_not =~ str } }
1290
+
1291
+
1292
+ end
1293
+
1294
+
1295
+ ### Test 33: Simple one-char class
1296
+
1297
+ describe "A correct program (Simple one-char class)" do
1298
+ prog = <<-'END'
1299
+ match 'x' end
1300
+ END
1301
+
1302
+ good = ["x", "uvwxyz"]
1303
+ bad = ["", "abc"]
1304
+ wanted = /[x]/
1305
+
1306
+ myprog = Program.new(prog)
1307
+ parsed = nil
1308
+
1309
+ it "should parse correctly" do
1310
+ parsed = myprog.parseable?
1311
+ myprog.debug_bad_program_parse unless parsed
1312
+ parsed.should == true
1313
+ end
1314
+
1315
+ rx = nil
1316
+ it "can be converted to a regex" do
1317
+ rx = myprog.regexp
1318
+ rx.class.should == Regexp
1319
+ end
1320
+
1321
+ # Check sanity: Is test valid?
1322
+ good.each {|str| it('has expected regex matching ' + str.inspect) { wanted.should =~ str } }
1323
+ bad.each {|str| it('has expected regex NOT matching ' + str.inspect) { wanted.should_not =~ str } }
1324
+
1325
+ # Is compiled result valid?
1326
+ good.each {|str| it('should match ' + str.inspect) { rx.should =~ str } }
1327
+ bad.each {|str| it('should NOT match ' + str.inspect) { rx.should_not =~ str } }
1328
+
1329
+
1330
+ end
1331
+
1332
+
1333
+ ### Test 34: Alternation of range and class
1334
+
1335
+ describe "A correct program (Alternation of range and class)" do
1336
+ prog = <<-'END'
1337
+ match `a-`f | 'xyz' end
1338
+ END
1339
+
1340
+ good = ["a", "x", "z", "c"]
1341
+ bad = ["", "jkl", "gw"]
1342
+ wanted = /([a-f]|[xyz])/
1343
+
1344
+ myprog = Program.new(prog)
1345
+ parsed = nil
1346
+
1347
+ it "should parse correctly" do
1348
+ parsed = myprog.parseable?
1349
+ myprog.debug_bad_program_parse unless parsed
1350
+ parsed.should == true
1351
+ end
1352
+
1353
+ rx = nil
1354
+ it "can be converted to a regex" do
1355
+ rx = myprog.regexp
1356
+ rx.class.should == Regexp
1357
+ end
1358
+
1359
+ # Check sanity: Is test valid?
1360
+ good.each {|str| it('has expected regex matching ' + str.inspect) { wanted.should =~ str } }
1361
+ bad.each {|str| it('has expected regex NOT matching ' + str.inspect) { wanted.should_not =~ str } }
1362
+
1363
+ # Is compiled result valid?
1364
+ good.each {|str| it('should match ' + str.inspect) { rx.should =~ str } }
1365
+ bad.each {|str| it('should NOT match ' + str.inspect) { rx.should_not =~ str } }
1366
+
1367
+
1368
+ end
1369
+
1370
+
1371
+ ### Test 35: Alternation of range and maybe-clause
1372
+
1373
+ describe "A correct program (Alternation of range and maybe-clause)" do
1374
+ prog = <<-'END'
1375
+ match `1-`6| maybe "#" end
1376
+ END
1377
+
1378
+ good = ["", "1#", "1", " 2# abc"]
1379
+ bad = []
1380
+ wanted = /([1-6]|(\#)?)/
1381
+
1382
+ myprog = Program.new(prog)
1383
+ parsed = nil
1384
+
1385
+ it "should parse correctly" do
1386
+ parsed = myprog.parseable?
1387
+ myprog.debug_bad_program_parse unless parsed
1388
+ parsed.should == true
1389
+ end
1390
+
1391
+ rx = nil
1392
+ it "can be converted to a regex" do
1393
+ rx = myprog.regexp
1394
+ rx.class.should == Regexp
1395
+ end
1396
+
1397
+ # Check sanity: Is test valid?
1398
+ good.each {|str| it('has expected regex matching ' + str.inspect) { wanted.should =~ str } }
1399
+ bad.each {|str| it('has expected regex NOT matching ' + str.inspect) { wanted.should_not =~ str } }
1400
+
1401
+ # Is compiled result valid?
1402
+ good.each {|str| it('should match ' + str.inspect) { rx.should =~ str } }
1403
+ bad.each {|str| it('should NOT match ' + str.inspect) { rx.should_not =~ str } }
1404
+
1405
+
1406
+ end
1407
+
1408
+
1409
+ ### Test 36: Four-way alternation
1410
+
1411
+ describe "A correct program (Four-way alternation)" do
1412
+ prog = <<-'END'
1413
+ match `a | `b|`c|`d end
1414
+ END
1415
+
1416
+ good = ["xyza", "xybz", "xcyz", "dxyz"]
1417
+ bad = ["", "every", "ghijk"]
1418
+ wanted = /(a|b|c|d)/
1419
+
1420
+ myprog = Program.new(prog)
1421
+ parsed = nil
1422
+
1423
+ it "should parse correctly" do
1424
+ parsed = myprog.parseable?
1425
+ myprog.debug_bad_program_parse unless parsed
1426
+ parsed.should == true
1427
+ end
1428
+
1429
+ rx = nil
1430
+ it "can be converted to a regex" do
1431
+ rx = myprog.regexp
1432
+ rx.class.should == Regexp
1433
+ end
1434
+
1435
+ # Check sanity: Is test valid?
1436
+ good.each {|str| it('has expected regex matching ' + str.inspect) { wanted.should =~ str } }
1437
+ bad.each {|str| it('has expected regex NOT matching ' + str.inspect) { wanted.should_not =~ str } }
1438
+
1439
+ # Is compiled result valid?
1440
+ good.each {|str| it('should match ' + str.inspect) { rx.should =~ str } }
1441
+ bad.each {|str| it('should NOT match ' + str.inspect) { rx.should_not =~ str } }
1442
+
1443
+
1444
+ end
1445
+
1446
+
1447
+ ### Test 37: Concatenation of range and class
1448
+
1449
+ describe "A correct program (Concatenation of range and class)" do
1450
+ prog = <<-'END'
1451
+ match `a-`f 'xyz' end
1452
+ END
1453
+
1454
+ good = ["ax", "fz", "cy"]
1455
+ bad = ["zf", "xa", "gz", "hp", "mx"]
1456
+ wanted = /[a-f][xyz]/
1457
+
1458
+ myprog = Program.new(prog)
1459
+ parsed = nil
1460
+
1461
+ it "should parse correctly" do
1462
+ parsed = myprog.parseable?
1463
+ myprog.debug_bad_program_parse unless parsed
1464
+ parsed.should == true
1465
+ end
1466
+
1467
+ rx = nil
1468
+ it "can be converted to a regex" do
1469
+ rx = myprog.regexp
1470
+ rx.class.should == Regexp
1471
+ end
1472
+
1473
+ # Check sanity: Is test valid?
1474
+ good.each {|str| it('has expected regex matching ' + str.inspect) { wanted.should =~ str } }
1475
+ bad.each {|str| it('has expected regex NOT matching ' + str.inspect) { wanted.should_not =~ str } }
1476
+
1477
+ # Is compiled result valid?
1478
+ good.each {|str| it('should match ' + str.inspect) { rx.should =~ str } }
1479
+ bad.each {|str| it('should NOT match ' + str.inspect) { rx.should_not =~ str } }
1480
+
1481
+
1482
+ end
1483
+
1484
+
1485
+ ### Test 38: Concat of strings and maybe-clause
1486
+
1487
+ describe "A correct program (Concat of strings and maybe-clause)" do
1488
+ prog = <<-'END'
1489
+ match "this" "that" maybe "other" end
1490
+ END
1491
+
1492
+ good = ["thisthat", "thisthatother", "abc thisthat xyz", "abc thisthatother xyz"]
1493
+ bad = ["", "abc", "this that", "this that other"]
1494
+ wanted = /thisthat(other)?/
1495
+
1496
+ myprog = Program.new(prog)
1497
+ parsed = nil
1498
+
1499
+ it "should parse correctly" do
1500
+ parsed = myprog.parseable?
1501
+ myprog.debug_bad_program_parse unless parsed
1502
+ parsed.should == true
1503
+ end
1504
+
1505
+ rx = nil
1506
+ it "can be converted to a regex" do
1507
+ rx = myprog.regexp
1508
+ rx.class.should == Regexp
1509
+ end
1510
+
1511
+ # Check sanity: Is test valid?
1512
+ good.each {|str| it('has expected regex matching ' + str.inspect) { wanted.should =~ str } }
1513
+ bad.each {|str| it('has expected regex NOT matching ' + str.inspect) { wanted.should_not =~ str } }
1514
+
1515
+ # Is compiled result valid?
1516
+ good.each {|str| it('should match ' + str.inspect) { rx.should =~ str } }
1517
+ bad.each {|str| it('should NOT match ' + str.inspect) { rx.should_not =~ str } }
1518
+
1519
+
1520
+ end
1521
+
1522
+
1523
+ ### Test 39: Simple repetition of class
1524
+
1525
+ describe "A correct program (Simple repetition of class)" do
1526
+ prog = <<-'END'
1527
+ match 3 * 'xyz' end
1528
+ END
1529
+
1530
+ good = ["xyz", "xxx", "yzy", "xyzzy123"]
1531
+ bad = ["", "abc", "xy", "axy", "xyb", "axyb"]
1532
+ wanted = /([xyz]){3}/
1533
+
1534
+ myprog = Program.new(prog)
1535
+ parsed = nil
1536
+
1537
+ it "should parse correctly" do
1538
+ parsed = myprog.parseable?
1539
+ myprog.debug_bad_program_parse unless parsed
1540
+ parsed.should == true
1541
+ end
1542
+
1543
+ rx = nil
1544
+ it "can be converted to a regex" do
1545
+ rx = myprog.regexp
1546
+ rx.class.should == Regexp
1547
+ end
1548
+
1549
+ # Check sanity: Is test valid?
1550
+ good.each {|str| it('has expected regex matching ' + str.inspect) { wanted.should =~ str } }
1551
+ bad.each {|str| it('has expected regex NOT matching ' + str.inspect) { wanted.should_not =~ str } }
1552
+
1553
+ # Is compiled result valid?
1554
+ good.each {|str| it('should match ' + str.inspect) { rx.should =~ str } }
1555
+ bad.each {|str| it('should NOT match ' + str.inspect) { rx.should_not =~ str } }
1556
+
1557
+
1558
+ end
1559
+
1560
+
1561
+ ### Test 40: Simple repetition of range
1562
+
1563
+ describe "A correct program (Simple repetition of range)" do
1564
+ prog = <<-'END'
1565
+ match 4 * `1-`6 end
1566
+ END
1567
+
1568
+ good = ["1111", "1234", "abc 6543 def"]
1569
+ bad = ["", "abc", "123", "123 4"]
1570
+ wanted = /([1-6]){4}/
1571
+
1572
+ myprog = Program.new(prog)
1573
+ parsed = nil
1574
+
1575
+ it "should parse correctly" do
1576
+ parsed = myprog.parseable?
1577
+ myprog.debug_bad_program_parse unless parsed
1578
+ parsed.should == true
1579
+ end
1580
+
1581
+ rx = nil
1582
+ it "can be converted to a regex" do
1583
+ rx = myprog.regexp
1584
+ rx.class.should == Regexp
1585
+ end
1586
+
1587
+ # Check sanity: Is test valid?
1588
+ good.each {|str| it('has expected regex matching ' + str.inspect) { wanted.should =~ str } }
1589
+ bad.each {|str| it('has expected regex NOT matching ' + str.inspect) { wanted.should_not =~ str } }
1590
+
1591
+ # Is compiled result valid?
1592
+ good.each {|str| it('should match ' + str.inspect) { rx.should =~ str } }
1593
+ bad.each {|str| it('should NOT match ' + str.inspect) { rx.should_not =~ str } }
1594
+
1595
+
1596
+ end
1597
+
1598
+
1599
+ ### Test 41: Complex repetition of char
1600
+
1601
+ describe "A correct program (Complex repetition of char)" do
1602
+ prog = <<-'END'
1603
+ match 3,5 * (`a) end
1604
+ END
1605
+
1606
+ good = ["aaa", "aaaa", "aaaaa", "xaaay", "aaaaaaa"]
1607
+ bad = ["", "abc", "aa"]
1608
+ wanted = /(a){3,5}/
1609
+
1610
+ myprog = Program.new(prog)
1611
+ parsed = nil
1612
+
1613
+ it "should parse correctly" do
1614
+ parsed = myprog.parseable?
1615
+ myprog.debug_bad_program_parse unless parsed
1616
+ parsed.should == true
1617
+ end
1618
+
1619
+ rx = nil
1620
+ it "can be converted to a regex" do
1621
+ rx = myprog.regexp
1622
+ rx.class.should == Regexp
1623
+ end
1624
+
1625
+ # Check sanity: Is test valid?
1626
+ good.each {|str| it('has expected regex matching ' + str.inspect) { wanted.should =~ str } }
1627
+ bad.each {|str| it('has expected regex NOT matching ' + str.inspect) { wanted.should_not =~ str } }
1628
+
1629
+ # Is compiled result valid?
1630
+ good.each {|str| it('should match ' + str.inspect) { rx.should =~ str } }
1631
+ bad.each {|str| it('should NOT match ' + str.inspect) { rx.should_not =~ str } }
1632
+
1633
+
1634
+ end
1635
+
1636
+
1637
+ ### Test 42: Complex repetition of parenthesized class
1638
+
1639
+ describe "A correct program (Complex repetition of parenthesized class)" do
1640
+ prog = <<-'END'
1641
+ match 4,7 * ('xyz') end
1642
+ END
1643
+
1644
+ good = ["xxxx", "yyyy", "xyzy", "xyzzy", "zyzzyva", "xyzxyz", "xyzxyzx", "xyzxyzxyzxyz"]
1645
+ bad = ["", "abc", "x", "xx", "xxx", "xyz xy"]
1646
+ wanted = /([xyz]){4,7}/
1647
+
1648
+ myprog = Program.new(prog)
1649
+ parsed = nil
1650
+
1651
+ it "should parse correctly" do
1652
+ parsed = myprog.parseable?
1653
+ myprog.debug_bad_program_parse unless parsed
1654
+ parsed.should == true
1655
+ end
1656
+
1657
+ rx = nil
1658
+ it "can be converted to a regex" do
1659
+ rx = myprog.regexp
1660
+ rx.class.should == Regexp
1661
+ end
1662
+
1663
+ # Check sanity: Is test valid?
1664
+ good.each {|str| it('has expected regex matching ' + str.inspect) { wanted.should =~ str } }
1665
+ bad.each {|str| it('has expected regex NOT matching ' + str.inspect) { wanted.should_not =~ str } }
1666
+
1667
+ # Is compiled result valid?
1668
+ good.each {|str| it('should match ' + str.inspect) { rx.should =~ str } }
1669
+ bad.each {|str| it('should NOT match ' + str.inspect) { rx.should_not =~ str } }
1670
+
1671
+
1672
+ end
1673
+
1674
+
1675
+ ### Test 43: Complex repetition of parenthesized range
1676
+
1677
+ describe "A correct program (Complex repetition of parenthesized range)" do
1678
+ prog = <<-'END'
1679
+ match 0,3 * (`1-`6) end
1680
+ END
1681
+
1682
+ good = ["", "1", "11", "111", "56", "654", "1111", "x123y", "x123456y"]
1683
+ bad = []
1684
+ wanted = /([1-6]){0,3}/
1685
+
1686
+ myprog = Program.new(prog)
1687
+ parsed = nil
1688
+
1689
+ it "should parse correctly" do
1690
+ parsed = myprog.parseable?
1691
+ myprog.debug_bad_program_parse unless parsed
1692
+ parsed.should == true
1693
+ end
1694
+
1695
+ rx = nil
1696
+ it "can be converted to a regex" do
1697
+ rx = myprog.regexp
1698
+ rx.class.should == Regexp
1699
+ end
1700
+
1701
+ # Check sanity: Is test valid?
1702
+ good.each {|str| it('has expected regex matching ' + str.inspect) { wanted.should =~ str } }
1703
+ bad.each {|str| it('has expected regex NOT matching ' + str.inspect) { wanted.should_not =~ str } }
1704
+
1705
+ # Is compiled result valid?
1706
+ good.each {|str| it('should match ' + str.inspect) { rx.should =~ str } }
1707
+ bad.each {|str| it('should NOT match ' + str.inspect) { rx.should_not =~ str } }
1708
+
1709
+
1710
+ end
1711
+
1712
+
1713
+ ### Test 44: Single char (anchored)
1714
+
1715
+ describe "A correct program (Single char (anchored))" do
1716
+ prog = <<-'END'
1717
+ match BOS `x EOS end
1718
+ END
1719
+
1720
+ good = ["x"]
1721
+ bad = ["yz", "", "ABC"]
1722
+ wanted = /^x$/
1723
+
1724
+ myprog = Program.new(prog)
1725
+ parsed = nil
1726
+
1727
+ it "should parse correctly" do
1728
+ parsed = myprog.parseable?
1729
+ myprog.debug_bad_program_parse unless parsed
1730
+ parsed.should == true
1731
+ end
1732
+
1733
+ rx = nil
1734
+ it "can be converted to a regex" do
1735
+ rx = myprog.regexp
1736
+ rx.class.should == Regexp
1737
+ end
1738
+
1739
+ # Check sanity: Is test valid?
1740
+ good.each {|str| it('has expected regex matching ' + str.inspect) { wanted.should =~ str } }
1741
+ bad.each {|str| it('has expected regex NOT matching ' + str.inspect) { wanted.should_not =~ str } }
1742
+
1743
+ # Is compiled result valid?
1744
+ good.each {|str| it('should match ' + str.inspect) { rx.should =~ str } }
1745
+ bad.each {|str| it('should NOT match ' + str.inspect) { rx.should_not =~ str } }
1746
+
1747
+
1748
+ end
1749
+
1750
+
1751
+ ### Test 45: Simple range (anchored)
1752
+
1753
+ describe "A correct program (Simple range (anchored))" do
1754
+ prog = <<-'END'
1755
+ match BOS `a-`f EOS end
1756
+ END
1757
+
1758
+ good = ["a", "b", "c", "d", "e", "f"]
1759
+ bad = ["xyz", "", "ABC"]
1760
+ wanted = /^[a-f]$/
1761
+
1762
+ myprog = Program.new(prog)
1763
+ parsed = nil
1764
+
1765
+ it "should parse correctly" do
1766
+ parsed = myprog.parseable?
1767
+ myprog.debug_bad_program_parse unless parsed
1768
+ parsed.should == true
1769
+ end
1770
+
1771
+ rx = nil
1772
+ it "can be converted to a regex" do
1773
+ rx = myprog.regexp
1774
+ rx.class.should == Regexp
1775
+ end
1776
+
1777
+ # Check sanity: Is test valid?
1778
+ good.each {|str| it('has expected regex matching ' + str.inspect) { wanted.should =~ str } }
1779
+ bad.each {|str| it('has expected regex NOT matching ' + str.inspect) { wanted.should_not =~ str } }
1780
+
1781
+ # Is compiled result valid?
1782
+ good.each {|str| it('should match ' + str.inspect) { rx.should =~ str } }
1783
+ bad.each {|str| it('should NOT match ' + str.inspect) { rx.should_not =~ str } }
1784
+
1785
+
1786
+ end
1787
+
1788
+
1789
+ ### Test 46: Negated range (anchored)
1790
+
1791
+ describe "A correct program (Negated range (anchored))" do
1792
+ prog = <<-'END'
1793
+ match BOS `c~`p EOS end
1794
+ END
1795
+
1796
+ good = ["a", "r"]
1797
+ bad = ["def", "mno", ""]
1798
+ wanted = /^[^c-p]$/
1799
+
1800
+ myprog = Program.new(prog)
1801
+ parsed = nil
1802
+
1803
+ it "should parse correctly" do
1804
+ parsed = myprog.parseable?
1805
+ myprog.debug_bad_program_parse unless parsed
1806
+ parsed.should == true
1807
+ end
1808
+
1809
+ rx = nil
1810
+ it "can be converted to a regex" do
1811
+ rx = myprog.regexp
1812
+ rx.class.should == Regexp
1813
+ end
1814
+
1815
+ # Check sanity: Is test valid?
1816
+ good.each {|str| it('has expected regex matching ' + str.inspect) { wanted.should =~ str } }
1817
+ bad.each {|str| it('has expected regex NOT matching ' + str.inspect) { wanted.should_not =~ str } }
1818
+
1819
+ # Is compiled result valid?
1820
+ good.each {|str| it('should match ' + str.inspect) { rx.should =~ str } }
1821
+ bad.each {|str| it('should NOT match ' + str.inspect) { rx.should_not =~ str } }
1822
+
1823
+
1824
+ end
1825
+
1826
+
1827
+ ### Test 47: Negated char (anchored)
1828
+
1829
+ describe "A correct program (Negated char (anchored))" do
1830
+ prog = <<-'END'
1831
+ match BOS ~`d EOS end
1832
+ END
1833
+
1834
+ good = ["x", "1"]
1835
+ bad = ["d", "dd", "abc"]
1836
+ wanted = /^[^d]$/
1837
+
1838
+ myprog = Program.new(prog)
1839
+ parsed = nil
1840
+
1841
+ it "should parse correctly" do
1842
+ parsed = myprog.parseable?
1843
+ myprog.debug_bad_program_parse unless parsed
1844
+ parsed.should == true
1845
+ end
1846
+
1847
+ rx = nil
1848
+ it "can be converted to a regex" do
1849
+ rx = myprog.regexp
1850
+ rx.class.should == Regexp
1851
+ end
1852
+
1853
+ # Check sanity: Is test valid?
1854
+ good.each {|str| it('has expected regex matching ' + str.inspect) { wanted.should =~ str } }
1855
+ bad.each {|str| it('has expected regex NOT matching ' + str.inspect) { wanted.should_not =~ str } }
1856
+
1857
+ # Is compiled result valid?
1858
+ good.each {|str| it('should match ' + str.inspect) { rx.should =~ str } }
1859
+ bad.each {|str| it('should NOT match ' + str.inspect) { rx.should_not =~ str } }
1860
+
1861
+
1862
+ end
1863
+
1864
+
1865
+ ### Test 48: POSIX class (anchored)
1866
+
1867
+ describe "A correct program (POSIX class (anchored))" do
1868
+ prog = <<-'END'
1869
+ match BOS %alnum EOS end
1870
+ END
1871
+
1872
+ good = ["c", "2"]
1873
+ bad = ["", "abc", "123", "-", ":", ",", "."]
1874
+ wanted = /^[[:alnum:]]$/
1875
+
1876
+ myprog = Program.new(prog)
1877
+ parsed = nil
1878
+
1879
+ it "should parse correctly" do
1880
+ parsed = myprog.parseable?
1881
+ myprog.debug_bad_program_parse unless parsed
1882
+ parsed.should == true
1883
+ end
1884
+
1885
+ rx = nil
1886
+ it "can be converted to a regex" do
1887
+ rx = myprog.regexp
1888
+ rx.class.should == Regexp
1889
+ end
1890
+
1891
+ # Check sanity: Is test valid?
1892
+ good.each {|str| it('has expected regex matching ' + str.inspect) { wanted.should =~ str } }
1893
+ bad.each {|str| it('has expected regex NOT matching ' + str.inspect) { wanted.should_not =~ str } }
1894
+
1895
+ # Is compiled result valid?
1896
+ good.each {|str| it('should match ' + str.inspect) { rx.should =~ str } }
1897
+ bad.each {|str| it('should NOT match ' + str.inspect) { rx.should_not =~ str } }
1898
+
1899
+
1900
+ end
1901
+
1902
+
1903
+ ### Test 49: Simple char class (anchored)
1904
+
1905
+ describe "A correct program (Simple char class (anchored))" do
1906
+ prog = <<-'END'
1907
+ match BOS 'prstu' EOS end
1908
+ END
1909
+
1910
+ good = ["u", "p", "s"]
1911
+ bad = ["", "abc", "x"]
1912
+ wanted = /^[prstu]$/
1913
+
1914
+ myprog = Program.new(prog)
1915
+ parsed = nil
1916
+
1917
+ it "should parse correctly" do
1918
+ parsed = myprog.parseable?
1919
+ myprog.debug_bad_program_parse unless parsed
1920
+ parsed.should == true
1921
+ end
1922
+
1923
+ rx = nil
1924
+ it "can be converted to a regex" do
1925
+ rx = myprog.regexp
1926
+ rx.class.should == Regexp
1927
+ end
1928
+
1929
+ # Check sanity: Is test valid?
1930
+ good.each {|str| it('has expected regex matching ' + str.inspect) { wanted.should =~ str } }
1931
+ bad.each {|str| it('has expected regex NOT matching ' + str.inspect) { wanted.should_not =~ str } }
1932
+
1933
+ # Is compiled result valid?
1934
+ good.each {|str| it('should match ' + str.inspect) { rx.should =~ str } }
1935
+ bad.each {|str| it('should NOT match ' + str.inspect) { rx.should_not =~ str } }
1936
+
1937
+
1938
+ end
1939
+
1940
+
1941
+ ### Test 50: Negated char class (anchored)
1942
+
1943
+ describe "A correct program (Negated char class (anchored))" do
1944
+ prog = <<-'END'
1945
+ match BOS ~'ilmnop' EOS end
1946
+ END
1947
+
1948
+ good = ["a", "e", "h"]
1949
+ bad = ["o", "i", "l"]
1950
+ wanted = /^[^ilmnop]$/
1951
+
1952
+ myprog = Program.new(prog)
1953
+ parsed = nil
1954
+
1955
+ it "should parse correctly" do
1956
+ parsed = myprog.parseable?
1957
+ myprog.debug_bad_program_parse unless parsed
1958
+ parsed.should == true
1959
+ end
1960
+
1961
+ rx = nil
1962
+ it "can be converted to a regex" do
1963
+ rx = myprog.regexp
1964
+ rx.class.should == Regexp
1965
+ end
1966
+
1967
+ # Check sanity: Is test valid?
1968
+ good.each {|str| it('has expected regex matching ' + str.inspect) { wanted.should =~ str } }
1969
+ bad.each {|str| it('has expected regex NOT matching ' + str.inspect) { wanted.should_not =~ str } }
1970
+
1971
+ # Is compiled result valid?
1972
+ good.each {|str| it('should match ' + str.inspect) { rx.should =~ str } }
1973
+ bad.each {|str| it('should NOT match ' + str.inspect) { rx.should_not =~ str } }
1974
+
1975
+
1976
+ end
1977
+
1978
+
1979
+ ### Test 51: Simple string (anchored)
1980
+
1981
+ describe "A correct program (Simple string (anchored))" do
1982
+ prog = <<-'END'
1983
+ match BOS "xyz" EOS end
1984
+ END
1985
+
1986
+ good = ["xyz"]
1987
+ bad = ["", "abc", "abcxyzdef", "xydefz"]
1988
+ wanted = /^xyz$/
1989
+
1990
+ myprog = Program.new(prog)
1991
+ parsed = nil
1992
+
1993
+ it "should parse correctly" do
1994
+ parsed = myprog.parseable?
1995
+ myprog.debug_bad_program_parse unless parsed
1996
+ parsed.should == true
1997
+ end
1998
+
1999
+ rx = nil
2000
+ it "can be converted to a regex" do
2001
+ rx = myprog.regexp
2002
+ rx.class.should == Regexp
2003
+ end
2004
+
2005
+ # Check sanity: Is test valid?
2006
+ good.each {|str| it('has expected regex matching ' + str.inspect) { wanted.should =~ str } }
2007
+ bad.each {|str| it('has expected regex NOT matching ' + str.inspect) { wanted.should_not =~ str } }
2008
+
2009
+ # Is compiled result valid?
2010
+ good.each {|str| it('should match ' + str.inspect) { rx.should =~ str } }
2011
+ bad.each {|str| it('should NOT match ' + str.inspect) { rx.should_not =~ str } }
2012
+
2013
+
2014
+ end
2015
+
2016
+
2017
+ ### Test 52: Single-bounded repetition (anchored)
2018
+
2019
+ describe "A correct program (Single-bounded repetition (anchored))" do
2020
+ prog = <<-'END'
2021
+ match BOS 5 * "xyz" EOS end
2022
+ END
2023
+
2024
+ good = ["xyzxyzxyzxyzxyz"]
2025
+ bad = ["xyzxyzxyzxyz", "abcxyzxyzxyzxyz", "xyzxyzxyzxyzabc"]
2026
+ wanted = /^(xyz){5}$/
2027
+
2028
+ myprog = Program.new(prog)
2029
+ parsed = nil
2030
+
2031
+ it "should parse correctly" do
2032
+ parsed = myprog.parseable?
2033
+ myprog.debug_bad_program_parse unless parsed
2034
+ parsed.should == true
2035
+ end
2036
+
2037
+ rx = nil
2038
+ it "can be converted to a regex" do
2039
+ rx = myprog.regexp
2040
+ rx.class.should == Regexp
2041
+ end
2042
+
2043
+ # Check sanity: Is test valid?
2044
+ good.each {|str| it('has expected regex matching ' + str.inspect) { wanted.should =~ str } }
2045
+ bad.each {|str| it('has expected regex NOT matching ' + str.inspect) { wanted.should_not =~ str } }
2046
+
2047
+ # Is compiled result valid?
2048
+ good.each {|str| it('should match ' + str.inspect) { rx.should =~ str } }
2049
+ bad.each {|str| it('should NOT match ' + str.inspect) { rx.should_not =~ str } }
2050
+
2051
+
2052
+ end
2053
+
2054
+
2055
+ ### Test 53: Double-bounded repetition (anchored)
2056
+
2057
+ describe "A correct program (Double-bounded repetition (anchored))" do
2058
+ prog = <<-'END'
2059
+ match BOS 3,4 * %alpha EOS end
2060
+ END
2061
+
2062
+ good = ["abc", "abcd"]
2063
+ bad = ["", "ab", "x", "abcde"]
2064
+ wanted = /^([[:alpha:]]){3,4}$/
2065
+
2066
+ myprog = Program.new(prog)
2067
+ parsed = nil
2068
+
2069
+ it "should parse correctly" do
2070
+ parsed = myprog.parseable?
2071
+ myprog.debug_bad_program_parse unless parsed
2072
+ parsed.should == true
2073
+ end
2074
+
2075
+ rx = nil
2076
+ it "can be converted to a regex" do
2077
+ rx = myprog.regexp
2078
+ rx.class.should == Regexp
2079
+ end
2080
+
2081
+ # Check sanity: Is test valid?
2082
+ good.each {|str| it('has expected regex matching ' + str.inspect) { wanted.should =~ str } }
2083
+ bad.each {|str| it('has expected regex NOT matching ' + str.inspect) { wanted.should_not =~ str } }
2084
+
2085
+ # Is compiled result valid?
2086
+ good.each {|str| it('should match ' + str.inspect) { rx.should =~ str } }
2087
+ bad.each {|str| it('should NOT match ' + str.inspect) { rx.should_not =~ str } }
2088
+
2089
+
2090
+ end
2091
+
2092
+
2093
+ ### Test 54: any-qualifier (anchored)
2094
+
2095
+ describe "A correct program (any-qualifier (anchored))" do
2096
+ prog = <<-'END'
2097
+ match BOS any "abc" EOS end
2098
+ END
2099
+
2100
+ good = ["", "abc", "abcabc", "abcabcabc"]
2101
+ bad = ["ab", "abcab", "xyz"]
2102
+ wanted = /^(abc)*$/
2103
+
2104
+ myprog = Program.new(prog)
2105
+ parsed = nil
2106
+
2107
+ it "should parse correctly" do
2108
+ parsed = myprog.parseable?
2109
+ myprog.debug_bad_program_parse unless parsed
2110
+ parsed.should == true
2111
+ end
2112
+
2113
+ rx = nil
2114
+ it "can be converted to a regex" do
2115
+ rx = myprog.regexp
2116
+ rx.class.should == Regexp
2117
+ end
2118
+
2119
+ # Check sanity: Is test valid?
2120
+ good.each {|str| it('has expected regex matching ' + str.inspect) { wanted.should =~ str } }
2121
+ bad.each {|str| it('has expected regex NOT matching ' + str.inspect) { wanted.should_not =~ str } }
2122
+
2123
+ # Is compiled result valid?
2124
+ good.each {|str| it('should match ' + str.inspect) { rx.should =~ str } }
2125
+ bad.each {|str| it('should NOT match ' + str.inspect) { rx.should_not =~ str } }
2126
+
2127
+
2128
+ end
2129
+
2130
+
2131
+ ### Test 55: many-qualifier (anchored)
2132
+
2133
+ describe "A correct program (many-qualifier (anchored))" do
2134
+ prog = <<-'END'
2135
+ match BOS many "def" EOS end
2136
+ END
2137
+
2138
+ good = ["def", "defdef", "defdefdef"]
2139
+ bad = ["", "d", "de", "defd", "xyz"]
2140
+ wanted = /^(def)+$/
2141
+
2142
+ myprog = Program.new(prog)
2143
+ parsed = nil
2144
+
2145
+ it "should parse correctly" do
2146
+ parsed = myprog.parseable?
2147
+ myprog.debug_bad_program_parse unless parsed
2148
+ parsed.should == true
2149
+ end
2150
+
2151
+ rx = nil
2152
+ it "can be converted to a regex" do
2153
+ rx = myprog.regexp
2154
+ rx.class.should == Regexp
2155
+ end
2156
+
2157
+ # Check sanity: Is test valid?
2158
+ good.each {|str| it('has expected regex matching ' + str.inspect) { wanted.should =~ str } }
2159
+ bad.each {|str| it('has expected regex NOT matching ' + str.inspect) { wanted.should_not =~ str } }
2160
+
2161
+ # Is compiled result valid?
2162
+ good.each {|str| it('should match ' + str.inspect) { rx.should =~ str } }
2163
+ bad.each {|str| it('should NOT match ' + str.inspect) { rx.should_not =~ str } }
2164
+
2165
+
2166
+ end
2167
+
2168
+
2169
+ ### Test 56: maybe-qualifier (anchored)
2170
+
2171
+ describe "A correct program (maybe-qualifier (anchored))" do
2172
+ prog = <<-'END'
2173
+ match BOS maybe "ghi" EOS end
2174
+ END
2175
+
2176
+ good = ["", "ghi"]
2177
+ bad = ["abghicd", "gh"]
2178
+ wanted = /^(ghi)?$/
2179
+
2180
+ myprog = Program.new(prog)
2181
+ parsed = nil
2182
+
2183
+ it "should parse correctly" do
2184
+ parsed = myprog.parseable?
2185
+ myprog.debug_bad_program_parse unless parsed
2186
+ parsed.should == true
2187
+ end
2188
+
2189
+ rx = nil
2190
+ it "can be converted to a regex" do
2191
+ rx = myprog.regexp
2192
+ rx.class.should == Regexp
2193
+ end
2194
+
2195
+ # Check sanity: Is test valid?
2196
+ good.each {|str| it('has expected regex matching ' + str.inspect) { wanted.should =~ str } }
2197
+ bad.each {|str| it('has expected regex NOT matching ' + str.inspect) { wanted.should_not =~ str } }
2198
+
2199
+ # Is compiled result valid?
2200
+ good.each {|str| it('should match ' + str.inspect) { rx.should =~ str } }
2201
+ bad.each {|str| it('should NOT match ' + str.inspect) { rx.should_not =~ str } }
2202
+
2203
+
2204
+ end
2205
+
2206
+
2207
+ ### Test 57: Simple concatenation of two strings (anchored)
2208
+
2209
+ describe "A correct program (Simple concatenation of two strings (anchored))" do
2210
+ prog = <<-'END'
2211
+ match BOS "abc" "def" EOS end
2212
+ END
2213
+
2214
+ good = ["abcdef"]
2215
+ bad = ["", "abcd", "xyzabcdef", "abcxyzdef", "abcdefxyz"]
2216
+ wanted = /^abcdef$/
2217
+
2218
+ myprog = Program.new(prog)
2219
+ parsed = nil
2220
+
2221
+ it "should parse correctly" do
2222
+ parsed = myprog.parseable?
2223
+ myprog.debug_bad_program_parse unless parsed
2224
+ parsed.should == true
2225
+ end
2226
+
2227
+ rx = nil
2228
+ it "can be converted to a regex" do
2229
+ rx = myprog.regexp
2230
+ rx.class.should == Regexp
2231
+ end
2232
+
2233
+ # Check sanity: Is test valid?
2234
+ good.each {|str| it('has expected regex matching ' + str.inspect) { wanted.should =~ str } }
2235
+ bad.each {|str| it('has expected regex NOT matching ' + str.inspect) { wanted.should_not =~ str } }
2236
+
2237
+ # Is compiled result valid?
2238
+ good.each {|str| it('should match ' + str.inspect) { rx.should =~ str } }
2239
+ bad.each {|str| it('should NOT match ' + str.inspect) { rx.should_not =~ str } }
2240
+
2241
+
2242
+ end
2243
+
2244
+
2245
+ ### Test 58: Concat of string and char class (anchored)
2246
+
2247
+ describe "A correct program (Concat of string and char class (anchored))" do
2248
+ prog = <<-'END'
2249
+ match BOS "abc" 'def' EOS end
2250
+ END
2251
+
2252
+ good = ["abcd", "abce", "abcf"]
2253
+ bad = ["", "ab", "abc", "abcx"]
2254
+ wanted = /^abc[def]$/
2255
+
2256
+ myprog = Program.new(prog)
2257
+ parsed = nil
2258
+
2259
+ it "should parse correctly" do
2260
+ parsed = myprog.parseable?
2261
+ myprog.debug_bad_program_parse unless parsed
2262
+ parsed.should == true
2263
+ end
2264
+
2265
+ rx = nil
2266
+ it "can be converted to a regex" do
2267
+ rx = myprog.regexp
2268
+ rx.class.should == Regexp
2269
+ end
2270
+
2271
+ # Check sanity: Is test valid?
2272
+ good.each {|str| it('has expected regex matching ' + str.inspect) { wanted.should =~ str } }
2273
+ bad.each {|str| it('has expected regex NOT matching ' + str.inspect) { wanted.should_not =~ str } }
2274
+
2275
+ # Is compiled result valid?
2276
+ good.each {|str| it('should match ' + str.inspect) { rx.should =~ str } }
2277
+ bad.each {|str| it('should NOT match ' + str.inspect) { rx.should_not =~ str } }
2278
+
2279
+
2280
+ end
2281
+
2282
+
2283
+ ### Test 59: Simple alternation (anchored)
2284
+
2285
+ describe "A correct program (Simple alternation (anchored))" do
2286
+ prog = <<-'END'
2287
+ match BOS ("abc" | "def") EOS end
2288
+ END
2289
+
2290
+ good = ["abc", "def"]
2291
+ bad = ["", "abde", "ab c d ef", "xdefy"]
2292
+ wanted = /^(abc|def)$/
2293
+
2294
+ myprog = Program.new(prog)
2295
+ parsed = nil
2296
+
2297
+ it "should parse correctly" do
2298
+ parsed = myprog.parseable?
2299
+ myprog.debug_bad_program_parse unless parsed
2300
+ parsed.should == true
2301
+ end
2302
+
2303
+ rx = nil
2304
+ it "can be converted to a regex" do
2305
+ rx = myprog.regexp
2306
+ rx.class.should == Regexp
2307
+ end
2308
+
2309
+ # Check sanity: Is test valid?
2310
+ good.each {|str| it('has expected regex matching ' + str.inspect) { wanted.should =~ str } }
2311
+ bad.each {|str| it('has expected regex NOT matching ' + str.inspect) { wanted.should_not =~ str } }
2312
+
2313
+ # Is compiled result valid?
2314
+ good.each {|str| it('should match ' + str.inspect) { rx.should =~ str } }
2315
+ bad.each {|str| it('should NOT match ' + str.inspect) { rx.should_not =~ str } }
2316
+
2317
+
2318
+ end
2319
+
2320
+
2321
+ ### Test 60: Alternation of concatenations (anchored)
2322
+
2323
+ describe "A correct program (Alternation of concatenations (anchored))" do
2324
+ prog = <<-'END'
2325
+ match BOS ("ab" "c" | "d" "ef") EOS end
2326
+ END
2327
+
2328
+ good = ["abc", "def"]
2329
+ bad = ["", "abde", "ab c d ef", "xdefy"]
2330
+ wanted = /^(abc|def)$/
2331
+
2332
+ myprog = Program.new(prog)
2333
+ parsed = nil
2334
+
2335
+ it "should parse correctly" do
2336
+ parsed = myprog.parseable?
2337
+ myprog.debug_bad_program_parse unless parsed
2338
+ parsed.should == true
2339
+ end
2340
+
2341
+ rx = nil
2342
+ it "can be converted to a regex" do
2343
+ rx = myprog.regexp
2344
+ rx.class.should == Regexp
2345
+ end
2346
+
2347
+ # Check sanity: Is test valid?
2348
+ good.each {|str| it('has expected regex matching ' + str.inspect) { wanted.should =~ str } }
2349
+ bad.each {|str| it('has expected regex NOT matching ' + str.inspect) { wanted.should_not =~ str } }
2350
+
2351
+ # Is compiled result valid?
2352
+ good.each {|str| it('should match ' + str.inspect) { rx.should =~ str } }
2353
+ bad.each {|str| it('should NOT match ' + str.inspect) { rx.should_not =~ str } }
2354
+
2355
+
2356
+ end
2357
+
2358
+
2359
+ ### Test 61: Precedence of concatenation over alternation (anchored)
2360
+
2361
+ describe "A correct program (Precedence of concatenation over alternation (anchored))" do
2362
+ prog = <<-'END'
2363
+ match BOS ("a" "b" | "c") EOS end
2364
+ END
2365
+
2366
+ good = ["ab", "c"]
2367
+ bad = ["", "b", "a", "d", "abc", "abcde"]
2368
+ wanted = /^(ab|c)$/
2369
+
2370
+ myprog = Program.new(prog)
2371
+ parsed = nil
2372
+
2373
+ it "should parse correctly" do
2374
+ parsed = myprog.parseable?
2375
+ myprog.debug_bad_program_parse unless parsed
2376
+ parsed.should == true
2377
+ end
2378
+
2379
+ rx = nil
2380
+ it "can be converted to a regex" do
2381
+ rx = myprog.regexp
2382
+ rx.class.should == Regexp
2383
+ end
2384
+
2385
+ # Check sanity: Is test valid?
2386
+ good.each {|str| it('has expected regex matching ' + str.inspect) { wanted.should =~ str } }
2387
+ bad.each {|str| it('has expected regex NOT matching ' + str.inspect) { wanted.should_not =~ str } }
2388
+
2389
+ # Is compiled result valid?
2390
+ good.each {|str| it('should match ' + str.inspect) { rx.should =~ str } }
2391
+ bad.each {|str| it('should NOT match ' + str.inspect) { rx.should_not =~ str } }
2392
+
2393
+
2394
+ end
2395
+
2396
+
2397
+ ### Test 62: Precedence of parens over concatenation (anchored)
2398
+
2399
+ describe "A correct program (Precedence of parens over concatenation (anchored))" do
2400
+ prog = <<-'END'
2401
+ match BOS "a" ("b" | "c") EOS end
2402
+ END
2403
+
2404
+ good = ["ab", "ac"]
2405
+ bad = ["a", "b", "c", "abc", "abx", "bac"]
2406
+ wanted = /^a(b|c)$/
2407
+
2408
+ myprog = Program.new(prog)
2409
+ parsed = nil
2410
+
2411
+ it "should parse correctly" do
2412
+ parsed = myprog.parseable?
2413
+ myprog.debug_bad_program_parse unless parsed
2414
+ parsed.should == true
2415
+ end
2416
+
2417
+ rx = nil
2418
+ it "can be converted to a regex" do
2419
+ rx = myprog.regexp
2420
+ rx.class.should == Regexp
2421
+ end
2422
+
2423
+ # Check sanity: Is test valid?
2424
+ good.each {|str| it('has expected regex matching ' + str.inspect) { wanted.should =~ str } }
2425
+ bad.each {|str| it('has expected regex NOT matching ' + str.inspect) { wanted.should_not =~ str } }
2426
+
2427
+ # Is compiled result valid?
2428
+ good.each {|str| it('should match ' + str.inspect) { rx.should =~ str } }
2429
+ bad.each {|str| it('should NOT match ' + str.inspect) { rx.should_not =~ str } }
2430
+
2431
+
2432
+ end
2433
+
2434
+
2435
+ ### Test 63: Anchors and alternation (anchored)
2436
+
2437
+ describe "A correct program (Anchors and alternation (anchored))" do
2438
+ prog = <<-'END'
2439
+ match BOS "x" | "y" EOS end
2440
+ END
2441
+
2442
+ good = ["xabc", "abcy"]
2443
+ bad = ["abc", "abcx", "yabc", "axb", "ayb", "axyb"]
2444
+ wanted = /(^x|y$)/
2445
+
2446
+ myprog = Program.new(prog)
2447
+ parsed = nil
2448
+
2449
+ it "should parse correctly" do
2450
+ parsed = myprog.parseable?
2451
+ myprog.debug_bad_program_parse unless parsed
2452
+ parsed.should == true
2453
+ end
2454
+
2455
+ rx = nil
2456
+ it "can be converted to a regex" do
2457
+ rx = myprog.regexp
2458
+ rx.class.should == Regexp
2459
+ end
2460
+
2461
+ # Check sanity: Is test valid?
2462
+ good.each {|str| it('has expected regex matching ' + str.inspect) { wanted.should =~ str } }
2463
+ bad.each {|str| it('has expected regex NOT matching ' + str.inspect) { wanted.should_not =~ str } }
2464
+
2465
+ # Is compiled result valid?
2466
+ good.each {|str| it('should match ' + str.inspect) { rx.should =~ str } }
2467
+ bad.each {|str| it('should NOT match ' + str.inspect) { rx.should_not =~ str } }
2468
+
2469
+
2470
+ end
2471
+
2472
+
2473
+ ### Test 64: Parens, concatenation, alternation (anchored)
2474
+
2475
+ describe "A correct program (Parens, concatenation, alternation (anchored))" do
2476
+ prog = <<-'END'
2477
+ match BOS ((maybe `0) `1-`9 | `1 D2) EOS end
2478
+ END
2479
+
2480
+ good = ["01", "09", "12"]
2481
+ bad = ["0", "00", "13"]
2482
+ wanted = /^((0)?[1-9]|1[0-2])$/
2483
+
2484
+ myprog = Program.new(prog)
2485
+ parsed = nil
2486
+
2487
+ it "should parse correctly" do
2488
+ parsed = myprog.parseable?
2489
+ myprog.debug_bad_program_parse unless parsed
2490
+ parsed.should == true
2491
+ end
2492
+
2493
+ rx = nil
2494
+ it "can be converted to a regex" do
2495
+ rx = myprog.regexp
2496
+ rx.class.should == Regexp
2497
+ end
2498
+
2499
+ # Check sanity: Is test valid?
2500
+ good.each {|str| it('has expected regex matching ' + str.inspect) { wanted.should =~ str } }
2501
+ bad.each {|str| it('has expected regex NOT matching ' + str.inspect) { wanted.should_not =~ str } }
2502
+
2503
+ # Is compiled result valid?
2504
+ good.each {|str| it('should match ' + str.inspect) { rx.should =~ str } }
2505
+ bad.each {|str| it('should NOT match ' + str.inspect) { rx.should_not =~ str } }
2506
+
2507
+
2508
+ end
2509
+
2510
+
2511
+ ### Test 65: Single backtick char (anchored)
2512
+
2513
+ describe "A correct program (Single backtick char (anchored))" do
2514
+ prog = <<-'END'
2515
+ match BOS `` EOS end
2516
+ END
2517
+
2518
+ good = ["`"]
2519
+ bad = ["", "abc", "this is a tick: `", "tock ` tock"]
2520
+ wanted = /^`$/
2521
+
2522
+ myprog = Program.new(prog)
2523
+ parsed = nil
2524
+
2525
+ it "should parse correctly" do
2526
+ parsed = myprog.parseable?
2527
+ myprog.debug_bad_program_parse unless parsed
2528
+ parsed.should == true
2529
+ end
2530
+
2531
+ rx = nil
2532
+ it "can be converted to a regex" do
2533
+ rx = myprog.regexp
2534
+ rx.class.should == Regexp
2535
+ end
2536
+
2537
+ # Check sanity: Is test valid?
2538
+ good.each {|str| it('has expected regex matching ' + str.inspect) { wanted.should =~ str } }
2539
+ bad.each {|str| it('has expected regex NOT matching ' + str.inspect) { wanted.should_not =~ str } }
2540
+
2541
+ # Is compiled result valid?
2542
+ good.each {|str| it('should match ' + str.inspect) { rx.should =~ str } }
2543
+ bad.each {|str| it('should NOT match ' + str.inspect) { rx.should_not =~ str } }
2544
+
2545
+
2546
+ end
2547
+
2548
+
2549
+ ### Test 66: Single backslash char (anchored)
2550
+
2551
+ describe "A correct program (Single backslash char (anchored))" do
2552
+ prog = <<-'END'
2553
+ match BOS `\ EOS end
2554
+ END
2555
+
2556
+ good = ["\\"]
2557
+ bad = ["\n", "\b", "neither \r nor \t", "trying \\n", "and \\b also"]
2558
+ wanted = /^\\$/
2559
+
2560
+ myprog = Program.new(prog)
2561
+ parsed = nil
2562
+
2563
+ it "should parse correctly" do
2564
+ parsed = myprog.parseable?
2565
+ myprog.debug_bad_program_parse unless parsed
2566
+ parsed.should == true
2567
+ end
2568
+
2569
+ rx = nil
2570
+ it "can be converted to a regex" do
2571
+ rx = myprog.regexp
2572
+ rx.class.should == Regexp
2573
+ end
2574
+
2575
+ # Check sanity: Is test valid?
2576
+ good.each {|str| it('has expected regex matching ' + str.inspect) { wanted.should =~ str } }
2577
+ bad.each {|str| it('has expected regex NOT matching ' + str.inspect) { wanted.should_not =~ str } }
2578
+
2579
+ # Is compiled result valid?
2580
+ good.each {|str| it('should match ' + str.inspect) { rx.should =~ str } }
2581
+ bad.each {|str| it('should NOT match ' + str.inspect) { rx.should_not =~ str } }
2582
+
2583
+
2584
+ end
2585
+
2586
+
2587
+ ### Test 67: Empty string (anchored)
2588
+
2589
+ describe "A correct program (Empty string (anchored))" do
2590
+ prog = <<-'END'
2591
+ match BOS "" EOS end
2592
+ END
2593
+
2594
+ good = [""]
2595
+ bad = ["abc"]
2596
+ wanted = /^$/
2597
+
2598
+ myprog = Program.new(prog)
2599
+ parsed = nil
2600
+
2601
+ it "should parse correctly" do
2602
+ parsed = myprog.parseable?
2603
+ myprog.debug_bad_program_parse unless parsed
2604
+ parsed.should == true
2605
+ end
2606
+
2607
+ rx = nil
2608
+ it "can be converted to a regex" do
2609
+ rx = myprog.regexp
2610
+ rx.class.should == Regexp
2611
+ end
2612
+
2613
+ # Check sanity: Is test valid?
2614
+ good.each {|str| it('has expected regex matching ' + str.inspect) { wanted.should =~ str } }
2615
+ bad.each {|str| it('has expected regex NOT matching ' + str.inspect) { wanted.should_not =~ str } }
2616
+
2617
+ # Is compiled result valid?
2618
+ good.each {|str| it('should match ' + str.inspect) { rx.should =~ str } }
2619
+ bad.each {|str| it('should NOT match ' + str.inspect) { rx.should_not =~ str } }
2620
+
2621
+
2622
+ end
2623
+
2624
+
2625
+ ### Test 68: Simple one-char class (anchored)
2626
+
2627
+ describe "A correct program (Simple one-char class (anchored))" do
2628
+ prog = <<-'END'
2629
+ match BOS 'x' EOS end
2630
+ END
2631
+
2632
+ good = ["x"]
2633
+ bad = ["", "abc", "uvwxyz"]
2634
+ wanted = /^[x]$/
2635
+
2636
+ myprog = Program.new(prog)
2637
+ parsed = nil
2638
+
2639
+ it "should parse correctly" do
2640
+ parsed = myprog.parseable?
2641
+ myprog.debug_bad_program_parse unless parsed
2642
+ parsed.should == true
2643
+ end
2644
+
2645
+ rx = nil
2646
+ it "can be converted to a regex" do
2647
+ rx = myprog.regexp
2648
+ rx.class.should == Regexp
2649
+ end
2650
+
2651
+ # Check sanity: Is test valid?
2652
+ good.each {|str| it('has expected regex matching ' + str.inspect) { wanted.should =~ str } }
2653
+ bad.each {|str| it('has expected regex NOT matching ' + str.inspect) { wanted.should_not =~ str } }
2654
+
2655
+ # Is compiled result valid?
2656
+ good.each {|str| it('should match ' + str.inspect) { rx.should =~ str } }
2657
+ bad.each {|str| it('should NOT match ' + str.inspect) { rx.should_not =~ str } }
2658
+
2659
+
2660
+ end
2661
+
2662
+
2663
+ ### Test 69: Alternation of range and class (anchored)
2664
+
2665
+ describe "A correct program (Alternation of range and class (anchored))" do
2666
+ prog = <<-'END'
2667
+ match BOS (`a-`f | 'xyz') EOS end
2668
+ END
2669
+
2670
+ good = ["a", "x", "z", "c"]
2671
+ bad = ["", "ab", "abc", "xy", "jkl", "gw"]
2672
+ wanted = /^([a-f]|[xyz])$/
2673
+
2674
+ myprog = Program.new(prog)
2675
+ parsed = nil
2676
+
2677
+ it "should parse correctly" do
2678
+ parsed = myprog.parseable?
2679
+ myprog.debug_bad_program_parse unless parsed
2680
+ parsed.should == true
2681
+ end
2682
+
2683
+ rx = nil
2684
+ it "can be converted to a regex" do
2685
+ rx = myprog.regexp
2686
+ rx.class.should == Regexp
2687
+ end
2688
+
2689
+ # Check sanity: Is test valid?
2690
+ good.each {|str| it('has expected regex matching ' + str.inspect) { wanted.should =~ str } }
2691
+ bad.each {|str| it('has expected regex NOT matching ' + str.inspect) { wanted.should_not =~ str } }
2692
+
2693
+ # Is compiled result valid?
2694
+ good.each {|str| it('should match ' + str.inspect) { rx.should =~ str } }
2695
+ bad.each {|str| it('should NOT match ' + str.inspect) { rx.should_not =~ str } }
2696
+
2697
+
2698
+ end
2699
+
2700
+
2701
+ ### Test 70: Alternation of range and maybe-clause (anchored)
2702
+
2703
+ describe "A correct program (Alternation of range and maybe-clause (anchored))" do
2704
+ prog = <<-'END'
2705
+ match BOS (`1-`6| maybe "#") EOS end
2706
+ END
2707
+
2708
+ good = ["", "1", "#", "6"]
2709
+ bad = ["55", "###"]
2710
+ wanted = /^([1-6]|(\#)?)$/
2711
+
2712
+ myprog = Program.new(prog)
2713
+ parsed = nil
2714
+
2715
+ it "should parse correctly" do
2716
+ parsed = myprog.parseable?
2717
+ myprog.debug_bad_program_parse unless parsed
2718
+ parsed.should == true
2719
+ end
2720
+
2721
+ rx = nil
2722
+ it "can be converted to a regex" do
2723
+ rx = myprog.regexp
2724
+ rx.class.should == Regexp
2725
+ end
2726
+
2727
+ # Check sanity: Is test valid?
2728
+ good.each {|str| it('has expected regex matching ' + str.inspect) { wanted.should =~ str } }
2729
+ bad.each {|str| it('has expected regex NOT matching ' + str.inspect) { wanted.should_not =~ str } }
2730
+
2731
+ # Is compiled result valid?
2732
+ good.each {|str| it('should match ' + str.inspect) { rx.should =~ str } }
2733
+ bad.each {|str| it('should NOT match ' + str.inspect) { rx.should_not =~ str } }
2734
+
2735
+
2736
+ end
2737
+
2738
+
2739
+ ### Test 71: Four-way alternation (anchored)
2740
+
2741
+ describe "A correct program (Four-way alternation (anchored))" do
2742
+ prog = <<-'END'
2743
+ match BOS (`a | `b|`c|`d) EOS end
2744
+ END
2745
+
2746
+ good = ["a", "b", "c", "d"]
2747
+ bad = ["", "ab", "every", "ghijk"]
2748
+ wanted = /^(a|b|c|d)$/
2749
+
2750
+ myprog = Program.new(prog)
2751
+ parsed = nil
2752
+
2753
+ it "should parse correctly" do
2754
+ parsed = myprog.parseable?
2755
+ myprog.debug_bad_program_parse unless parsed
2756
+ parsed.should == true
2757
+ end
2758
+
2759
+ rx = nil
2760
+ it "can be converted to a regex" do
2761
+ rx = myprog.regexp
2762
+ rx.class.should == Regexp
2763
+ end
2764
+
2765
+ # Check sanity: Is test valid?
2766
+ good.each {|str| it('has expected regex matching ' + str.inspect) { wanted.should =~ str } }
2767
+ bad.each {|str| it('has expected regex NOT matching ' + str.inspect) { wanted.should_not =~ str } }
2768
+
2769
+ # Is compiled result valid?
2770
+ good.each {|str| it('should match ' + str.inspect) { rx.should =~ str } }
2771
+ bad.each {|str| it('should NOT match ' + str.inspect) { rx.should_not =~ str } }
2772
+
2773
+
2774
+ end
2775
+
2776
+
2777
+ ### Test 72: Concatenation of range and class (anchored)
2778
+
2779
+ describe "A correct program (Concatenation of range and class (anchored))" do
2780
+ prog = <<-'END'
2781
+ match BOS `a-`f 'xyz' EOS end
2782
+ END
2783
+
2784
+ good = ["ax", "fz", "cy"]
2785
+ bad = ["axe", "fz123", "zf", "xa", "gz", "hp", "mx"]
2786
+ wanted = /^[a-f][xyz]$/
2787
+
2788
+ myprog = Program.new(prog)
2789
+ parsed = nil
2790
+
2791
+ it "should parse correctly" do
2792
+ parsed = myprog.parseable?
2793
+ myprog.debug_bad_program_parse unless parsed
2794
+ parsed.should == true
2795
+ end
2796
+
2797
+ rx = nil
2798
+ it "can be converted to a regex" do
2799
+ rx = myprog.regexp
2800
+ rx.class.should == Regexp
2801
+ end
2802
+
2803
+ # Check sanity: Is test valid?
2804
+ good.each {|str| it('has expected regex matching ' + str.inspect) { wanted.should =~ str } }
2805
+ bad.each {|str| it('has expected regex NOT matching ' + str.inspect) { wanted.should_not =~ str } }
2806
+
2807
+ # Is compiled result valid?
2808
+ good.each {|str| it('should match ' + str.inspect) { rx.should =~ str } }
2809
+ bad.each {|str| it('should NOT match ' + str.inspect) { rx.should_not =~ str } }
2810
+
2811
+
2812
+ end
2813
+
2814
+
2815
+ ### Test 73: Concat of strings and maybe-clause (anchored)
2816
+
2817
+ describe "A correct program (Concat of strings and maybe-clause (anchored))" do
2818
+ prog = <<-'END'
2819
+ match BOS "this" "that" maybe "other" EOS end
2820
+ END
2821
+
2822
+ good = ["thisthat", "thisthatother"]
2823
+ bad = ["", "abc", "this that", "this that other", "abc thisthat xyz", "abc thisthatother xyz"]
2824
+ wanted = /^thisthat(other)?$/
2825
+
2826
+ myprog = Program.new(prog)
2827
+ parsed = nil
2828
+
2829
+ it "should parse correctly" do
2830
+ parsed = myprog.parseable?
2831
+ myprog.debug_bad_program_parse unless parsed
2832
+ parsed.should == true
2833
+ end
2834
+
2835
+ rx = nil
2836
+ it "can be converted to a regex" do
2837
+ rx = myprog.regexp
2838
+ rx.class.should == Regexp
2839
+ end
2840
+
2841
+ # Check sanity: Is test valid?
2842
+ good.each {|str| it('has expected regex matching ' + str.inspect) { wanted.should =~ str } }
2843
+ bad.each {|str| it('has expected regex NOT matching ' + str.inspect) { wanted.should_not =~ str } }
2844
+
2845
+ # Is compiled result valid?
2846
+ good.each {|str| it('should match ' + str.inspect) { rx.should =~ str } }
2847
+ bad.each {|str| it('should NOT match ' + str.inspect) { rx.should_not =~ str } }
2848
+
2849
+
2850
+ end
2851
+
2852
+
2853
+ ### Test 74: Simple repetition of class (anchored)
2854
+
2855
+ describe "A correct program (Simple repetition of class (anchored))" do
2856
+ prog = <<-'END'
2857
+ match BOS 3 * 'xyz' EOS end
2858
+ END
2859
+
2860
+ good = ["xyz", "xxx", "yzy"]
2861
+ bad = ["", "abc", "xy", "axy", "xyb", "axyb", "xyzzy123"]
2862
+ wanted = /^([xyz]){3}$/
2863
+
2864
+ myprog = Program.new(prog)
2865
+ parsed = nil
2866
+
2867
+ it "should parse correctly" do
2868
+ parsed = myprog.parseable?
2869
+ myprog.debug_bad_program_parse unless parsed
2870
+ parsed.should == true
2871
+ end
2872
+
2873
+ rx = nil
2874
+ it "can be converted to a regex" do
2875
+ rx = myprog.regexp
2876
+ rx.class.should == Regexp
2877
+ end
2878
+
2879
+ # Check sanity: Is test valid?
2880
+ good.each {|str| it('has expected regex matching ' + str.inspect) { wanted.should =~ str } }
2881
+ bad.each {|str| it('has expected regex NOT matching ' + str.inspect) { wanted.should_not =~ str } }
2882
+
2883
+ # Is compiled result valid?
2884
+ good.each {|str| it('should match ' + str.inspect) { rx.should =~ str } }
2885
+ bad.each {|str| it('should NOT match ' + str.inspect) { rx.should_not =~ str } }
2886
+
2887
+
2888
+ end
2889
+
2890
+
2891
+ ### Test 75: Simple repetition of range (anchored)
2892
+
2893
+ describe "A correct program (Simple repetition of range (anchored))" do
2894
+ prog = <<-'END'
2895
+ match BOS 4 * `1-`6 EOS end
2896
+ END
2897
+
2898
+ good = ["1111", "1234"]
2899
+ bad = ["", "abc", "123", "123 4", "abc 6543 def"]
2900
+ wanted = /^([1-6]){4}$/
2901
+
2902
+ myprog = Program.new(prog)
2903
+ parsed = nil
2904
+
2905
+ it "should parse correctly" do
2906
+ parsed = myprog.parseable?
2907
+ myprog.debug_bad_program_parse unless parsed
2908
+ parsed.should == true
2909
+ end
2910
+
2911
+ rx = nil
2912
+ it "can be converted to a regex" do
2913
+ rx = myprog.regexp
2914
+ rx.class.should == Regexp
2915
+ end
2916
+
2917
+ # Check sanity: Is test valid?
2918
+ good.each {|str| it('has expected regex matching ' + str.inspect) { wanted.should =~ str } }
2919
+ bad.each {|str| it('has expected regex NOT matching ' + str.inspect) { wanted.should_not =~ str } }
2920
+
2921
+ # Is compiled result valid?
2922
+ good.each {|str| it('should match ' + str.inspect) { rx.should =~ str } }
2923
+ bad.each {|str| it('should NOT match ' + str.inspect) { rx.should_not =~ str } }
2924
+
2925
+
2926
+ end
2927
+
2928
+
2929
+ ### Test 76: Complex repetition of char (anchored)
2930
+
2931
+ describe "A correct program (Complex repetition of char (anchored))" do
2932
+ prog = <<-'END'
2933
+ match BOS 3,5 * (`a) EOS end
2934
+ END
2935
+
2936
+ good = ["aaa", "aaaa", "aaaaa"]
2937
+ bad = ["", "abc", "aa", "xaaay", "aaaaaaa"]
2938
+ wanted = /^(a){3,5}$/
2939
+
2940
+ myprog = Program.new(prog)
2941
+ parsed = nil
2942
+
2943
+ it "should parse correctly" do
2944
+ parsed = myprog.parseable?
2945
+ myprog.debug_bad_program_parse unless parsed
2946
+ parsed.should == true
2947
+ end
2948
+
2949
+ rx = nil
2950
+ it "can be converted to a regex" do
2951
+ rx = myprog.regexp
2952
+ rx.class.should == Regexp
2953
+ end
2954
+
2955
+ # Check sanity: Is test valid?
2956
+ good.each {|str| it('has expected regex matching ' + str.inspect) { wanted.should =~ str } }
2957
+ bad.each {|str| it('has expected regex NOT matching ' + str.inspect) { wanted.should_not =~ str } }
2958
+
2959
+ # Is compiled result valid?
2960
+ good.each {|str| it('should match ' + str.inspect) { rx.should =~ str } }
2961
+ bad.each {|str| it('should NOT match ' + str.inspect) { rx.should_not =~ str } }
2962
+
2963
+
2964
+ end
2965
+
2966
+
2967
+ ### Test 77: Complex repetition of parenthesized class (anchored)
2968
+
2969
+ describe "A correct program (Complex repetition of parenthesized class (anchored))" do
2970
+ prog = <<-'END'
2971
+ match BOS 4,7 * ('xyz') EOS end
2972
+ END
2973
+
2974
+ good = ["xxxx", "yyyy", "xyzy", "xyzzy", "xyzxyz", "xyzxyzx"]
2975
+ bad = ["", "abc", "x", "xx", "xxx", "xyz xy", "xyzxyzxyzxyz", "zyzzyva"]
2976
+ wanted = /^([xyz]){4,7}$/
2977
+
2978
+ myprog = Program.new(prog)
2979
+ parsed = nil
2980
+
2981
+ it "should parse correctly" do
2982
+ parsed = myprog.parseable?
2983
+ myprog.debug_bad_program_parse unless parsed
2984
+ parsed.should == true
2985
+ end
2986
+
2987
+ rx = nil
2988
+ it "can be converted to a regex" do
2989
+ rx = myprog.regexp
2990
+ rx.class.should == Regexp
2991
+ end
2992
+
2993
+ # Check sanity: Is test valid?
2994
+ good.each {|str| it('has expected regex matching ' + str.inspect) { wanted.should =~ str } }
2995
+ bad.each {|str| it('has expected regex NOT matching ' + str.inspect) { wanted.should_not =~ str } }
2996
+
2997
+ # Is compiled result valid?
2998
+ good.each {|str| it('should match ' + str.inspect) { rx.should =~ str } }
2999
+ bad.each {|str| it('should NOT match ' + str.inspect) { rx.should_not =~ str } }
3000
+
3001
+
3002
+ end
3003
+
3004
+
3005
+ ### Test 78: Complex repetition of parenthesized range (anchored)
3006
+
3007
+ describe "A correct program (Complex repetition of parenthesized range (anchored))" do
3008
+ prog = <<-'END'
3009
+ match BOS 0,3 * (`1-`6) EOS end
3010
+ END
3011
+
3012
+ good = ["", "1", "11", "111", "56", "654"]
3013
+ bad = ["1111", "x123y", "x123456y"]
3014
+ wanted = /^([1-6]){0,3}$/
3015
+
3016
+ myprog = Program.new(prog)
3017
+ parsed = nil
3018
+
3019
+ it "should parse correctly" do
3020
+ parsed = myprog.parseable?
3021
+ myprog.debug_bad_program_parse unless parsed
3022
+ parsed.should == true
3023
+ end
3024
+
3025
+ rx = nil
3026
+ it "can be converted to a regex" do
3027
+ rx = myprog.regexp
3028
+ rx.class.should == Regexp
3029
+ end
3030
+
3031
+ # Check sanity: Is test valid?
3032
+ good.each {|str| it('has expected regex matching ' + str.inspect) { wanted.should =~ str } }
3033
+ bad.each {|str| it('has expected regex NOT matching ' + str.inspect) { wanted.should_not =~ str } }
3034
+
3035
+ # Is compiled result valid?
3036
+ good.each {|str| it('should match ' + str.inspect) { rx.should =~ str } }
3037
+ bad.each {|str| it('should NOT match ' + str.inspect) { rx.should_not =~ str } }
3038
+
3039
+
3040
+ end
3041
+
3042
+
3043
+ ### Test 79: Simple lookaround (pos-ahead)
3044
+
3045
+ describe "A correct program (Simple lookaround (pos-ahead))" do
3046
+ prog = <<-'END'
3047
+ match find "X" with "Y" end
3048
+ END
3049
+
3050
+ good = ["XY"]
3051
+ bad = ["X", "Y", "YX"]
3052
+ wanted = /(?=XY)X/
3053
+
3054
+ myprog = Program.new(prog)
3055
+ parsed = nil
3056
+
3057
+ it "should parse correctly" do
3058
+ parsed = myprog.parseable?
3059
+ myprog.debug_bad_program_parse unless parsed
3060
+ parsed.should == true
3061
+ end
3062
+
3063
+ rx = nil
3064
+ it "can be converted to a regex" do
3065
+ rx = myprog.regexp
3066
+ rx.class.should == Regexp
3067
+ end
3068
+
3069
+ # Check sanity: Is test valid?
3070
+ good.each {|str| it('has expected regex matching ' + str.inspect) { wanted.should =~ str } }
3071
+ bad.each {|str| it('has expected regex NOT matching ' + str.inspect) { wanted.should_not =~ str } }
3072
+
3073
+ # Is compiled result valid?
3074
+ good.each {|str| it('should match ' + str.inspect) { rx.should =~ str } }
3075
+ bad.each {|str| it('should NOT match ' + str.inspect) { rx.should_not =~ str } }
3076
+
3077
+
3078
+ end
3079
+
3080
+
3081
+ ### Test 80: Simple lookaround (neg-ahead)
3082
+
3083
+ describe "A correct program (Simple lookaround (neg-ahead))" do
3084
+ prog = <<-'END'
3085
+ match find "X" without "Y" end
3086
+ END
3087
+
3088
+ good = ["X", "YX"]
3089
+ bad = ["XY", "Y"]
3090
+ wanted = /(?!XY)X/
3091
+
3092
+ myprog = Program.new(prog)
3093
+ parsed = nil
3094
+
3095
+ it "should parse correctly" do
3096
+ parsed = myprog.parseable?
3097
+ myprog.debug_bad_program_parse unless parsed
3098
+ parsed.should == true
3099
+ end
3100
+
3101
+ rx = nil
3102
+ it "can be converted to a regex" do
3103
+ rx = myprog.regexp
3104
+ rx.class.should == Regexp
3105
+ end
3106
+
3107
+ # Check sanity: Is test valid?
3108
+ good.each {|str| it('has expected regex matching ' + str.inspect) { wanted.should =~ str } }
3109
+ bad.each {|str| it('has expected regex NOT matching ' + str.inspect) { wanted.should_not =~ str } }
3110
+
3111
+ # Is compiled result valid?
3112
+ good.each {|str| it('should match ' + str.inspect) { rx.should =~ str } }
3113
+ bad.each {|str| it('should NOT match ' + str.inspect) { rx.should_not =~ str } }
3114
+
3115
+
3116
+ end
3117
+
3118
+
3119
+ ### Test 81: Simple lookaround (pos-behind)
3120
+
3121
+ describe "A correct program (Simple lookaround (pos-behind))" do
3122
+ prog = <<-'END'
3123
+ match with "X" find "Y" end
3124
+ END
3125
+
3126
+ good = ["XY"]
3127
+ bad = ["YX", "Y", "X"]
3128
+ wanted = /(?<=X)Y/
3129
+
3130
+ myprog = Program.new(prog)
3131
+ parsed = nil
3132
+
3133
+ it "should parse correctly" do
3134
+ parsed = myprog.parseable?
3135
+ myprog.debug_bad_program_parse unless parsed
3136
+ parsed.should == true
3137
+ end
3138
+
3139
+ rx = nil
3140
+ it "can be converted to a regex" do
3141
+ rx = myprog.regexp
3142
+ rx.class.should == Regexp
3143
+ end
3144
+
3145
+ # Check sanity: Is test valid?
3146
+ good.each {|str| it('has expected regex matching ' + str.inspect) { wanted.should =~ str } }
3147
+ bad.each {|str| it('has expected regex NOT matching ' + str.inspect) { wanted.should_not =~ str } }
3148
+
3149
+ # Is compiled result valid?
3150
+ good.each {|str| it('should match ' + str.inspect) { rx.should =~ str } }
3151
+ bad.each {|str| it('should NOT match ' + str.inspect) { rx.should_not =~ str } }
3152
+
3153
+
3154
+ end
3155
+
3156
+
3157
+ ### Test 82: Simple lookaround (neg-behind)
3158
+
3159
+ describe "A correct program (Simple lookaround (neg-behind))" do
3160
+ prog = <<-'END'
3161
+ match without "X" find "Y" end
3162
+ END
3163
+
3164
+ good = ["aY", "Y"]
3165
+ bad = ["XY", "X"]
3166
+ wanted = /(?<!X)Y/
3167
+
3168
+ myprog = Program.new(prog)
3169
+ parsed = nil
3170
+
3171
+ it "should parse correctly" do
3172
+ parsed = myprog.parseable?
3173
+ myprog.debug_bad_program_parse unless parsed
3174
+ parsed.should == true
3175
+ end
3176
+
3177
+ rx = nil
3178
+ it "can be converted to a regex" do
3179
+ rx = myprog.regexp
3180
+ rx.class.should == Regexp
3181
+ end
3182
+
3183
+ # Check sanity: Is test valid?
3184
+ good.each {|str| it('has expected regex matching ' + str.inspect) { wanted.should =~ str } }
3185
+ bad.each {|str| it('has expected regex NOT matching ' + str.inspect) { wanted.should_not =~ str } }
3186
+
3187
+ # Is compiled result valid?
3188
+ good.each {|str| it('should match ' + str.inspect) { rx.should =~ str } }
3189
+ bad.each {|str| it('should NOT match ' + str.inspect) { rx.should_not =~ str } }
3190
+
3191
+
3192
+ end
3193
+
3194
+
3195
+ ### Test 83: Positive lookahead
3196
+
3197
+ describe "A correct program (Positive lookahead)" do
3198
+ prog = <<-'END'
3199
+ match find (3*D " dollars") with 3*D end
3200
+ END
3201
+
3202
+ good = ["101 dollars"]
3203
+ bad = ["102 pesos"]
3204
+ wanted = /(?=\d{3} dollars)\d{3}/
3205
+
3206
+ myprog = Program.new(prog)
3207
+ parsed = nil
3208
+
3209
+ it "should parse correctly" do
3210
+ parsed = myprog.parseable?
3211
+ myprog.debug_bad_program_parse unless parsed
3212
+ parsed.should == true
3213
+ end
3214
+
3215
+ rx = nil
3216
+ it "can be converted to a regex" do
3217
+ rx = myprog.regexp
3218
+ rx.class.should == Regexp
3219
+ end
3220
+
3221
+ # Check sanity: Is test valid?
3222
+ good.each {|str| it('has expected regex matching ' + str.inspect) { wanted.should =~ str } }
3223
+ bad.each {|str| it('has expected regex NOT matching ' + str.inspect) { wanted.should_not =~ str } }
3224
+
3225
+ # Is compiled result valid?
3226
+ good.each {|str| it('should match ' + str.inspect) { rx.should =~ str } }
3227
+ bad.each {|str| it('should NOT match ' + str.inspect) { rx.should_not =~ str } }
3228
+
3229
+
3230
+ end
3231
+
3232
+
3233
+ ### Test 84: Negative lookahead
3234
+
3235
+ describe "A correct program (Negative lookahead)" do
3236
+ prog = <<-'END'
3237
+ match find 3*D without " pesos" end
3238
+ END
3239
+
3240
+ good = ["103 dollars", "104 euros"]
3241
+ bad = ["105 pesos"]
3242
+ wanted = /(?!\d{3} pesos)\d{3}/
3243
+
3244
+ myprog = Program.new(prog)
3245
+ parsed = nil
3246
+
3247
+ it "should parse correctly" do
3248
+ parsed = myprog.parseable?
3249
+ myprog.debug_bad_program_parse unless parsed
3250
+ parsed.should == true
3251
+ end
3252
+
3253
+ rx = nil
3254
+ it "can be converted to a regex" do
3255
+ rx = myprog.regexp
3256
+ rx.class.should == Regexp
3257
+ end
3258
+
3259
+ # Check sanity: Is test valid?
3260
+ good.each {|str| it('has expected regex matching ' + str.inspect) { wanted.should =~ str } }
3261
+ bad.each {|str| it('has expected regex NOT matching ' + str.inspect) { wanted.should_not =~ str } }
3262
+
3263
+ # Is compiled result valid?
3264
+ good.each {|str| it('should match ' + str.inspect) { rx.should =~ str } }
3265
+ bad.each {|str| it('should NOT match ' + str.inspect) { rx.should_not =~ str } }
3266
+
3267
+
3268
+ end
3269
+
3270
+
3271
+ ### Test 85: Positive lookbehind
3272
+
3273
+ describe "A correct program (Positive lookbehind)" do
3274
+ prog = <<-'END'
3275
+ match with "USD" find 3*D end
3276
+ END
3277
+
3278
+ good = ["USD106"]
3279
+ bad = ["EUR107"]
3280
+ wanted = /(?<=USD)\d{3}/
3281
+
3282
+ myprog = Program.new(prog)
3283
+ parsed = nil
3284
+
3285
+ it "should parse correctly" do
3286
+ parsed = myprog.parseable?
3287
+ myprog.debug_bad_program_parse unless parsed
3288
+ parsed.should == true
3289
+ end
3290
+
3291
+ rx = nil
3292
+ it "can be converted to a regex" do
3293
+ rx = myprog.regexp
3294
+ rx.class.should == Regexp
3295
+ end
3296
+
3297
+ # Check sanity: Is test valid?
3298
+ good.each {|str| it('has expected regex matching ' + str.inspect) { wanted.should =~ str } }
3299
+ bad.each {|str| it('has expected regex NOT matching ' + str.inspect) { wanted.should_not =~ str } }
3300
+
3301
+ # Is compiled result valid?
3302
+ good.each {|str| it('should match ' + str.inspect) { rx.should =~ str } }
3303
+ bad.each {|str| it('should NOT match ' + str.inspect) { rx.should_not =~ str } }
3304
+
3305
+
3306
+ end
3307
+
3308
+
3309
+ ### Test 86: Negative lookbehind
3310
+
3311
+ describe "A correct program (Negative lookbehind)" do
3312
+ prog = <<-'END'
3313
+ match without "USD" find 3*D end
3314
+ END
3315
+
3316
+ good = ["EUR108"]
3317
+ bad = ["USD109"]
3318
+ wanted = /(?<!USD)\d{3}/
3319
+
3320
+ myprog = Program.new(prog)
3321
+ parsed = nil
3322
+
3323
+ it "should parse correctly" do
3324
+ parsed = myprog.parseable?
3325
+ myprog.debug_bad_program_parse unless parsed
3326
+ parsed.should == true
3327
+ end
3328
+
3329
+ rx = nil
3330
+ it "can be converted to a regex" do
3331
+ rx = myprog.regexp
3332
+ rx.class.should == Regexp
3333
+ end
3334
+
3335
+ # Check sanity: Is test valid?
3336
+ good.each {|str| it('has expected regex matching ' + str.inspect) { wanted.should =~ str } }
3337
+ bad.each {|str| it('has expected regex NOT matching ' + str.inspect) { wanted.should_not =~ str } }
3338
+
3339
+ # Is compiled result valid?
3340
+ good.each {|str| it('should match ' + str.inspect) { rx.should =~ str } }
3341
+ bad.each {|str| it('should NOT match ' + str.inspect) { rx.should_not =~ str } }
3342
+
3343
+
3344
+ end
3345
+
3346
+
3347
+ end