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(ast) click to toggle source

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
add_to(list, result) click to toggle source

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
error_for(values) click to toggle source

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
escape(string, *args) click to toggle source

@see Mustermann::AST::Translator#expand @!visibility private

Calls superclass method
# 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
expand(values) click to toggle source

@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
expandable?(values) click to toggle source

@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
expandable_keys(keys) click to toggle source

@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
for_capture(node, **options) click to toggle source

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
keys() click to toggle source

all the known keys @!visibility private

# File lib/mustermann/ast/expander.rb, line 72
def keys
  @keys ||= []
end
mappings() click to toggle source

maps sorted key list to sprintf patterns and filters @!visibility private

# File lib/mustermann/ast/expander.rb, line 66
def mappings
  @mappings ||= {}
end
pattern(string = "", *keys, **filters) click to toggle source

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
pattern_for(node, **options) click to toggle source

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