regexador 0.4.5 → 0.4.6

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