/
parser.cr
57 lines (54 loc) · 1.46 KB
/
parser.cr
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
class PublicSuffix
# Defines the `.parse` method for parsing rules.
#
module Parser
# A collection of rules.
#
struct Term
# The type of `Term` items.
#
alias Type = Hash(String | Symbol, Term | Bool)
delegate :empty?, :has_key?, :[]=, :[], :[]?, to: @term
@term = Type.new
end
# Parses rules into internal representation.
#
# Parsing the following:
# com
# *.jp
# *.hokkaido.jp
# *.tokyo.jp
# !pref.hokkaido.jp
# !metro.tokyo.jp
#
# Yields:
# Term{
# "com" => Term{:term => true},
# "jp" => Term{
# "tokyo" => Term{"!metro" => Term{:term => true}, "*" => Term{:term => true}},
# "hokkaido" => Term{"!pref" => Term{:term => true}, "*" => Term{:term => true}},
# "*" => Term{:term => true}
# }
# }
#
def self.parse(rules : Enumerable(String))
return Term{:term => false} if rules.empty?
rules.reduce(Term.new) do |acc, rule|
rule = rule.gsub(/\s.*/, "")
unless rule.starts_with?("//") || rule.empty?
tmp = acc
rule.split(".").reject(&.empty?).reverse.each do |p|
if tmp.is_a?(Term)
tmp[p] = Term.new unless tmp.has_key?(p)
tmp = tmp[p]
end
end
if tmp.is_a?(Term)
tmp[:term] = true
end
end
acc
end
end
end
end