Class: Synvert::Core::NodeQuery::Compiler::Expression

Inherits:
Object
  • Object
show all
Defined in:
lib/synvert/core/node_query/compiler/expression.rb

Overview

Expression represents a node query expression.

Instance Method Summary collapse

Constructor Details

#initialize(selector: nil, rest: nil, relationship: nil) ⇒ Expression

Initialize a Expression.



10
11
12
13
14
# File 'lib/synvert/core/node_query/compiler/expression.rb', line 10

def initialize(selector: nil, rest: nil, relationship: nil)
  @selector = selector
  @rest = rest
  @relationship = relationship
end

Instance Method Details

#match?(node) ⇒ Boolean

Check if the node matches the expression.



19
20
21
# File 'lib/synvert/core/node_query/compiler/expression.rb', line 19

def match?(node)
  !query_nodes(node).empty?
end

#query_nodes(node, descendant_match: true) ⇒ Array<Parser::AST::Node>

Query nodes by the expression.

  • If relationship is nil, it will match in all recursive child nodes and return matching nodes.

  • If relationship is :decendant, it will match in all recursive child nodes.

  • If relationship is :child, it will match in direct child nodes.

  • If relationship is :next_sibling, it try to match next sibling node.

  • If relationship is :subsequent_sibling, it will match in all sibling nodes.



33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
# File 'lib/synvert/core/node_query/compiler/expression.rb', line 33

def query_nodes(node, descendant_match: true)
  matching_nodes = find_nodes_without_relationship(node, descendant_match: descendant_match)
  if @relationship.nil?
    return matching_nodes
  end

  expression_nodes = matching_nodes.map do |matching_node|
    case @relationship
    when :descendant
      nodes = []
      matching_node.recursive_children { |child_node|
        nodes += @rest.query_nodes(child_node, descendant_match: false)
      }
      nodes
    when :child
      matching_node.children.map { |child_node| @rest.query_nodes(child_node, descendant_match: false) }
                   .flatten
    when :next_sibling
      @rest.query_nodes(matching_node.siblings.first, descendant_match: false)
    when :subsequent_sibling
      matching_node.siblings.map { |sibling_node| @rest.query_nodes(sibling_node, descendant_match: false) }
                   .flatten
    end
  end.flatten
end

#to_sObject



59
60
61
62
63
64
65
66
67
68
69
70
71
# File 'lib/synvert/core/node_query/compiler/expression.rb', line 59

def to_s
  return @selector.to_s unless @rest

  result = []
  result << @selector if @selector
  case @relationship
  when :child then result << '>'
  when :subsequent_sibling then result << '~'
  when :next_sibling then result << '+'
  end
  result << @rest
  result.map(&:to_s).join(' ')
end