class Mobj::Token

Public Class Methods

new(type, *args) click to toggle source
# File lib/mobj.rb, line 17
def initialize(type, *args)
  @type, @path, @options = type.to_sym, nil, {}
  tokens = []
  args.each do |arg|
    if arg.h?
      @options.merge!(arg)
    elsif arg.s?
      tokens << arg.sym
    else
      tokens << arg
    end
  end
  @path = tokens.sequester!
end

Public Instance Methods

extract(obj, path) click to toggle source
# File lib/mobj.rb, line 34
def extract(obj, path)
  obj.__mobj__reparent
  if path == :* || obj.nil?
    obj
  elsif obj.a?
    if path[0] == '*' && obj.respond_to?(path[1..-1].sym)
      obj.__send__(path[1..-1].sym)
    else
      obj.map { |o| extract(o, path) }
    end
  elsif path.a?
    path.map { |pth| obj[pth.sym] }
  elsif path[0] == '*' && obj.respond_to?(path[1..-1].sym)
    obj.__send__(path[1..-1].sym)
  elsif obj.respond_to?(:[]) && (obj.h? || path.to_s =~ /[0-9.-]+/)
    if obj.h?
      obj[path.sym]
    else
      obj[path.to_s.to_i] if path.to_s =~ /^\d+$/
    end
  elsif obj.respond_to?(path.sym)
    obj.__send__(path.sym)
  else
    nil
  end
end
find(obj, match) click to toggle source
# File lib/mobj.rb, line 61
def find(obj, match)
  if obj.a?
    obj.map do |child|
      find(child, match)
    end
  elsif obj.respond_to?(:keys)
    found = obj.keys.each.with_object({}) { |key, fnd|
      m = key.to_s.match(match)
      fnd[key] = m if m
    }

    flat = found.values.flat_map(&:captures).empty?

    found.each.with_object(flat ? [] : {}) { |(key, m), map|
      if map.a?
        map << obj[key]
      else
        named = m.to_h.invert
        name = if named.empty?
          m.captures.empty? ? key : m.captures.sequester!
        else
          named.find { |k, v| !k.nil? }.attempt(key).last
        end
        map[name] = obj[key]
      end
    }

  end
end
to_s() click to toggle source
# File lib/mobj.rb, line 32
def to_s() "#{@type.to_s.upcase}(#@path#{ " => #@options" unless @options.empty?})" end
walk(obj, root = obj) click to toggle source
# File lib/mobj.rb, line 91
def walk(obj, root = obj)
  obj, root = Circle.wrap!(obj), Circle.wrap!(root)
  val = case @type
          when :literal
            @path.to_s
          when :path
            extract(obj, @path)
          when :regex
            find(obj, @path)
          when :up
            if obj.respond_to? :parent
              obj.__mobj__parent || obj.__mobj__parent
            else
              obj.__mobj__parent
            end
          when :any
            if obj.a?
              obj.map { |o| walk(o, root) }
            else
              @path.return_first { |token| token.walk(obj, root) }
            end
          when :all
            matches = @path.map { |token| token.walk(obj, root) }
            matches.compact.size == @path.size ? matches : nil
          when :each
            @path.map { |token| token.walk(obj, root) }
          when :lookup
            lookup = @path.walk(obj)
            if lookup.a?
              lookup.flatten.map { |lu| lu.tokenize.walk(root) }.flatten(1)
            else
              lookup.tokenize.walk(root)
            end
          when :inverse
            raise "not implemented yet. not sure how to implement yet, actually. please continue to hold. your call is important to us."
          when :root
            tree = [@path].flatten
            while (path = tree.shift)
              obj = path.walk(obj)
            end
            obj.a? ? obj.flatten : obj
        end

  val = @options[:indexes] ? val.values_at(*@options[:indexes]) : val
  val
end