machete 0.4.0 → 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,16 +1,17 @@
1
1
  class Machete::Parser
2
2
 
3
+ token NIL
3
4
  token TRUE
4
5
  token FALSE
5
- token NIL
6
6
  token INTEGER
7
+ token SYMBOL
7
8
  token STRING
9
+ token REGEXP
8
10
  token ANY
9
11
  token EVEN
10
12
  token ODD
11
13
  token METHOD_NAME
12
14
  token CLASS_NAME
13
- token SYMBOL
14
15
 
15
16
  start expression
16
17
 
@@ -41,6 +42,27 @@ attrs : attr
41
42
  | attrs "," attr { result = val[0].merge(val[2]) }
42
43
 
43
44
  attr : method_name "=" expression { result = { val[0].to_sym => val[2] } }
45
+ | method_name "^=" SYMBOL {
46
+ result = {
47
+ val[0].to_sym => SymbolRegexpMatcher.new(
48
+ Regexp.new("^" + Regexp.escape(symbol_value(val[2]).to_s))
49
+ )
50
+ }
51
+ }
52
+ | method_name "$=" SYMBOL {
53
+ result = {
54
+ val[0].to_sym => SymbolRegexpMatcher.new(
55
+ Regexp.new(Regexp.escape(symbol_value(val[2]).to_s) + "$")
56
+ )
57
+ }
58
+ }
59
+ | method_name "*=" SYMBOL {
60
+ result = {
61
+ val[0].to_sym => SymbolRegexpMatcher.new(
62
+ Regexp.new(Regexp.escape(symbol_value(val[2]).to_s))
63
+ )
64
+ }
65
+ }
44
66
  | method_name "^=" STRING {
45
67
  result = {
46
68
  val[0].to_sym => StringRegexpMatcher.new(
@@ -62,14 +84,21 @@ attr : method_name "=" expression { result = { val[0].to_sym => val[2] } }
62
84
  )
63
85
  }
64
86
  }
87
+ | method_name "*=" REGEXP {
88
+ result = {
89
+ val[0].to_sym => IndifferentRegexpMatcher.new(
90
+ Regexp.new(regexp_value(val[2]))
91
+ )
92
+ }
93
+ }
65
94
 
66
95
  # Hack to overcome the fact that some tokens will lex as simple tokens, not
67
96
  # METHOD_NAME tokens, and that "reserved words" will lex as separate kinds of
68
97
  # tokens.
69
98
  method_name : METHOD_NAME
99
+ | NIL
70
100
  | TRUE
71
101
  | FALSE
72
- | NIL
73
102
  | ANY
74
103
  | EVEN
75
104
  | ODD
@@ -109,12 +138,13 @@ quantifier : "*" { result = [0, nil, 1] }
109
138
  | "{" EVEN "}" { result = [0, nil, 2] }
110
139
  | "{" ODD "}" { result = [1, nil, 2] }
111
140
 
112
- literal : SYMBOL { result = LiteralMatcher.new(val[0][1..-1].to_sym) }
141
+ literal : NIL { result = LiteralMatcher.new(nil) }
142
+ | TRUE { result = LiteralMatcher.new(true) }
143
+ | FALSE { result = LiteralMatcher.new(false) }
113
144
  | INTEGER { result = LiteralMatcher.new(integer_value(val[0])) }
145
+ | SYMBOL { result = LiteralMatcher.new(symbol_value(val[0])) }
114
146
  | STRING { result = LiteralMatcher.new(string_value(val[0])) }
115
- | TRUE { result = LiteralMatcher.new(true) }
116
- | FALSE { result = LiteralMatcher.new(false) }
117
- | NIL { result = LiteralMatcher.new(nil) }
147
+ | REGEXP { result = LiteralMatcher.new(regexp_value(val[0])) }
118
148
 
119
149
  any : ANY { result = AnyMatcher.new }
120
150
 
@@ -143,12 +173,16 @@ def integer_value(value)
143
173
  elsif value =~ /^0[xX]/
144
174
  value[2..-1].to_i(16)
145
175
  elsif value =~ /^0/
146
- value[1..-1].to_i(8)
176
+ value.to_i(8)
147
177
  else
148
178
  value.to_i
149
179
  end
150
180
  end
151
181
 
182
+ def symbol_value(value)
183
+ value[1..-1].to_sym
184
+ end
185
+
152
186
  def string_value(value)
153
187
  quote = value[0..0]
154
188
  if quote == "'"
@@ -173,6 +207,19 @@ def string_value(value)
173
207
  end
174
208
  end
175
209
 
