|
|
@ -6,6 +6,7 @@ class NonTerminal: |
|
|
|
self.__isNullable = False |
|
|
|
self.__productions = [] |
|
|
|
self.__first = [] |
|
|
|
self.__follow = [] |
|
|
|
self.__firstSetIsGenerated = False; |
|
|
|
|
|
|
|
self.__string = string |
|
|
@ -49,6 +50,45 @@ class NonTerminal: |
|
|
|
|
|
|
|
self.__firstSetIsGenrated = True; |
|
|
|
|
|
|
|
def addToFollowSet(self, marker): |
|
|
|
self.__follow.append(marker) |
|
|
|
|
|
|
|
def generateFollowSet(self): |
|
|
|
for production in self.__productions: |
|
|
|
self.__extendFollowSetsBasedOnProduction(production) |
|
|
|
|
|
|
|
def __extendFollowSetsBasedOnProduction(self, production): |
|
|
|
for i in range(len(production)): |
|
|
|
atom = production[i] |
|
|
|
|
|
|
|
if isinstance(atom, NonTerminal): |
|
|
|
if self.__isPossiblyLastInProduction(i, production): |
|
|
|
atom.extendFollowWithFollowOf(self) |
|
|
|
else: |
|
|
|
atom.extendFollowWithFirstOf(production[i + 1]) |
|
|
|
|
|
|
|
def __isPossiblyLastInProduction(self, index, production): |
|
|
|
for j in range(index, len(production)): |
|
|
|
if isinstance(production[j], Terminal): |
|
|
|
return False |
|
|
|
|
|
|
|
if not production[j].isNullable(): |
|
|
|
return False |
|
|
|
|
|
|
|
return True |
|
|
|
|
|
|
|
def extendFollowWithFollowOf(self, atom): |
|
|
|
for el in atom.getFollowSet(): |
|
|
|
self.addToFollowSet(el) |
|
|
|
|
|
|
|
def extendFollowWithFirstOf(self, atom): |
|
|
|
for el in atom.getFirstSet(): |
|
|
|
if not el.isEmptyString(): |
|
|
|
self.addToFollowSet(el) |
|
|
|
|
|
|
|
def getFollowSet(self): |
|
|
|
return self.__follow |
|
|
|
|
|
|
|
def __addFirsSetForProduction(self, production): |
|
|
|
stillNullable = True |
|
|
|
lenProd = len(production) |
|
|
|