Added Oga::Ruby::Node
This class will be used for building Ruby ASTs that will be generated based on XPath expressions.
This commit is contained in:
1 parent
c25879f18e
commit
6673f176d8
3 files changed
+280
No files matched your search
@@ -49,6 +49,8 @@ require 'oga/html/parser'
|
||||
require 'oga/html/sax_parser'
|
||||
require 'oga/html/entities'
|
||||
|
||||
require 'oga/ruby/node'
|
||||
|
||||
require 'oga/xpath/lexer'
|
||||
require 'oga/xpath/parser'
|
||||
require 'oga/xpath/evaluator'
|
||||
|
||||
@@ -0,0 +1,147 @@
|
||||
module Oga
|
||||
module Ruby
|
||||
##
|
||||
# Class representing a single node in a Ruby AST.
|
||||
#
|
||||
# The setup of this class is roughly based on the "ast" Gem. The "ast" Gem
|
||||
# is not used for this class as it provides too many methods that might
|
||||
# conflict with this class' {#method_missing}.
|
||||
#
|
||||
# ASTs can be built by creating a node and then chaining various method
|
||||
# calls together. For example, the following could be used to build an "if"
|
||||
# statement:
|
||||
#
|
||||
# number1 = Node.new(:lit, %w{10})
|
||||
# number2 = Node.new(:lit, %w{20})
|
||||
#
|
||||
# (number2 > number1).if_true do
|
||||
# Node.new(:lit, %w{30})
|
||||
# end
|
||||
#
|
||||
# When serialized to Ruby this would roughly lead to the following code:
|
||||
#
|
||||
# if 20 > 10
|
||||
# 30
|
||||
# end
|
||||
#
|
||||
# @private
|
||||
#
|
||||
class Node < BasicObject
|
||||
# @return [Symbol]
|
||||
attr_reader :type
|
||||
|
||||
# @param [Symbol] type
|
||||
# @param [Array] children
|
||||
def initialize(type, children = [])
|
||||
@type = type.to_sym
|
||||
@children = children
|
||||
end
|
||||
|
||||
# @return [Array]
|
||||
def to_a
|
||||
@children
|
||||
end
|
||||
|
||||
##
|
||||
# Returns an assignment node.
|
||||
#
|
||||
# @param [Oga::Ruby::Node] other
|
||||
# @return [Oga::Ruby::Node]
|
||||
#
|
||||
def assign(other)
|
||||
Node.new(:assign, [self, other])
|
||||
end
|
||||
|
||||
##
|
||||
# Returns an equality expression node.
|
||||
#
|
||||
# @param [Oga::Ruby::Node] other
|
||||
# @return [Oga::Ruby::Node]
|
||||
#
|
||||
def eq(other)
|
||||
Node.new(:eq, [self, other])
|
||||
end
|
||||
|
||||
##
|
||||
# Returns a boolean "and" node.
|
||||
#
|
||||
# @param [Oga::Ruby::Node] other
|
||||
# @return [Oga::Ruby::Node]
|
||||
#
|
||||
def and(other)
|
||||
Node.new(:and, [self, other])
|
||||
end
|
||||
|
||||
##
|
||||
# Returns a boolean "or" node.
|
||||
#
|
||||
# @param [Oga::Ruby::Node] other
|
||||
# @return [Oga::Ruby::Node]
|
||||
#
|
||||
def or(other)
|
||||
Node.new(:or, [self, other])
|
||||
end
|
||||
|
||||
##
|
||||
# Returns a node for Ruby's "is_a?" method.
|
||||
#
|
||||
# @param [Class] klass
|
||||
# @return [Oga::Ruby::Node]
|
||||
#
|
||||
def is_a?(klass)
|
||||
Node.new(:send, [self, 'is_a?', Node.new(:lit, [klass.to_s])])
|
||||
end
|
||||
|
||||
##
|
||||
# Wraps the current node in a block.
|
||||
#
|
||||
# @param [Array] args Arguments (as Node instances) to pass to the block.
|
||||
# @return [Oga::Ruby::Node]
|
||||
#
|
||||
def add_block(*args)
|
||||
Node.new(:block, [self, args, yield])
|
||||
end
|
||||
|
||||
##
|
||||
# Wraps the current node in an if statement node.
|
||||
#
|
||||
# The body of this statement is set to the return value of the supplied
|
||||
# block.
|
||||
#
|
||||
# @return [Oga::Ruby::Node]
|
||||
#
|
||||
def if_true
|
||||
Node.new(:if, [self, yield])
|
||||
end
|
||||
|
||||
##
|
||||
# Chains two nodes together.
|
||||
#
|
||||
# @param [Oga::Ruby::Node] other
|
||||
# @return [Oga::Ruby::Node]
|
||||
#
|
||||
def followed_by(other)
|
||||
Node.new(:begin, [self, other])
|
||||
end
|
||||
|
||||
##
|
||||
# Returns a node for a method call.
|
||||
#
|
||||
# @param [Symbol] name The name of the method to call.
|
||||
#
|
||||
# @param [Array] args Any arguments (as Node instances) to pass to the
|
||||
# method.
|
||||
#
|
||||
# @return [Oga::Ruby::Node]
|
||||
#
|
||||
def method_missing(name, *args)
|
||||
Node.new(:send, [self, name.to_s, *args])
|
||||
end
|
||||
|
||||
# @return [String]
|
||||
def inspect
|
||||
"(#{type} #{@children.map(&:inspect).join(' ')})"
|
||||
end
|
||||
end # Node
|
||||
end # Ruby
|
||||
end # Oga
|
||||
Reference in new issue
Block a user