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
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?
.
608 609 610 |
# File 'lib/sexp.rb', line 608 def self.match_subs= o @@match_subs = o end |
.match_subs? ⇒ Boolean
Should #=~ match sub-trees?
601 602 603 |
# File 'lib/sexp.rb', line 601 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)
690 691 692 |
# File 'lib/sexp.rb', line 690 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)]
663 664 665 666 667 668 |
# File 'lib/sexp.rb', line 663 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
646 647 648 649 650 651 |
# File 'lib/sexp.rb', line 646 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
710 711 712 |
# File 'lib/sexp.rb', line 710 def >> other Sibling.new self, other end |
#greedy? ⇒ Boolean
Is this matcher greedy? Defaults to false.
717 718 719 |
# File 'lib/sexp.rb', line 717 def greedy? false end |
#inspect ⇒ Object
:nodoc:
721 722 723 724 725 |
# File 'lib/sexp.rb', line 721 def inspect # :nodoc: s = super s[0] = "q" s end |
#pretty_print(q) ⇒ Object
:nodoc:
727 728 729 730 731 732 733 |
# File 'lib/sexp.rb', line 727 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?
623 624 625 626 627 628 629 630 631 632 633 634 635 636 |
# File 'lib/sexp.rb', line 623 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 |