Parent

Files

Parslet::Pattern

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.

Public Class Methods

new(pattern) click to toggle source
# File lib/parslet/pattern.rb, line 22
def initialize(pattern)
  @pattern = pattern
end

Public Instance Methods

element_match(tree, exp, bindings) click to toggle source

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.

@api private

# File lib/parslet/pattern.rb, line 49
def element_match(tree, exp, bindings) 
  # p [:elm, tree, exp]
  case [tree, exp].map { |e| e.class }
    when [Hash,Hash]
      return element_match_hash(tree, exp, bindings)
    when [Array,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) click to toggle source

@api private

# File lib/parslet/pattern.rb, line 89
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) click to toggle source

@api private

# File lib/parslet/pattern.rb, line 73
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) click to toggle source

@api private

# File lib/parslet/pattern.rb, line 98
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) click to toggle source

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' }

@param subtree [String, Hash, Array] poro subtree returned by a parse @param bindings [Hash] variable bindings to be verified @return [Hash, nil] On success: variable bindings that allow a match. On

failure: nil
# 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

[Validate]

Generated with the Darkfish Rdoc Generator 2.