def _ascii_diagram_to_coords(diagram: str) -> list[tuple[int, int]]:
    """Parse ASCII art device layout into info about qids coordinates

    Args:
        diagram: String representing the qid layout. Each line represents
            a row. Alphanumeric characters are assigned as qid.
            Dots ('.'), dashes ('-'), and spaces (' ') are treated as
            empty locations in the grid. If diagram has characters other
            than alphanumerics, spacers, and newlines ('\n'), an error will
            be thrown. The top-left corner of the diagram will be have
            coordinate (0,0).

    Returns:
        A list of Tuples corresponding to the coordinates for qids in the
        provided diagram

    Raises:
        ValueError: If the input string contains an invalid character.
    """
    lines = diagram.strip().split('\n')
    no_qid_characters = ['.', '-', ' ']
    qid_coords = []
    for row, line in enumerate(lines):
        for col, c in enumerate(line.strip()):
            if c not in no_qid_characters:
                if not c.isalnum():
                    raise ValueError("Input string has invalid character")
                qid_coords.append((row, col))
    return qid_coords
Parse ASCII art device layout into info about qids coordinates

    Args:
        diagram: String representing the qid layout. Each line represents
            a row. Alphanumeric characters are assigned as qid.
            Dots ('.'), dashes ('-'), and spaces (' ') are treated as
            empty locations in the grid. If diagram has characters other
            than alphanumerics, spacers, and newlines ('
'), an error will
            be thrown. The top-left corner of the diagram will be have
            coordinate (0,0).

    Returns:
        A list of Tuples corresponding to the coordinates for qids in the
        provided diagram

    Raises:
        ValueError: If the input string contains an invalid character.
    
cirq-core/cirq/devices/grid_qubit.py