class Raabro::Tree

def c0; @children[0]; end

def c0; @children[0]; end

def c1; @children[1]; end

def c1; @children[1]; end

def c2; @children[2]; end

def c2; @children[2]; end

def c3; @children[3]; end

def c3; @children[3]; end

def c4; @children[4]; end

def c4; @children[4]; end

def clast; @children.last; end

def clast; @children.last; end

def empty?

def empty?
  @result == 1 && @length == 0
end

def even_children

def even_children
  cs = []; @children.each_with_index { |c, i| cs << c if i.even? }; cs
end

def extract_error

def extract_error
bro.pp(self, colors: true)
  err_tree, stack = lookup_error || lookup_all_error
  line, column = line_and_column(err_tree.offset)
  err_message =
    if stack
      path = stack
       .compact.reverse.take(3).reverse
       .collect(&:inspect).join('/')
      "parsing failed .../#{path}"
    else
      "parsing failed, not all input was consumed"
    end
  visual =
    visual(line, column)
  [ line, column, err_tree.offset, err_message, visual ]
end

def gather(name=nil, acc=[])

def gather(name=nil, acc=[])
  name = name ? name.to_s : nil
  if (@name && name == nil) || (@name.to_s == name)
    acc << self
  else
    subgather(name, acc)
  end
  acc
end

def initialize(name, parter, input)

def initialize(name, parter, input)
  @result = 0
  @name = name
  @parter = parter
  @input = input
  @offset = input.offset
  @length = 0
  @children = []
end

def line_and_column(offset)

def line_and_column(offset)
  line = 1
  column = 0
  (0..offset).each do |off|
    column += 1
    next unless @input.at(off) == "\n"
    line += 1
    column = 0
  end
  [ line, column ]
end

def lookup(name=nil)

def lookup(name=nil)
  name = name ? name.to_s : nil
  return self if @name && name == nil
  return self if @name.to_s == name
  sublookup(name)
end

def lookup_all_error


consuming all the input)
words lookup the point up until which the parser stopped (not
Not "lookup all errors" but "lookup all error", in other
def lookup_all_error
nt "lae(): "; Raabro.pp(self, colors: true)
  @children.each { |c| return [ c, nil ] if c.result == 0 }
  @children.reverse.each { |c| es = c.lookup_all_error; return es if es }
  nil
end

def lookup_error(stack=[])

def lookup_error(stack=[])
nt "le(): "; Raabro.pp(self, colors: true)
  return nil if @result != 0
  return [ self, stack ] if @children.empty?
  @children.each { |c|
    es = c.lookup_error(stack.dup.push(self.name))
    return es if es }
  nil
end

def nonstring(l=7)

def nonstring(l=7)
  @input.string[@offset, l]
end

def odd_children

def odd_children
  cs = []; @children.each_with_index { |c, i| cs << c if i.odd? }; cs
end

def prune!

def prune!
  @children = successful_children
end

def string

def string
  @input.string[@offset, @length]
end

def subgather(name=nil, acc=[])

def subgather(name=nil, acc=[])
  @children.each { |c| c.gather(name, acc) }
  acc
end

def sublookup(name=nil)

def sublookup(name=nil)
  @children.each { |c| if n = c.lookup(name); return n; end }
  nil
end

def successful_children

def successful_children
  @children.select { |c| c.result == 1 }
end

def to_a(opts={})

def to_a(opts={})
  opts = Array(opts).inject({}) { |h, e| h[e] = true; h } \
    unless opts.is_a?(Hash)
  cn =
    if opts[:leaves] && (@result == 1) && @children.empty?
      string
    elsif opts[:children] != false
      @children.collect { |e| e.to_a(opts) }
    else
      @children.length
    end
  [ @name, @result, @offset, @length, @note, @parter, cn ]
end

def to_s(depth=0, io=StringIO.new)

def to_s(depth=0, io=StringIO.new)
  io.print "\n" if depth > 0
  io.print '  ' * depth
  io.print "#{@result} #{@name.inspect} #{@offset},#{@length}"
  io.print result == 1 && children.size == 0 ? ' ' + string.inspect : ''
  @children.each { |c| c.to_s(depth + 1, io) }
  depth == 0 ? io.string : nil
end

def visual(line, column)

def visual(line, column)
  @input.string.split("\n")[line - 1] + "\n" +
  ' ' * (column - 1) + '^---'
end