def getDirectFollowSets(self, FIRST):
        """
            1. If $ is the input end-marker, and S is the start symbol, $ belongs to FOLLOW(S).
            2. If there is a production, A -> Alpha B Beta, then FOLLOW(B) contains (FIRST(Beta) - epsilon)
            3. If there is a production, A -> Alpha B, or a production A -> Alpha B Beta, where  epsilon is in FIRST(Beta) , then FOLLOW(B) contains FOLLOW(A).
        """
        self.init_follow = {v:set() for v in self.v }
        self.containsFOLLOWOf = set()
        for v in self.v:
            if v == self.np[0][0]:  # Starting Production
                self.init_follow[v] = set(['$']) # $ is in follow of 'S' applying rule 1
            for prod in self.g[v]:
                for i in range(len(prod)):
                    if prod[i] in self.v and i+1 < len(prod):
                        if prod[i+1] in self.t:
                            self.init_follow[prod[i]] |= set([prod[i+1]])
                        else:
                            t = i + 1
                            while t < len(prod) and prod[t] in self.nullables_map:
                                if self.nullables_map[prod[t]] == True:
                                    self.init_follow[prod[i]] |= FIRST[prod[t]]-set(['epsilon'])
                                else:
                                    self.init_follow[prod[i]] |= FIRST[prod[t]]
                                    break
                                t += 1
                            if t >= len(prod): # every thing on rhs of prod[i] could produce epsison, rule - 3
                                self.containsFOLLOWOf |= set([(prod[i], v)])
                            else: #prod[i+1] is a non nullable prod or prod[t] was a terminal
                                if prod[t] in self.t:
                                    self.init_follow[prod[i]] |= set([prod[t]])
                                else:
                                    self.init_follow[prod[i]] |= FIRST[prod[t]]-set(['epsilon'])

                    elif prod[i] in self.v:
                        self.containsFOLLOWOf |= set([(prod[i], v)])         # applying rule 2

        #self.containsFOLLOWOf = set([(a, b) for (a, b) in self.containsFOLLOWOf if a != b]) # remove the self loops
        return self.init_follow

            1. If $ is the input end-marker, and S is the start symbol, $ belongs to FOLLOW(S).
            2. If there is a production, A -> Alpha B Beta, then FOLLOW(B) contains (FIRST(Beta) - epsilon)
            3. If there is a production, A -> Alpha B, or a production A -> Alpha B Beta, where  epsilon is in FIRST(Beta) , then FOLLOW(B) contains FOLLOW(A).
        
recipes/Python/579140_Follow_Sets_Construction/recipe-579140.py