<commit_before>=begin
Copyright 2011 <NAME>
See README for licence information.
http://babel-bridge.rubyforge.org/
=end

module BabelBridge
# rule node
# subclassed automatically by parser.rule for each unique non-terminal
class RuleNode < NonTerminalNode

  def initialize(parent, delimiter_pattern = nil)
    @num_match_attempts = 0
    @delimiter_pattern = delimiter_pattern
    super parent
  end

  def match_names
    @match_names ||= []
  end

  def match_name_is_poly(name)
    return unless name
    if current = matches_by_name[name]
      matches_by_name[name] = MultiMatchesArray.new([current]) if !current.kind_of? MultiMatchesArray
    else
      matches_by_name[name] = MultiMatchesArray.new
    end
  end

  def add_match_name(match,name)
    return unless name
    if current = matches_by_name[name]
      matches_by_name[name] = MultiMatchesArray.new([current]) if !current.kind_of? MultiMatchesArray
      matches_by_name[name] << match
    else
      matches_by_name[name] = match
    end
  end

  def matches_by_name
    @matches_by_name||={}
  end

  def inspect(options={})
    return relative_class_name if matches.length==0
    matches = @matches
    matches=matches.select{|m|!m.many_delimiter} unless options[:verbose]
    matches_inspected = matches.collect{|a|a.inspect(options)}.compact
    if matches_inspected.length==0 then nil
    elsif matches_inspected.length==1
      m = matches_inspected[0]
      ret = "#{relative_class_name} > "+matches_inspected[0]
      if options[:simple]
        ret = if m["\n"] then m
        else
          # just show the first and last nodes in the chain
          ret.gsub(/( > [A-Z][a-zA-Z0-9:]+ > (\.\.\. > )?)/," > ... > ")
        end
      end
      ret
    else
      (["#{relative_class_name}"]+matches_inspected).join("\n").gsub("\n","\n  ")
    end
  end

  #********************
  # alter methods
  #********************

  # returns where to forward missing methods calls to (safe to override for custom behavior; respond_to? and method_missing will "do the right thing")
  # returns nil if there is no object to forward to that will respond to the call
  # default: forward to the first match that responds to method_name
  def forward_to(method_name)
    matches.each {|m| return m if m.respond_to?(method_name)}
    nil
  end

  def respond_to?(method_name)
    super ||
    matches_by_name[method_name] ||
    forward_to(method_name)
  end

  def method_missing(method_name, *args)  #method_name is a symbol
    return matches_by_name[method_name] if matches_by_name.has_key?(method_name)

    if f = forward_to(method_name)
      return f.send(method_name,*args)
    end

    raise "#{path_string onlychildren_list}: no methods or named pattern elements match: #{method_name.inspect} on #{self.class} instance"
  end

  # adds a match with name (optional)<commit_msg>Fix ruby 2.3 depreciation warning<commit_after>=begin
Copyright 2011 <NAME>
See README for licence information.
http://babel-bridge.rubyforge.org/
=end

module BabelBridge
# rule node
# subclassed automatically by parser.rule for each unique non-terminal
class RuleNode < NonTerminalNode

  def initialize(parent, delimiter_pattern = nil)
    @num_match_attempts = 0
    @delimiter_pattern = delimiter_pattern
    super parent
  end

  def match_names
    @match_names ||= []
  end

  def match_name_is_poly(name)
    return unless name
    if current = matches_by_name[name]
      matches_by_name[name] = MultiMatchesArray.new([current]) if !current.kind_of? MultiMatchesArray
    else
      matches_by_name[name] = MultiMatchesArray.new
    end
  end

  def add_match_name(match,name)
    return unless name
    if current = matches_by_name[name]
      matches_by_name[name] = MultiMatchesArray.new([current]) if !current.kind_of? MultiMatchesArray
      matches_by_name[name] << match
    else
      matches_by_name[name] = match
    end
  end

  def matches_by_name
    @matches_by_name||={}
  end

  def inspect(options={})
    return relative_class_name if matches.length==0
    matches = @matches
    matches=matches.select{|m|!m.many_delimiter} unless options[:verbose]
    matches_inspected = matches.collect{|a|a.inspect(options)}.compact
    if matches_inspected.length==0 then nil
    elsif matches_inspected.length==1
      m = matches_inspected[0]
      ret = "#{relative_class_name} > "+matches_inspected[0]
      if options[:simple]
        ret = if m["\n"] then m
        else
          # just show the first and last nodes in the chain
          ret.gsub(/( > [A-Z][a-zA-Z0-9:]+ > (\.\.\. > )?)/," > ... > ")
        end
      end
      ret
    else
      (["#{relative_class_name}"]+matches_inspected).join("\n").gsub("\n","\n  ")
    end
  end

  #********************
  # alter methods
  #********************

  # returns where to forward missing methods calls to (safe to override for custom behavior; respond_to? and method_missing will "do the right thing")
  # returns nil if there is no object to forward to that will respond to the call
  # default: forward to the first match that responds to method_name
  def forward_to(method_name)
    matches.each {|m| return m if m.respond_to?(method_name)}
    nil
  end

  def respond_to?(method_name, include_all = false)
    super ||
    matches_by_name[method_name] ||
    forward_to(method_name)
  end

  def method_missing(method_name, *args)  #method_name is a symbol
    return matches_by_name[method_name] if matches_by_name.has_key?(method_name)

    if f = forward_to(method_name)
      return f.send(method_name,*args)
    end

    raise "#{path_string onlychildren_list}: no methods or named pattern elements match: #{method_name.inspect} on #{self.class} instance"
  end

  # adds a match with name (optional)
{'fraction_non_alphanumeric': 0.11161413895176737, 'fraction_numerical': 0.004527250565906321, 'mean_word_length': 3.5192761605035403, 'pattern_counts': {'":': 0, '<': 11, '<?xml version=': 0, '>': 17, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5610769', 'n_tokens_mistral': 1854, 'n_tokens_neox': 1794, 'n_words': 481}