Class: Parslet::Pattern
- Inherits:
-
Object
- Object
- Parslet::Pattern
- Defined in:
- lib/parslet/pattern.rb
Overview
Matches trees against expressions. Trees are formed by arrays and hashes for expressing membership and sequence. The leafs of the tree are other classes.
A tree issued by the parslet library might look like this:
{
:function_call => {
:name => 'foobar',
:args => [1, 2, 3]
}
}
A pattern that would match against this tree would be:
{ :function_call => { :name => simple(:name), :args => sequence(:args) }}
Note that Parslet::Pattern only matches at a given subtree; it wont try to match recursively. To do that, please use Parslet::Transform.
Defined Under Namespace
Classes: SequenceBind, SimpleBind, SubtreeBind
Instance Method Summary collapse
-
#element_match(tree, exp, bindings) ⇒ Object
private
Returns true if the tree element given by
tree
matches the expression given byexp
. - #element_match_ary_single(sequence, exp, bindings) ⇒ Object private
- #element_match_binding(tree, exp, bindings) ⇒ Object private
- #element_match_hash(tree, exp, bindings) ⇒ Object private
-
#initialize(pattern) ⇒ Pattern
constructor
A new instance of Pattern.
-
#match(subtree, bindings = nil) ⇒ Hash?
Decides if the given subtree matches this pattern.
Constructor Details
#initialize(pattern) ⇒ Pattern
Returns a new instance of Pattern.
22 23 24 |
# File 'lib/parslet/pattern.rb', line 22 def initialize(pattern) @pattern = pattern end |
Instance Method Details
#element_match(tree, exp, bindings) ⇒ Object
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Returns true if the tree element given by tree
matches the expression given by exp
. This match must respect bindings already made in bindings
. Note that bindings is carried along and modified.
49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 |
# File 'lib/parslet/pattern.rb', line 49 def element_match(tree, exp, bindings) # p [:elm, tree, exp] if tree.is_a?(Hash) && exp.is_a?(Hash) return element_match_hash(tree, exp, bindings) elsif tree.is_a?(Array) && exp.is_a?(Array) return element_match_ary_single(tree, exp, bindings) else # If elements match exactly, then that is good enough in all cases return true if exp === tree # If exp is a bind variable: Check if the binding matches if exp.respond_to?(:can_bind?) && exp.can_bind?(tree) return element_match_binding(tree, exp, bindings) end # Otherwise: No match (we don't know anything about the element # combination) return false end end |
#element_match_ary_single(sequence, exp, bindings) ⇒ Object
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
88 89 90 91 92 93 |
# File 'lib/parslet/pattern.rb', line 88 def element_match_ary_single(sequence, exp, bindings) return false if sequence.size != exp.size return sequence.zip(exp).all? { |elt, subexp| element_match(elt, subexp, bindings) } end |
#element_match_binding(tree, exp, bindings) ⇒ Object
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
72 73 74 75 76 77 78 79 80 81 82 83 84 |
# File 'lib/parslet/pattern.rb', line 72 def element_match_binding(tree, exp, bindings) var_name = exp.variable_name # TODO test for the hidden :_ feature. if var_name && bound_value = bindings[var_name] return bound_value == tree end # New binding: bindings.store var_name, tree return true end |
#element_match_hash(tree, exp, bindings) ⇒ Object
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 |
# File 'lib/parslet/pattern.rb', line 97 def element_match_hash(tree, exp, bindings) # Early failure when one hash is bigger than the other return false unless exp.size == tree.size # We iterate over expected pattern, since we demand that the keys that # are there should be in tree as well. exp.each do |expected_key, expected_value| return false unless tree.has_key? expected_key # Recurse into the value and stop early on failure value = tree[expected_key] return false unless element_match(value, expected_value, bindings) end return true end |
#match(subtree, bindings = nil) ⇒ Hash?
Decides if the given subtree matches this pattern. Returns the bindings made on a successful match or nil if the match fails. If you specify bindings to be a hash, the mappings in it will be treated like bindings made during an attempted match.
Pattern.new('a').match('a', :foo => 'bar') # => { :foo => 'bar' }
38 39 40 41 |
# File 'lib/parslet/pattern.rb', line 38 def match(subtree, bindings=nil) bindings = bindings && bindings.dup || Hash.new return bindings if element_match(subtree, @pattern, bindings) end |