# File lib/asciidoctor/parser.rb, line 2276
  def self.next_table(table_reader, parent, attributes)
    table = Table.new(parent, attributes)
    if (attributes.has_key? 'title')
      table.title = attributes.delete 'title'
      table.assign_caption attributes.delete('caption')
    end

    if (attributes.key? 'cols') && !(col_specs = parse_col_specs attributes['cols']).empty?
      table.create_columns col_specs
      explicit_col_specs = true
    else
      explicit_col_specs = false
    end

    skipped = table_reader.skip_blank_lines

    parser_ctx = Table::ParserContext.new(table_reader, table, attributes)
    loop_idx = -1
    while table_reader.has_more_lines?
      loop_idx += 1
      line = table_reader.read_line

      if skipped == 0 && loop_idx.zero? && !attributes.has_key?('options') &&
          !(next_line = table_reader.peek_line).nil? && next_line.empty?
        table.has_header_option = true
        table.set_option 'header'
      end

      if parser_ctx.format == 'psv'
        if parser_ctx.starts_with_delimiter? line
          line = line[1..-1]
          # push an empty cell spec if boundary at start of line
          parser_ctx.close_open_cell
        else
          next_cell_spec, line = parse_cell_spec(line, :start, parser_ctx.delimiter)
          # if the cell spec is not null, then we're at a cell boundary
          if !next_cell_spec.nil?
            parser_ctx.close_open_cell next_cell_spec
          else
            # QUESTION do we not advance to next line? if so, when will we if we came into this block?
          end
        end
      end

      seen = false
      while !seen || !line.empty?
        seen = true
        if (m = parser_ctx.match_delimiter(line))
          if parser_ctx.format == 'csv'
            if parser_ctx.buffer_has_unclosed_quotes?(m.pre_match)
              # throw it back, it's too small
              line = parser_ctx.skip_matched_delimiter(m)
              next
            end
          else
            if m.pre_match.end_with? '\\'
              # skip over escaped delimiter
              # handle special case when end of line is reached (see issue #1306)
              if (line = parser_ctx.skip_matched_delimiter(m, true)).empty?
                parser_ctx.buffer = %(#{parser_ctx.buffer}#{EOL})
                parser_ctx.keep_cell_open
                break
              end
              next
            end
          end

          if parser_ctx.format == 'psv'
            next_cell_spec, cell_text = parse_cell_spec(m.pre_match, :end)
            parser_ctx.push_cell_spec next_cell_spec
            parser_ctx.buffer = %(#{parser_ctx.buffer}#{cell_text})
          else
            parser_ctx.buffer = %(#{parser_ctx.buffer}#{m.pre_match})
          end

          if (line = m.post_match) == ''
            # hack to prevent dropping empty cell found at end of line (see issue #1106)
            seen = false
          end

          parser_ctx.close_cell
        else
          # no other delimiters to see here
          # suck up this line into the buffer and move on
          parser_ctx.buffer = %(#{parser_ctx.buffer}#{line}#{EOL})
          # QUESTION make stripping endlines in csv data an option? (unwrap-option?)
          if parser_ctx.format == 'csv'
            parser_ctx.buffer = %(#{parser_ctx.buffer.rstrip} )
          end
          line = ''
          if parser_ctx.format == 'psv' || (parser_ctx.format == 'csv' &&
              parser_ctx.buffer_has_unclosed_quotes?)
            parser_ctx.keep_cell_open
          else
            parser_ctx.close_cell true
          end
        end
      end

      skipped = table_reader.skip_blank_lines unless parser_ctx.cell_open?

      unless table_reader.has_more_lines?
        # NOTE may have already closed cell in csv or dsv table (see previous call to parser_ctx.close_cell(true))
        parser_ctx.close_cell true if parser_ctx.cell_open?
      end
    end

    unless (table.attributes['colcount'] ||= table.columns.size) == 0 || explicit_col_specs
      table.assign_col_widths
    end

    table.partition_header_footer attributes

    table
  end