Class: Sexp::Matcher
Overview
Defines a family of objects that can be used to match sexps to certain types of patterns, much like regexps can be used on strings. Generally you won’t use this class directly.
You would normally create a matcher using the top-level #s method, but with a block, calling into the Sexp factory methods. For example:
s{ s(:class, m(/^Test/), _, ___) }
This creates a matcher for classes whose names start with “Test”. It uses Sexp.m to create a Sexp::Matcher::Pattern matcher, Sexp._ to create a Sexp::Matcher::Wild matcher, and Sexp._ to create a Sexp::Matcher::Remaining matcher. It works like this:
s{ # start to create a pattern
s( # create a sexp matcher
:class. # for class nodes
m(/^Test/), # matching name slots that start with "Test"
_, # any superclass value
___ # and whatever is in the class
)
}
Then you can use that with #=~, #/, Sexp#replace_sexp, and others.
For more examples, see the various Sexp class methods, the examples, and the tests supplied with Sexp.
-
For pattern creation, see factory methods: Sexp::_, Sexp::_, etc.
-
For matching returning truthy/falsey results, see Sexp#=~.
-
For case expressions, see Matcher#===.
-
For getting all subtree matches, see Sexp#/.
If rdoc didn’t suck, these would all be links.
Direct Known Subclasses
All, Any, Atom, Child, Include, Not, Pattern, Remaining, Sibling, Type, Wild
Defined Under Namespace
Classes: Parser
Constant Summary
Constants inherited from Sexp
Instance Attribute Summary
Attributes inherited from Sexp
Class Method Summary collapse
-
.match_subs=(o) ⇒ Object
Setter for
match_subs?
. -
.match_subs? ⇒ Boolean
Should #=~ match sub-trees?.
-
.parse(s) ⇒ Object
Parse a lispy string representation of a matcher into a Matcher.
Instance Method Summary collapse
-
#&(other) ⇒ Object
Combines the Matcher with another Matcher, the resulting one will be satisfied only if both Matchers would be satisfied.
-
#-@ ⇒ Object
Returns a Matcher that matches whenever this Matcher would not have matched.
-
#/(sexp) ⇒ Object
Searches through
sexp
for all sub-trees that match this matcher and returns a MatchCollection for each match. -
#=~(sexp) ⇒ Object
(also: #===)
Tree equivalent to String#=~, returns true if
self
matchessexp
as a whole or in a sub-tree (ifmatch_subs?
). -
#>>(other) ⇒ Object
Returns a Matcher that matches if this has a sibling
o
. -
#greedy? ⇒ Boolean
Is this matcher greedy? Defaults to false.
-
#inspect ⇒ Object
:nodoc:.
-
#pretty_print(q) ⇒ Object
:nodoc:.
-
#satisfy?(o) ⇒ Boolean
Does this matcher actually match
o
? Returns falsey ifo
is not a Sexp or if any sub-tree ofo
is not satisfied by or equal to its corresponding sub-matcher. -
#|(other) ⇒ Object
Combines the Matcher with another Matcher, the resulting one will be satisfied if either Matcher would be satisfied.
Methods inherited from Sexp
#==, _, ___, all, any, #array_type?, atom, child, #compact, #deep_each, #depth, #each_of_type, #each_sexp, #find_and_replace_all, #find_node, #find_nodes, from_array, #gsub, include, #initialize, #line_max, m, #map, #mass, #method_missing, #new, not?, #replace_sexp, #respond_to?, s, #search_each, #sexp_body, #sexp_body=, #sexp_type, #sexp_type=, #shift, #structure, #sub, t, #to_a
Constructor Details
This class inherits a constructor from Sexp
Dynamic Method Handling
This class handles dynamic methods through the method_missing method in the class Sexp
Class Method Details
.match_subs=(o) ⇒ Object
Setter for match_subs?
.
611 612 613 |
# File 'lib/sexp.rb', line 611 def self.match_subs= o @@match_subs = o end |
.match_subs? ⇒ Boolean
Should #=~ match sub-trees?
604 605 606 |
# File 'lib/sexp.rb', line 604 def self.match_subs? @@match_subs end |
Instance Method Details
#&(other) ⇒ Object
Combines the Matcher with another Matcher, the resulting one will be satisfied only if both Matchers would be satisfied.
TODO: redirect Example:
t(:a) & include(:b)
693 694 695 |
# File 'lib/sexp.rb', line 693 def & other All.new self, other end |
#/(sexp) ⇒ Object
Searches through sexp
for all sub-trees that match this matcher and returns a MatchCollection for each match.
TODO: redirect? Example:
Q{ s(:b) } / s(:a, s(:b)) => [s(:b)]
666 667 668 669 670 671 |
# File 'lib/sexp.rb', line 666 def / sexp raise ArgumentError, "can't both be matchers" if Matcher === sexp # TODO: move search_each into matcher? MatchCollection.new sexp.search_each(self).to_a end |
#=~(sexp) ⇒ Object Also known as: ===
Tree equivalent to String#=~, returns true if self
matches sexp
as a whole or in a sub-tree (if match_subs?
).
TODO: maybe this should NOT be aliased to === ?
TODO: example
649 650 651 652 653 654 |
# File 'lib/sexp.rb', line 649 def =~ sexp raise ArgumentError, "Can't both be matchers: %p" % [sexp] if Matcher === sexp self.satisfy?(sexp) || (self.class.match_subs? && sexp.each_sexp.any? { |sub| self =~ sub }) end |
#>>(other) ⇒ Object
713 714 715 |
# File 'lib/sexp.rb', line 713 def >> other Sibling.new self, other end |
#greedy? ⇒ Boolean
Is this matcher greedy? Defaults to false.
720 721 722 |
# File 'lib/sexp.rb', line 720 def greedy? false end |
#inspect ⇒ Object
:nodoc:
724 725 726 727 728 |
# File 'lib/sexp.rb', line 724 def inspect # :nodoc: s = super s[0] = "q" s end |
#pretty_print(q) ⇒ Object
:nodoc:
730 731 732 733 734 735 736 |
# File 'lib/sexp.rb', line 730 def pretty_print q # :nodoc: q.group 1, "q(", ")" do q.seplist self do |v| q.pp v end end end |
#satisfy?(o) ⇒ Boolean
Does this matcher actually match o
? Returns falsey if o
is not a Sexp or if any sub-tree of o
is not satisfied by or equal to its corresponding sub-matcher.
– TODO: push this up to Sexp and make this the workhorse TODO: do the same with ===/satisfy?
626 627 628 629 630 631 632 633 634 635 636 637 638 639 |
# File 'lib/sexp.rb', line 626 def satisfy? o return unless o.kind_of?(Sexp) && (length == o.length || Matcher === last && last.greedy?) each_with_index.all? { |child, i| sexp = o.at i if Sexp === child then # TODO: when will this NOT be a matcher? sexp = o.sexp_body i if child.respond_to?(:greedy?) && child.greedy? child.satisfy? sexp else child == sexp end } end |