210
+ REGEXP_OPTIONS = {
211
+ 'i' => Regexp::IGNORECASE,
212
+ 'm' => Regexp::MULTILINE,
213
+ 'x' => Regexp::EXTENDED
214
+ }
215
+
216
+ def regexp_value(value)
217
+ /\A\/(.*)\/([imx]*)\z/ =~ value
218
+ pattern, options = $1, $2
219
+
220
+ Regexp.new(pattern, options.chars.map { |ch| REGEXP_OPTIONS[ch] }.inject(:|))
221
+ end
222
+
176
223
  # "^" needs to be here because if it were among operators recognized by
177
224
  # METHOD_NAME, "^=" would be recognized as two tokens.
178
225
  SIMPLE_TOKENS = [
@@ -195,9 +242,9 @@ SIMPLE_TOKENS = [
195
242
  ]
196
243
 
197
244
  COMPLEX_TOKENS = [
245
+ [:NIL, /^nil/],
198
246
  [:TRUE, /^true/],
199
247
  [:FALSE, /^false/],
200
- [:NIL, /^nil/],
201
248
  # INTEGER needs to be before METHOD_NAME, otherwise e.g. "+1" would be
202
249
  # recognized as two tokens.
203
250
  [
@@ -219,6 +266,28 @@ COMPLEX_TOKENS = [
219
266
  )
220
267
  /x
221
268
  ],
269
+ [
270
+ :SYMBOL,
271
+ /^
272
+ :
273
+ (
274
+ # class name
275
+ [A-Z][a-zA-Z0-9_]*
276
+ |
277
+ # regular method name
278
+ [a-z_][a-zA-Z0-9_]*[?!=]?
279
+ |
280
+ # instance variable name
281
+ @[a-zA-Z_][a-zA-Z0-9_]*
282
+ |
283
+ # class variable name
284
+ @@[a-zA-Z_][a-zA-Z0-9_]*
285
+ |
286
+ # operator (sorted by length, then alphabetically)
287
+ (<=>|===|\[\]=|\*\*|\+@|-@|<<|<=|==|=~|>=|>>|\[\]|[%&*+\-\/<>^`|~])
288
+ )
289
+ /x
290
+ ],
222
291
  [
223
292
  :STRING,
224
293
  /^
@@ -248,6 +317,26 @@ COMPLEX_TOKENS = [
248
317
  )
249
318
  /x
250
319
  ],
320
+ [
321
+ :REGEXP,
322
+ /^
323
+ \/
324
+ (
325
+ \\ # escape
326
+ (
327
+ [\\\/ntrfvaebs\(\)\[\]\{\}\-\.\?\*\+\|\^\$] # one-character escape
328
+ |
329
+ [0-7]{2,3} # octal number escape
330
+ |
331
+ x[0-9a-fA-F]{1,2} # hexadecimal number escape
332
+ )
333
+ |
334
+ [^\/] # regular character
335
+ )*
336
+ \/
337
+ [imx]*
338
+ /x
339
+ ],
251
340
  # ANY, EVEN and ODD need to be before METHOD_NAME, otherwise they would be
252
341
  # recognized as method names.
253
342
  [:ANY, /^any/],
@@ -268,23 +357,7 @@ COMPLEX_TOKENS = [
268
357
  )
269
358
  /x
270
359
  ],
271
- [:CLASS_NAME, /^[A-Z][a-zA-Z0-9_]*/],
272
- [
273
- :SYMBOL,
274
- /^
275
- :
276
- (
277
- # class name
278
- [A-Z][a-zA-Z0-9_]*
279
- |
280
- # regular method name
281
- [a-z_][a-zA-Z0-9_]*[?!=]?
282
- |
283
- # operator (sorted by length, then alphabetically)
284
- (<=>|===|\[\]=|\*\*|\+@|-@|<<|<=|==|=~|>=|>>|\[\]|[%&*+\-\/<>^`|~])
285
- )
286
- /x
287
- ]
360
+ [:CLASS_NAME, /^[A-Z][a-zA-Z0-9_]*/]
288
361
  ]
289
362
 
290
363
  def next_token
@@ -13,8 +13,8 @@ Gem::Specification.new do |s|
13
13
  in the code, etc.
14
14
  EOT
15
15
 
16
- s.author = "David Majda"
17
- s.email = "dmajda@suse.de"
16
+ s.authors = ["David Majda", "Piotr Niełacny"]
17
+ s.email = ["dmajda@suse.cz", "piotr.nielacny@gmail.com"]
18
18
  s.homepage = "https://github.com/openSUSE/machete"
19
19
  s.license = "MIT"
20
20
 
@@ -49,6 +49,10 @@ module Machete::Matchers
49
49
  end
50
50
  end
51
51
 
52
+ describe Matcher do
53
+ # Nothing to spec.
54
+ end
55
+
52
56
  describe ChoiceMatcher do
53
57
  before :each do
54
58
  @alternatives = [
@@ -116,7 +120,7 @@ module Machete::Matchers
116
120
  @matcher = NodeMatcher.new(:RegexLiteral, @attrs)
117
121
  end
118
122
 
119
- describe "initializa" do
123
+ describe "initialize" do
120
124
  describe "when passed one parameter" do
121
125
  it "sets attributes correctly" do
122
126
  matcher = NodeMatcher.new(:RegexLiteral)
@@ -409,9 +413,9 @@ module Machete::Matchers
409
413
  end
410
414
  end
411
415
 
412
- describe StringRegexpMatcher do
413
- before :each do
414
- @matcher = StringRegexpMatcher.new(/abcd/)
416
+ describe RegexpMatcher do
417
+ before do
418
+ @matcher = RegexpMatcher.new(/abcd/)
415
419
  end
416
420
 
417
421
  describe "initialize" do
@@ -425,27 +429,81 @@ module Machete::Matchers
425
429
  @matcher.should == @matcher
426
430
  end
427
431
 
428
- it "returns true when passed a StartsWithMatcher initialized with the same parameters" do
429
- @matcher.should == StringRegexpMatcher.new(/abcd/)
432
+ it "returns true when passed a RegexpMatcher initialized with the same parameters" do
433
+ @matcher.should == RegexpMatcher.new(/abcd/)
430
434
  end
431
435
 
432
436
  it "returns false when passed some random object" do
433
437
  @matcher.should_not == Object.new
434
438
  end
435
439
 
436
- it "returns false when passed a subclass of StartsWithMatcher initialized with the same parameters" do
437
- class SubclassedStringRegexpMatcher < StringRegexpMatcher
440
+ it "returns false when passed a subclass of RegexpMatcher initialized with the same parameters" do
441
+ class SubclassedRegexpMatcher < RegexpMatcher
438
442
  end
439
443
 
440
- @matcher.should_not == SubclassedStringRegexpMatcher.new(/abcd/)
444
+ @matcher.should_not == SubclassedRegexpMatcher.new(/abcd/)
441
445
  end
442
446
 
443
- it "returns false when passed a StartsWithMatcher initialized with different parameters" do
444
- @matcher.should_not == StringRegexpMatcher.new(/efgh/)
447
+ it "returns false when passed a RegexpMatcher initialized with different parameters" do
448
+ @matcher.should_not == RegexpMatcher.new(/efgh/)
445
449
  end
446
450
  end
451
+ end
452
+
453
+ describe SymbolRegexpMatcher do
454
+ before do
455
+ @matcher = SymbolRegexpMatcher.new(/abcd/)
456
+ end
447
457
 
448
458
  describe "matches?" do
459
+ it "matches a symbol matching the regexp" do
460
+ @matcher.matches?(:efghabcdijkl).should be_true
461
+ end
462
+
463
+ it "does not match a symbol not matching the regexp" do
464
+ @matcher.matches?(:efghijkl).should be_false
465
+ end
466
+
467
+ it "does not match some random object" do
468
+ @matcher.matches?(Object.new).should be_false
469
+ end
470
+ end
471
+ end
472
+
473
+ describe StringRegexpMatcher do
474
+ before :each do
475
+ @matcher = StringRegexpMatcher.new(/abcd/)
476
+ end
477
+
478
+ describe "matches?" do
479
+ it "matches a string matching the regexp" do
480
+ @matcher.matches?("efghabcdijkl").should be_true
481
+ end
482
+
483
+ it "does not match a string not matching the regexp" do
484
+ @matcher.matches?("efghijkl").should be_false
485
+ end
486
+
487
+ it "does not match some random object" do
488
+ @matcher.matches?(Object.new).should be_false
489
+ end
490
+ end
491
+ end
492
+
493
+ describe IndifferentRegexpMatcher do
494
+ before :each do
495
+ @matcher = IndifferentRegexpMatcher.new(/abcd/)
496
+ end
497
+
498
+ describe "matches?" do
499
+ it "matches a symbol matching the regexp" do
500
+ @matcher.matches?(:efghabcdijkl).should be_true
501
+ end
502
+
503
+ it "does not match a symbol not matching the regexp" do
504
+ @matcher.matches?(:efghijkl).should be_false
505
+ end
506
+
449
507
  it "matches a string matching the regexp" do
450
508
  @matcher.matches?("efghabcdijkl").should be_true
451
509
  end
@@ -72,7 +72,30 @@ module Machete
72
72
 
73
73
  # Canonical attr is "a = 42".
74
74
  it "parses attr" do
75
+ # Expressions
75
76
  'Foo<a = 42 | 43>'.should be_parsed_as(NodeMatcher.new(:Foo, :a => @ch4243))
77
+
78
+ # Symbols
79
+ 'Foo<a ^= :a>'.should be_parsed_as(
80
+ NodeMatcher.new(:Foo, :a => SymbolRegexpMatcher.new(/^a/))
81
+ )
82
+ 'Foo<a ^= :+>'.should be_parsed_as(
83
+ NodeMatcher.new(:Foo, :a => SymbolRegexpMatcher.new(/^\+/))
84
+ )
85
+ 'Foo<a $= :a>'.should be_parsed_as(
86
+ NodeMatcher.new(:Foo, :a => SymbolRegexpMatcher.new(/a$/))
87
+ )
88
+ 'Foo<a $= :+>'.should be_parsed_as(
89
+ NodeMatcher.new(:Foo, :a => SymbolRegexpMatcher.new(/\+$/))
90
+ )
91
+ 'Foo<a *= :a>'.should be_parsed_as(
92
+ NodeMatcher.new(:Foo, :a => SymbolRegexpMatcher.new(/a/))
93
+ )
94
+ 'Foo<a *= :+>'.should be_parsed_as(
95
+ NodeMatcher.new(:Foo, :a => SymbolRegexpMatcher.new(/\+/))
96
+ )
97
+
98
+ # Strings
76
99
  'Foo<a ^= "abcd">'.should be_parsed_as(
77
100
  NodeMatcher.new(:Foo, :a => StringRegexpMatcher.new(/^abcd/))
78
101
  )
@@ -97,15 +120,32 @@ module Machete
97
120
  /\[\]\{\}\(\)\|\-\*\.\\\?\+\^\$\ \#\t\f\v\n\r/
98
121
  ))
