class Mustermann::AST::Transformer::ArrayTransform

@!visibility private
Inserts with_look_ahead nodes wherever appropriate

def create_lookahead(elements, *args)

@!visibility private
turn look ahead buffer into look ahead node
def create_lookahead(elements, *args)
  return elements unless elements.size > 1
  [Node[:with_look_ahead].new(elements, *args, start: elements.first.start, stop: elements.last.stop)]
end

def expect_lookahead?(element)

@!visibility private
can the current element deal with a look-ahead?
def expect_lookahead?(element)
  return element.class == Node[:capture] unless element.is_a? Node[:group]
  element.payload.all? { |e| expect_lookahead?(e) }
end

def list_for(element)

@!visibility private
helper method for deciding where to put an element for now
def list_for(element)
  expect_lookahead?(element) ? lookahead_buffer : payload
end

def lookahead?(element, in_lookahead = false)

@!visibility private
can the given element be used in a look-ahead?
def lookahead?(element, in_lookahead = false)
  case element
  when Node[:char]     then in_lookahead
  when Node[:group]    then lookahead_payload?(element.payload, in_lookahead)
  when Node[:optional] then lookahead?(element.payload, true) or expect_lookahead?(element.payload)
  end
end

def lookahead_buffer

@!visibility private
buffer for potential look ahead
def lookahead_buffer
  @lookahead_buffer ||= []
end

def lookahead_payload?(payload, in_lookahead)

@!visibility private
does the list of elements look look-ahead-ish to you?
def lookahead_payload?(payload, in_lookahead)
  return unless payload[0..-2].all? { |e| lookahead?(e, in_lookahead) }
  expect_lookahead?(payload.last) or lookahead?(payload.last, in_lookahead)
end

def payload

@!visibility private
the new array
def payload
  @payload ||= []
end

def track(element)

@!visibility private
handle a single element from the array
def track(element)
  return list_for(element) << element if lookahead_buffer.empty?
  return lookahead_buffer  << element if lookahead? element
  lookahead = lookahead_buffer.dup
  lookahead = create_lookahead(lookahead, false) if element.is_a? Node[:separator]
  lookahead_buffer.clear
  payload.concat(lookahead) << element
end

def translate

@!visibility private
transform the array
def translate
  each { |e| track t(e) }
  payload.concat create_lookahead(lookahead_buffer, true)
end