Sha256: 669d6d6462d37fe3abc742019069ebb0f9ee538c97bdd21903f078025cca3ab0

Contents?: true

Size: 1.83 KB

Versions: 6

Compression:

Stored size: 1.83 KB

Contents

require 'strscan'

module TogoStanza::Stanza
  class SearchQuery
    def initialize(query)
      @raw = query
    end

    attr_reader :raw

    def to_filter(method, var_name)
      "FILTER (#{to_clause(method, var_name)})"
    end

    def tokens
      @tokens ||= begin
        scanner = StringScanner.new(@raw)
        scanner.skip /\s+/

        parse(scanner)
      end
    end

    private

    def to_clause(method, var_name)
      case method.to_s
      when 'regex', 'contains'
        tokens.each_with_object('') {|token, acc|
          case token
          when :lparen
            acc << '('
          when :rparen
            acc << ')'
          when :or
            acc << ' || '
          when :and
            acc << ' && '
          else
            acc << "#{method}(?#{var_name}, #{token.inspect})"
          end
        }
      when 'bif_contains'
        clause = tokens.each_with_object('') {|token, acc|
          case token
          when :lparen
            acc << '('
          when :rparen
            acc << ')'
          when :or
            acc << ' OR '
          when :and
            acc << ' AND '
          else
            acc << token.inspect
          end
        }

        "bif:contains(?#{var_name}, '#{clause}')"
      else
        raise ArgumentError, method
      end
    end

    def parse(scanner, tokens = [])
      scanner.skip /\s+\z/

      return tokens if scanner.eos?

      if scanner.scan(/"((?:[^\\"]|\\.)*)"/)
        tokens << scanner[1].gsub(/\\(.)/, '\1')
      elsif scanner.scan(/\(\s*/)
        tokens << :lparen
      elsif scanner.scan(/\s*\)/)
        tokens << :rparen
      elsif scanner.scan(/\s*OR\s*/)
        tokens << :or
      elsif scanner.scan(/\s*AND\s*|\s+/)
        tokens << :and
      else
        tokens << scanner.scan(/\S+(?<!\))/)
      end

      parse(scanner, tokens)
    end
  end
end

Version data entries

6 entries across 6 versions & 1 rubygems

Version Path
togostanza-1.3.1 lib/togostanza/stanza/search_query.rb
togostanza-1.3.0 lib/togostanza/stanza/search_query.rb
togostanza-1.2.2 lib/togostanza/stanza/search_query.rb
togostanza-1.2.1 lib/togostanza/stanza/search_query.rb
togostanza-1.2.0 lib/togostanza/stanza/search_query.rb
togostanza-1.1.0 lib/togostanza/stanza/search_query.rb