99
122
  )
123
+
124
+ # Regexps
125
+ 'Foo<a *= /abcd/>'.should be_parsed_as(
126
+ NodeMatcher.new(:Foo, :a => IndifferentRegexpMatcher.new(/abcd/))
127
+ )
128
+ 'Foo<a *= /abcd/i>'.should be_parsed_as(
129
+ NodeMatcher.new(:Foo, :a => IndifferentRegexpMatcher.new(/abcd/i))
130
+ )
131
+ 'Foo<a *= /abcd/m>'.should be_parsed_as(
132
+ NodeMatcher.new(:Foo, :a => IndifferentRegexpMatcher.new(/abcd/m))
133
+ )
134
+ 'Foo<a *= /abcd/x>'.should be_parsed_as(
135
+ NodeMatcher.new(:Foo, :a => IndifferentRegexpMatcher.new(/abcd/x))
136
+ )
137
+ 'Foo<a *= /abcd/imx>'.should be_parsed_as(
138
+ NodeMatcher.new(:Foo, :a => IndifferentRegexpMatcher.new(/abcd/imx))
139
+ )
100
140
  end
101
141
 
102
142
  # Canonical method_name is "a".
103
143
  it "parses method_name" do
104
144
  'Foo<a = 42>'.should be_parsed_as(node_matcher_with_attr(:a))
