<SYSTEM_TASK:>
Solve the following problem using Python, implementing the functions described below, one line at a time
<END_TASK>
<USER_TASK:>
Description:
 def parse_GSM(filepath, entry_name=None):
 """Parse GSM entry from SOFT file. Args: filepath (:obj:`str` or :obj:`Iterable`):
 Path to file with 1 GSM entry or list of lines representing GSM from GSE file. entry_name (:obj:`str`, optional):
 Name of the entry. By default it is inferred from the data. Returns: :obj:`GEOparse.GSM`: A GSM object. """

    if isinstance(filepath, str):
        with utils.smart_open(filepath) as f:
            soft = []
            has_table = False
            for line in f:
                if "_table_begin" in line or (not line.startswith(("^", "!", "#"))):
                    has_table = True
                soft.append(line.rstrip())
    else:
        soft = []
        has_table = False
        for line in filepath:
            if "_table_begin" in line or (not line.startswith(("^", "!", "#"))):
                has_table = True
            soft.append(line.rstrip())

    if entry_name is None:
        sets = [i for i in soft if i.startswith("^")]
        if len(sets) > 1:
            raise Exception("More than one entry in GPL")
        if len(sets) == 0:
            raise NoEntriesException(
                "No entries found. Check the if accession is correct!")
        entry_name = parse_entry_name(sets[0])

    columns = parse_columns(soft)
    metadata = parse_metadata(soft)
    if has_table:
        table_data = parse_table_data(soft)
    else:
        table_data = DataFrame()

    gsm = GSM(name=entry_name,
              table=table_data,
              metadata=metadata,
              columns=columns)

    return gsm