Sha256: ee99d630bbc431a3a20b03035666233cde198bd42cef4c078119d5eb1ab4f02d

Contents?: true

Size: 1.93 KB

Versions: 1

Compression:

Stored size: 1.93 KB

Contents

require 'strscan'
require 'to_regexp'

class JsonPath
  # Parser parses and evaluates an expression passed to @_current_node.
  class Parser
    def initialize(node)
      @_current_node = node
    end

    def parse(exp)
      exps = exp.split(/(&&)|(\|\|)/)
      ret = parse_exp(exps.shift)
      exps.each_with_index do |item, index|
        case item
        when '&&'
          ret &&= parse_exp(exps[index + 1])
        when '||'
          ret ||= parse_exp(exps[index + 1])
        end
      end
      ret
    end

    def parse_exp(exp)
      exp = exp.sub(/@/, '').gsub(/^\(/, '').gsub(/\)$/, '').gsub(/"/, '\'').strip
      scanner = StringScanner.new(exp)
      elements = []
      until scanner.eos?
        if scanner.scan(/\./)
          sym = scanner.scan(/\w+/)
          op = scanner.scan(/./)
          num = scanner.scan(/\d+/)
          return @_current_node.send(sym.to_sym).send(op.to_sym, num.to_i)
        end
        if t = scanner.scan(/\['[a-zA-Z@&\*\/\$%\^\?_]+'\]+/)
          elements << t.gsub(/\[|\]|'|\s+/, '')
        elsif t = scanner.scan(/(\s+)?[<>=][=~]?(\s+)?/)
          operator = t
        elsif t = scanner.scan(/(\s+)?'?.*'?(\s+)?/)
          operand = operator.strip == "=~" ? t.to_regexp : t.delete("'").strip
        elsif t = scanner.scan(/\/\w+\//)

        elsif t = scanner.scan(/.*/)
          raise "Could not process symbol: #{t}"
        end
      end
      el = dig(elements, @_current_node)
      return false unless el
      return true if operator.nil? && el

      el = Float(el) rescue el
      operand = Float(operand) rescue operand
      el.send(operator.strip, operand)
    end

    private

    # @TODO: Remove this once JsonPath no longer supports ruby versions below 2.3
    def dig(keys, hash)
      return hash unless hash.is_a? Hash
      return nil unless hash.key?(keys.first)
      return hash.fetch(keys.first) if keys.size == 1
      prev = keys.shift
      dig(keys, hash.fetch(prev))
    end
  end
end

Version data entries

1 entries across 1 versions & 1 rubygems

Version Path
jsonpath-0.8.11 lib/jsonpath/parser.rb