145
+ 'Foo<nil = 42>'.should be_parsed_as(node_matcher_with_attr(:nil))
105
146
  'Foo<true = 42>'.should be_parsed_as(node_matcher_with_attr(:true))
106
147
  'Foo<false = 42>'.should be_parsed_as(node_matcher_with_attr(:false))
107
148
  'Foo<any = 42>'.should be_parsed_as(node_matcher_with_attr(:any))
108
- 'Foo<any = 42>'.should be_parsed_as(node_matcher_with_attr(:any))
109
149
  'Foo<even = 42>'.should be_parsed_as(node_matcher_with_attr(:even))
110
150
  'Foo<odd = 42>'.should be_parsed_as(node_matcher_with_attr(:odd))
111
151
  'Foo<* = 42>'.should be_parsed_as(node_matcher_with_attr(:*))
@@ -166,12 +206,13 @@ module Machete
166
206
 
167
207
  # Canonical literal is "42".
168
208
  it "parses literal" do
169
- ':a'.should be_parsed_as(LiteralMatcher.new(:a))
170
- '42'.should be_parsed_as(@i42)
171
- '"abcd"'.should be_parsed_as(LiteralMatcher.new("abcd"))
209
+ 'nil'.should be_parsed_as(LiteralMatcher.new(nil))
172
210
  'true'.should be_parsed_as(LiteralMatcher.new(true))
