#!/usr/bin/env ruby
require 'ostruct'
require 'set'
require 'delegate'
module Keywords
module_function
def extensions
@extensions
end
def keywords
@keywords
end
def build_tree(keys)
tree = Hash.new()
offset = 0
while true
has_more = false
keys.each do |key|
if key.length < offset + 1
next
end
has_more = true
func_name = key[0..offset];
if tree.has_key?(func_name)
tree[func_name].add(key[offset + 1])
else
tree[func_name] = Set[key[offset + 1]]
end
end
if has_more
offset += 1
next
end
break
end
return tree
end
def wrap_data(data)
@extensions = Hash.new()
if !data || !data.extensions || !data.keywords
return
end
@keywords = data.keywords.map do |keyword|
keyword.string = keyword.name
keyword
end
data.extensions.each do |extension|
@extensions[extension.name] = Hash.new()
all_words = data.keywords.select do |desc|
s_kw = Set.new(desc&.keyword)
groups = [s_kw, Set.new(desc&.keyword_like), Set.new(desc&.custom_handler)]
groups.combination(2).each { |a,b| raise "Conflicting keyword type" unless (a & b).empty? }
active = Set.new();
groups.each { |group| active.merge(group) }
raise "Unknown extension" unless active.subset?(Set.new(data.extensions.map { |ext| ext.name }))
active.include? extension.name
end
keywords = data.keywords.select do |desc|
desc&.keyword&.include? extension.name or desc&.custom_handler&.include? extension.name
end
@extensions[extension.name]['keywords'] = keywords
@extensions[extension.name]['keyword_starts'] = Set.new(keywords.map { |desc| desc.name[0] })
@extensions[extension.name]['all_words'] = all_words
@extensions[extension.name]['all_word_starts'] = Set.new(all_words.map { |desc| desc.name[0] })
@extensions[extension.name]['tree'] = build_tree(all_words.map { |desc| desc.name })
end
end
end
def Gen.on_require(data)
Keywords.wrap_data(data)
end