You are an expert in writing code in many different languages. Your goal is to perform code completion for the following code, keeping in mind the rest of the code and the file meta data.
    Metadata details:
    filename: block_table.go
    path of file: ./repos/markdown/parser
    
    the code of the file until where you have to start completion: package parser

import "github.com/gomarkdown/markdown/ast"

// check if the specified position is preceded by an odd number of backslashes
func isBackslashEscaped(data []byte, i int) bool {
	backslashes := 0
	for i-backslashes-1 >= 0 && data[i-backslashes-1] == '\\' {
		backslashes++
	}
	return backslashes&1 == 1
}

func (p *Parser) tableRow(data []byte, columns []ast.CellAlignFlags, header bool) {
	p.AddBlock(&ast.TableRow{})
	col := 0

	i := skipChar(data, 0, '|')

	n := len(data)
	colspans := 0 // keep track of total colspan in this row.
	for col = 0; col < len(columns) && i < n; col++ {
		colspan := 0
		i = skipChar(data, i, ' ')

		cellStart := i

		// If we are in a codespan we should discount any | we see, check for that here and skip ahead.
		if isCode, _ := codeSpan(p, data[i:], 0); isCode > 0 {
			i += isCode - 1
		}

		for i < n && (data[i] != '|' || isBackslashEscaped(data, i)) && data[i] != '\n' {
			i++
		}

		cellEnd := i

		// skip the end-of-cell marker, possibly taki
    
func (p *Parser) tableRow(data []byte, columns []ast.CellAlignFlags, header bool) {
	p.AddBlock(&ast.TableRow{})
	col := 0

	i := skipChar(data, 0, '|')

	n := len(data)
	colspans := 0 // keep track of total colspan in this row.
	for col = 0; col < len(columns) && i < n; col++ {
		colspan := 0
		i = skipChar(data, i, ' ')

		cellStart := i

		// If we are in a codespan we should discount any | we see, check for that here and skip ahead.
		if isCode, _ := codeSpan(p, data[i:], 0); isCode > 0 {
			i += isCode - 1
		}

		for i < n && (data[i] != '|' || isBackslashEscaped(data, i)) && data[i] != '\n' {
			i++
		}

		cellEnd := i

		// skip the end-of-cell marker, possibly taking us past end of buffer
		// each _extra_ | means a colspan
		for i < len(data) && data[i] == '|' && !isBackslashEscaped(data, i) {
			i++
			colspan++
		}
		// only colspan > 1 make sense.
		if colspan < 2 {
			colspan = 0
		}

		for cellEnd > cellStart && cellEnd-1 < n && data[cellEnd-1] == ' ' {
			cellEnd--
		}

		block := &ast.TableCell{
			IsHeader: header,
			Align:    columns[col],
			ColSpan:  colspan,
		}
		block.Content = data[cellStart:cellEnd]
		if cellStart == cellEnd && colspans > 0 {
			// an empty cell that we should ignore, it exists because of colspan
			colspans--
		} else {
			p.AddBlock(block)
		}

		if colspan > 0 {
			colspans += colspan - 1
		}
	}

	// pad it out with empty columns to get the right number
	for ; col < len(columns); col++ {
		block := &ast.TableCell{
			IsHeader: header,
			Align:    columns[col],
		}
		p.AddBlock(block)
	}

	// silently ignore rows with too many cells
}