173
211
  'false'.should be_parsed_as(LiteralMatcher.new(false))
174
- 'nil'.should be_parsed_as(LiteralMatcher.new(nil))
212
+ '42'.should be_parsed_as(@i42)
213
+ ':a'.should be_parsed_as(LiteralMatcher.new(:a))
214
+ '"abcd"'.should be_parsed_as(LiteralMatcher.new("abcd"))
215
+ '/abcd/'.should be_parsed_as(LiteralMatcher.new(/abcd/))
175
216
  end
176
217
 
177
218
  # Canonical any is "any".
@@ -179,6 +220,11 @@ module Machete
179
220
  'any'.should be_parsed_as(AnyMatcher.new)
180
221
  end
181
222
 
223
+ # Canonical NIL is "nil".
224
+ it "parses NIL" do
225
+ 'nil'.should be_parsed_as(LiteralMatcher.new(nil))
226
+ end
227
+
182
228
  # Canonical TRUE is "true".
183
229
  it "parses TRUE" do
184
230
  'true'.should be_parsed_as(LiteralMatcher.new(true))
@@ -189,11 +235,6 @@ module Machete
189
235
  'false'.should be_parsed_as(LiteralMatcher.new(false))
190
236
  end
191
237
 
192
- # Canonical NIL is "nil".
193
- it "parses NIL" do
194
- 'nil'.should be_parsed_as(LiteralMatcher.new(nil))
195
- end
196
-
197
238
  # Canonical INTEGER is "42".
198
239
  it "parses INTEGER" do
199
240
  # Sign
@@ -275,6 +316,94 @@ module Machete
275
316
  '1_2_3_4'.should be_parsed_as(LiteralMatcher.new(1234))
276
317
  end
277
318
 
