machete 0.4.0 → 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/.gitignore +2 -0
- data/CHANGELOG +13 -0
- data/Gemfile +4 -0
- data/README.md +85 -22
- data/Rakefile +2 -2
- data/VERSION +1 -1
- data/lib/machete.rb +87 -43
- data/lib/machete/matchers.rb +24 -14
- data/lib/machete/parser.y +99 -26
- data/machete.gemspec +2 -2
- data/spec/machete/matchers_spec.rb +69 -11
- data/spec/machete/parser_spec.rb +183 -68
- data/spec/machete_spec.rb +44 -16
- metadata +17 -15
data/.gitignore
CHANGED
data/CHANGELOG
CHANGED
@@ -1,5 +1,18 @@
|
|
1
|
+
0.5.0 (2012-08-19)
|
2
|
+
------------------
|
3
|
+
|
4
|
+
* Support for matching symbols using "^=", "$=" and "*=" operators.
|
5
|
+
* Support for regexp literals and matching regexps using "*=" operator.
|
6
|
+
* Extended symbol grammar to cover symbols denoting instance and class variable
|
7
|
+
names (:@foo, :@@bar).
|
8
|
+
* Matchete#matches? and Machete#find accept the pattern also in compiled
|
9
|
+
form (instance of Machete:Matchers::Matcher class).
|
10
|
+
* Works in Rubinius 1.9 mode.
|
11
|
+
* Internal code improvements and fixes.
|
12
|
+
|
1
13
|
0.4.0 (2011-10-18)
|
2
14
|
------------------
|
15
|
+
|
3
16
|
* Support for "true", "false" and "nil" literals.
|
4
17
|
* New "*=" operator matching part of a string.
|
5
18
|
* Bundler support.
|
data/Gemfile
CHANGED
data/README.md
CHANGED
@@ -1,12 +1,16 @@
|
|
1
1
|
Machete
|
2
2
|
=======
|
3
3
|
|
4
|
-
Machete is a simple tool for matching Rubinius AST nodes against patterns. You
|
4
|
+
Machete is a simple tool for matching Rubinius AST nodes against patterns. You
|
5
|
+
can use it if you are writing any kind of tool that processes Ruby code and
|
6
|
+
needs to do some work on specific types of nodes, needs to find patterns in the
|
7
|
+
code, etc.
|
5
8
|
|
6
9
|
Installation
|
7
10
|
------------
|
8
11
|
|
9
|
-
You need to install [Rubinius](http://rubini.us/)
|
12
|
+
You need to install current development version of [Rubinius](http://rubini.us/)
|
13
|
+
first. You can then install Machete:
|
10
14
|
|
11
15
|
$ gem install machete
|
12
16
|
|
@@ -17,19 +21,21 @@ First, require the library:
|
|
17
21
|
|
18
22
|
require "machete"
|
19
23
|
|
20
|
-
You can now use one of two methods Machete offers: `Machete.matches?` and
|
24
|
+
You can now use one of two methods Machete offers: `Machete.matches?` and
|
25
|
+
`Machete.find`.
|
21
26
|
|
22
27
|
The `Machete.matches?` method matches a Rubinus AST node against a pattern:
|
23
28
|
|
24
|
-
Machete.matches?('foo.bar'.to_ast, 'Send<
|
29
|
+
Machete.matches?('foo.bar'.to_ast, 'Send<name = :bar>')
|
25
30
|
# => true
|
26
31
|
|
27
|
-
Machete.matches?('42'.to_ast, 'Send<
|
32
|
+
Machete.matches?('42'.to_ast, 'Send<name = :bar>')
|
28
33
|
# => false
|
29
34
|
|
30
35
|
(See below for pattern syntax description.)
|
31
36
|
|
32
|
-
The `Machete.find` method finds all nodes in a Rubinius AST tree matching a
|
37
|
+
The `Machete.find` method finds all nodes in a Rubinius AST tree matching a
|
38
|
+
pattern:
|
33
39
|
|
34
40
|
Machete.find('42 + 43 + 44'.to_ast, 'FixnumLiteral')
|
35
41
|
# => [
|
@@ -38,12 +44,24 @@ The `Machete.find` method finds all nodes in a Rubinius AST tree matching a patt
|
|
38
44
|
# #<Rubinius::AST::FixnumLiteral:0x10c0 @value=42 @line=1>
|
39
45
|
# ]
|
40
46
|
|
47
|
+
Both `Machete.matches?` and `Machete.find` also accept patterns in their
|
48
|
+
compiled form (instance of `Machete::Matchers::Matcher`):
|
49
|
+
|
50
|
+
Machete.matches?(
|
51
|
+
'foo.bar'.to_ast,
|
52
|
+
Machete::Matchers::NodeMatcher.new("Send",
|
53
|
+
:name => Machete::Matchers::LiteralMatcher.new(:bar)
|
54
|
+
)
|
55
|
+
)
|
56
|
+
# => true
|
57
|
+
|
41
58
|
Pattern Syntax
|
42
59
|
--------------
|
43
60
|
|
44
61
|
### Basics
|
45
62
|
|
46
|
-
Rubinius AST consists of instances of classes that represent various types of
|
63
|
+
Rubinius AST consists of instances of classes that represent various types of
|
64
|
+
nodes:
|
47
65
|
|
48
66
|
'42'.to_ast # => #<Rubinius::AST::FixnumLiteral:0xf28 @value=42 @line=1>
|
49
67
|
'"abcd"'.to_ast # => #<Rubinius::AST::StringLiteral:0xf60 @line=1 @string="abcd">
|
@@ -58,25 +76,31 @@ To specify multiple alternatives, use the choice operator:
|
|
58
76
|
Machete.matches?('42'.to_ast, 'FixnumLiteral | StringLiteral') # => true
|
59
77
|
Machete.matches?('"abcd"'.to_ast, 'FixnumLiteral | StringLiteral') # => true
|
60
78
|
|
61
|
-
If you don't care about the node type at all, use the `any` keyword (this is
|
79
|
+
If you don't care about the node type at all, use the `any` keyword (this is
|
80
|
+
most useful when matching arrays — see below):
|
62
81
|
|
63
82
|
Machete.matches?('42'.to_ast, 'any') # => true
|
64
83
|
Machete.matches?('"abcd"'.to_ast, 'any') # => true
|
65
84
|
|
66
85
|
### Node Attributes
|
67
86
|
|
68
|
-
If you want to match a specific attribute of a node, specify its value inside
|
87
|
+
If you want to match a specific attribute of a node, specify its value inside
|
88
|
+
`<...>` right after the node name:
|
69
89
|
|
70
90
|
Machete.matches?('42'.to_ast, 'FixnumLiteral<value = 42>') # => true
|
71
91
|
Machete.matches?('45'.to_ast, 'FixnumLiteral<value = 42>') # => false
|
72
92
|
|
73
|
-
The attribute value can be `
|
93
|
+
The attribute value can be `nil`, `true`, `false`, integer, symbol, string,
|
94
|
+
regexp, array or other pattern. The last option means you can easily match
|
95
|
+
nested nodes recursively. You can also specify multiple attributes:
|
74
96
|
|
75
97
|
Machete.matches?('foo.bar'.to_ast, 'Send<receiver = Send<receiver = Self, name = :foo>, name = :bar>') # => true
|
76
98
|
|
77
|
-
#### String Attributes
|
99
|
+
#### String And Symbol Attributes
|
78
100
|
|
79
|
-
When matching string attributes values, you don't have to do a whole-string
|
101
|
+
When matching string attributes values, you don't have to do a whole-string
|
102
|
+
match using the `=` operator. You can also match the beginning, the end or a
|
103
|
+
part of a string attribute value using the `^=`, `$=` and `*=` operators:
|
80
104
|
|
81
105
|
Machete.matches?('"abcd"'.to_ast, 'StringLiteral<string ^= "ab">') # => true
|
82
106
|
Machete.matches?('"efgh"'.to_ast, 'StringLiteral<string ^= "ab">') # => false
|
@@ -85,9 +109,31 @@ When matching string attributes values, you don't have to do a whole-string matc
|
|
85
109
|
Machete.matches?('"abcd"'.to_ast, 'StringLiteral<string *= "bc">') # => true
|
86
110
|
Machete.matches?('"efgh"'.to_ast, 'StringLiteral<string *= "bc">') # => false
|
87
111
|
|
112
|
+
Match symbol attributes works in the same way:
|
113
|
+
|
114
|
+
Machete.matches?(':abcd'.to_ast, 'SymbolLiteral<value ^= :ab>') # => true
|
115
|
+
Machete.matches?(':efgh'.to_ast, 'SymbolLiteral<value ^= :ab>') # => false
|
116
|
+
Machete.matches?(':abcd'.to_ast, 'SymbolLiteral<value $= :cd>') # => true
|
117
|
+
Machete.matches?(':efgh'.to_ast, 'SymbolLiteral<value $= :cd>') # => false
|
118
|
+
Machete.matches?(':abcd'.to_ast, 'SymbolLiteral<value *= :bc>') # => true
|
119
|
+
Machete.matches?(':efgh'.to_ast, 'SymbolLiteral<value *= :bc>') # => false
|
120
|
+
|
121
|
+
In addition, you can match string and symbol attributes using regular
|
122
|
+
expressions together with the `*=` operator:
|
123
|
+
|
124
|
+
Machete.matches?('"abcd"'.to_ast, 'StringLiteral<string *= /bc/>') # => true
|
125
|
+
Machete.matches?('"efgh"'.to_ast, 'StringLiteral<string *= /bc/>') # => false
|
126
|
+
|
127
|
+
Machete.matches?(':abcd'.to_ast, 'SymbolLiteral<value *= /bc/>') # => true
|
128
|
+
Machete.matches?(':efgh'.to_ast, 'SymbolLiteral<value *= /bc/>') # => false
|
129
|
+
|
130
|
+
The regular expressions can take the `i`, `m` and `x` options with the same
|
131
|
+
semantics as in Ruby.
|
132
|
+
|
88
133
|
#### Array Attributes
|
89
134
|
|
90
|
-
When matching array attribute values, the simplest way is to specify the array
|
135
|
+
When matching array attribute values, the simplest way is to specify the array
|
136
|
+
elements exactly. They will be matched one-by-one.
|
91
137
|
|
92
138
|
Machete.matches?('[1, 2]'.to_ast, 'ArrayLiteral<body = [FixnumLiteral<value = 1>, FixnumLiteral<value = 2>]>') # => true
|
93
139
|
|
@@ -96,7 +142,9 @@ If you don't care about the node type of some array elements, you can use `any`:
|
|
96
142
|
Machete.matches?('[1, 2]'.to_ast, 'ArrayLiteral<body = [any, FixnumLiteral<value = 2>]>') # => true
|
97
143
|
Machete.matches?('["abcd", 2]'.to_ast, 'ArrayLiteral<body = [any, FixnumLiteral<value = 2>]>') # => true
|
98
144
|
|
99
|
-
The best thing about array matching is that you can use quantifiers for
|
145
|
+
The best thing about array matching is that you can use quantifiers for
|
146
|
+
elements: `*`, `+`, `?`, `{n}`, `{n,}`, `{,n}`, `{m,n}`. Their meaning is the
|
147
|
+
same as in Perl-like regular expressions:
|
100
148
|
|
101
149
|
Machete.matches?('[2]'.to_ast, 'ArrayLiteral<body = [any*, FixnumLiteral<value = 2>]>') # => true
|
102
150
|
Machete.matches?('[1, 2]'.to_ast, 'ArrayLiteral<body = [any*, FixnumLiteral<value = 2>]>') # => true
|
@@ -126,7 +174,8 @@ The best thing about array matching is that you can use quantifiers for elements
|
|
126
174
|
Machete.matches?('[1, 1, 2]'.to_ast, 'ArrayLiteral<body = [any{1,2}, FixnumLiteral<value = 2>]>') # => true
|
127
175
|
Machete.matches?('[1, 1, 1, 2]'.to_ast, 'ArrayLiteral<body = [any{1,2}, FixnumLiteral<value = 2>]>') # => false
|
128
176
|
|
129
|
-
There are also two unusual quantifiers: `{even}` and `{odd}`. They specify that
|
177
|
+
There are also two unusual quantifiers: `{even}` and `{odd}`. They specify that
|
178
|
+
the quantified expression must repeat even or odd number of times:
|
130
179
|
|
131
180
|
Machete.matches?('[1, 2]'.to_ast, 'ArrayLiteral<body = [any{even}, FixnumLiteral<value = 2>]>') # => false
|
132
181
|
Machete.matches?('[1, 1, 2]'.to_ast, 'ArrayLiteral<body = [any{even}, FixnumLiteral<value = 2>]>') # => true
|
@@ -134,26 +183,40 @@ There are also two unusual quantifiers: `{even}` and `{odd}`. They specify that
|
|
134
183
|
Machete.matches?('[1, 2]'.to_ast, 'ArrayLiteral<body = [any{odd}, FixnumLiteral<value = 2>]>') # => true
|
135
184
|
Machete.matches?('[1, 1, 2]'.to_ast, 'ArrayLiteral<body = [any{odd}, FixnumLiteral<value = 2>]>') # => false
|
136
185
|
|
137
|
-
These quantifiers are best used when matching hashes containing a specific key
|
186
|
+
These quantifiers are best used when matching hashes containing a specific key
|
187
|
+
or value. This is because in Rubinius AST both hash keys and values are
|
188
|
+
flattened into one array and the only thing distinguishing them is even or odd
|
189
|
+
position.
|
138
190
|
|
139
191
|
### More Information
|
140
192
|
|
141
|
-
For more details about the syntax see the `lib/machete/parser.y` file which
|
193
|
+
For more details about the syntax see the `lib/machete/parser.y` file which
|
194
|
+
contains the pattern parser.
|
142
195
|
|
143
196
|
FAQ
|
144
197
|
---
|
145
198
|
|
146
|
-
**Why did you chose Rubinius AST as a base? Aren't there other tools for Ruby
|
199
|
+
**Why did you chose Rubinius AST as a base? Aren't there other tools for Ruby
|
200
|
+
parsing which are not VM-specific?**
|
147
201
|
|
148
202
|
There are three other tools which were considered but each has its issues:
|
149
203
|
|
150
|
-
* [parse_tree](http://parsetree.rubyforge.org/) — unmaintained and unsupported
|
151
|
-
|
152
|
-
* [
|
204
|
+
* [parse_tree](http://parsetree.rubyforge.org/) — unmaintained and unsupported
|
205
|
+
for 1.9
|
206
|
+
* [ruby_parser](http://parsetree.rubyforge.org/) — sometimes reports wrong line
|
207
|
+
numbers for the nodes (this is a killer for some use cases)
|
208
|
+
* [Ripper](http://rubyforge.org/projects/ripper/) — usable but the generated AST
|
209
|
+
is too low level (the patterns would be too complex and low-level)
|
153
210
|
|
154
211
|
Rubinius AST is also by far the easiest to work with.
|
155
212
|
|
213
|
+
Compatibility
|
214
|
+
-------------
|
215
|
+
|
216
|
+
Machete is compatible with both the 1.8 and 1.9 mode of Rubinius.
|
217
|
+
|
156
218
|
Acknowledgement
|
157
219
|
---------------
|
158
220
|
|
159
|
-
The general idea and inspiration for the pattern syntax was taken form Python's
|
221
|
+
The general idea and inspiration for the pattern syntax was taken form Python's
|
222
|
+
[2to3](http://docs.python.org/library/2to3.html) tool.
|
data/Rakefile
CHANGED
@@ -5,8 +5,8 @@ desc "Generate the expression parser"
|
|
5
5
|
task :parser do
|
6
6
|
source = "lib/machete/parser.y"
|
7
7
|
target = "lib/machete/parser.rb"
|
8
|
-
unless uptodate?(target, source)
|
9
|
-
|
8
|
+
unless uptodate?(target, [source])
|
9
|
+
sh "racc -o #{target} #{source}"
|
10
10
|
end
|
11
11
|
end
|
12
12
|
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.
|
1
|
+
0.5.0
|
data/lib/machete.rb
CHANGED
@@ -3,53 +3,97 @@ require File.expand_path(File.dirname(__FILE__) + "/machete/parser")
|
|
3
3
|
require File.expand_path(File.dirname(__FILE__) + "/machete/version")
|
4
4
|
|
5
5
|
module Machete
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
6
|
+
class << self
|
7
|
+
# Matches a Rubinius AST node against a pattern.
|
8
|
+
#
|
9
|
+
# @param [Rubinius::AST::Node] node node to match
|
10
|
+
# @param [String, Machete::Matchers::Matcher] pattern pattern to match the
|
11
|
+
# node against, either as a string (see {file:README.md} for syntax
|
12
|
+
# description) or in compiled form
|
13
|
+
#
|
14
|
+
# @example Test using a string pattern
|
15
|
+
# Machete.matches?('foo.bar'.to_ast, 'Send<name = :bar>')
|
16
|
+
# # => true
|
17
|
+
#
|
18
|
+
# Machete.matches?('42'.to_ast, 'Send<name = :bar>')
|
19
|
+
# # => false
|
20
|
+
#
|
21
|
+
# @example Test using a compiled pattern
|
22
|
+
# Machete.matches?(
|
23
|
+
# 'foo.bar'.to_ast,
|
24
|
+
# Machete::Matchers::NodeMatcher.new("Send",
|
25
|
+
# :name => Machete::Matchers::LiteralMatcher.new(:bar)
|
26
|
+
# )
|
27
|
+
# )
|
28
|
+
# # => true
|
29
|
+
#
|
30
|
+
# Machete.matches?(
|
31
|
+
# '42'.to_ast,
|
32
|
+
# Machete::Matchers::NodeMatcher.new("Send",
|
33
|
+
# :name => Machete::Matchers::LiteralMatcher.new(:bar)
|
34
|
+
# )
|
35
|
+
# )
|
36
|
+
# # => false
|
37
|
+
#
|
38
|
+
# @return [Boolean] +true+ if the node matches the pattern, +false+
|
39
|
+
# otherwise
|
40
|
+
#
|
41
|
+
# @raise [Matchete::Parser::SyntaxError] if the pattern is invalid
|
42
|
+
def matches?(node, pattern)
|
43
|
+
compiled_pattern(pattern).matches?(node)
|
44
|
+
end
|
45
|
+
|
46
|
+
# Finds all nodes in a Rubinius AST matching a pattern.
|
47
|
+
#
|
48
|
+
# @param [Rubinius::AST::Node] ast tree to search
|
49
|
+
# @param [String, Machete::Matchers::Matcher] pattern pattern to match the
|
50
|
+
# nodes against, either as a string (see {file:README.md} for syntax
|
51
|
+
# description) or in compiled form
|
52
|
+
#
|
53
|
+
# @example Search using a string pattern
|
54
|
+
# Machete.find('42 + 43 + 44'.to_ast, 'FixnumLiteral')
|
55
|
+
# # => [
|
56
|
+
# # #<Rubinius::AST::FixnumLiteral:0x10b0 @value=44 @line=1>,
|
57
|
+
# # #<Rubinius::AST::FixnumLiteral:0x10b8 @value=43 @line=1>,
|
58
|
+
# # #<Rubinius::AST::FixnumLiteral:0x10c0 @value=42 @line=1>
|
59
|
+
# # ]
|
60
|
+
#
|
61
|
+
# @example Search using a compiled pattern
|
62
|
+
# Machete.find(
|
63
|
+
# '42 + 43 + 44'.to_ast,
|
64
|
+
# Machete::Matchers::NodeMatcher.new("FixnumLiteral")
|
65
|
+
# )
|
66
|
+
# # => [
|
67
|
+
# # #<Rubinius::AST::FixnumLiteral:0x10b0 @value=44 @line=1>,
|
68
|
+
# # #<Rubinius::AST::FixnumLiteral:0x10b8 @value=43 @line=1>,
|
69
|
+
# # #<Rubinius::AST::FixnumLiteral:0x10c0 @value=42 @line=1>
|
70
|
+
# # ]
|
71
|
+
#
|
72
|
+
# @return [Array] list of matching nodes (in unspecified order)
|
73
|
+
#
|
74
|
+
# @raise [Matchete::Parser::SyntaxError] if the pattern is invalid
|
75
|
+
def find(ast, pattern)
|
76
|
+
matcher = compiled_pattern(pattern)
|
25
77
|
|
26
|
-
|
27
|
-
|
28
|
-
# @param [Rubinius::AST::Node] ast tree to search
|
29
|
-
# @param [String] pattern pattern to match the nodes against (see {file:README.md} for syntax description)
|
30
|
-
#
|
31
|
-
# @example
|
32
|
-
# Machete.find('42 + 43 + 44'.to_ast, 'FixnumLiteral')
|
33
|
-
# # => [
|
34
|
-
# # #<Rubinius::AST::FixnumLiteral:0x10b0 @value=44 @line=1>,
|
35
|
-
# # #<Rubinius::AST::FixnumLiteral:0x10b8 @value=43 @line=1>,
|
36
|
-
# # #<Rubinius::AST::FixnumLiteral:0x10c0 @value=42 @line=1>
|
37
|
-
# # ]
|
38
|
-
#
|
39
|
-
# @return [Array] list of matching nodes (in unspecified order)
|
40
|
-
#
|
41
|
-
# @raise [Matchete::Parser::SyntaxError] if the pattern is invalid
|
42
|
-
def self.find(ast, pattern)
|
43
|
-
matcher = Parser.new.parse(pattern)
|
78
|
+
result = []
|
79
|
+
result << ast if matcher.matches?(ast)
|
44
80
|
|
45
|
-
|
46
|
-
|
81
|
+
ast.walk(true) do |dummy, node|
|
82
|
+
result << node if matcher.matches?(node)
|
83
|
+
true
|
84
|
+
end
|
47
85
|
|
48
|
-
|
49
|
-
result << node if matcher.matches?(node)
|
50
|
-
true
|
86
|
+
result
|
51
87
|
end
|
52
88
|
|
53
|
-
|
89
|
+
private
|
90
|
+
|
91
|
+
def compiled_pattern(pattern)
|
92
|
+
if pattern.is_a?(String)
|
93
|
+
Parser.new.parse(pattern)
|
94
|
+
else
|
95
|
+
pattern
|
96
|
+
end
|
97
|
+
end
|
54
98
|
end
|
55
99
|
end
|
data/lib/machete/matchers.rb
CHANGED
@@ -1,7 +1,5 @@
|
|
1
1
|
module Machete
|
2
|
-
# @private
|
3
2
|
module Matchers
|
4
|
-
# @private
|
5
3
|
class Quantifier
|
6
4
|
# :min should be always set, :max can be nil (meaning infinity)
|
7
5
|
attr_reader :matcher, :min, :max, :step
|
@@ -19,8 +17,10 @@ module Machete
|
|
19
17
|
end
|
20
18
|
end
|
21
19
|
|
22
|
-
|
23
|
-
|
20
|
+
class Matcher
|
21
|
+
end
|
22
|
+
|
23
|
+
class ChoiceMatcher < Matcher
|
24
24
|
attr_reader :alternatives
|
25
25
|
|
26
26
|
def initialize(alternatives)
|
@@ -36,8 +36,7 @@ module Machete
|
|
36
36
|
end
|
37
37
|
end
|
38
38
|
|
39
|
-
|
40
|
-
class NodeMatcher
|
39
|
+
class NodeMatcher < Matcher
|
41
40
|
attr_reader :class_name, :attrs
|
42
41
|
|
43
42
|
def initialize(class_name, attrs = {})
|
@@ -56,8 +55,7 @@ module Machete
|
|
56
55
|
end
|
57
56
|
end
|
58
57
|
|
59
|
-
|
60
|
-
class ArrayMatcher
|
58
|
+
class ArrayMatcher < Matcher
|
61
59
|
attr_reader :items
|
62
60
|
|
63
61
|
def initialize(items)
|
@@ -119,8 +117,7 @@ module Machete
|
|
119
117
|
end
|
120
118
|
end
|
121
119
|
|
122
|
-
|
123
|
-
class LiteralMatcher
|
120
|
+
class LiteralMatcher < Matcher
|
124
121
|
attr_reader :literal
|
125
122
|
|
126
123
|
def initialize(literal)
|
@@ -136,8 +133,7 @@ module Machete
|
|
136
133
|
end
|
137
134
|
end
|
138
135
|
|
139
|
-
|
140
|
-
class StringRegexpMatcher
|
136
|
+
class RegexpMatcher < Matcher
|
141
137
|
attr_reader :regexp
|
142
138
|
|
143
139
|
def initialize(regexp)
|
@@ -147,14 +143,28 @@ module Machete
|
|
147
143
|
def ==(other)
|
148
144
|
other.instance_of?(self.class) && @regexp == other.regexp
|
149
145
|
end
|
146
|
+
end
|
150
147
|
|
148
|
+
class SymbolRegexpMatcher < RegexpMatcher
|
149
|
+
def matches?(node)
|
150
|
+
node.is_a?(Symbol) && node.to_s =~ @regexp
|
151
|
+
end
|
152
|
+
end
|
153
|
+
|
154
|
+
class StringRegexpMatcher < RegexpMatcher
|
151
155
|
def matches?(node)
|
152
156
|
node.is_a?(String) && node =~ @regexp
|
153
157
|
end
|
154
158
|
end
|
155
159
|
|
156
|
-
|
157
|
-
|
160
|
+
class IndifferentRegexpMatcher < RegexpMatcher
|
161
|
+
def matches?(node)
|
162
|
+
(node.is_a?(Symbol) && node.to_s =~ @regexp) ||
|
163
|
+
(node.is_a?(String) && node =~ @regexp)
|
164
|
+
end
|
165
|
+
end
|
166
|
+
|
167
|
+
class AnyMatcher < Matcher
|
158
168
|
def ==(other)
|
159
169
|
other.instance_of?(self.class)
|
160
170
|
end
|