local output = assert(io.open('.asma.tal', 'w'))
local process_subtree
process_subtree = function(items)
  local middle = math.floor(#items / 2 + 1.25)
  local node = items[middle]
  if not node then
    return 
  end
  node.left = process_subtree((function()
    local _accum_0 = { }
    local _len_0 = 1
    for i, item in ipairs(items) do
      if i < middle then
        _accum_0[_len_0] = item
        _len_0 = _len_0 + 1
      end
    end
    return _accum_0
  end)())
  node.right = process_subtree((function()
    local _accum_0 = { }
    local _len_0 = 1
    for i, item in ipairs(items) do
      if i > middle then
        _accum_0[_len_0] = item
        _len_0 = _len_0 + 1
      end
    end
    return _accum_0
  end)())
  return node
end
local process_tree
process_tree = function(items)
  local sorted_items
  do
    local _accum_0 = { }
    local _len_0 = 1
    for _index_0 = 1, #items do
      local item = items[_index_0]
      _accum_0[_len_0] = item
      _len_0 = _len_0 + 1
    end
    sorted_items = _accum_0
  end
  table.sort(sorted_items, function(a, b)
    return a.order < b.order
  end);
  (process_subtree(sorted_items)).label = '&_entry'
  for _index_0 = 1, #items do
    local item = items[_index_0]
    output:write(('\t%-11s %-10s %-12s %s%s\n'):format(item.label, item.left and item.left.ref or ' $2', (item.right and item.right.ref or ' $2') .. item.extra, item.key, item.rest))
  end
end
local parse_tree
parse_tree = function(it)
  local items = { }
  for l in it do
    if l == '' then
      process_tree(items)
      output:write('\n')
      return 
    end
    local item = {
      extra = ''
    }
    item.key, item.rest = l:match('^%s*%S+%s+%S+%s+%S+%s+(%S+)(.*)')
    if item.key:match('^%&') then
      item.extra = (' %s'):format(item.key)
      item.key, item.rest = item.rest:match('^%s+(%S+)(.*)')
    end
    if item.key:match('^%"') then
      item.order = item.key:sub(2)
    elseif item.key:match('^%x%x') then
      item.order = string.char(tonumber(item.key, 16))
    else
      error(('unknown key: %q'):format(item.key))
    end
    if item.order:match('^%a') then
      item.label = ('&%s'):format(item.order)
    elseif item.order:match('^.$') then
      item.label = ('&%x'):format(item.order:byte())
    else
      error(('unknown label: %q'):format(item.order))
    end
    item.ref = (':%s'):format(item.label)
    table.insert(items, item)
  end
end
local it = assert(io.lines('projects/library/asma.tal'))
local waiting_for_cut = true
for l in it do
  output:write(l)
  output:write('\n')
  if l:find('--- cut here ---', 1, true) then
    waiting_for_cut = false
  end
  if not waiting_for_cut and '@' == l:sub(1, 1) then
    parse_tree(it)
  end
end
output:close()
return os.execute('mv .asma.tal projects/library/asma.tal')