319
+ # Canonical SYMBOL is ":a".
320
+ it "parses SYMBOL" do
321
+ # Class names
322
+ ':A'.should be_parsed_as(LiteralMatcher.new(:A))
323
+ ':Z'.should be_parsed_as(LiteralMatcher.new(:Z))
324
+ ':Aa'.should be_parsed_as(LiteralMatcher.new(:Aa))
325
+ ':Az'.should be_parsed_as(LiteralMatcher.new(:Az))
326
+ ':AA'.should be_parsed_as(LiteralMatcher.new(:AA))
327
+ ':AZ'.should be_parsed_as(LiteralMatcher.new(:AZ))
328
+ ':A0'.should be_parsed_as(LiteralMatcher.new(:A0))
329
+ ':A9'.should be_parsed_as(LiteralMatcher.new(:A9))
330
+ ':A_'.should be_parsed_as(LiteralMatcher.new(:A_))
331
+ ':Abcd'.should be_parsed_as(LiteralMatcher.new(:Abcd))
332
+
333
+ # Regular method names
334
+ ':a'.should be_parsed_as(LiteralMatcher.new(:a))
335
+ ':z'.should be_parsed_as(LiteralMatcher.new(:z))
336
+ ':_'.should be_parsed_as(LiteralMatcher.new(:_))
337
+ ':aa'.should be_parsed_as(LiteralMatcher.new(:aa))
338
+ ':az'.should be_parsed_as(LiteralMatcher.new(:az))
339
+ ':aA'.should be_parsed_as(LiteralMatcher.new(:aA))
340
+ ':aZ'.should be_parsed_as(LiteralMatcher.new(:aZ))
341
+ ':a0'.should be_parsed_as(LiteralMatcher.new(:a0))
342
+ ':a9'.should be_parsed_as(LiteralMatcher.new(:a9))
343
+ ':a_'.should be_parsed_as(LiteralMatcher.new(:a_))
344
+ ':abcd'.should be_parsed_as(LiteralMatcher.new(:abcd))
345
+ ':a?'.should be_parsed_as(LiteralMatcher.new(:a?))
346
+ ':a!'.should be_parsed_as(LiteralMatcher.new(:a!))
347
+ ':a='.should be_parsed_as(LiteralMatcher.new(:a=))
348
+
349
+ # Instance variable name
350
+ ':@a'.should be_parsed_as(LiteralMatcher.new(:@a))
351
+ ':@z'.should be_parsed_as(LiteralMatcher.new(:@z))
352
+ ':@A'.should be_parsed_as(LiteralMatcher.new(:@A))
353
+ ':@Z'.should be_parsed_as(LiteralMatcher.new(:@Z))
354
+ ':@_'.should be_parsed_as(LiteralMatcher.new(:@_))
355
+ ':@aa'.should be_parsed_as(LiteralMatcher.new(:@aa))
356
+ ':@az'.should be_parsed_as(LiteralMatcher.new(:@az))
357
+ ':@aA'.should be_parsed_as(LiteralMatcher.new(:@aA))
358
+ ':@aZ'.should be_parsed_as(LiteralMatcher.new(:@aZ))
359
+ ':@a0'.should be_parsed_as(LiteralMatcher.new(:@a0))
360
+ ':@a9'.should be_parsed_as(LiteralMatcher.new(:@a9))
361
+ ':@a_'.should be_parsed_as(LiteralMatcher.new(:@a_))
362
+ ':@abcd'.should be_parsed_as(LiteralMatcher.new(:@abcd))
363
+
364
+ # Class variable name
365
+ ':@@a'.should be_parsed_as(LiteralMatcher.new(:@@a))
366
+ ':@@z'.should be_parsed_as(LiteralMatcher.new(:@@z))
367
+ ':@@A'.should be_parsed_as(LiteralMatcher.new(:@@A))
368
+ ':@@Z'.should be_parsed_as(LiteralMatcher.new(:@@Z))
369
+ ':@@_'.should be_parsed_as(LiteralMatcher.new(:@@_))
370
+ ':@@aa'.should be_parsed_as(LiteralMatcher.new(:@@aa))
371
+ ':@@az'.should be_parsed_as(LiteralMatcher.new(:@@az))
372
+ ':@@aA'.should be_parsed_as(LiteralMatcher.new(:@@aA))
373
+ ':@@aZ'.should be_parsed_as(LiteralMatcher.new(:@@aZ))
374
+ ':@@a0'.should be_parsed_as(LiteralMatcher.new(:@@a0))
375
+ ':@@a9'.should be_parsed_as(LiteralMatcher.new(:@@a9))
376
+ ':@@a_'.should be_parsed_as(LiteralMatcher.new(:@@a_))
377
+ ':@@abcd'.should be_parsed_as(LiteralMatcher.new(:@@abcd))
378
+
379
+ # Operators (sorted alphabetically)
380
+ ':%'.should be_parsed_as(LiteralMatcher.new(:%))
381
+ ':&'.should be_parsed_as(LiteralMatcher.new(:&))
382
+ ':*'.should be_parsed_as(LiteralMatcher.new(:*))
383
+ ':**'.should be_parsed_as(LiteralMatcher.new(:**))
384
+ ':+'.should be_parsed_as(LiteralMatcher.new(:+))
385
+ ':+@'.should be_parsed_as(LiteralMatcher.new(:+@))
386
+ ':-'.should be_parsed_as(LiteralMatcher.new(:-))
387
+ ':-@'.should be_parsed_as(LiteralMatcher.new(:-@))
388
+ ':/'.should be_parsed_as(LiteralMatcher.new(:/))
389
+ ':<'.should be_parsed_as(LiteralMatcher.new(:<))
390
+ ':<<'.should be_parsed_as(LiteralMatcher.new(:<<))
391
+ ':<='.should be_parsed_as(LiteralMatcher.new(:<=))
392
+ ':<=>'.should be_parsed_as(LiteralMatcher.new(:<=>))
393
+ ':=='.should be_parsed_as(LiteralMatcher.new(:==))
394
+ ':==='.should be_parsed_as(LiteralMatcher.new(:===))
395
+ ':=~'.should be_parsed_as(LiteralMatcher.new(:=~))
396
+ ':>'.should be_parsed_as(LiteralMatcher.new(:>))
397
+ ':>='.should be_parsed_as(LiteralMatcher.new(:>=))
398
+ ':>>'.should be_parsed_as(LiteralMatcher.new(:>>))
399
+ ':[]'.should be_parsed_as(LiteralMatcher.new(:[]))
400
+ ':[]='.should be_parsed_as(LiteralMatcher.new(:[]=))
401
+ ':^'.should be_parsed_as(LiteralMatcher.new(:^))
402
+ ':`'.should be_parsed_as(LiteralMatcher.new(:`))
403
+ ':|'.should be_parsed_as(LiteralMatcher.new(:|))
404
+ ':~'.should be_parsed_as(LiteralMatcher.new(:~))
405
+ end
406
+
278
407
  # Canonical STRING is "\"abcd\"".
279
408
  it "parses STRING" do
280
409
  "''".should be_parsed_as(LiteralMatcher.new(""))
@@ -309,6 +438,50 @@ module Machete
309
438
  '"abc"'.should be_parsed_as(LiteralMatcher.new("abc"))
310
439
  end
311
440
 
441
+ # Canonical REGEXP is /regexp/.
442
+ it "parses REGEXP" do
443
+ '//'.should be_parsed_as(LiteralMatcher.new(//))
444
+ '/a/'.should be_parsed_as(LiteralMatcher.new(/a/))
445
+ '/\\\\/'.should be_parsed_as(LiteralMatcher.new(/\\/))
446
+ '/\//'.should be_parsed_as(LiteralMatcher.new(/\//))
447
+ '/\\n/'.should be_parsed_as(LiteralMatcher.new(/\n/))
448
+ '/\\t/'.should be_parsed_as(LiteralMatcher.new(/\t/))
449
+ '/\\r/'.should be_parsed_as(LiteralMatcher.new(/\r/))
450
+ '/\\f/'.should be_parsed_as(LiteralMatcher.new(/\f/))
451
+ '/\\v/'.should be_parsed_as(LiteralMatcher.new(/\v/))
452
+ '/\\a/'.should be_parsed_as(LiteralMatcher.new(/\a/))
453
+ '/\\e/'.should be_parsed_as(LiteralMatcher.new(/\e/))
454
+ '/\\b/'.should be_parsed_as(LiteralMatcher.new(/\b/))
455
+ '/\\s/'.should be_parsed_as(LiteralMatcher.new(/\s/))
456
+ '/\\(/'.should be_parsed_as(LiteralMatcher.new(/\(/))
457
+ '/\\)/'.should be_parsed_as(LiteralMatcher.new(/\)/))
458
+ '/\\[/'.should be_parsed_as(LiteralMatcher.new(/\[/))
459
+ '/\\]/'.should be_parsed_as(LiteralMatcher.new(/\]/))
460
+ '/\\{/'.should be_parsed_as(LiteralMatcher.new(/\{/))
461
+ '/\\}/'.should be_parsed_as(LiteralMatcher.new(/\}/))
462
+ '/\\-/'.should be_parsed_as(LiteralMatcher.new(/\-/))
463
+ '/\\./'.should be_parsed_as(LiteralMatcher.new(/\./))
464
+ '/\\?/'.should be_parsed_as(LiteralMatcher.new(/\?/))
465
+ '/\\*/'.should be_parsed_as(LiteralMatcher.new(/\*/))
466
+ '/\\+/'.should be_parsed_as(LiteralMatcher.new(/\+/))
467
+ '/\\|/'.should be_parsed_as(LiteralMatcher.new(/\|/))
468
+ '/\\^/'.should be_parsed_as(LiteralMatcher.new(/\^/))
469
+ '/\\$/'.should be_parsed_as(LiteralMatcher.new(/\$/))
470
+ '/\\00/'.should be_parsed_as(LiteralMatcher.new(/\00/))
471
+ '/\\07/'.should be_parsed_as(LiteralMatcher.new(/\07/))
472
+ '/\\70/'.should be_parsed_as(LiteralMatcher.new(/\70/))
473
+ '/\\77/'.should be_parsed_as(LiteralMatcher.new(/\77/))
474
+ '/\\123/'.should be_parsed_as(LiteralMatcher.new(/\123/))
475
+ '/\\x0/'.should be_parsed_as(LiteralMatcher.new(/\x0/))
476
+ '/\\x9/'.should be_parsed_as(LiteralMatcher.new(/\x9/))
477
+ '/\\xa/'.should be_parsed_as(LiteralMatcher.new(/\xa/))
478
+ '/\\xf/'.should be_parsed_as(LiteralMatcher.new(/\xf/))
479
+ '/\\xA/'.should be_parsed_as(LiteralMatcher.new(/\xA/))
480
+ '/\\xF/'.should be_parsed_as(LiteralMatcher.new(/\xF/))
481
+ '/\\x12/'.should be_parsed_as(LiteralMatcher.new(/\x12/))
482
+ '/abc/'.should be_parsed_as(LiteralMatcher.new(/abc/))
483
+ end
484
+
312
485
  # Canonical ANY is "any".
313
486
  it "parses ANY" do
314
487
  'any'.should be_parsed_as(AnyMatcher.new)
@@ -382,64 +555,6 @@ module Machete
382
555
  'Abcd'.should be_parsed_as(NodeMatcher.new(:Abcd))
383
556
  end
384
557
 
385
- # Canonical SYMBOL is ":a".
386
- it "parses SYMBOL" do
387
- # Class names
388
- ':A'.should be_parsed_as(LiteralMatcher.new(:A))
389
- ':Z'.should be_parsed_as(LiteralMatcher.new(:Z))
390
- ':Aa'.should be_parsed_as(LiteralMatcher.new(:Aa))
391
- ':Az'.should be_parsed_as(LiteralMatcher.new(:Az))
392
- ':AA'.should be_parsed_as(LiteralMatcher.new(:AA))
393
- ':AZ'.should be_parsed_as(LiteralMatcher.new(:AZ))
394
- ':A0'.should be_parsed_as(LiteralMatcher.new(:A0))
395
- ':A9'.should be_parsed_as(LiteralMatcher.new(:A9))
396
- ':A_'.should be_parsed_as(LiteralMatcher.new(:A_))
397
- ':Abcd'.should be_parsed_as(LiteralMatcher.new(:Abcd))
398
-
399
- # Regular method names
400
- ':a'.should be_parsed_as(LiteralMatcher.new(:a))
401
- ':z'.should be_parsed_as(LiteralMatcher.new(:z))
402
- ':_'.should be_parsed_as(LiteralMatcher.new(:_))
403
- ':aa'.should be_parsed_as(LiteralMatcher.new(:aa))
404
- ':az'.should be_parsed_as(LiteralMatcher.new(:az))
405
- ':aA'.should be_parsed_as(LiteralMatcher.new(:aA))
406
- ':aZ'.should be_parsed_as(LiteralMatcher.new(:aZ))
407
- ':a0'.should be_parsed_as(LiteralMatcher.new(:a0))
408
- ':a9'.should be_parsed_as(LiteralMatcher.new(:a9))
409
- ':a_'.should be_parsed_as(LiteralMatcher.new(:a_))
410
- ':abcd'.should be_parsed_as(LiteralMatcher.new(:abcd))
411
- ':a?'.should be_parsed_as(LiteralMatcher.new(:a?))
412
- ':a!'.should be_parsed_as(LiteralMatcher.new(:a!))
413
- ':a='.should be_parsed_as(LiteralMatcher.new(:a=))
414
-
415
- # Operators (sorted alphabetically)
416
- ':%'.should be_parsed_as(LiteralMatcher.new(:%))
417
- ':&'.should be_parsed_as(LiteralMatcher.new(:&))
418
- ':*'.should be_parsed_as(LiteralMatcher.new(:*))
419
- ':**'.should be_parsed_as(LiteralMatcher.new(:**))
420
- ':+'.should be_parsed_as(LiteralMatcher.new(:+))
421
- ':+@'.should be_parsed_as(LiteralMatcher.new(:+@))
422
- ':-'.should be_parsed_as(LiteralMatcher.new(:-))
423
- ':-@'.should be_parsed_as(LiteralMatcher.new(:-@))
424
- ':/'.should be_parsed_as(LiteralMatcher.new(:/))
425
- ':<'.should be_parsed_as(LiteralMatcher.new(:<))
426
- ':<<'.should be_parsed_as(LiteralMatcher.new(:<<))
427
- ':<='.should be_parsed_as(LiteralMatcher.new(:<=))
428
- ':<=>'.should be_parsed_as(LiteralMatcher.new(:<=>))
429
- ':=='.should be_parsed_as(LiteralMatcher.new(:==))
430
- ':==='.should be_parsed_as(LiteralMatcher.new(:===))
431
- ':=~'.should be_parsed_as(LiteralMatcher.new(:=~))
432
- ':>'.should be_parsed_as(LiteralMatcher.new(:>))
433
- ':>='.should be_parsed_as(LiteralMatcher.new(:>=))
434
- ':>>'.should be_parsed_as(LiteralMatcher.new(:>>))
435
- ':[]'.should be_parsed_as(LiteralMatcher.new(:[]))
436
- ':[]='.should be_parsed_as(LiteralMatcher.new(:[]=))
437
- ':^'.should be_parsed_as(LiteralMatcher.new(:^))
438
- ':`'.should be_parsed_as(LiteralMatcher.new(:`))
439
- ':|'.should be_parsed_as(LiteralMatcher.new(:|))
440
- ':~'.should be_parsed_as(LiteralMatcher.new(:~))
441
- end
442
-
443
558
  it "skips whitespace before tokens" do
444
559
  '42'.should be_parsed_as(@i42)
445
560
  ' 42'.should be_parsed_as(@i42)