class Foodcritic::Gherkin::TagExpression

def add(tags_with_negation_and_limits)

def add(tags_with_negation_and_limits)
  negatives, positives = tags_with_negation_and_limits.partition{|tag| tag =~ /^~/}
  @ands << (store_and_extract_limits(negatives, true) + store_and_extract_limits(positives, false))
end

def empty?

def empty?
  @ands.empty?
end

def evaluate(tags)

def evaluate(tags)
  return true if @ands.flatten.empty?
  vars = Hash[*tags.map{|tag| [tag.name, true]}.flatten]
  raise "No vars" if vars.nil? # Useless statement to prevent ruby warnings about unused var
  !!Kernel.eval(ruby_expression)
end

def initialize(tag_expressions)

def initialize(tag_expressions)
  @ands = []
  @limits = {}
  tag_expressions.each do |expr|
    add(expr.strip.split(/\s*,\s*/))
  end
end

def ruby_expression

def ruby_expression
  "(" + @ands.map do |ors|
    ors.map do |tag|
      if tag =~ /^~(.*)/
        "!vars['#{$1}']"
      else
        "vars['#{tag}']"
      end
    end.join("||")
  end.join(")&&(") + ")"
end

def store_and_extract_limits(tags_with_negation_and_limits, negated)

def store_and_extract_limits(tags_with_negation_and_limits, negated)
  tags_with_negation = []
  tags_with_negation_and_limits.each do |tag_with_negation_and_limit|
    tag_with_negation, limit = tag_with_negation_and_limit.split(':')
    tags_with_negation << tag_with_negation
    if limit
      tag_without_negation = negated ? tag_with_negation[1..-1] : tag_with_negation
      if @limits[tag_without_negation] && @limits[tag_without_negation] != limit.to_i
        raise "Inconsistent tag limits for #{tag_without_negation}: #{@limits[tag_without_negation]} and #{limit.to_i}"
      end
      @limits[tag_without_negation] = limit.to_i
    end
  end
  tags_with_negation
end