This repository has been archived by the owner on Mar 11, 2021. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 162
/
parser.rb
70 lines (60 loc) · 2.67 KB
/
parser.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
module DC
module Search
# Our first stab at a Search::Parser will just use simple regexs to pull out
# fielded queries ... so, no nesting.
#
# All the regex matchers live in the Search module.
#
# We should try to adopt Google conventions, if possible, after:
# http://www.google.com/help/cheatsheet.html
class Parser
include DC::Access
# Parse a raw query_string, returning a DC::Search::Query that knows
# about the text, fields, projects, and attributes it's composed of.
def parse(query_string='')
@text, @access = nil, nil
@fields, @accounts, @groups, @projects, @project_ids, @doc_ids, @attributes, @filters, @data =
[], [], [], [], [], [], [], [], []
fields = query_string.scan(Matchers::FIELD).map {|m| [m[0], m[3]] }
search_text = query_string.gsub(Matchers::FIELD, '').squeeze(' ').strip
@text = search_text.present? ? search_text : nil
process_fields_and_projects(fields)
Query.new(:text => @text, :fields => @fields, :projects => @projects,
:accounts => @accounts, :groups => @groups, :project_ids => @project_ids,
:doc_ids => @doc_ids, :attributes => @attributes, :access => @access,
:filters => @filters, :data => @data)
end
# Extract the portions of the query that are fields, attributes,
# and projects.
def process_fields_and_projects(fields)
fields.each do |pair|
type = pair.first.gsub(/(^['"]|['"]$)/, '')
value = pair.last.gsub(/(^['"]|['"]$)/, '')
case type.downcase
when 'account' then @accounts << value.to_i
when 'group' then @groups << value.downcase
when 'filter' then @filters << value.downcase.to_sym
when 'access' then @access = ACCESS_MAP[value.strip.to_sym]
when 'project' then @projects << value
when 'projectid' then @project_ids << value.to_i
when 'document' then @doc_ids << value.to_i
else
process_field(type, value)
end
end
end
# Convert an individual field or attribute search into a DC::Search::Field.
def process_field(kind, value)
field = Field.new(match_kind(kind), value.strip)
return @attributes << field if field.attribute?
return @fields << field if field.entity?
return @data << field
end
# Convert a field kind string into its canonical form, by searching
# through all the valid kinds for a match.
def match_kind(kind)
DC::VALID_KINDS.detect {|s| s.match(Regexp.new(kind.downcase)) } || kind
end
end
end
end