lib/jsonpath/parser.rb in jsonpath-1.0.5 vs lib/jsonpath/parser.rb in jsonpath-1.0.6

- old
+ new

@@ -1,13 +1,14 @@ # frozen_string_literal: true require 'strscan' -require 'to_regexp' class JsonPath # Parser parses and evaluates an expression passed to @_current_node. class Parser + REGEX = /\A\/(.+)\/([imxnesu]*)\z|\A%r{(.+)}([imxnesu]*)\z/ + def initialize(node) @_current_node = node @_expr_map = {} end @@ -69,17 +70,20 @@ elsif (t = scanner.scan(/(\s+)?[<>=!\-+][=~]?(\s+)?/)) operator = t elsif (t = scanner.scan(/(\s+)?'?.*'?(\s+)?/)) # If we encounter a node which does not contain `'` it means #  that we are dealing with a boolean type. - operand = if t == 'true' - true - elsif t == 'false' - false - else - operator.to_s.strip == '=~' ? t.to_regexp : t.gsub(%r{^'|'$}, '').strip - end + operand = + if t == 'true' + true + elsif t == 'false' + false + elsif operator.to_s.strip == '=~' + parse_regex(t) + else + t.gsub(%r{^'|'$}, '').strip + end elsif (t = scanner.scan(/\/\w+\//)) elsif (t = scanner.scan(/.*/)) raise "Could not process symbol: #{t}" end end @@ -99,9 +103,34 @@ el.__send__(operator.strip, operand) end private + + # /foo/i -> Regex.new("foo", Regexp::IGNORECASE) without using eval + # also supports %r{foo}i + # following https://github.com/seamusabshere/to_regexp/blob/master/lib/to_regexp.rb + def parse_regex(t) + t =~ REGEX + content = $1 || $3 + options = $2 || $4 + + raise "unsupported regex #{t} use /foo/ style" if !content || !options + + content = content.gsub '\\/', '/' + + flags = 0 + flags |= Regexp::IGNORECASE if options.include?('i') + flags |= Regexp::MULTILINE if options.include?('m') + flags |= Regexp::EXTENDED if options.include?('x') + + # 'n' = none, 'e' = EUC, 's' = SJIS, 'u' = UTF-8 + lang = options.scan(/[nes]/).join.downcase # ignores u since that is default and causes a warning + + args = [content, flags] + args << lang unless lang.empty? # avoid warning + Regexp.new(*args) + end #  This will break down a parenthesis from the left to the right #  and replace the given expression with it's returned value. # It does this in order to make it easy to eliminate groups # one-by-one.