code: def _read_lnk(tokens):
      
      # < FROM : TO > or < FROM # TO > or < TOK... > or < @ EDGE >
      lnk = None
      if tokens[0] == '<':
          tokens.popleft()  # we just checked this is a left angle
          if tokens[0] == '>':
              pass  # empty <> brackets the same as no lnk specified
          # edge lnk: ['@', EDGE, ...]
          elif tokens[0] == '@':
              tokens.popleft()  # remove the @
              lnk = Lnk.edge(tokens.popleft())  # edge lnks only have one number
          # character span lnk: [FROM, ':', TO, ...]
          elif tokens[1] == ':':
              lnk = Lnk.charspan(tokens.popleft(), tokens[1])
              tokens.popleft()  # this should be the colon
              tokens.popleft()  # and this is the cto
          # chart vertex range lnk: [FROM, '#', TO, ...]
          elif tokens[1] == '#':
              lnk = Lnk.chartspan(tokens.popleft(), tokens[1])
              tokens.popleft()  # this should be the hash
              tokens.popleft()  # and this is the to vertex
          # tokens lnk: [(TOK,)+ ...]
          else:
              lnkdata = []
              while tokens[0] != '>':
                  lnkdata.append(int(tokens.popleft()))
              lnk = Lnk.tokens(lnkdata)
          _read_literals(tokens, '>')
      return lnk
docs: Read and return a tuple of the pred's lnk type and lnk value,
         if a pred lnk is specified.