def address_to_line_no(address: str, assembly_code: list) -> int:
    """Finds the line number of an address.

    Converts the address information to line number. Expected address 
    information is in bare hexadecimal format without any 0x, h, etc. extension.
    A sample address is "101e8". This address information is the first value
    of each instruction line in assembly code of the program.

    The addresses in assembly code ends with colon symbol (:). A sample first 
    value in of instruction line is "101c4:". Therefore, during extaction of
    this value from the instruction line, colon symbol is discarded.

    Parameters
    ----------
    address : str
        The address whose line number will be searched.
    assembly_code : list of str
        Assembly code in which the address will be searched.

    Returns
    -------
    int
        The line number of the of the address if successful.
    
    Raises
    ------
    Exception
        If the address is not found in the assembly code.
    """

    line_no: int = -1
    found: bool = False

    for index, line in enumerate(assembly_code):
        tokens = line.split()
        # If len(tokens >=3) this is a valid code line.
        # -1 is to discard the colon symbol (:) at the end of the token.
        if len(tokens) >= 3 and tokens[0][:-1] == address:
            line_no = index
            break

    if line_no == -1:
        raise Exception("The address could not be found in the current assembly "
                        "file. The line number of address could not be "
                        "determined. Address: " + address)
    else:
        return line_no