class Mustermann::AST::Expander
Looks at an AST, remembers the important bits of information to do an ultra fast expansion.
@!visibility private
Public Instance Methods
add a tree for expansion @!visibility private
# File lib/mustermann/ast/expander.rb, line 78 def add(ast) translate(ast).each do |keys, pattern, filter| self.keys.concat(keys).uniq! mappings[keys.sort] ||= [keys, pattern, filter] end end
Creates the product of two of our secret internal data structures. @!visibility private
# File lib/mustermann/ast/expander.rb, line 137 def add_to(list, result) list << [[], ""] if list.empty? list.inject([]) { |l, (k1, p1, f1)| l + result.map { |k2, p2, f2| [k1+k2, p1+p2, **f1, **f2] } } end
helper method for raising an error for unexpandable values @!visibility private
# File lib/mustermann/ast/expander.rb, line 117 def error_for(values) expansions = mappings.keys.map(&:inspect).join(" or ") raise error_class, "cannot expand with keys %p, possible expansions: %s" % [values.keys.sort, expansions] end
@see Mustermann::AST::Translator#expand @!visibility private
# File lib/mustermann/ast/expander.rb, line 124 def escape(string, *args) # URI::Parser is pretty slow, let's not send every string to it, even if it's unnecessary string =~ /\A\w*\Z/ ? string : super end
@see Mustermann::Pattern#expand @!visibility private
# File lib/mustermann/ast/expander.rb, line 93 def expand(values) values = values.each_with_object({}){ |(key, value), new_hash| new_hash[value.instance_of?(Array) ? [key] * value.length : key] = value } keys, pattern, filters = mappings.fetch(values.keys.flatten.sort) { error_for(values) } filters.each { |key, filter| values[key] &&= escape(values[key], also_escape: filter) } pattern % (values[keys] || values.values_at(*keys)) end
@see Mustermann::Pattern#expandable? @!visibility private
# File lib/mustermann/ast/expander.rb, line 103 def expandable?(values) values = values.keys if values.respond_to? :keys values = values.sort if values.respond_to? :sort mappings.include? values end
@see Mustermann::Expander#with_rest @!visibility private
# File lib/mustermann/ast/expander.rb, line 111 def expandable_keys(keys) mappings.keys.select { |k| (k - keys).empty? }.max_by(&:size) || keys end
helper method for captures @!visibility private
# File lib/mustermann/ast/expander.rb, line 59 def for_capture(node, **options) name = node.name.to_sym pattern('%s', name, name => /(?!#{pattern_for(node, **options)})./) end
all the known keys @!visibility private
# File lib/mustermann/ast/expander.rb, line 72 def keys @keys ||= [] end
maps sorted key list to sprintf patterns and filters @!visibility private
# File lib/mustermann/ast/expander.rb, line 66 def mappings @mappings ||= {} end
Turns a sprintf pattern into our secret internal data structure. @!visibility private
# File lib/mustermann/ast/expander.rb, line 131 def pattern(string = "", *keys, **filters) [[keys, string, filters]] end
helper method for getting a capture's pattern. @!visibility private
# File lib/mustermann/ast/expander.rb, line 87 def pattern_for(node, **options) Compiler.new.decorator_for(node).pattern(**options) end