diff --git a/src/grammar.py b/src/grammar.py index 4c47e08..861baac 100644 --- a/src/grammar.py +++ b/src/grammar.py @@ -2,15 +2,16 @@ from terminal import Terminal from nonTerminal import NonTerminal class Grammar: - __atomKeyMapping = [] - __productions = [] - __first = {} + def __init__(self): + self.__nonTerminals = {} + self.__terminals = {} + self.__startSymbol = None; + self.__endMarker = Terminal("$") - __nonTerminals = {} - __terminals = {} - def addProduction(self, nonTerminal, atoms): - + if self.__startSymbol == None: + self.__startSymbol = nonTerminal; + self.__startSymbol.addToFollowSet(self.__endMarker); self.__addAtom(nonTerminal); @@ -45,6 +46,7 @@ class Grammar: def generateMetrics(self): self.__generateFirstSets() + self.__generateFollowSets() def __generateFirstSets(self): @@ -52,6 +54,9 @@ class Grammar: nonTerminal = self.__nonTerminals[key] nonTerminal.generateFirstSet(); + def __generateFollowSets(self): + for key in self.__nonTerminals: + self.__nonTerminals[key].generateFollowSet() def printNullableSet(self): output = "Nullable = { " diff --git a/src/nonTerminal.py b/src/nonTerminal.py index 26fa743..4dcc11c 100644 --- a/src/nonTerminal.py +++ b/src/nonTerminal.py @@ -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) diff --git a/src/testParser.py b/src/testParser.py index 2fa071a..2472910 100755 --- a/src/testParser.py +++ b/src/testParser.py @@ -18,5 +18,3 @@ grm.printNullableSet() print("----------------") grm.printFirstSets() - -#prs.printGrammar();